From 21d73d30b645b92bca94e12254b2d4355a07ff6a Mon Sep 17 00:00:00 2001 From: Alexander Frank Date: Tue, 16 Jul 2024 18:52:11 +0200 Subject: [PATCH 1/6] Allow marking a destination as dialog composable in the nav graph --- .../kotlin/de/onecode/compass/api/Dialog.kt | 5 +++ .../descriptions/DestinationDescription.kt | 1 + .../ksp/discovery/DestinationVisitor.kt | 13 ++++++- .../compass/ksp/generator/CodeGeneration.kt | 6 +++ .../navigation/AddComposablesBody.kt | 8 +++- .../de/onecode/compass/demo/MainActivity.kt | 8 +++- .../compass/demo/dialog/MyDialogScreen.kt | 38 +++++++++++++++++++ .../compass/demo/home/HomeDescription.kt | 6 +++ .../onecode/compass/demo/home/HomeScreen.kt | 7 ++++ 9 files changed, 89 insertions(+), 3 deletions(-) create mode 100644 compass/api/src/main/kotlin/de/onecode/compass/api/Dialog.kt create mode 100644 demo/app/src/main/kotlin/de/onecode/compass/demo/dialog/MyDialogScreen.kt diff --git a/compass/api/src/main/kotlin/de/onecode/compass/api/Dialog.kt b/compass/api/src/main/kotlin/de/onecode/compass/api/Dialog.kt new file mode 100644 index 0000000..013c2f2 --- /dev/null +++ b/compass/api/src/main/kotlin/de/onecode/compass/api/Dialog.kt @@ -0,0 +1,5 @@ +package de.onecode.compass.api + +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.BINARY) +annotation class Dialog diff --git a/compass/ksp/src/main/kotlin/de/onecode/compass/ksp/descriptions/DestinationDescription.kt b/compass/ksp/src/main/kotlin/de/onecode/compass/ksp/descriptions/DestinationDescription.kt index dc38988..cc33a1a 100644 --- a/compass/ksp/src/main/kotlin/de/onecode/compass/ksp/descriptions/DestinationDescription.kt +++ b/compass/ksp/src/main/kotlin/de/onecode/compass/ksp/descriptions/DestinationDescription.kt @@ -6,4 +6,5 @@ data class DestinationDescription( val navigationTargets: List, val isHome: Boolean, val isTop: Boolean, + val isDialog: Boolean, ) : NamedWithParameters diff --git a/compass/ksp/src/main/kotlin/de/onecode/compass/ksp/discovery/DestinationVisitor.kt b/compass/ksp/src/main/kotlin/de/onecode/compass/ksp/discovery/DestinationVisitor.kt index f0966c8..bfa494c 100644 --- a/compass/ksp/src/main/kotlin/de/onecode/compass/ksp/discovery/DestinationVisitor.kt +++ b/compass/ksp/src/main/kotlin/de/onecode/compass/ksp/discovery/DestinationVisitor.kt @@ -5,6 +5,7 @@ import com.google.devtools.ksp.symbol.KSType import com.google.devtools.ksp.symbol.KSVisitorVoid import com.squareup.kotlinpoet.ksp.toClassName import de.onecode.compass.api.Destination +import de.onecode.compass.api.Dialog import de.onecode.compass.api.Home import de.onecode.compass.api.Navigation import de.onecode.compass.api.Parameter @@ -32,8 +33,17 @@ class DestinationVisitor : KSVisitorVoid() { ?: error("Could not find annotation ${Destination::name} on ${classDeclaration.className}") val isHome = classDeclaration.filterAnnotations(Home::class).iterator().hasNext() val isTop = classDeclaration.filterAnnotations(Top::class).iterator().hasNext() + val isDialog = classDeclaration.filterAnnotations(Dialog::class).iterator().hasNext() val destinationName = destination.getDestinationName(classDeclaration) + if (isDialog && isTop) { + error("Destination $destinationName is marked as ${Dialog::class.qualifiedName} and ${Top::class.qualifiedName}. A Dialog can't also be Top") + } + + if (isDialog && isHome) { + error("Destination $destinationName is marked as ${Dialog::class.qualifiedName} and ${Home::class.qualifiedName}. A Dialog can't also be Home") + } + val navTargets = classDeclaration.filterAnnotations(Navigation::class) .map { navigationAnnotation -> val target = navigationAnnotation.getParameterValue(Navigation::to.name, classDeclaration) @@ -76,7 +86,8 @@ class DestinationVisitor : KSVisitorVoid() { parameters = parameters.toList(), navigationTargets = navTargets.toList(), isHome = isHome, - isTop = isTop + isTop = isTop, + isDialog = isDialog, ) } diff --git a/compass/ksp/src/main/kotlin/de/onecode/compass/ksp/generator/CodeGeneration.kt b/compass/ksp/src/main/kotlin/de/onecode/compass/ksp/generator/CodeGeneration.kt index 040b017..6406f75 100644 --- a/compass/ksp/src/main/kotlin/de/onecode/compass/ksp/generator/CodeGeneration.kt +++ b/compass/ksp/src/main/kotlin/de/onecode/compass/ksp/generator/CodeGeneration.kt @@ -21,9 +21,15 @@ fun generateNavigatorCode(graph: GraphDescription): FileSpec { val destinations = graph.destinations val subGraphs = graph.subGraphs + val hasDialog = graph.destinations.any { it.isDialog } || subGraphs.fold(true) {acc, destination -> acc && destination.destinations.any { it.isDialog }} + return createFileSpec(graph) .addImport("androidx.compose.runtime", "CompositionLocalProvider", "compositionLocalOf") .apply { + if(hasDialog) { + addImport("androidx.navigation.compose", "dialog") + } + if (destinations.isNotEmpty()) { addType(createCompassController(destinations)) addFunction(createRememberCompassController()) diff --git a/compass/ksp/src/main/kotlin/de/onecode/compass/ksp/generator/navigation/AddComposablesBody.kt b/compass/ksp/src/main/kotlin/de/onecode/compass/ksp/generator/navigation/AddComposablesBody.kt index c03abda..064d3d0 100644 --- a/compass/ksp/src/main/kotlin/de/onecode/compass/ksp/generator/navigation/AddComposablesBody.kt +++ b/compass/ksp/src/main/kotlin/de/onecode/compass/ksp/generator/navigation/AddComposablesBody.kt @@ -47,7 +47,7 @@ private fun DestinationDescription.toNavigationComposableCodeBlock(): CodeBlock private fun buildComposableCodeBlock(destination: DestinationDescription, statements: CodeBlock.Builder.() -> Unit): CodeBlock = buildCodeBlock { - beginControlFlow("composable(route = %S, arguments = %L)", destination.route, navigationArgumentsCodeBlock(destination)) + beginControlFlow("%L(route = %S, arguments = %L)", destination.toGraphFunctionName(), destination.route, navigationArgumentsCodeBlock(destination)) statements() endControlFlow() } @@ -80,3 +80,9 @@ private fun navigationArgumentsCodeBlock(description: DestinationDescription): C } } } + +private fun DestinationDescription.toGraphFunctionName(): String = + when(isDialog) { + true -> "dialog" + false -> "composable" + } diff --git a/demo/app/src/main/kotlin/de/onecode/compass/demo/MainActivity.kt b/demo/app/src/main/kotlin/de/onecode/compass/demo/MainActivity.kt index 2196ecf..6417227 100644 --- a/demo/app/src/main/kotlin/de/onecode/compass/demo/MainActivity.kt +++ b/demo/app/src/main/kotlin/de/onecode/compass/demo/MainActivity.kt @@ -20,6 +20,7 @@ import androidx.lifecycle.viewmodel.compose.viewModel import de.onecode.compass.Compass import de.onecode.compass.demo.destinations.attachFeatureComposable import de.onecode.compass.demo.details.DetailsScreen +import de.onecode.compass.demo.dialog.MyDialogScreen import de.onecode.compass.demo.home.HomeScreen import de.onecode.compass.demo.home.SubHomeScreen import de.onecode.compass.demo.theme.NavGraphConfigComposeTheme @@ -76,10 +77,15 @@ fun Main() { homeScreen { HomeScreen( onToSub = { navigateToSubHome(optionalParam = getOptionalParam()) }, - onToFeature = { navigateToFeatureComposable(Random.nextFloat()) } + onToFeature = { navigateToFeatureComposable(Random.nextFloat()) }, + onToDialog = ::navigateToMyDialog ) } + myDialogScreen { + MyDialogScreen(onClose = ::popBackStack) + } + subHomeScreen { SubHomeScreen( optionalValue = optionalParam diff --git a/demo/app/src/main/kotlin/de/onecode/compass/demo/dialog/MyDialogScreen.kt b/demo/app/src/main/kotlin/de/onecode/compass/demo/dialog/MyDialogScreen.kt new file mode 100644 index 0000000..d9cbbe7 --- /dev/null +++ b/demo/app/src/main/kotlin/de/onecode/compass/demo/dialog/MyDialogScreen.kt @@ -0,0 +1,38 @@ +package de.onecode.compass.demo.dialog + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.unit.dp + +@Composable +fun MyDialogScreen( + onClose: () -> Unit, + modifier: Modifier = Modifier, +) { + Column( + modifier = modifier + .clip(RoundedCornerShape(4.dp)) + .background(MaterialTheme.colorScheme.background) + .padding(16.dp), + ) { + Text(text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.") + Spacer(modifier = Modifier.size(8.dp)) + TextButton( + onClick = onClose, + modifier = Modifier.align(Alignment.End) + ) { + Text(text = "Close") + } + } +} \ No newline at end of file diff --git a/demo/app/src/main/kotlin/de/onecode/compass/demo/home/HomeDescription.kt b/demo/app/src/main/kotlin/de/onecode/compass/demo/home/HomeDescription.kt index 2892734..c8d0dce 100644 --- a/demo/app/src/main/kotlin/de/onecode/compass/demo/home/HomeDescription.kt +++ b/demo/app/src/main/kotlin/de/onecode/compass/demo/home/HomeDescription.kt @@ -1,6 +1,7 @@ package de.onecode.compass.demo.home import de.onecode.compass.api.Destination +import de.onecode.compass.api.Dialog import de.onecode.compass.api.Home import de.onecode.compass.api.Navigation import de.onecode.compass.api.Parameter @@ -10,8 +11,13 @@ import de.onecode.compass.demo.destinations.FeatureComposableDestination @Home @Navigation(to = SubHomeDestination::class) @Navigation(to = FeatureComposableDestination::class) +@Navigation(to = MyDialogDestination::class) object HomeDescription @Destination(name = "SubHome") @Parameter("optionalParam", type = String::class, required = false) object SubHomeDestination + +@Dialog +@Destination(name = "MyDialog") +object MyDialogDestination \ No newline at end of file diff --git a/demo/app/src/main/kotlin/de/onecode/compass/demo/home/HomeScreen.kt b/demo/app/src/main/kotlin/de/onecode/compass/demo/home/HomeScreen.kt index 5941d46..0709f64 100644 --- a/demo/app/src/main/kotlin/de/onecode/compass/demo/home/HomeScreen.kt +++ b/demo/app/src/main/kotlin/de/onecode/compass/demo/home/HomeScreen.kt @@ -14,6 +14,7 @@ import androidx.compose.ui.unit.dp fun HomeScreen( onToSub: () -> Unit, onToFeature: () -> Unit, + onToDialog: () -> Unit, ) { Column(verticalArrangement = Arrangement.SpaceBetween) { Button( @@ -29,5 +30,11 @@ fun HomeScreen( ) { Text(text = "GoTo Feature") } + + Spacer(modifier = Modifier.size(16.dp)) + + Button(onClick = onToDialog) { + Text(text = "GoTo Dialog") + } } } From 2525aa5c215457c5f201be8b8a12d894b8357a8d Mon Sep 17 00:00:00 2001 From: Alexander Frank Date: Tue, 16 Jul 2024 18:52:31 +0200 Subject: [PATCH 2/6] Adapt tests and added new tests for dialog destinations --- .../compass/ksp/CheckGraphStateTest.kt | 36 ++++-- .../ksp/discovery/DestinationVisitorTest.kt | 11 ++ .../compass/ksp/discovery/GraphVisitorTest.kt | 14 +-- .../compass/ksp/discovery/TestUtils.kt | 17 ++- .../ksp/generator/CodeGeneratorTest.kt | 119 ++++++++++++------ .../common/NavigationFunctionTest.kt | 4 +- .../context/CreateContextClassTest.kt | 13 +- .../context/CreateSubGraphContextTest.kt | 6 +- .../navigation/CreateCompassComposableTest.kt | 11 +- .../navigation/CreateCompassControllerTest.kt | 26 ++-- .../navigation/CreateSubGraphFunctionTest.kt | 17 ++- .../screenbuilder/CreateScreenBuilderTest.kt | 10 +- .../CreateSubGraphBuilderTest.kt | 10 +- .../compass/ksp/util/DestinationCreator.kt | 22 ++++ 14 files changed, 196 insertions(+), 120 deletions(-) create mode 100644 compass/ksp/src/test/kotlin/de/onecode/compass/ksp/util/DestinationCreator.kt diff --git a/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/CheckGraphStateTest.kt b/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/CheckGraphStateTest.kt index bf49568..73477db 100644 --- a/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/CheckGraphStateTest.kt +++ b/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/CheckGraphStateTest.kt @@ -15,14 +15,16 @@ class CheckGraphStateTest { parameters = emptyList(), navigationTargets = emptyList(), isHome = true, - isTop = false + isTop = false, + isDialog = false, ) val description2 = DestinationDescription( name = "bar", parameters = emptyList(), navigationTargets = emptyList(), isHome = true, - isTop = false + isTop = false, + isDialog = false, ) val graph = GraphDescription(listOf(description1, description2), emptyList()) @@ -38,14 +40,16 @@ class CheckGraphStateTest { parameters = emptyList(), navigationTargets = emptyList(), isHome = true, - isTop = false + isTop = false, + isDialog = false, ) val description2 = DestinationDescription( name = "bar", parameters = emptyList(), navigationTargets = emptyList(), isHome = false, - isTop = false + isTop = false, + isDialog = false, ) val graph = GraphDescription(listOf(description1, description2), emptyList()) @@ -62,14 +66,16 @@ class CheckGraphStateTest { parameters = emptyList(), navigationTargets = emptyList(), isHome = false, - isTop = false + isTop = false, + isDialog = false, ) val description2 = DestinationDescription( name = "bar", parameters = emptyList(), navigationTargets = emptyList(), isHome = false, - isTop = false + isTop = false, + isDialog = false, ) val graph = GraphDescription(listOf(description1, description2), emptyList()) @@ -96,14 +102,16 @@ class CheckGraphStateTest { parameters = emptyList(), navigationTargets = emptyList(), isHome = true, - isTop = false + isTop = false, + isDialog = false, ) val sub2 = DestinationDescription( name = "sub2", parameters = emptyList(), navigationTargets = emptyList(), isHome = true, - isTop = false + isTop = false, + isDialog = false, ) val sub = SubGraphDescription("sub", listOf(sub1, sub2)) val graph = GraphDescription(emptyList(), listOf(sub)) @@ -120,14 +128,16 @@ class CheckGraphStateTest { parameters = emptyList(), navigationTargets = emptyList(), isHome = false, - isTop = false + isTop = false, + isDialog = false, ) val sub2 = DestinationDescription( name = "sub2", parameters = emptyList(), navigationTargets = emptyList(), isHome = false, - isTop = false + isTop = false, + isDialog = false, ) val sub = SubGraphDescription("sub", listOf(sub1, sub2)) val graph = GraphDescription(emptyList(), listOf(sub)) @@ -144,14 +154,16 @@ class CheckGraphStateTest { parameters = emptyList(), navigationTargets = emptyList(), isHome = true, - isTop = false + isTop = false, + isDialog = false, ) val sub2 = DestinationDescription( name = "sub2", parameters = emptyList(), navigationTargets = emptyList(), isHome = false, - isTop = true + isTop = true, + isDialog = false, ) val sub = SubGraphDescription("sub", listOf(sub1, sub2)) val graph = GraphDescription(emptyList(), listOf(sub)) diff --git a/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/discovery/DestinationVisitorTest.kt b/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/discovery/DestinationVisitorTest.kt index 40f3759..80ce029 100644 --- a/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/discovery/DestinationVisitorTest.kt +++ b/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/discovery/DestinationVisitorTest.kt @@ -2,6 +2,7 @@ package de.onecode.compass.ksp.discovery import com.google.common.truth.Truth.assertThat import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows class DestinationVisitorTest { @Test @@ -181,4 +182,14 @@ class DestinationVisitorTest { assertThat(destinationDescription3.isHome).isFalse() assertThat(destinationDescription3.isTop).isTrue() } + + @Test + fun `Dialog can't be also Home`() { + val destinationVisitor = DestinationVisitor() + val destination1 = declareDestination(destinationVisitor, name = "Destination1", isHome = true, isDialog = true) + + assertThrows { + destination1.accept(destinationVisitor, Unit) + } + } } diff --git a/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/discovery/GraphVisitorTest.kt b/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/discovery/GraphVisitorTest.kt index b212fae..934561c 100644 --- a/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/discovery/GraphVisitorTest.kt +++ b/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/discovery/GraphVisitorTest.kt @@ -1,15 +1,15 @@ package de.onecode.compass.ksp.discovery import com.google.common.truth.Truth.assertThat -import de.onecode.compass.ksp.descriptions.DestinationDescription +import de.onecode.compass.ksp.util.destination import org.junit.jupiter.api.Test class GraphVisitorTest { @Test fun `create graph description without sub graph`() { val destinations = listOf( - DestinationDescription(name = "D1", parameters = emptyList(), navigationTargets = emptyList(), isHome = true, isTop = false), - DestinationDescription(name = "D2", parameters = emptyList(), navigationTargets = emptyList(), isHome = false, isTop = false) + destination(name = "D1", isHome = true), + destination(name = "D2") ) val graphVisitor = GraphVisitor(destinations) @@ -23,11 +23,11 @@ class GraphVisitorTest { @Test fun `create graph description with sub graph`() { - val s1 = DestinationDescription(name = "S1", parameters = emptyList(), navigationTargets = emptyList(), isHome = true, isTop = false) - val s2 = DestinationDescription(name = "S2", parameters = emptyList(), navigationTargets = emptyList(), isHome = false, isTop = false) + val s1 = destination(name = "S1", isHome = true) + val s2 = destination(name = "S2") val destinations = listOf( - DestinationDescription(name = "D1", parameters = emptyList(), navigationTargets = emptyList(), isHome = true, isTop = false), - DestinationDescription(name = "D2", parameters = emptyList(), navigationTargets = emptyList(), isHome = false, isTop = false), + destination(name = "D1", isHome = true), + destination(name = "D2"), s1, s2 ) diff --git a/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/discovery/TestUtils.kt b/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/discovery/TestUtils.kt index 80bc0e7..e04d6f6 100644 --- a/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/discovery/TestUtils.kt +++ b/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/discovery/TestUtils.kt @@ -6,6 +6,7 @@ import com.google.devtools.ksp.symbol.KSName import com.google.devtools.ksp.symbol.KSType import com.google.devtools.ksp.symbol.KSValueArgument import de.onecode.compass.api.Destination +import de.onecode.compass.api.Dialog import de.onecode.compass.api.Home import de.onecode.compass.api.Navigation import de.onecode.compass.api.Parameter @@ -22,11 +23,19 @@ internal fun declareDestination( name: String = "", isHome: Boolean = false, isTop: Boolean = false, + isDialog: Boolean = false, typeName: String = "TestDestination", parameters: () -> List = { emptyList() }, navigationTargets: () -> List = { emptyList() }, ): KSClassDeclaration { - val annotationsOnDestination = createAnnotationsForDestination(name, isHome, isTop, parameters, navigationTargets) + val annotationsOnDestination = createAnnotationsForDestination( + name = name, + isHome = isHome, + isTop = isTop, + isDialog = isDialog, + parameters = parameters, + navigationTargets = navigationTargets + ) return mockk { every { simpleName } returns ksName(typeName) @@ -41,6 +50,7 @@ internal fun createAnnotationsForDestination( name: String = "", isHome: Boolean = false, isTop: Boolean = false, + isDialog: Boolean = false, parameters: () -> List = { emptyList() }, navigationTargets: () -> List = { emptyList() }, ): List { @@ -52,7 +62,10 @@ internal fun createAnnotationsForDestination( val top = isTop .ifTrue { createAnnotation(Top::class) } - return listOfNotNull(destination, home, top, *parameters().toTypedArray(), *navigationTargets().toTypedArray()) + val dialog = isDialog + .ifTrue { createAnnotation(Dialog::class) } + + return listOfNotNull(destination, home, top, dialog, *parameters().toTypedArray(), *navigationTargets().toTypedArray()) } internal fun createDestination(destinationName: String? = null): KSAnnotation = createAnnotation(Destination::class) { diff --git a/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/generator/CodeGeneratorTest.kt b/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/generator/CodeGeneratorTest.kt index 10d7ae9..11c49f7 100644 --- a/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/generator/CodeGeneratorTest.kt +++ b/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/generator/CodeGeneratorTest.kt @@ -1,11 +1,11 @@ package de.onecode.compass.ksp.generator import de.onecode.compass.ksp.assertGeneratedCode -import de.onecode.compass.ksp.descriptions.DestinationDescription import de.onecode.compass.ksp.descriptions.GraphDescription import de.onecode.compass.ksp.descriptions.NavigationTarget import de.onecode.compass.ksp.descriptions.ParameterDescription import de.onecode.compass.ksp.descriptions.SubGraphDescription +import de.onecode.compass.ksp.util.destination import de.onecode.compass.ksp.writeToString import org.junit.jupiter.api.Test @@ -14,19 +14,14 @@ class CodeGeneratorTest { @Test fun `Two destinations not top and no subgraph`() { val param1 = ParameterDescription(name = "param1", type = "kotlin.Int", required = true) - val description1 = DestinationDescription( + val description1 = destination( name = "foo", - parameters = emptyList(), navigationTargets = listOf(NavigationTarget("bar", listOf(param1))), isHome = true, - isTop = false ) - val description2 = DestinationDescription( + val description2 = destination( name = "bar", parameters = listOf(param1), - navigationTargets = emptyList(), - isHome = false, - isTop = false ) val graph = GraphDescription( destinations = listOf(description1, description2), @@ -216,19 +211,15 @@ class CodeGeneratorTest { @Test fun `Two destinations one top and no subgraph`() { val param1 = ParameterDescription(name = "param1", type = "kotlin.Int", required = true) - val description1 = DestinationDescription( + val description1 = destination( name = "foo", - parameters = emptyList(), navigationTargets = listOf(NavigationTarget("bar", listOf(param1))), isHome = true, - isTop = false ) - val description2 = DestinationDescription( + val description2 = destination( name = "bar", parameters = listOf(param1), - navigationTargets = emptyList(), - isHome = false, - isTop = true + isTop = true, ) val graph = GraphDescription( destinations = listOf(description1, description2), @@ -436,34 +427,23 @@ class CodeGeneratorTest { @Test fun `Two destinations one top and subgraph`() { val param1 = ParameterDescription(name = "param1", type = "kotlin.Int", required = true) - val description1 = DestinationDescription( + val description1 = destination( name = "foo", - parameters = emptyList(), navigationTargets = listOf(NavigationTarget("bar", listOf(param1))), isHome = true, - isTop = false ) - val description2 = DestinationDescription( + val description2 = destination( name = "bar", parameters = listOf(param1), - navigationTargets = emptyList(), - isHome = false, - isTop = true + isTop = true, ) - val sub1 = DestinationDescription( + val sub1 = destination( name = "sub1", - parameters = emptyList(), - navigationTargets = emptyList(), isHome = true, - isTop = false ) - val sub2 = DestinationDescription( + val sub2 = destination( name = "sub1", - parameters = emptyList(), - navigationTargets = emptyList(), - isHome = false, - isTop = false ) val sub = SubGraphDescription("sub", listOf(sub1, sub2)) val graph = GraphDescription( @@ -734,19 +714,13 @@ class CodeGeneratorTest { @Test fun `Two destinations no home`() { val param1 = ParameterDescription(name = "param1", type = "kotlin.Int", required = true) - val description1 = DestinationDescription( + val description1 = destination( name = "foo", - parameters = emptyList(), navigationTargets = listOf(NavigationTarget("bar", listOf(param1))), - isHome = false, - isTop = false ) - val description2 = DestinationDescription( + val description2 = destination( name = "bar", parameters = listOf(param1), - navigationTargets = emptyList(), - isHome = false, - isTop = false ) val graph = GraphDescription(listOf(description1, description2), emptyList()) @@ -835,4 +809,71 @@ class CodeGeneratorTest { """ ) } + + @Test + fun `Destination as dialog`() { + val description1 = destination( + name = "foo", + isHome = true, + ) + val description2 = destination( + name = "bar", + isDialog = true, + ) + + val graph = GraphDescription(listOf(description1, description2), emptyList()) + + val code = writeToString { + generateAddDestinationCode(graph) + } + + assertGeneratedCode( + generated = code, + expected = + """ + package de.onecode.compass + + import androidx.compose.runtime.Composable + import androidx.navigation.NavBackStackEntry + import androidx.navigation.NavGraphBuilder + import androidx.navigation.NavHostController + import androidx.navigation.compose.NavHost + import androidx.navigation.compose.composable + import de.onecode.compass.runtime.CommonContext + import de.onecode.compass.runtime.LocalNavHostController + import javax.`annotation`.processing.Generated + import kotlin.Unit + + public fun NavGraphBuilder.fooScreen(composable: @Composable fooContext.() -> Unit) { + composable(route = "foo", arguments = emptyList() + ) { + val current = LocalNavHostController.current + val context = fooContext(current, it) + composable(context) + } + } + + @Generated + public class fooContext( + navHostController: NavHostController, + navBackStackEntry: NavBackStackEntry, + ) : CommonContext(navHostController, navBackStackEntry) + + public fun NavGraphBuilder.barScreen(composable: @Composable barContext.() -> Unit) { + dialog(route = "bar", arguments = emptyList() + ) { + val current = LocalNavHostController.current + val context = barContext(current, it) + composable(context) + } + } + + @Generated + public class barContext( + navHostController: NavHostController, + navBackStackEntry: NavBackStackEntry, + ) : CommonContext(navHostController, navBackStackEntry) + """ + ) + } } diff --git a/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/generator/common/NavigationFunctionTest.kt b/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/generator/common/NavigationFunctionTest.kt index d18884f..e1396a7 100644 --- a/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/generator/common/NavigationFunctionTest.kt +++ b/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/generator/common/NavigationFunctionTest.kt @@ -4,17 +4,17 @@ import com.squareup.kotlinpoet.KModifier import com.squareup.kotlinpoet.PropertySpec import de.onecode.compass.ksp.assertGeneratedCode import de.onecode.compass.ksp.buildTestFile -import de.onecode.compass.ksp.descriptions.DestinationDescription import de.onecode.compass.ksp.descriptions.NavigationTarget import de.onecode.compass.ksp.descriptions.ParameterDescription import de.onecode.compass.ksp.generator.navHostControllerClass +import de.onecode.compass.ksp.util.destination import org.junit.jupiter.api.Test @Suppress("RedundantVisibilityModifier", "RemoveRedundantQualifierName") class NavigationFunctionTest { @Test fun `navigation function for Destination without parameters`() { - val description = DestinationDescription(name = "foo", parameters = emptyList(), navigationTargets = emptyList(), isHome = false, isTop = false) + val description = destination(name = "foo") val navControllerParamName = "navHostController" val code = buildTestFile { diff --git a/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/generator/context/CreateContextClassTest.kt b/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/generator/context/CreateContextClassTest.kt index b5d8225..ca23c52 100644 --- a/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/generator/context/CreateContextClassTest.kt +++ b/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/generator/context/CreateContextClassTest.kt @@ -2,16 +2,16 @@ package de.onecode.compass.ksp.generator.context import de.onecode.compass.ksp.assertGeneratedCode import de.onecode.compass.ksp.buildTestFile -import de.onecode.compass.ksp.descriptions.DestinationDescription import de.onecode.compass.ksp.descriptions.NavigationTarget import de.onecode.compass.ksp.descriptions.ParameterDescription +import de.onecode.compass.ksp.util.destination import org.junit.jupiter.api.Test @Suppress("RedundantVisibilityModifier", "RemoveRedundantQualifierName", "ClassName") class CreateContextClassTest { @Test fun `Destination Context with no parameters and no navigation`() { - val description = DestinationDescription("foo", parameters = emptyList(), navigationTargets = emptyList(), isHome = false, isTop = false) + val description = destination("foo") val code = buildTestFile { addType(createContextClass(description, "CommonContext")) @@ -37,12 +37,9 @@ class CreateContextClassTest { @Test fun `Destination Context with one parameter and no navigation`() { - val description = DestinationDescription( + val description = destination( name = "foo", parameters = listOf(ParameterDescription(name = "param1", type = "kotlin.String", required = true)), - navigationTargets = emptyList(), - isHome = false, - isTop = false ) val code = buildTestFile { @@ -77,12 +74,10 @@ class CreateContextClassTest { @Test fun `Destination Context with one parameter and one navigation that also has one parameter`() { - val description = DestinationDescription( + val description = destination( "foo", parameters = listOf(ParameterDescription(name = "param1", type = "kotlin.String", required = true)), navigationTargets = listOf(NavigationTarget("target", listOf(ParameterDescription(name = "targetParam1", type = "kotlin.Int", required = true)))), - isHome = false, - isTop = false ) val code = buildTestFile { diff --git a/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/generator/context/CreateSubGraphContextTest.kt b/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/generator/context/CreateSubGraphContextTest.kt index c0843f3..432e610 100644 --- a/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/generator/context/CreateSubGraphContextTest.kt +++ b/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/generator/context/CreateSubGraphContextTest.kt @@ -2,16 +2,16 @@ package de.onecode.compass.ksp.generator.context import de.onecode.compass.ksp.assertGeneratedCode import de.onecode.compass.ksp.buildTestFile -import de.onecode.compass.ksp.descriptions.DestinationDescription import de.onecode.compass.ksp.descriptions.SubGraphDescription +import de.onecode.compass.ksp.util.destination import org.junit.jupiter.api.Test @Suppress("RedundantVisibilityModifier", "ClassName") class CreateSubGraphContextTest { @Test fun `SubGraph Context`() { - val description1 = DestinationDescription("foo", parameters = emptyList(), navigationTargets = emptyList(), isHome = true, isTop = false) - val description2 = DestinationDescription("bar", parameters = emptyList(), navigationTargets = emptyList(), isHome = false, isTop = false) + val description1 = destination("foo", isHome = true) + val description2 = destination("bar") val subGraph = SubGraphDescription("sub", listOf(description1, description2)) val code = buildTestFile { diff --git a/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/generator/navigation/CreateCompassComposableTest.kt b/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/generator/navigation/CreateCompassComposableTest.kt index 112a646..1976b5d 100644 --- a/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/generator/navigation/CreateCompassComposableTest.kt +++ b/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/generator/navigation/CreateCompassComposableTest.kt @@ -2,20 +2,17 @@ package de.onecode.compass.ksp.generator.navigation import de.onecode.compass.ksp.assertGeneratedCode import de.onecode.compass.ksp.buildTestFile -import de.onecode.compass.ksp.descriptions.DestinationDescription import de.onecode.compass.ksp.descriptions.ParameterDescription +import de.onecode.compass.ksp.util.destination import org.junit.jupiter.api.Test @Suppress("RedundantVisibilityModifier", "TestFunctionName") class CreateCompassComposableTest { @Test fun `Navigator with a destination without parameters`() { - val description = DestinationDescription( + val description = destination( name = "foo", - parameters = emptyList(), - navigationTargets = emptyList(), isHome = true, - isTop = false ) val code = buildTestFile { @@ -61,12 +58,10 @@ class CreateCompassComposableTest { @Test fun `Navigator with a destination with a parameter`() { - val description = DestinationDescription( + val description = destination( name = "foo", parameters = listOf(ParameterDescription(name = "param1", type = "kotlin.Int", required = true)), - navigationTargets = emptyList(), isHome = true, - isTop = false ) val code = buildTestFile { diff --git a/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/generator/navigation/CreateCompassControllerTest.kt b/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/generator/navigation/CreateCompassControllerTest.kt index 056c47a..dc4e298 100644 --- a/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/generator/navigation/CreateCompassControllerTest.kt +++ b/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/generator/navigation/CreateCompassControllerTest.kt @@ -2,21 +2,18 @@ package de.onecode.compass.ksp.generator.navigation import de.onecode.compass.ksp.assertGeneratedCode import de.onecode.compass.ksp.buildTestFile -import de.onecode.compass.ksp.descriptions.DestinationDescription import de.onecode.compass.ksp.descriptions.NavigationTarget import de.onecode.compass.ksp.descriptions.ParameterDescription +import de.onecode.compass.ksp.util.destination import org.junit.jupiter.api.Test @Suppress("RedundantVisibilityModifier", "RemoveRedundantQualifierName", "TestFunctionName") class CreateCompassControllerTest { @Test fun `CompassController with one Destination no top`() { - val description = DestinationDescription( + val description = destination( name = "foo", - parameters = emptyList(), - navigationTargets = emptyList(), isHome = true, - isTop = false ) val code = buildTestFile { @@ -92,19 +89,14 @@ class CreateCompassControllerTest { @Test fun `CompassController with two Destination no top`() { val param1 = ParameterDescription(name = "param1", type = "kotlin.Int", required = true) - val description1 = DestinationDescription( + val description1 = destination( name = "foo", - parameters = emptyList(), navigationTargets = listOf(NavigationTarget("bar", listOf(param1))), isHome = true, - isTop = false ) - val description2 = DestinationDescription( + val description2 = destination( name = "bar", parameters = listOf(param1), - navigationTargets = emptyList(), - isHome = false, - isTop = false ) val code = buildTestFile { @@ -180,19 +172,15 @@ class CreateCompassControllerTest { @Test fun `CompassController with two Destination and one top`() { val param1 = ParameterDescription(name = "param1", type = "kotlin.Int", required = true) - val description1 = DestinationDescription( + val description1 = destination( name = "foo", - parameters = emptyList(), navigationTargets = listOf(NavigationTarget("bar", listOf(param1))), isHome = true, - isTop = false ) - val description2 = DestinationDescription( + val description2 = destination( name = "bar", parameters = listOf(param1), - navigationTargets = emptyList(), - isHome = false, - isTop = true + isTop = true, ) val code = buildTestFile { diff --git a/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/generator/navigation/CreateSubGraphFunctionTest.kt b/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/generator/navigation/CreateSubGraphFunctionTest.kt index 56ca31c..e23f964 100644 --- a/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/generator/navigation/CreateSubGraphFunctionTest.kt +++ b/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/generator/navigation/CreateSubGraphFunctionTest.kt @@ -2,10 +2,10 @@ package de.onecode.compass.ksp.generator.navigation import de.onecode.compass.ksp.assertGeneratedCode import de.onecode.compass.ksp.buildTestFile -import de.onecode.compass.ksp.descriptions.DestinationDescription import de.onecode.compass.ksp.descriptions.NavigationTarget import de.onecode.compass.ksp.descriptions.ParameterDescription import de.onecode.compass.ksp.descriptions.SubGraphDescription +import de.onecode.compass.ksp.util.destination import org.junit.jupiter.api.Test @Suppress("RedundantVisibilityModifier") @@ -13,19 +13,14 @@ class CreateSubGraphFunctionTest { @Test fun `SuGraph function with two destinations`() { val param1 = ParameterDescription(name = "param1", type = "kotlin.Int", required = true) - val description1 = DestinationDescription( + val description1 = destination( name = "foo", - parameters = emptyList(), navigationTargets = listOf(NavigationTarget("bar", listOf(param1))), isHome = true, - isTop = false ) - val description2 = DestinationDescription( + val description2 = destination( name = "bar", parameters = listOf(param1), - navigationTargets = emptyList(), - isHome = false, - isTop = false ) val subGraph = SubGraphDescription( name = "sub", @@ -71,7 +66,11 @@ class CreateSubGraphFunctionTest { @Test fun `SuGraph function with a home with parameters`() { val param1 = ParameterDescription(name = "param1", type = "kotlin.Int", required = true) - val description = DestinationDescription("foo", parameters = listOf(param1), navigationTargets = emptyList(), isHome = true, isTop = false) + val description = destination( + name = "foo", + parameters = listOf(param1), + isHome = true, + ) val subGraph = SubGraphDescription("sub", listOf(description)) val code = buildTestFile { diff --git a/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/generator/screenbuilder/CreateScreenBuilderTest.kt b/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/generator/screenbuilder/CreateScreenBuilderTest.kt index 007a909..40d0a1e 100644 --- a/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/generator/screenbuilder/CreateScreenBuilderTest.kt +++ b/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/generator/screenbuilder/CreateScreenBuilderTest.kt @@ -2,15 +2,15 @@ package de.onecode.compass.ksp.generator.screenbuilder import de.onecode.compass.ksp.assertGeneratedCode import de.onecode.compass.ksp.buildTestFile -import de.onecode.compass.ksp.descriptions.DestinationDescription +import de.onecode.compass.ksp.util.destination import org.junit.jupiter.api.Test @Suppress("RedundantVisibilityModifier") class CreateScreenBuilderTest { @Test fun `ScreenBuilder interface`() { - val description1 = DestinationDescription(name = "foo", parameters = emptyList(), navigationTargets = emptyList(), isHome = true, isTop = false) - val description2 = DestinationDescription(name = "bar", parameters = emptyList(), navigationTargets = emptyList(), isHome = false, isTop = false) + val description1 = destination(name = "foo", isHome = true) + val description2 = destination(name = "bar") val code = buildTestFile { addType(createScreenBuilderInterface(listOf(description1, description2))) @@ -38,8 +38,8 @@ class CreateScreenBuilderTest { @Test fun `ScreenBuilder implementation`() { - val description1 = DestinationDescription(name = "foo", parameters = emptyList(), navigationTargets = emptyList(), isHome = true, isTop = false) - val description2 = DestinationDescription(name = "bar", parameters = emptyList(), navigationTargets = emptyList(), isHome = false, isTop = false) + val description1 = destination(name = "foo", isHome = true) + val description2 = destination(name = "bar") val code = buildTestFile { addType(createScreenBuilderImplementation(listOf(description1, description2))) diff --git a/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/generator/screenbuilder/CreateSubGraphBuilderTest.kt b/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/generator/screenbuilder/CreateSubGraphBuilderTest.kt index 58b5b13..2b505fc 100644 --- a/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/generator/screenbuilder/CreateSubGraphBuilderTest.kt +++ b/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/generator/screenbuilder/CreateSubGraphBuilderTest.kt @@ -2,16 +2,16 @@ package de.onecode.compass.ksp.generator.screenbuilder import de.onecode.compass.ksp.assertGeneratedCode import de.onecode.compass.ksp.buildTestFile -import de.onecode.compass.ksp.descriptions.DestinationDescription import de.onecode.compass.ksp.descriptions.SubGraphDescription +import de.onecode.compass.ksp.util.destination import org.junit.jupiter.api.Test @Suppress("RedundantVisibilityModifier", "ClassName") class CreateSubGraphBuilderTest { @Test fun `SubGraphBuilder interface`() { - val description1 = DestinationDescription(name = "foo", parameters = emptyList(), navigationTargets = emptyList(), isHome = true, isTop = false) - val description2 = DestinationDescription(name = "bar", parameters = emptyList(), navigationTargets = emptyList(), isHome = false, isTop = false) + val description1 = destination(name = "foo", isHome = true) + val description2 = destination(name = "bar") val subGraph = SubGraphDescription(name = "sub", listOf(description1, description2)) val code = buildTestFile { @@ -40,8 +40,8 @@ class CreateSubGraphBuilderTest { @Test fun `ScreenBuilder implementation`() { - val description1 = DestinationDescription(name = "foo", parameters = emptyList(), navigationTargets = emptyList(), isHome = true, isTop = false) - val description2 = DestinationDescription(name = "bar", parameters = emptyList(), navigationTargets = emptyList(), isHome = false, isTop = false) + val description1 = destination(name = "foo", isHome = true) + val description2 = destination(name = "bar") val subGraph = SubGraphDescription(name = "sub", listOf(description1, description2)) val code = buildTestFile { diff --git a/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/util/DestinationCreator.kt b/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/util/DestinationCreator.kt new file mode 100644 index 0000000..a141f1b --- /dev/null +++ b/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/util/DestinationCreator.kt @@ -0,0 +1,22 @@ +package de.onecode.compass.ksp.util + +import de.onecode.compass.ksp.descriptions.DestinationDescription +import de.onecode.compass.ksp.descriptions.NavigationTarget +import de.onecode.compass.ksp.descriptions.ParameterDescription + +internal fun destination( + name: String, + parameters: List = emptyList(), + navigationTargets: List = emptyList(), + isHome: Boolean = false, + isTop: Boolean = false, + isDialog: Boolean = false +): DestinationDescription = + DestinationDescription( + name = name, + parameters = parameters, + navigationTargets = navigationTargets, + isHome = isHome, + isTop = isTop, + isDialog = isDialog, + ) \ No newline at end of file From a26224d197f534d8a975fe85c712435fc8e82c5b Mon Sep 17 00:00:00 2001 From: Alexander Frank Date: Tue, 16 Jul 2024 19:07:11 +0200 Subject: [PATCH 3/6] Fix detekt --- build-common/src/main/resources/detekt.yml | 2 ++ .../de/onecode/compass/ksp/util/DestinationCreator.kt | 2 +- .../kotlin/de/onecode/compass/demo/MainActivity.kt | 10 ++-------- .../de/onecode/compass/demo/dialog/MyDialogScreen.kt | 6 ++++-- .../de/onecode/compass/demo/home/HomeDescription.kt | 2 +- demo/app/src/main/res/values/strings.xml | 1 + 6 files changed, 11 insertions(+), 12 deletions(-) diff --git a/build-common/src/main/resources/detekt.yml b/build-common/src/main/resources/detekt.yml index d46b207..ea35f18 100644 --- a/build-common/src/main/resources/detekt.yml +++ b/build-common/src/main/resources/detekt.yml @@ -17,6 +17,8 @@ complexity: LongMethod: excludes: - "**/test/**" + LongParameterList: + functionThreshold: 7 naming: FunctionNaming: diff --git a/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/util/DestinationCreator.kt b/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/util/DestinationCreator.kt index a141f1b..2c0f2c9 100644 --- a/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/util/DestinationCreator.kt +++ b/compass/ksp/src/test/kotlin/de/onecode/compass/ksp/util/DestinationCreator.kt @@ -19,4 +19,4 @@ internal fun destination( isHome = isHome, isTop = isTop, isDialog = isDialog, - ) \ No newline at end of file + ) diff --git a/demo/app/src/main/kotlin/de/onecode/compass/demo/MainActivity.kt b/demo/app/src/main/kotlin/de/onecode/compass/demo/MainActivity.kt index 6417227..30de4fd 100644 --- a/demo/app/src/main/kotlin/de/onecode/compass/demo/MainActivity.kt +++ b/demo/app/src/main/kotlin/de/onecode/compass/demo/MainActivity.kt @@ -42,7 +42,6 @@ class MainActivity : ComponentActivity() { @Composable fun Main() { val compassController = rememberCompassController() - val isHome by compassController.currentDestinationIsHome() val isDetails by compassController.currentDestinationIsDetails() @@ -53,17 +52,13 @@ fun Main() { selected = isHome, label = { Text(text = "Home") }, onClick = { compassController.navigateToHome() }, - icon = { - Icon(imageVector = Icons.Default.Home, contentDescription = "") - } + icon = { Icon(imageVector = Icons.Default.Home, contentDescription = "") } ) NavigationBarItem( selected = isDetails, label = { Text(text = "Wizard") }, onClick = { compassController.navigateToDetails(Random.nextInt()) }, - icon = { - Icon(imageVector = Icons.AutoMirrored.Filled.List, contentDescription = "") - } + icon = { Icon(imageVector = Icons.AutoMirrored.Filled.List, contentDescription = "") } ) } } @@ -102,7 +97,6 @@ fun Main() { } navGraphBuilder.attachWizardSubGraph() - navGraphBuilder.attachFeatureComposable() } } diff --git a/demo/app/src/main/kotlin/de/onecode/compass/demo/dialog/MyDialogScreen.kt b/demo/app/src/main/kotlin/de/onecode/compass/demo/dialog/MyDialogScreen.kt index d9cbbe7..58a43f6 100644 --- a/demo/app/src/main/kotlin/de/onecode/compass/demo/dialog/MyDialogScreen.kt +++ b/demo/app/src/main/kotlin/de/onecode/compass/demo/dialog/MyDialogScreen.kt @@ -13,7 +13,9 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp +import de.onecode.compass.demo.R @Composable fun MyDialogScreen( @@ -26,7 +28,7 @@ fun MyDialogScreen( .background(MaterialTheme.colorScheme.background) .padding(16.dp), ) { - Text(text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.") + Text(text = stringResource(R.string.lorem_ipsum)) Spacer(modifier = Modifier.size(8.dp)) TextButton( onClick = onClose, @@ -35,4 +37,4 @@ fun MyDialogScreen( Text(text = "Close") } } -} \ No newline at end of file +} diff --git a/demo/app/src/main/kotlin/de/onecode/compass/demo/home/HomeDescription.kt b/demo/app/src/main/kotlin/de/onecode/compass/demo/home/HomeDescription.kt index c8d0dce..0a2dd5c 100644 --- a/demo/app/src/main/kotlin/de/onecode/compass/demo/home/HomeDescription.kt +++ b/demo/app/src/main/kotlin/de/onecode/compass/demo/home/HomeDescription.kt @@ -20,4 +20,4 @@ object SubHomeDestination @Dialog @Destination(name = "MyDialog") -object MyDialogDestination \ No newline at end of file +object MyDialogDestination diff --git a/demo/app/src/main/res/values/strings.xml b/demo/app/src/main/res/values/strings.xml index 11fa307..9b13292 100644 --- a/demo/app/src/main/res/values/strings.xml +++ b/demo/app/src/main/res/values/strings.xml @@ -1,3 +1,4 @@ Compass Demo + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. \ No newline at end of file From 829cafe34e21eeb00dcb65711af49b48aabe2d15 Mon Sep 17 00:00:00 2001 From: Alexander Frank Date: Tue, 16 Jul 2024 19:21:18 +0200 Subject: [PATCH 4/6] Fix dialog import --- .../de/onecode/compass/ksp/generator/CodeGeneration.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compass/ksp/src/main/kotlin/de/onecode/compass/ksp/generator/CodeGeneration.kt b/compass/ksp/src/main/kotlin/de/onecode/compass/ksp/generator/CodeGeneration.kt index 6406f75..af243c1 100644 --- a/compass/ksp/src/main/kotlin/de/onecode/compass/ksp/generator/CodeGeneration.kt +++ b/compass/ksp/src/main/kotlin/de/onecode/compass/ksp/generator/CodeGeneration.kt @@ -21,12 +21,12 @@ fun generateNavigatorCode(graph: GraphDescription): FileSpec { val destinations = graph.destinations val subGraphs = graph.subGraphs - val hasDialog = graph.destinations.any { it.isDialog } || subGraphs.fold(true) {acc, destination -> acc && destination.destinations.any { it.isDialog }} + val hasDialog = graph.destinations.any { it.isDialog } || (subGraphs.isNotEmpty() && subGraphs.fold(true) { acc, destination -> acc && destination.destinations.any { it.isDialog } }) return createFileSpec(graph) .addImport("androidx.compose.runtime", "CompositionLocalProvider", "compositionLocalOf") .apply { - if(hasDialog) { + if (hasDialog) { addImport("androidx.navigation.compose", "dialog") } @@ -114,7 +114,7 @@ private fun FileSpec.Builder.addParameterExtensionsOnSavedStateHandle(destinatio allParameters.forEach { parameter -> val existingParameterType = existingParameters[parameter.name] when { - existingParameterType == null -> { + existingParameterType == null -> { addFunction(createParameterExtensionOnSavedStateHandle(parameter)) existingParameters[parameter.name] = parameter.type } From bc3438f8f9d2c39e87e15cdcaf0481d30c925d03 Mon Sep 17 00:00:00 2001 From: Alexander Frank Date: Tue, 16 Jul 2024 19:27:14 +0200 Subject: [PATCH 5/6] Fix detekt --- .../kotlin/de/onecode/compass/ksp/generator/CodeGeneration.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compass/ksp/src/main/kotlin/de/onecode/compass/ksp/generator/CodeGeneration.kt b/compass/ksp/src/main/kotlin/de/onecode/compass/ksp/generator/CodeGeneration.kt index af243c1..4f45dff 100644 --- a/compass/ksp/src/main/kotlin/de/onecode/compass/ksp/generator/CodeGeneration.kt +++ b/compass/ksp/src/main/kotlin/de/onecode/compass/ksp/generator/CodeGeneration.kt @@ -21,7 +21,8 @@ fun generateNavigatorCode(graph: GraphDescription): FileSpec { val destinations = graph.destinations val subGraphs = graph.subGraphs - val hasDialog = graph.destinations.any { it.isDialog } || (subGraphs.isNotEmpty() && subGraphs.fold(true) { acc, destination -> acc && destination.destinations.any { it.isDialog } }) + val subGraphHasDialog = subGraphs.isNotEmpty() && subGraphs.fold(true) { acc, destination -> acc && destination.destinations.any { it.isDialog } } + val hasDialog = graph.destinations.any { it.isDialog } || subGraphHasDialog return createFileSpec(graph) .addImport("androidx.compose.runtime", "CompositionLocalProvider", "compositionLocalOf") From d8c8a5ee10a5846f54f663c7abd55e27985b051e Mon Sep 17 00:00:00 2001 From: Alexander Frank Date: Tue, 16 Jul 2024 19:34:55 +0200 Subject: [PATCH 6/6] Added a description for Dialog to the README --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index bd1a5ef..e46165c 100644 --- a/README.md +++ b/README.md @@ -176,6 +176,12 @@ Navigation methods for `@Top` destinations are generated in the `CompoassControl `@Top` annotations are only supported in the main graph, they are disallowed in a sub graph. **Important**: Don't forget to pass it to the `Compass` again, to make sure the same instance is used by you and the `Compass` +### @Dialog + +`@Dialog` marks a destination to be dialog composable in the NavGraph. +Annotating a destination that way leads to the usage of the `dialog` function instead of the `composable` function under the hood. +The destination won't be displayed fullscreen anymore. + ### @SubGraph In addition to a main graph which will generate the `Compass`, destinations can also be grouped together into a subgraph. The subgraph can be defined independently and later included into an