NTP-14898 Notify Me HP Nudge fixes (#14154)

This commit is contained in:
Aparna Vadlamani
2024-12-16 17:05:36 +05:30
committed by GitHub
parent 1b4e8b61d9
commit 08c7052b2e
16 changed files with 211 additions and 132 deletions

View File

@@ -267,7 +267,6 @@ dependencies {
implementation project(":navi-pay")
implementation project(":navi-payment")
implementation project(":navi-rr")
implementation libs.accompanist.permissions
implementation libs.accompanist.systemuicontroller
implementation libs.android.gms.playServicesAds
implementation libs.android.gms.playServicesAuth

View File

@@ -75,6 +75,21 @@ class AppSettingsAnalytics {
}
inner class NotificationSettings {
fun onPushNotificationPermissionGranted() {
NaviTrackEvent.trackEvent(
eventName =
analyticsPrefix + "notification_screen_push_notification_permission_granted"
)
}
fun onPushNotificationPermissionDenied(inAppAllowable: Boolean) {
NaviTrackEvent.trackEvent(
eventName =
analyticsPrefix + "notification_screen_push_notification_permission_denied",
eventValues = mapOf("in_app_allowable" to inAppAllowable.toString())
)
}
fun onNotificationScreenLanded() {
NaviTrackEvent.trackEvent(eventName = analyticsPrefix + "notification_screen_land")
}

View File

@@ -7,8 +7,7 @@
package com.naviapp.appsettings.ui.screens
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import android.Manifest
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
@@ -29,9 +28,14 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.google.accompanist.permissions.ExperimentalPermissionsApi
import com.navi.common.permission.PermissionResult
import com.navi.common.permission.rememberMultiplePermissions
import com.naviapp.R
import com.naviapp.appsettings.activity.AppSettingsActivity
import com.naviapp.appsettings.analytics.AppSettingsAnalytics
import com.naviapp.appsettings.model.notificationSettings.BottomSheetContent
import com.naviapp.appsettings.model.notificationSettings.NotificationSettingsBottomSheetType
import com.naviapp.appsettings.model.notificationSettings.NotificationSettingsUiEvents
import com.naviapp.appsettings.model.notificationSettings.SettingsState
import com.naviapp.appsettings.ui.bottomSheets.NotificationSettingsBottomSheet
@@ -51,6 +55,7 @@ import com.naviapp.models.response.NotificationSettings
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
@OptIn(ExperimentalPermissionsApi::class)
@Destination
@Composable
fun NotificationSettingsScreen(
@@ -63,19 +68,50 @@ fun NotificationSettingsScreen(
val isPushNotificationPermissionEnabled = remember {
mutableStateOf(hasNotificationPermission(activity))
}
InitLifecycleListener(isPushNotificationPermissionEnabled, activity, viewModel)
val state by viewModel.state.collectAsStateWithLifecycle()
val permissionLauncher =
rememberLauncherForActivityResult(
contract = ActivityResultContracts.RequestPermission(),
onResult = { enabled ->
handleNotificationSettingChange(
viewModel,
listOf(NotificationSettings(SettingsMedium.PUSH_NOTIFICATION, enabled))
)
val pushNotificationPermission =
rememberMultiplePermissions(permissions = listOf(Manifest.permission.POST_NOTIFICATIONS)) {
when (it) {
PermissionResult.AllGranted -> {
analytics.onPushNotificationPermissionGranted()
}
PermissionResult.HardDenied -> {
analytics.onPushNotificationPermissionDenied(false)
viewModel.sendEvent(
NotificationSettingsUiEvents.ShowBottomSheet(
bottomSheetContent =
BottomSheetContent(
composableType =
NotificationSettingsBottomSheetType.OPEN_SETTINGS
)
)
)
}
PermissionResult.ShowRationale -> {
analytics.onPushNotificationPermissionDenied(true)
}
PermissionResult.None -> {}
}
)
}
LaunchedEffect(pushNotificationPermission.allPermissionsGranted) {
if (
isPushNotificationPermissionEnabled.value !=
pushNotificationPermission.allPermissionsGranted
) {
isPushNotificationPermissionEnabled.value =
pushNotificationPermission.allPermissionsGranted
handleNotificationSettingChange(
viewModel,
listOf(
NotificationSettings(
SettingsMedium.PUSH_NOTIFICATION,
pushNotificationPermission.allPermissionsGranted
)
)
)
}
}
val state by viewModel.state.collectAsStateWithLifecycle()
LaunchedEffect(Unit) {
analytics.onNotificationScreenLanded()
@@ -138,21 +174,25 @@ fun NotificationSettingsScreen(
settingsState = settingsState,
enableAllNotifications = {
enableAllNotifications(
isPushNotificationPermissionEnabled.value,
settingsState,
activity,
viewModel,
permissionLauncher
isPushNotificationPermissionEnabled =
isPushNotificationPermissionEnabled.value,
settingsState = settingsState,
viewModel = viewModel,
launchPermissionRequest = {
pushNotificationPermission.launchMultiplePermissionRequest()
}
)
},
onCheckedChange = { setting, enabled ->
onNotificationToggleChange(
isPushNotificationPermissionEnabled.value,
setting,
enabled,
activity,
permissionLauncher,
viewModel
isPushNotificationPermissionEnabled =
isPushNotificationPermissionEnabled.value,
setting = setting,
enabled = enabled,
viewModel = viewModel,
launchPermissionRequest = {
pushNotificationPermission.launchMultiplePermissionRequest()
}
)
},
)

View File

@@ -22,8 +22,6 @@ import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.ripple
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.key
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
@@ -34,9 +32,6 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.compose.LocalLifecycleOwner
import com.navi.base.utils.orFalse
import com.navi.elex.atoms.ElexImage
import com.navi.elex.atoms.ElexText
@@ -44,55 +39,15 @@ import com.navi.elex.font.FontWeightEnum
import com.navi.naviwidgets.utils.NaviWidgetIconUtils.ICON_PURPLE_RETRY
import com.navi.naviwidgets.utils.NaviWidgetIconUtils.getImageFromIconCode
import com.naviapp.R
import com.naviapp.appsettings.activity.AppSettingsActivity
import com.naviapp.appsettings.analytics.AppSettingsAnalytics
import com.naviapp.appsettings.model.notificationSettings.SettingsState
import com.naviapp.appsettings.ui.common.ScreenSectionHeading
import com.naviapp.appsettings.ui.common.SwitchableSetting
import com.naviapp.appsettings.ui.common.SwitchableSettingsContainer
import com.naviapp.appsettings.utils.SettingsMedium
import com.naviapp.appsettings.utils.getIconCodeFromMedium
import com.naviapp.appsettings.utils.handleNotificationSettingChange
import com.naviapp.appsettings.utils.hasNotificationPermission
import com.naviapp.appsettings.viewmodel.NotificationSettingsVM
import com.naviapp.home.utils.shimmerEffect
import com.naviapp.models.response.NotificationSettings
@Composable
fun InitLifecycleListener(
isPushNotificationPermissionEnabled: MutableState<Boolean>,
activity: AppSettingsActivity,
viewModel: NotificationSettingsVM
) {
val lifecycleOwner = LocalLifecycleOwner.current
DisposableEffect(lifecycleOwner) {
val observer = LifecycleEventObserver { _, event ->
when (event) {
Lifecycle.Event.ON_RESUME -> {
val currentPushNotificationStatus = hasNotificationPermission(activity)
if (
isPushNotificationPermissionEnabled.value != currentPushNotificationStatus
) {
isPushNotificationPermissionEnabled.value = currentPushNotificationStatus
handleNotificationSettingChange(
viewModel,
listOf(
NotificationSettings(
SettingsMedium.PUSH_NOTIFICATION,
currentPushNotificationStatus
)
)
)
}
}
else -> {}
}
}
lifecycleOwner.lifecycle.addObserver(observer)
onDispose { lifecycleOwner.lifecycle.removeObserver(observer) }
}
}
@Composable
fun NotificationSettingsContainer(
settingsState: SettingsState.Success,

View File

@@ -11,14 +11,11 @@ import android.Manifest
import android.app.Activity
import android.content.pm.PackageManager
import android.os.Build
import androidx.activity.compose.ManagedActivityResultLauncher
import androidx.core.app.ActivityCompat.shouldShowRequestPermissionRationale
import androidx.core.content.ContextCompat
import com.navi.naviwidgets.utils.NaviWidgetIconUtils.ICON_BLACK_BELL_NOTIFICATION
import com.navi.naviwidgets.utils.NaviWidgetIconUtils.ICON_PURPLE_RETRY
import com.navi.naviwidgets.utils.NaviWidgetIconUtils.ICON_SMS
import com.navi.naviwidgets.utils.NaviWidgetIconUtils.ICON_WHATSAPP
import com.naviapp.appsettings.activity.AppSettingsActivity
import com.naviapp.appsettings.model.notificationSettings.BottomSheetContent
import com.naviapp.appsettings.model.notificationSettings.NotificationSettingsBottomSheetType
import com.naviapp.appsettings.model.notificationSettings.NotificationSettingsUiEvents
@@ -31,25 +28,11 @@ fun hasNotificationPermission(context: Activity): Boolean {
PackageManager.PERMISSION_GRANTED
}
fun getNotificationPermission(
activity: AppSettingsActivity,
permissionLauncher: ManagedActivityResultLauncher<String, Boolean>,
onEvent: (NotificationSettingsUiEvents) -> Unit
) {
if (
Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU &&
shouldShowRequestPermissionRationale(activity, Manifest.permission.POST_NOTIFICATIONS)
) {
permissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
fun getNotificationPermission(launchPermissionRequest: () -> Unit, showBottomSheet: () -> Unit) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
launchPermissionRequest()
} else {
onEvent(
NotificationSettingsUiEvents.ShowBottomSheet(
bottomSheetContent =
BottomSheetContent(
composableType = NotificationSettingsBottomSheetType.OPEN_SETTINGS
)
)
)
showBottomSheet()
}
}
@@ -76,9 +59,8 @@ fun getIconCodeFromMedium(medium: SettingsMedium?): String {
fun enableAllNotifications(
isPushNotificationPermissionEnabled: Boolean,
settingsState: SettingsState.Success,
activity: AppSettingsActivity,
viewModel: NotificationSettingsVM,
permissionLauncher: ManagedActivityResultLauncher<String, Boolean>
launchPermissionRequest: () -> Unit
) {
val updatedList =
settingsState.notificationSettingsList.map { notificationSetting ->
@@ -91,9 +73,17 @@ fun enableAllNotifications(
handleNotificationSettingChange(viewModel, updatedList)
if (isPushNotificationPermissionEnabled.not()) {
getNotificationPermission(
activity,
permissionLauncher,
onEvent = { event -> viewModel.sendEvent(event) }
launchPermissionRequest = launchPermissionRequest,
showBottomSheet = {
viewModel.sendEvent(
NotificationSettingsUiEvents.ShowBottomSheet(
bottomSheetContent =
BottomSheetContent(
composableType = NotificationSettingsBottomSheetType.OPEN_SETTINGS
)
)
)
}
)
}
}
@@ -102,9 +92,8 @@ fun onNotificationToggleChange(
isPushNotificationPermissionEnabled: Boolean,
setting: NotificationSettings,
enabled: Boolean,
activity: AppSettingsActivity,
permissionLauncher: ManagedActivityResultLauncher<String, Boolean>,
viewModel: NotificationSettingsVM
viewModel: NotificationSettingsVM,
launchPermissionRequest: () -> Unit
) {
if (
setting.medium == SettingsMedium.PUSH_NOTIFICATION &&
@@ -112,9 +101,17 @@ fun onNotificationToggleChange(
isPushNotificationPermissionEnabled.not()
) {
getNotificationPermission(
activity = activity,
permissionLauncher = permissionLauncher,
onEvent = { event -> viewModel.sendEvent(event) }
launchPermissionRequest = launchPermissionRequest,
showBottomSheet = {
viewModel.sendEvent(
NotificationSettingsUiEvents.ShowBottomSheet(
bottomSheetContent =
BottomSheetContent(
composableType = NotificationSettingsBottomSheetType.OPEN_SETTINGS
)
)
)
}
)
} else {
handleNotificationSettingChange(viewModel, listOf(setting.copy(enabled = enabled)))

View File

@@ -7,6 +7,7 @@
package com.naviapp.home.compose.home.ui.content
import android.Manifest
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
@@ -32,10 +33,9 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.google.accompanist.permissions.ExperimentalPermissionsApi
import com.google.accompanist.permissions.isGranted
import com.google.accompanist.permissions.rememberPermissionState
import com.google.accompanist.permissions.shouldShowRationale
import com.navi.common.alchemist.model.AlchemistWidgetModelDefinition
import com.navi.common.permission.PermissionResult
import com.navi.common.permission.rememberMultiplePermissions
import com.navi.common.utils.CommonNaviAnalytics
import com.navi.common.utils.Constants.NOTIFY_WIDGET_DATA
import com.navi.elex.atoms.ElexAsyncImage
@@ -55,20 +55,35 @@ fun HomeNotifyMeWidget(
notifyMeAnalytics: CommonNaviAnalytics.NotifyMe =
CommonNaviAnalytics.naviAnalytics.NotifyMe(HOME_SCREEN_IN_CAPS)
) {
val notificationPermission =
rememberPermissionState(permission = android.Manifest.permission.POST_NOTIFICATIONS)
val pushNotificationPermission =
rememberMultiplePermissions(permissions = listOf(Manifest.permission.POST_NOTIFICATIONS)) {
when (it) {
PermissionResult.AllGranted -> {
notifyMeAnalytics.notifyMeNudgePermissionGrantedEvent()
}
PermissionResult.HardDenied -> {
notifyMeAnalytics.notifyMeNudgePermissionDeniedEvent(inAppAllowable = false)
showBottomSheet()
}
PermissionResult.ShowRationale -> {
notifyMeAnalytics.notifyMeNudgePermissionDeniedEvent(inAppAllowable = true)
}
PermissionResult.None -> {}
}
}
val widgetData = widget.widgetData?.data?.get(NOTIFY_WIDGET_DATA) as? NotifyMeWidgetData
val visible by remember { mutableStateOf(notificationPermission.status.isGranted.not()) }
LaunchedEffect(notificationPermission.status.isGranted) {
if (notificationPermission.status.isGranted) {
notifyMeAnalytics.notifyMeNudgePermissionGrantedEvent()
val visible by remember {
mutableStateOf(pushNotificationPermission.allPermissionsGranted.not())
}
LaunchedEffect(pushNotificationPermission.allPermissionsGranted) {
if (pushNotificationPermission.allPermissionsGranted) {
onPermissionGranted(true)
}
}
if (visible) {
notifyMeAnalytics.notifyMeNudgeViewEvent()
NotifyMeUI(
permissionGranted = notificationPermission.status.isGranted,
permissionGranted = (pushNotificationPermission.allPermissionsGranted),
widgetData,
onDismissNudge = {
notifyMeAnalytics.notifyMeNudgeDismissEvent()
@@ -76,12 +91,7 @@ fun HomeNotifyMeWidget(
},
onClick = {
notifyMeAnalytics.notifyMeNudgeClickEvent()
if (notificationPermission.status.shouldShowRationale) {
notifyMeAnalytics.notifyMeNudgePermissionPromptShownEvent()
notificationPermission.launchPermissionRequest()
} else {
showBottomSheet()
}
pushNotificationPermission.launchMultiplePermissionRequest()
}
)
}