diff --git a/wear/src/main/java/io/homeassistant/companion/android/home/HomeActivity.kt b/wear/src/main/java/io/homeassistant/companion/android/home/HomeActivity.kt index 3f823f5b2d5..9efd810792a 100644 --- a/wear/src/main/java/io/homeassistant/companion/android/home/HomeActivity.kt +++ b/wear/src/main/java/io/homeassistant/companion/android/home/HomeActivity.kt @@ -1,11 +1,15 @@ package io.homeassistant.companion.android.home +import android.Manifest import android.content.Context import android.content.Intent +import android.os.Build import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent +import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.viewModels +import androidx.core.app.NotificationManagerCompat import androidx.core.net.toUri import androidx.lifecycle.Lifecycle import androidx.lifecycle.lifecycleScope @@ -32,11 +36,18 @@ class HomeActivity : ComponentActivity(), HomeView { private var entityUpdateJob: Job? = null + private val permissionRequest = registerForActivityResult(ActivityResultContracts.RequestPermission()) { + mainViewModel.refreshNotificationPermission() + } + companion object { private const val TAG = "HomeActivity" + private const val EXTRA_FROM_ONBOARDING = "from_onboarding" - fun newInstance(context: Context): Intent { - return Intent(context, HomeActivity::class.java) + fun newInstance(context: Context, fromOnboarding: Boolean = false): Intent { + return Intent(context, HomeActivity::class.java).apply { + putExtra(EXTRA_FROM_ONBOARDING, fromOnboarding) + } } fun getCameraTileSettingsIntent( @@ -110,6 +121,14 @@ class HomeActivity : ComponentActivity(), HomeView { mainViewModel.updateUI() } } + if ( + intent.getBooleanExtra(EXTRA_FROM_ONBOARDING, false) && + Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && + !NotificationManagerCompat.from(this@HomeActivity).areNotificationsEnabled() + ) { + permissionRequest.launch(Manifest.permission.POST_NOTIFICATIONS) + intent.removeExtra(EXTRA_FROM_ONBOARDING) + } } override fun onPause() { diff --git a/wear/src/main/java/io/homeassistant/companion/android/home/MainViewModel.kt b/wear/src/main/java/io/homeassistant/companion/android/home/MainViewModel.kt index 5b49a7f4d04..ab4be5a1fcd 100644 --- a/wear/src/main/java/io/homeassistant/companion/android/home/MainViewModel.kt +++ b/wear/src/main/java/io/homeassistant/companion/android/home/MainViewModel.kt @@ -12,6 +12,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import androidx.compose.runtime.snapshots.SnapshotStateList import androidx.compose.runtime.toMutableStateList +import androidx.core.app.NotificationManagerCompat import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel @@ -130,6 +131,8 @@ class MainViewModel @Inject constructor( private set var isAssistantAppAllowed by mutableStateOf(true) private set + var areNotificationsAllowed by mutableStateOf(false) + private set fun supportedDomains(): List = HomePresenterImpl.supportedDomains @@ -159,6 +162,8 @@ class MainViewModel @Inject constructor( ) isAssistantAppAllowed = app.packageManager.getComponentEnabledSetting(assistantAppComponent) != PackageManager.COMPONENT_ENABLED_STATE_DISABLED + + refreshNotificationPermission() } } @@ -546,6 +551,10 @@ class MainViewModel @Inject constructor( isAssistantAppAllowed = allowed } + fun refreshNotificationPermission() { + areNotificationsAllowed = NotificationManagerCompat.from(app).areNotificationsEnabled() + } + fun logout() { homePresenter.onLogoutClicked() diff --git a/wear/src/main/java/io/homeassistant/companion/android/home/views/HomeView.kt b/wear/src/main/java/io/homeassistant/companion/android/home/views/HomeView.kt index 1ffd48b7836..c0021c11b92 100644 --- a/wear/src/main/java/io/homeassistant/companion/android/home/views/HomeView.kt +++ b/wear/src/main/java/io/homeassistant/companion/android/home/views/HomeView.kt @@ -1,5 +1,9 @@ package io.homeassistant.companion.android.home.views +import android.content.Intent +import android.provider.Settings +import androidx.activity.compose.rememberLauncherForActivityResult +import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateOf @@ -134,6 +138,9 @@ fun LoadHomePage( ) } composable(SCREEN_SETTINGS) { + val notificationLaunch = rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) { + mainViewModel.refreshNotificationPermission() + } SettingsView( loadingState = mainViewModel.loadingState.value, favorites = mainViewModel.favoriteEntityIds.value, @@ -159,6 +166,7 @@ fun LoadHomePage( isToastEnabled = mainViewModel.isToastEnabled.value, isFavoritesOnly = mainViewModel.isFavoritesOnly, isAssistantAppAllowed = mainViewModel.isAssistantAppAllowed, + areNotificationsAllowed = mainViewModel.areNotificationsAllowed, onHapticEnabled = { mainViewModel.setHapticEnabled(it) }, onToastEnabled = { mainViewModel.setToastEnabled(it) }, setFavoritesOnly = { mainViewModel.setWearFavoritesOnly(it) }, @@ -169,7 +177,14 @@ fun LoadHomePage( mainViewModel.loadTemplateTiles() swipeDismissableNavController.navigate("$ROUTE_TEMPLATE_TILE/$SCREEN_SELECT_TEMPLATE_TILE") }, - onAssistantAppAllowed = mainViewModel::setAssistantApp + onAssistantAppAllowed = mainViewModel::setAssistantApp, + onClickNotifications = { + notificationLaunch.launch( + Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS).apply { + putExtra(Settings.EXTRA_APP_PACKAGE, context.packageName) + } + ) + } ) } composable(SCREEN_SET_FAVORITES) { diff --git a/wear/src/main/java/io/homeassistant/companion/android/home/views/SettingsView.kt b/wear/src/main/java/io/homeassistant/companion/android/home/views/SettingsView.kt index 43137e4c5bb..551e5fc1f0e 100644 --- a/wear/src/main/java/io/homeassistant/companion/android/home/views/SettingsView.kt +++ b/wear/src/main/java/io/homeassistant/companion/android/home/views/SettingsView.kt @@ -68,12 +68,14 @@ fun SettingsView( isToastEnabled: Boolean, isFavoritesOnly: Boolean, isAssistantAppAllowed: Boolean, + areNotificationsAllowed: Boolean, onHapticEnabled: (Boolean) -> Unit, onToastEnabled: (Boolean) -> Unit, setFavoritesOnly: (Boolean) -> Unit, onClickCameraTile: () -> Unit, onClickTemplateTiles: () -> Unit, - onAssistantAppAllowed: (Boolean) -> Unit + onAssistantAppAllowed: (Boolean) -> Unit, + onClickNotifications: () -> Unit ) { WearAppTheme { ThemeLazyColumn { @@ -224,6 +226,20 @@ fun SettingsView( colors = getToggleButtonColors() ) } + if (!areNotificationsAllowed) { + item { + ListHeader( + id = commonR.string.notifications + ) + } + item { + SecondarySettingsChip( + icon = CommunityMaterial.Icon.cmd_bell_ring, + label = stringResource(commonR.string.suggestion_notifications_title), + onClick = onClickNotifications + ) + } + } item { ListHeader( id = commonR.string.account @@ -268,11 +284,13 @@ private fun PreviewSettingsView() { isToastEnabled = false, isFavoritesOnly = false, isAssistantAppAllowed = true, + areNotificationsAllowed = false, onHapticEnabled = {}, onToastEnabled = {}, setFavoritesOnly = {}, onClickCameraTile = {}, onClickTemplateTiles = {}, - onAssistantAppAllowed = {} + onAssistantAppAllowed = {}, + onClickNotifications = {} ) } diff --git a/wear/src/main/java/io/homeassistant/companion/android/onboarding/integration/MobileAppIntegrationActivity.kt b/wear/src/main/java/io/homeassistant/companion/android/onboarding/integration/MobileAppIntegrationActivity.kt index 3c5a0078f8c..ebe2cee0156 100644 --- a/wear/src/main/java/io/homeassistant/companion/android/onboarding/integration/MobileAppIntegrationActivity.kt +++ b/wear/src/main/java/io/homeassistant/companion/android/onboarding/integration/MobileAppIntegrationActivity.kt @@ -57,7 +57,7 @@ class MobileAppIntegrationActivity : AppCompatActivity(), MobileAppIntegrationVi } override fun deviceRegistered() { - val intent = HomeActivity.newInstance(this) + val intent = HomeActivity.newInstance(this, fromOnboarding = true) // empty the back stack intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK startActivity(intent) diff --git a/wear/src/main/java/io/homeassistant/companion/android/phone/PhoneSettingsListener.kt b/wear/src/main/java/io/homeassistant/companion/android/phone/PhoneSettingsListener.kt index abe9f973e56..5c1a6351bef 100755 --- a/wear/src/main/java/io/homeassistant/companion/android/phone/PhoneSettingsListener.kt +++ b/wear/src/main/java/io/homeassistant/companion/android/phone/PhoneSettingsListener.kt @@ -194,7 +194,7 @@ class PhoneSettingsListener : WearableListenerService(), DataClient.OnDataChange updateTiles() } - val intent = HomeActivity.newInstance(applicationContext) + val intent = HomeActivity.newInstance(applicationContext, fromOnboarding = true) intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK startActivity(intent) } catch (e: Exception) {