Skip to content

Commit 0f76fb1

Browse files
authored
Merge pull request #12 from NordicPlayground/bugfix/simple-destinations
Navigating to simple destinations fixed
2 parents 054b014 + c688a38 commit 0f76fb1

File tree

7 files changed

+121
-12
lines changed

7 files changed

+121
-12
lines changed

app/src/main/java/no/nordicsemi/android/common/test/MainActivity.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import dagger.hilt.android.AndroidEntryPoint
3737
import no.nordicsemi.android.common.navigation.NavigationView
3838
import no.nordicsemi.android.common.test.main.MainDestination
3939
import no.nordicsemi.android.common.test.scanner.ScannerDestination
40+
import no.nordicsemi.android.common.test.simple.HelloDestination
4041
import no.nordicsemi.android.common.theme.NordicActivity
4142
import no.nordicsemi.android.common.theme.NordicTheme
4243

@@ -48,7 +49,7 @@ class MainActivity : NordicActivity() {
4849

4950
setContent {
5051
NordicTheme {
51-
NavigationView(MainDestination + ScannerDestination)
52+
NavigationView(MainDestination + ScannerDestination + HelloDestination)
5253
}
5354
}
5455
}

app/src/main/java/no/nordicsemi/android/common/test/main/page/BasicViewsPage.kt

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import no.nordicsemi.android.common.navigation.NavigationResult
2626
import no.nordicsemi.android.common.navigation.Navigator
2727
import no.nordicsemi.android.common.test.R
2828
import no.nordicsemi.android.common.test.scanner.Scanner
29+
import no.nordicsemi.android.common.test.simple.Hello
2930
import no.nordicsemi.android.common.theme.NordicTheme
3031
import no.nordicsemi.android.common.theme.view.PagerViewItem
3132
import no.nordicsemi.android.common.theme.view.RssiIcon
@@ -40,7 +41,8 @@ val BasicsPage = PagerViewItem("Basics") {
4041

4142
BasicViewsScreen(
4243
device = device?.let { DeviceInfo(it) },
43-
onOpenScanner = { vm.openScanner() }
44+
onOpenScanner = { vm.openScanner() },
45+
onOpenSimple = { vm.openSimple() },
4446
)
4547
}
4648

@@ -69,6 +71,10 @@ class BasicPageViewModel @Inject constructor(
6971
// This is Mesh Proxy Service UUID
7072
navigator.navigateTo(Scanner, ParcelUuid(UUID.fromString("00001828-0000-1000-8000-00805F9B34FB")))
7173
}
74+
75+
fun openSimple() {
76+
navigator.navigateTo(Hello)
77+
}
7278
}
7379

7480
@SuppressLint("MissingPermission")
@@ -84,6 +90,7 @@ data class DeviceInfo(
8490
private fun BasicViewsScreen(
8591
device: DeviceInfo?,
8692
onOpenScanner: () -> Unit,
93+
onOpenSimple: () -> Unit,
8794
) {
8895
Column(
8996
modifier = Modifier
@@ -92,6 +99,12 @@ private fun BasicViewsScreen(
9299
verticalArrangement = Arrangement.spacedBy(16.dp),
93100
horizontalAlignment = Alignment.CenterHorizontally,
94101
) {
102+
Button(
103+
onClick = onOpenSimple
104+
) {
105+
Text(text = stringResource(id = R.string.action_simple))
106+
}
107+
95108
Button(
96109
onClick = onOpenScanner
97110
) {
@@ -249,7 +262,8 @@ private fun ContentPreview() {
249262
NordicTheme {
250263
BasicViewsScreen(
251264
device = null,
252-
onOpenScanner = {}
265+
onOpenScanner = {},
266+
onOpenSimple = {},
253267
)
254268
}
255269
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package no.nordicsemi.android.common.test.simple
2+
3+
import androidx.compose.foundation.layout.*
4+
import androidx.compose.material3.Button
5+
import androidx.compose.material3.ExperimentalMaterial3Api
6+
import androidx.compose.material3.Text
7+
import androidx.compose.runtime.Composable
8+
import androidx.compose.ui.Alignment
9+
import androidx.compose.ui.Modifier
10+
import androidx.compose.ui.res.stringResource
11+
import androidx.compose.ui.tooling.preview.Preview
12+
import androidx.compose.ui.unit.dp
13+
import androidx.hilt.navigation.compose.hiltViewModel
14+
import no.nordicsemi.android.common.navigation.createSimpleDestination
15+
import no.nordicsemi.android.common.navigation.defineDestination
16+
import no.nordicsemi.android.common.navigation.viewmodel.SimpleNavigationViewModel
17+
import no.nordicsemi.android.common.test.R
18+
import no.nordicsemi.android.common.theme.NordicTheme
19+
import no.nordicsemi.android.common.theme.view.NordicAppBar
20+
21+
/**
22+
* This is an example of a simple destination.
23+
*
24+
* A simple destination does not take any parameters and does not return any result.
25+
*/
26+
val Hello = createSimpleDestination("hello")
27+
28+
val HelloDestination = defineDestination(Hello) {
29+
val vm: SimpleNavigationViewModel = hiltViewModel()
30+
31+
HelloScreen(
32+
modifier = Modifier.fillMaxWidth(),
33+
onNavigateUp = { vm.navigateUp() }
34+
)
35+
}
36+
37+
@OptIn(ExperimentalMaterial3Api::class)
38+
@Composable
39+
private fun HelloScreen(
40+
onNavigateUp: () -> Unit,
41+
modifier: Modifier = Modifier,
42+
) {
43+
Column(
44+
modifier = modifier,
45+
) {
46+
NordicAppBar(
47+
text = stringResource(id = R.string.hello),
48+
onNavigationButtonClick = onNavigateUp,
49+
)
50+
51+
Column(
52+
modifier = Modifier.fillMaxSize(),
53+
verticalArrangement = Arrangement.spacedBy(16.dp, Alignment.CenterVertically),
54+
horizontalAlignment = Alignment.CenterHorizontally,
55+
) {
56+
Text(text = stringResource(id = R.string.hello))
57+
58+
Button(onClick = onNavigateUp) {
59+
Text(text = stringResource(id = R.string.action_dialog))
60+
}
61+
}
62+
}
63+
}
64+
65+
@Preview
66+
@Composable
67+
private fun SimpleContentPreview() {
68+
NordicTheme {
69+
HelloScreen(onNavigateUp = {})
70+
}
71+
}

app/src/main/res/values/strings.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,17 @@
6262
<string name="wizard_step_inactive">Inactive</string>
6363
<string name="wizard_text_inactive">This is not yet available</string>
6464

65+
<string name="action_simple">Say Hello</string>
6566
<string name="action_scanner">Open Scanner</string>
6667
<string name="action_no_op">Button</string>
6768
<string name="action_disabled">Disabled</string>
6869
<string name="action_destroy">Destroy</string>
70+
<string name="action_dialog">Open Dialog</string>
6971

7072
<string name="option">Important option</string>
7173

74+
<string name="hello">Hello!</string>
75+
7276
<string name="warning_title">No parachute</string>
7377
<string name="warning_text">It\'s too late to do anything.</string>
7478
<string name="warning_normal">Try anyway</string>

navigation/src/main/java/no/nordicsemi/android/common/navigation/Navigator.kt

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,21 @@ interface Navigator {
1919
fun <R> resultFrom(from: DestinationId<*, R>): Flow<NavigationResult<R>>
2020

2121
/**
22-
* Requests navigation to the given destination. An optional parameter can be passed.
22+
* Requests navigation to the given destination. An required parameter must be passed.
2323
*
2424
* @param to The destination to navigate to.
2525
* @param args An optional argument to pass to the destination. The argument will be saved
2626
* in [SavedStateHandle], therefore it must be savable to a [Bundle].
2727
*/
2828
fun <A> navigateTo(to: DestinationId<A, *>, args: @RawValue A)
2929

30+
/**
31+
* Requests navigation to the given destination which takes no input parameter.
32+
*
33+
* @param to The destination to navigate to.
34+
*/
35+
fun navigateTo(to: DestinationId<Unit, *>) = navigateTo(to, Unit)
36+
3037
/**
3138
* Navigates up to previous destination, or finishes the Activity.
3239
*/
@@ -70,4 +77,12 @@ fun <A> SavedStateHandle.getOrNull(destination: DestinationId<A?, *>): A? =
7077
* @param destination The current destination.
7178
*/
7279
fun <A> SavedStateHandle.get(destination: DestinationId<A & Any, *>): A =
73-
get(destination.name) ?: error("Destination '${destination.name}' requires a non-nullable argument")
80+
get(destination.name) ?: error("Destination '${destination.name}' requires a non-nullable argument")
81+
82+
/**
83+
* Returns the argument for the current destination.
84+
*
85+
* @param destination The current destination.
86+
*/
87+
fun SavedStateHandle.get(destination: DestinationId<Unit, *>): Nothing =
88+
error("Destination '${destination.name}' does not have an argument")

navigation/src/main/java/no/nordicsemi/android/common/navigation/internal/NavigationExecutor.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ internal data class NavigationTarget<A>(
1818
val destination: DestinationId<A, *>,
1919
val args: @RawValue A
2020
) {
21-
fun toBundle() = bundleOf(destination.name to args)
21+
fun toBundle() = if (args is Unit) bundleOf() else bundleOf(destination.name to args)
2222
}
2323

2424
internal sealed class NavigationResultState

navigation/src/main/java/no/nordicsemi/android/common/navigation/viewmodel/SimpleNavigationViewModel.kt

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,20 @@ open class SimpleNavigationViewModel @Inject constructor(
1919
/**
2020
* Returns the parameter of the current destination, or null, if hasn't been set.
2121
*/
22-
fun <A> nullableParameterOf(destinationId: DestinationId<A?, *>): A? {
23-
return savedStateHandle.getOrNull(destinationId)
24-
}
22+
fun <A> nullableParameterOf(destinationId: DestinationId<A?, *>): A? =
23+
savedStateHandle.getOrNull(destinationId)
2524

2625
/**
2726
* Returns the parameter of the current destination, or null, if hasn't been set.
2827
*/
29-
fun <A> parameterOf(destinationId: DestinationId<A & Any, *>): A {
30-
return savedStateHandle.get(destinationId)
31-
}
28+
fun <A> parameterOf(destinationId: DestinationId<A & Any, *>): A =
29+
savedStateHandle.get(destinationId)
30+
31+
/**
32+
* Returns the parameter of the current destination, or null, if hasn't been set.
33+
*/
34+
fun parameterOf(destinationId: DestinationId<Unit, *>): Nothing =
35+
savedStateHandle.get(destinationId)
3236

3337
/**
3438
* Returns the parameter of the current destination, or null, if hasn't been set.

0 commit comments

Comments
 (0)