diff --git a/composeApp/src/commonMain/kotlin/DI.kt b/composeApp/src/commonMain/kotlin/DI.kt index 60c11fd..b8bffc1 100644 --- a/composeApp/src/commonMain/kotlin/DI.kt +++ b/composeApp/src/commonMain/kotlin/DI.kt @@ -22,6 +22,8 @@ import ui.device.DeviceHomeViewInteractor import ui.file.FileSystemViewInteractor import ui.home.HomeViewInteractor import ui.iosServices.IOSServicesScreenViewInteractor +import ui.openForResultExample.OpenForResultConfirmationViewInteractor +import ui.openForResultExample.OpenForResultExampleViewInteractor import ui.popups.PopupsScreenViewInteractor import ui.viewStateExample.ViewStateExampleViewInteractor @@ -59,4 +61,6 @@ fun commonModule() = module { factory { IOSServicesScreenViewInteractor(get()) } factory { CapabilityScreenViewInteractor(get()) } factory { ColorPickerViewInteractor() } + factory { OpenForResultExampleViewInteractor(get()) } + factory { OpenForResultConfirmationViewInteractor(get()) } } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/coordinator/AppCoordinator.kt b/composeApp/src/commonMain/kotlin/coordinator/AppCoordinator.kt index c3ff0f2..e796b06 100644 --- a/composeApp/src/commonMain/kotlin/coordinator/AppCoordinator.kt +++ b/composeApp/src/commonMain/kotlin/coordinator/AppCoordinator.kt @@ -37,4 +37,15 @@ class AppCoordinator(): Coordinator( fun colorPickerClicked() = push(Route.ColorPicker) fun htmlDemoClicked() = push(Route.WebDemo) fun windowInfoClicked() = push(Route.WindowInfo) + fun openForResultExampleClicked() = push(Route.OpenForResultExample) + suspend fun openForResultExampleConfirmationClicked() = transactionWithResult(Boolean::class) { + push(Route.OpenForResultExampleConfirmation) + } + fun openForResultExampleConfirmationYesClicked() { + pop { withResult(true) } + } + fun openForResultExampleConfirmationNoClicked() { + pop { withResult(false) } + } + } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/ui/Route.kt b/composeApp/src/commonMain/kotlin/ui/Route.kt index 3289ed8..5de81bd 100644 --- a/composeApp/src/commonMain/kotlin/ui/Route.kt +++ b/composeApp/src/commonMain/kotlin/ui/Route.kt @@ -22,6 +22,8 @@ sealed class Route( data object ColorPicker : Route(webRoutePath = "/color-picker") data object WebDemo : Route(webRoutePath = "/web-demo") data object WindowInfo : Route(webRoutePath = "/window-info") + data object OpenForResultExample : Route(webRoutePath = "/open-for-result") + data object OpenForResultExampleConfirmation : Route(webRoutePath = "/open-for-result-confirmation") companion object { val deepLinks = Router.buildDeepLinks { diff --git a/composeApp/src/commonMain/kotlin/ui/app/App.kt b/composeApp/src/commonMain/kotlin/ui/app/App.kt index 924750e..ac4b2c7 100644 --- a/composeApp/src/commonMain/kotlin/ui/app/App.kt +++ b/composeApp/src/commonMain/kotlin/ui/app/App.kt @@ -23,6 +23,8 @@ import ui.markdown.MarkdownScreen import ui.popups.PopupsScreen import ui.viewStateExample.ViewStateExampleScreen import ui.htmlDemo.HtmlDemoScreen +import ui.openForResultExample.OpenForResultConfirmationScreen +import ui.openForResultExample.OpenForResultExampleScreen import ui.widgets.WidgetsScreen import ui.windowInfo.WindowInfoScreen @@ -62,6 +64,8 @@ fun App( RouteTransitionDirection.Out } ) + is Route.OpenForResultExample -> OpenForResultExampleScreen() + is Route.OpenForResultExampleConfirmation -> OpenForResultConfirmationScreen() } } } diff --git a/composeApp/src/commonMain/kotlin/ui/home/HomeScreen.kt b/composeApp/src/commonMain/kotlin/ui/home/HomeScreen.kt index c5826db..5391ec2 100644 --- a/composeApp/src/commonMain/kotlin/ui/home/HomeScreen.kt +++ b/composeApp/src/commonMain/kotlin/ui/home/HomeScreen.kt @@ -102,6 +102,10 @@ fun HomeScreen( content = { Text("Window Info") }, onClick = interactor::windowInfoButtonClicked, ) + Button( + content = { Text("Open Route For Result Example") }, + onClick = interactor::openForResultClicked, + ) Button( content = { Text(rememberKmpString(Strings.iosServices)) }, onClick = interactor::iosServicesButtonClicked, diff --git a/composeApp/src/commonMain/kotlin/ui/home/HomeViewInteractor.kt b/composeApp/src/commonMain/kotlin/ui/home/HomeViewInteractor.kt index bf2a554..75d0045 100644 --- a/composeApp/src/commonMain/kotlin/ui/home/HomeViewInteractor.kt +++ b/composeApp/src/commonMain/kotlin/ui/home/HomeViewInteractor.kt @@ -19,4 +19,5 @@ class HomeViewInteractor( fun colorPickerButtonClicked() = coordinator.colorPickerClicked() fun htmlDemoButtonClicked() = coordinator.htmlDemoClicked() fun windowInfoButtonClicked() = coordinator.windowInfoClicked() + fun openForResultClicked() = coordinator.openForResultExampleClicked() } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/ui/openForResultExample/OpenForResultConfirmationScreen.kt b/composeApp/src/commonMain/kotlin/ui/openForResultExample/OpenForResultConfirmationScreen.kt new file mode 100644 index 0000000..3e62cf8 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/ui/openForResultExample/OpenForResultConfirmationScreen.kt @@ -0,0 +1,45 @@ +package ui.openForResultExample + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material.Button +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.outsidesource.oskitcompose.interactor.collectAsState +import com.outsidesource.oskitcompose.lib.rememberInjectForRoute +import ui.common.Screen + +@Composable +fun OpenForResultConfirmationScreen( + interactor: OpenForResultConfirmationViewInteractor = rememberInjectForRoute() +) { + val state = interactor.collectAsState() + + Screen("Example Route with Result") { + Column( + modifier = Modifier.fillMaxSize(), + verticalArrangement = Arrangement.spacedBy(8.dp, Alignment.CenterVertically), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Text("Return Result:") + + Row( + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + Button( + content = { Text("True") }, + onClick = interactor::yesClicked + ) + Button( + content = { Text("False") }, + onClick = interactor::noClicked + ) + } + } + } +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/ui/openForResultExample/OpenForResultConfirmationViewInteractor.kt b/composeApp/src/commonMain/kotlin/ui/openForResultExample/OpenForResultConfirmationViewInteractor.kt new file mode 100644 index 0000000..61925fc --- /dev/null +++ b/composeApp/src/commonMain/kotlin/ui/openForResultExample/OpenForResultConfirmationViewInteractor.kt @@ -0,0 +1,23 @@ +package ui.openForResultExample + +import com.outsidesource.oskitkmp.interactor.Interactor +import coordinator.AppCoordinator + +data class ConfirmationViewState( + val result: Boolean? = null, +) + +class OpenForResultConfirmationViewInteractor( + private val coordinator: AppCoordinator +): Interactor( + initialState = ConfirmationViewState() +) { + + fun yesClicked() { + coordinator.openForResultExampleConfirmationYesClicked() + } + + fun noClicked() { + coordinator.openForResultExampleConfirmationNoClicked() + } +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/ui/openForResultExample/OpenForResultExampleScreen.kt b/composeApp/src/commonMain/kotlin/ui/openForResultExample/OpenForResultExampleScreen.kt new file mode 100644 index 0000000..ecc47f9 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/ui/openForResultExample/OpenForResultExampleScreen.kt @@ -0,0 +1,47 @@ +package ui.openForResultExample + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material.Button +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import com.outsidesource.oskitcompose.interactor.collectAsState +import com.outsidesource.oskitcompose.lib.rememberInjectForRoute +import ui.common.Screen + +@Composable +fun OpenForResultExampleScreen( + interactor: OpenForResultExampleViewInteractor = rememberInjectForRoute() +) { + val state = interactor.collectAsState() + + Screen("Open Route For Result Example") { + Column( + modifier = Modifier.fillMaxSize(), + verticalArrangement = Arrangement.spacedBy(8.dp, Alignment.CenterVertically), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Text( + "This example shows how to launch a route and await a result from it.\n" + + "Press the button to open the confirmation screen and receive " + + "the user’s selection as the result.\n", + textAlign = TextAlign.Center + ) + + Button( + content = { Text("Open Confirmation Route") }, + onClick = interactor::openConfirmationRouteClicked + ) + + if (state.exampleDialogWasEverLaunched) { + Text("Returned result: ${state.result?.toString() ?: "Cancelled"}") + } + + } + } +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/ui/openForResultExample/OpenForResultExampleViewInteractor.kt b/composeApp/src/commonMain/kotlin/ui/openForResultExample/OpenForResultExampleViewInteractor.kt new file mode 100644 index 0000000..f09aca5 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/ui/openForResultExample/OpenForResultExampleViewInteractor.kt @@ -0,0 +1,26 @@ +package ui.openForResultExample + +import com.outsidesource.oskitkmp.interactor.Interactor +import com.outsidesource.oskitkmp.outcome.unwrapOrNull +import coordinator.AppCoordinator +import kotlinx.coroutines.launch + +data class OpenForResultExampleViewState( + val result: Boolean? = null, + val exampleDialogWasEverLaunched: Boolean = false, +) + +class OpenForResultExampleViewInteractor( + private val coordinator: AppCoordinator +): Interactor( + initialState = OpenForResultExampleViewState() +) { + + fun openConfirmationRouteClicked() { + update { state -> state.copy(exampleDialogWasEverLaunched = true) } + interactorScope.launch { + val res = coordinator.openForResultExampleConfirmationClicked().unwrapOrNull() + update { state -> state.copy(result = res) } + } + } +} \ No newline at end of file