Skip to content
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

[#547] Define "results" for the "Up" navigation to deliver result to previous screens #530

Merged
merged 5 commits into from
Dec 6, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package co.nimblehq.sample.compose.extensions

import androidx.lifecycle.SavedStateHandle

fun <T> SavedStateHandle.getThenRemove(key: String): T? {
return if (contains(key)) {
val value = get<T>(key)
remove<T>(key)
value
} else null
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import co.nimblehq.sample.compose.ui.base.BaseDestination
import co.nimblehq.sample.compose.ui.screens.main.mainNavGraph

@Composable
fun AppNavigation(
fun AppNavGraph(
navController: NavHostController,
) {
NavHost(
Expand Down Expand Up @@ -44,7 +44,12 @@ fun NavGraphBuilder.composable(
*/
fun NavHostController.navigate(destination: BaseDestination, parcel: Pair<String, Any?>? = null) {
when (destination) {
is BaseDestination.Up -> navigateUp()
is BaseDestination.Up -> {
destination.results.forEach { (key, value) ->
previousBackStackEntry?.savedStateHandle?.set(key, value)
}
navigateUp()
}
else -> {
parcel?.let { (key, value) ->
currentBackStackEntry?.savedStateHandle?.set(key, value)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package co.nimblehq.sample.compose.ui.base

import androidx.navigation.NamedNavArgument

const val KeyResultOk = "keyResultOk"

abstract class BaseDestination(val route: String = "") {

open val arguments: List<NamedNavArgument> = emptyList()
Expand All @@ -10,5 +12,10 @@ abstract class BaseDestination(val route: String = "") {

open var parcelableArgument: Pair<String, Any?> = "" to null

object Up : BaseDestination()
data class Up(val results: HashMap<String, Any> = hashMapOf()) : BaseDestination() {

fun addResult(key: String, value: Any) = apply {
results[key] = value
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.navigation.compose.rememberNavController
import co.nimblehq.sample.compose.ui.AppNavigation
import co.nimblehq.sample.compose.ui.AppNavGraph
import co.nimblehq.sample.compose.ui.theme.ComposeTheme
import dagger.hilt.android.AndroidEntryPoint

Expand All @@ -15,7 +15,7 @@ class MainActivity : ComponentActivity() {
super.onCreate(savedInstanceState)
setContent {
ComposeTheme {
AppNavigation(navController = rememberNavController())
AppNavGraph(navController = rememberNavController())
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ package co.nimblehq.sample.compose.ui.screens.main
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavHostController
import androidx.navigation.navigation
import co.nimblehq.sample.compose.extensions.getThenRemove
import co.nimblehq.sample.compose.model.UiModel
import co.nimblehq.sample.compose.ui.AppDestination
import co.nimblehq.sample.compose.ui.base.KeyResultOk
import co.nimblehq.sample.compose.ui.composable
import co.nimblehq.sample.compose.ui.navigate
import co.nimblehq.sample.compose.ui.screens.main.home.HomeScreen
Expand All @@ -18,11 +20,14 @@ fun NavGraphBuilder.mainNavGraph(
route = AppDestination.MainNavGraph.route,
startDestination = MainDestination.Home.destination
) {
composable(destination = MainDestination.Home) {
composable(destination = MainDestination.Home) { backStackEntry ->
val isResultOk = backStackEntry.savedStateHandle
.getThenRemove<Boolean>(KeyResultOk) ?: false
HomeScreen(
navigator = { destination ->
navController.navigate(destination, destination.parcelableArgument)
}
},
isResultOk = isResultOk,
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import kotlinx.coroutines.flow.*
fun HomeScreen(
viewModel: HomeViewModel = hiltViewModel(),
navigator: (destination: BaseDestination) -> Unit,
isResultOk: Boolean = false,
) {
val context = LocalContext.current
viewModel.error.collectAsEffect { e -> e.showToast(context) }
Expand All @@ -43,6 +44,12 @@ fun HomeScreen(
}
}

LaunchedEffect(Unit) {
if (isResultOk) {
context.showToast(context.getString(R.string.message_updated))
}
}

CameraPermission()

HomeScreenContent(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package co.nimblehq.sample.compose.ui.screens.main.second

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Button
import androidx.compose.material.Scaffold
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
Expand All @@ -13,7 +15,9 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.hilt.navigation.compose.hiltViewModel
import co.nimblehq.sample.compose.R
import co.nimblehq.sample.compose.ui.base.BaseDestination
import co.nimblehq.sample.compose.ui.base.KeyResultOk
import co.nimblehq.sample.compose.ui.common.AppBar
import co.nimblehq.sample.compose.ui.theme.AppTheme.dimensions
import co.nimblehq.sample.compose.ui.theme.ComposeTheme

@Composable
Expand All @@ -22,11 +26,19 @@ fun SecondScreen(
navigator: (destination: BaseDestination) -> Unit,
id: String,
) {
SecondScreenContent(id)
SecondScreenContent(
id = id,
onUpdateClick = {
navigator(BaseDestination.Up().addResult(KeyResultOk, true))
},
)
}

@Composable
private fun SecondScreenContent(id: String) {
private fun SecondScreenContent(
id: String,
onUpdateClick: () -> Unit,
) {
Scaffold(topBar = {
AppBar(R.string.second_title_bar)
}) { paddingValues ->
Expand All @@ -35,10 +47,20 @@ private fun SecondScreenContent(id: String) {
.fillMaxSize()
.padding(paddingValues)
) {
Text(
text = stringResource(R.string.second_id_title, id),
modifier = Modifier.align(Alignment.Center)
)
Column(modifier = Modifier.align(Alignment.Center)) {
Text(
text = stringResource(R.string.second_id_title, id),
)

Button(
onClick = { onUpdateClick() },
modifier = Modifier.padding(dimensions.spacingMedium)
) {
Text(
text = stringResource(R.string.second_update)
)
}
}
}
}
}
Expand All @@ -47,6 +69,9 @@ private fun SecondScreenContent(id: String) {
@Composable
private fun SecondScreenPreview() {
ComposeTheme {
SecondScreenContent("1")
SecondScreenContent(
id = "1",
onUpdateClick = {},
)
}
}
2 changes: 2 additions & 0 deletions sample-compose/app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@

<string name="second_title_bar">Second</string>
<string name="second_id_title">ID: %1$s</string>
<string name="second_update">Update</string>

<string name="third_title_bar">Third</string>
<string name="third_data_title">Data: %s</string>
<string name="third_edit_menu_title">Edit</string>

<string name="message_first_time_launch">This is the first time launch</string>
<string name="message_updated">Updated!</string>
</resources>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package co.nimblehq.template.compose.extensions

import androidx.lifecycle.SavedStateHandle

fun <T> SavedStateHandle.getThenRemove(key: String): T? {
return if (contains(key)) {
val value = get<T>(key)
remove<T>(key)
value
} else null
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import co.nimblehq.template.compose.ui.base.BaseDestination
import co.nimblehq.template.compose.ui.screens.main.mainNavGraph

@Composable
fun AppNavigation(
fun AppNavGraph(
navController: NavHostController,
) {
NavHost(
Expand All @@ -38,7 +38,12 @@ fun NavGraphBuilder.composable(

fun NavHostController.navigate(destination: BaseDestination) {
when (destination) {
is BaseDestination.Up -> navigateUp()
is BaseDestination.Up -> {
destination.results.forEach { (key, value) ->
previousBackStackEntry?.savedStateHandle?.set(key, value)
}
navigateUp()
}
else -> navigate(route = destination.destination)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,10 @@ abstract class BaseDestination(val route: String = "") {

open var destination: String = route

object Up : BaseDestination()
data class Up(val results: HashMap<String, Any> = hashMapOf()) : BaseDestination() {

fun addResult(key: String, value: Any) = apply {
results[key] = value
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.navigation.compose.rememberNavController
import co.nimblehq.template.compose.ui.AppNavigation
import co.nimblehq.template.compose.ui.AppNavGraph
import co.nimblehq.template.compose.ui.theme.ComposeTheme
import dagger.hilt.android.AndroidEntryPoint

Expand All @@ -15,7 +15,7 @@ class MainActivity : ComponentActivity() {
super.onCreate(savedInstanceState)
setContent {
ComposeTheme {
AppNavigation(navController = rememberNavController())
AppNavGraph(navController = rememberNavController())
}
}
}
Expand Down
Loading