-
Notifications
You must be signed in to change notification settings - Fork 3.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Change the Notification permission flow #1099
Changes from 1 commit
f313b4e
cfa1d51
f193218
b5b0095
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -59,12 +59,14 @@ import androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridItemSpan | |
import androidx.compose.foundation.lazy.staggeredgrid.rememberLazyStaggeredGridState | ||
import androidx.compose.foundation.shape.CornerSize | ||
import androidx.compose.foundation.shape.RoundedCornerShape | ||
import androidx.compose.material3.AlertDialog | ||
import androidx.compose.material3.Icon | ||
import androidx.compose.material3.MaterialTheme | ||
import androidx.compose.material3.Surface | ||
import androidx.compose.material3.Text | ||
import androidx.compose.runtime.Composable | ||
import androidx.compose.runtime.LaunchedEffect | ||
import androidx.compose.runtime.collectAsState | ||
import androidx.compose.runtime.getValue | ||
import androidx.compose.ui.Alignment | ||
import androidx.compose.ui.Modifier | ||
|
@@ -116,16 +118,22 @@ internal fun ForYouRoute( | |
val feedState by viewModel.feedState.collectAsStateWithLifecycle() | ||
val isSyncing by viewModel.isSyncing.collectAsStateWithLifecycle() | ||
val deepLinkedUserNewsResource by viewModel.deepLinkedNewsResource.collectAsStateWithLifecycle() | ||
val showDialog by viewModel.dialogState.collectAsState() | ||
val askNotificationPermission by viewModel.showNotificationPermission.collectAsState() | ||
|
||
ForYouScreen( | ||
isSyncing = isSyncing, | ||
onboardingUiState = onboardingUiState, | ||
feedState = feedState, | ||
deepLinkedUserNewsResource = deepLinkedUserNewsResource, | ||
askShowDialog = showDialog, | ||
askNotificationPermission = askNotificationPermission, | ||
onTopicCheckedChanged = viewModel::updateTopicSelection, | ||
onDeepLinkOpened = viewModel::onDeepLinkOpened, | ||
onTopicClick = onTopicClick, | ||
saveFollowedTopics = viewModel::dismissOnboarding, | ||
showNotificationPermissionDialog = viewModel::toggleDialog, | ||
showNotificationPermission = viewModel::showNotificationPermission, | ||
onNewsResourcesCheckedChanged = viewModel::updateNewsResourceSaved, | ||
onNewsResourceViewed = { viewModel.setNewsResourceViewed(it, true) }, | ||
modifier = modifier, | ||
|
@@ -138,10 +146,14 @@ internal fun ForYouScreen( | |
onboardingUiState: OnboardingUiState, | ||
feedState: NewsFeedUiState, | ||
deepLinkedUserNewsResource: UserNewsResource?, | ||
askShowDialog: Boolean, | ||
askNotificationPermission: Boolean, | ||
onTopicCheckedChanged: (String, Boolean) -> Unit, | ||
onTopicClick: (String) -> Unit, | ||
onDeepLinkOpened: (String) -> Unit, | ||
saveFollowedTopics: () -> Unit, | ||
showNotificationPermissionDialog: () -> Unit, | ||
showNotificationPermission: () -> Unit, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suggest renaming these to |
||
onNewsResourcesCheckedChanged: (String, Boolean) -> Unit, | ||
onNewsResourceViewed: (String) -> Unit, | ||
modifier: Modifier = Modifier, | ||
|
@@ -160,6 +172,18 @@ internal fun ForYouScreen( | |
) | ||
TrackScrollJank(scrollableState = state, stateName = "forYou:feed") | ||
|
||
if(askShowDialog){ | ||
ShowDialog( | ||
showNotificationPermissionDialog, | ||
showNotificationPermission | ||
) | ||
} | ||
|
||
if(askNotificationPermission){ | ||
NotificationPermissionEffect() | ||
showNotificationPermission() | ||
} | ||
|
||
Box( | ||
modifier = modifier | ||
.fillMaxSize(), | ||
|
@@ -177,6 +201,7 @@ internal fun ForYouScreen( | |
onboardingUiState = onboardingUiState, | ||
onTopicCheckedChanged = onTopicCheckedChanged, | ||
saveFollowedTopics = saveFollowedTopics, | ||
askNotificationPermission = showNotificationPermissionDialog, | ||
// Custom LayoutModifier to remove the enforced parent 16.dp contentPadding | ||
// from the LazyVerticalGrid and enable edge-to-edge scrolling for this section | ||
interestsItemModifier = Modifier.layout { measurable, constraints -> | ||
|
@@ -244,7 +269,7 @@ internal fun ForYouScreen( | |
) | ||
} | ||
TrackScreenViewEvent(screenName = "ForYou") | ||
NotificationPermissionEffect() | ||
// NotificationPermissionEffect() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Before merging, commented out code should be removed entirely. |
||
DeepLinkEffect( | ||
deepLinkedUserNewsResource, | ||
onDeepLinkOpened, | ||
|
@@ -260,6 +285,7 @@ private fun LazyStaggeredGridScope.onboarding( | |
onboardingUiState: OnboardingUiState, | ||
onTopicCheckedChanged: (String, Boolean) -> Unit, | ||
saveFollowedTopics: () -> Unit, | ||
askNotificationPermission: () -> Unit, | ||
interestsItemModifier: Modifier = Modifier, | ||
) { | ||
when (onboardingUiState) { | ||
|
@@ -298,7 +324,10 @@ private fun LazyStaggeredGridScope.onboarding( | |
modifier = Modifier.fillMaxWidth(), | ||
) { | ||
NiaButton( | ||
onClick = saveFollowedTopics, | ||
onClick = { | ||
askNotificationPermission() | ||
saveFollowedTopics() | ||
}, | ||
enabled = onboardingUiState.isDismissable, | ||
modifier = Modifier | ||
.padding(horizontal = 24.dp) | ||
|
@@ -444,6 +473,38 @@ fun TopicIcon( | |
) | ||
} | ||
|
||
@Composable | ||
private fun ShowDialog( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suggest renaming this function to |
||
onDismissRequest: ()-> Unit, | ||
askNotificationPermission: () -> Unit | ||
) { | ||
AlertDialog( | ||
onDismissRequest = onDismissRequest, | ||
title = { | ||
Text(text = "Grant Notification Permission") | ||
}, | ||
text = { | ||
Text("Would you like to be informed when new content is published on these topics, content is typically published every few days?") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. String resources should be placed in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @arvindri2005 Please do not resolve comments before they have actually been resolved. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have fixed this in the latest commit cfa1d51 |
||
}, | ||
confirmButton = { | ||
NiaButton( | ||
onClick = { | ||
askNotificationPermission() | ||
onDismissRequest() | ||
}, | ||
) { | ||
Text(text = "OK") | ||
} | ||
}, | ||
dismissButton = { | ||
NiaButton(onClick = onDismissRequest ) { | ||
Text(text ="Cancel") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To maintain consistency and ease of localization, the "Ok" and the "Cancel" strings also should be included in the string file. |
||
} | ||
}, | ||
) | ||
} | ||
|
||
|
||
@Composable | ||
@OptIn(ExperimentalPermissionsApi::class) | ||
private fun NotificationPermissionEffect() { | ||
|
@@ -516,8 +577,12 @@ fun ForYouScreenPopulatedFeed( | |
feed = userNewsResources, | ||
), | ||
deepLinkedUserNewsResource = null, | ||
askShowDialog = false, | ||
askNotificationPermission = false, | ||
onTopicCheckedChanged = { _, _ -> }, | ||
saveFollowedTopics = {}, | ||
showNotificationPermission = {}, | ||
showNotificationPermissionDialog = {}, | ||
onNewsResourcesCheckedChanged = { _, _ -> }, | ||
onNewsResourceViewed = {}, | ||
onTopicClick = {}, | ||
|
@@ -542,8 +607,12 @@ fun ForYouScreenOfflinePopulatedFeed( | |
feed = userNewsResources, | ||
), | ||
deepLinkedUserNewsResource = null, | ||
askShowDialog = false, | ||
askNotificationPermission = false, | ||
onTopicCheckedChanged = { _, _ -> }, | ||
saveFollowedTopics = {}, | ||
showNotificationPermission = {}, | ||
showNotificationPermissionDialog = {}, | ||
onNewsResourcesCheckedChanged = { _, _ -> }, | ||
onNewsResourceViewed = {}, | ||
onTopicClick = {}, | ||
|
@@ -571,8 +640,12 @@ fun ForYouScreenTopicSelection( | |
feed = userNewsResources, | ||
), | ||
deepLinkedUserNewsResource = null, | ||
askShowDialog = false, | ||
askNotificationPermission = false, | ||
onTopicCheckedChanged = { _, _ -> }, | ||
saveFollowedTopics = {}, | ||
showNotificationPermission = {}, | ||
showNotificationPermissionDialog = {}, | ||
onNewsResourcesCheckedChanged = { _, _ -> }, | ||
onNewsResourceViewed = {}, | ||
onTopicClick = {}, | ||
|
@@ -592,8 +665,12 @@ fun ForYouScreenLoading() { | |
onboardingUiState = OnboardingUiState.Loading, | ||
feedState = NewsFeedUiState.Loading, | ||
deepLinkedUserNewsResource = null, | ||
askShowDialog = false, | ||
askNotificationPermission = false, | ||
onTopicCheckedChanged = { _, _ -> }, | ||
saveFollowedTopics = {}, | ||
showNotificationPermission = {}, | ||
showNotificationPermissionDialog = {}, | ||
onNewsResourcesCheckedChanged = { _, _ -> }, | ||
onNewsResourceViewed = {}, | ||
onTopicClick = {}, | ||
|
@@ -618,8 +695,12 @@ fun ForYouScreenPopulatedAndLoading( | |
feed = userNewsResources, | ||
), | ||
deepLinkedUserNewsResource = null, | ||
askShowDialog = false, | ||
askNotificationPermission = false, | ||
onTopicCheckedChanged = { _, _ -> }, | ||
saveFollowedTopics = {}, | ||
showNotificationPermission = {}, | ||
showNotificationPermissionDialog = {}, | ||
onNewsResourcesCheckedChanged = { _, _ -> }, | ||
onNewsResourceViewed = {}, | ||
onTopicClick = {}, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,6 +31,7 @@ import com.google.samples.apps.nowinandroid.core.ui.NewsFeedUiState | |
import com.google.samples.apps.nowinandroid.feature.foryou.navigation.LINKED_NEWS_RESOURCE_ID | ||
import dagger.hilt.android.lifecycle.HiltViewModel | ||
import kotlinx.coroutines.flow.Flow | ||
import kotlinx.coroutines.flow.MutableStateFlow | ||
import kotlinx.coroutines.flow.SharingStarted | ||
import kotlinx.coroutines.flow.StateFlow | ||
import kotlinx.coroutines.flow.combine | ||
|
@@ -109,6 +110,23 @@ class ForYouViewModel @Inject constructor( | |
initialValue = OnboardingUiState.Loading, | ||
) | ||
|
||
private val _showNotificationPermission = MutableStateFlow(false) | ||
val showNotificationPermission: StateFlow<Boolean> = _showNotificationPermission | ||
private val _dialogState = MutableStateFlow(false) | ||
val dialogState: StateFlow<Boolean> = _dialogState | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could this be named more descriptively? It's not clear which dialog this state is for. |
||
|
||
fun toggleDialog() { | ||
viewModelScope.launch { | ||
_dialogState.emit(!_dialogState.value) | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. _dialogState.update {} is simpler There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
you want something Like this |
||
} | ||
fun showNotificationPermission() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The name of this function is |
||
viewModelScope.launch { | ||
_showNotificationPermission.emit(!_showNotificationPermission.value) | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above 🙏 |
||
} | ||
|
||
|
||
fun updateTopicSelection(topicId: String, isChecked: Boolean) { | ||
viewModelScope.launch { | ||
userDataRepository.setTopicIdFollowed(topicId, isChecked) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like all of the changes here are to make existing tests pass, could we add a new test for the updated flow?