diff --git a/composeApp/src/androidMain/kotlin/PlatformDI.kt b/composeApp/src/androidMain/kotlin/PlatformDI.kt index 62ccf66..0d89b04 100644 --- a/composeApp/src/androidMain/kotlin/PlatformDI.kt +++ b/composeApp/src/androidMain/kotlin/PlatformDI.kt @@ -1,5 +1,7 @@ import android.content.Context import com.outsidesource.oskitkmp.storage.KmpKvStore +import com.outsidesource.oskitkmp.systemui.IKmpSettingsScreenOpener +import com.outsidesource.oskitkmp.systemui.KmpSettingsScreenOpener import org.koin.dsl.bind import org.koin.dsl.module import service.swift.ISwiftExampleService @@ -11,4 +13,5 @@ actual fun platformModule(platformContext: PlatformContext) = module { single { platformContext.context } single { NoOpSwiftExampleService() } bind ISwiftExampleService::class single { KmpKvStore(appContext = get()) } + single { KmpSettingsScreenOpener(context = get()) } bind IKmpSettingsScreenOpener::class } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/DI.kt b/composeApp/src/commonMain/kotlin/DI.kt index 60c11fd..ace3bb8 100644 --- a/composeApp/src/commonMain/kotlin/DI.kt +++ b/composeApp/src/commonMain/kotlin/DI.kt @@ -23,6 +23,7 @@ import ui.file.FileSystemViewInteractor import ui.home.HomeViewInteractor import ui.iosServices.IOSServicesScreenViewInteractor import ui.popups.PopupsScreenViewInteractor +import ui.settingsOpenerExample.SettingsOpenerExampleViewInteractor import ui.viewStateExample.ViewStateExampleViewInteractor fun initKoin( @@ -59,4 +60,5 @@ fun commonModule() = module { factory { IOSServicesScreenViewInteractor(get()) } factory { CapabilityScreenViewInteractor(get()) } factory { ColorPickerViewInteractor() } + factory { SettingsOpenerExampleViewInteractor(get(), 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..fb9efc0 100644 --- a/composeApp/src/commonMain/kotlin/coordinator/AppCoordinator.kt +++ b/composeApp/src/commonMain/kotlin/coordinator/AppCoordinator.kt @@ -35,6 +35,7 @@ class AppCoordinator(): Coordinator( fun widgetsClicked() = push(Route.Widgets) fun capabilityClicked() = push(Route.Capability) fun colorPickerClicked() = push(Route.ColorPicker) + fun settingsOpenerExampleClicked() = push(Route.SettingsOpenerExample) fun htmlDemoClicked() = push(Route.WebDemo) fun windowInfoClicked() = push(Route.WindowInfo) } \ 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..4c40aeb 100644 --- a/composeApp/src/commonMain/kotlin/ui/Route.kt +++ b/composeApp/src/commonMain/kotlin/ui/Route.kt @@ -20,6 +20,7 @@ sealed class Route( data object Widgets: Route(webRoutePath = "/widgets") data object Capability : Route(webRoutePath = "/capability") data object ColorPicker : Route(webRoutePath = "/color-picker") + data object SettingsOpenerExample: Route(webRoutePath = "/settings-opener") data object WebDemo : Route(webRoutePath = "/web-demo") data object WindowInfo : Route(webRoutePath = "/window-info") diff --git a/composeApp/src/commonMain/kotlin/ui/app/App.kt b/composeApp/src/commonMain/kotlin/ui/app/App.kt index 924750e..a55181f 100644 --- a/composeApp/src/commonMain/kotlin/ui/app/App.kt +++ b/composeApp/src/commonMain/kotlin/ui/app/App.kt @@ -25,6 +25,7 @@ import ui.viewStateExample.ViewStateExampleScreen import ui.htmlDemo.HtmlDemoScreen import ui.widgets.WidgetsScreen import ui.windowInfo.WindowInfoScreen +import ui.settingsOpenerExample.SettingsOpenerExampleScreen @Composable fun App( @@ -54,6 +55,7 @@ fun App( is Route.Widgets -> WidgetsScreen() is Route.Capability -> CapabilityScreen() is Route.ColorPicker -> ColorPickerScreen() + is Route.SettingsOpenerExample -> SettingsOpenerExampleScreen() is Route.WindowInfo -> WindowInfoScreen() is Route.WebDemo -> HtmlDemoScreen( transitionDirection = if (it == interactor.getActiveRoute()) { diff --git a/composeApp/src/commonMain/kotlin/ui/home/HomeScreen.kt b/composeApp/src/commonMain/kotlin/ui/home/HomeScreen.kt index c5826db..7c98ab3 100644 --- a/composeApp/src/commonMain/kotlin/ui/home/HomeScreen.kt +++ b/composeApp/src/commonMain/kotlin/ui/home/HomeScreen.kt @@ -94,6 +94,10 @@ fun HomeScreen( content = { Text("Capability") }, onClick = interactor::capabilityButtonClicked, ) + Button( + content = { Text("App & System Settings Opener") }, + onClick = interactor::settingsOpenerExampleButtonClicked, + ) Button( content = { Text("Color Picker") }, onClick = interactor::colorPickerButtonClicked, diff --git a/composeApp/src/commonMain/kotlin/ui/home/HomeViewInteractor.kt b/composeApp/src/commonMain/kotlin/ui/home/HomeViewInteractor.kt index bf2a554..f1d19ac 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 settingsOpenerExampleButtonClicked() = coordinator.settingsOpenerExampleClicked() } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/ui/settingsOpenerExample/SettingsOpenerExampleScreen.kt b/composeApp/src/commonMain/kotlin/ui/settingsOpenerExample/SettingsOpenerExampleScreen.kt new file mode 100644 index 0000000..93de7f3 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/ui/settingsOpenerExample/SettingsOpenerExampleScreen.kt @@ -0,0 +1,65 @@ +package ui.settingsOpenerExample + +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.foundation.layout.padding +import androidx.compose.material.Button +import androidx.compose.material.Text +import androidx.compose.material.TextField +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import ui.common.Screen +import com.outsidesource.oskitcompose.interactor.collectAsState +import com.outsidesource.oskitcompose.lib.rememberInjectForRoute +import ui.viewStateExample.ViewStateExampleViewInteractor + +@Composable +fun SettingsOpenerExampleScreen( + interactor: SettingsOpenerExampleViewInteractor = rememberInjectForRoute() +) { + val state = interactor.collectAsState() + + Screen("Settings Opener") { + Column( + modifier = Modifier.fillMaxSize(), + verticalArrangement = Arrangement.spacedBy(8.dp, Alignment.CenterVertically), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + + Button( + content = { Text("Open App Settings") }, + onClick = interactor::appSettingsClicked + ) + ResultLabel(state.appSettingsOutcome) + + Button( + content = { Text("Open System Settings") }, + onClick = interactor::systemSettingsClicked + ) + ResultLabel(state.systemSettingsOutcome) + + Button( + content = { Text("Open Bluetooth Settings") }, + onClick = interactor::bluetoothSettingsClicked + ) + ResultLabel(state.btSettingsOutcome) + + Button( + content = { Text("Open Location Settings") }, + onClick = interactor::locationSettingsClicked + ) + ResultLabel(state.locationSettingsOutcome) + } + } +} + +@Composable +private fun ResultLabel(message: String?) { + if (!message.isNullOrBlank()) { + Text("Result is $message", modifier = Modifier.padding(top = 4.dp, bottom = 16.dp)) + } +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/ui/settingsOpenerExample/SettingsOpenerExampleViewInteractor.kt b/composeApp/src/commonMain/kotlin/ui/settingsOpenerExample/SettingsOpenerExampleViewInteractor.kt new file mode 100644 index 0000000..608021c --- /dev/null +++ b/composeApp/src/commonMain/kotlin/ui/settingsOpenerExample/SettingsOpenerExampleViewInteractor.kt @@ -0,0 +1,66 @@ +package ui.settingsOpenerExample + +import com.outsidesource.oskitkmp.interactor.Interactor +import com.outsidesource.oskitkmp.systemui.IKmpSettingsScreenOpener +import com.outsidesource.oskitkmp.systemui.SettingsScreenType +import coordinator.AppCoordinator +import kotlinx.coroutines.launch + +data class SettingsOpenerExampleViewState( + val appSettingsOutcome: String? = null, + val systemSettingsOutcome: String? = null, + val btSettingsOutcome: String? = null, + val locationSettingsOutcome: String? = null, +) + +class SettingsOpenerExampleViewInteractor( + private val coordinator: AppCoordinator, + private val settingsScreenOpener: IKmpSettingsScreenOpener +) : Interactor( + initialState = SettingsOpenerExampleViewState() +) { + + fun appSettingsClicked() { + interactorScope.launch { + val res = settingsScreenOpener.open(SettingsScreenType.App) + update { state -> + state.copy( + appSettingsOutcome = res.toString() + ) + } + } + } + + fun systemSettingsClicked() { + interactorScope.launch { + val res = settingsScreenOpener.open(SettingsScreenType.SystemSettings) + update { state -> + state.copy( + systemSettingsOutcome = res.toString() + ) + } + } + } + + fun bluetoothSettingsClicked() { + interactorScope.launch { + val res = settingsScreenOpener.open(SettingsScreenType.Bluetooth) + update { state -> + state.copy( + btSettingsOutcome = res.toString() + ) + } + } + } + + fun locationSettingsClicked() { + interactorScope.launch { + val res = settingsScreenOpener.open(SettingsScreenType.Location) + update { state -> + state.copy( + locationSettingsOutcome = res.toString() + ) + } + } + } +} \ No newline at end of file diff --git a/composeApp/src/desktopMain/kotlin/PlatformDI.kt b/composeApp/src/desktopMain/kotlin/PlatformDI.kt index 0313422..0417e0f 100644 --- a/composeApp/src/desktopMain/kotlin/PlatformDI.kt +++ b/composeApp/src/desktopMain/kotlin/PlatformDI.kt @@ -1,5 +1,7 @@ import com.outsidesource.oskitkmp.storage.KmpKvStore +import com.outsidesource.oskitkmp.systemui.IKmpSettingsScreenOpener +import com.outsidesource.oskitkmp.systemui.KmpSettingsScreenOpener import org.koin.dsl.bind import org.koin.dsl.module import service.swift.ISwiftExampleService @@ -10,4 +12,5 @@ actual class PlatformContext actual fun platformModule(platformContext: PlatformContext) = module { single { NoOpSwiftExampleService() } bind ISwiftExampleService::class single { KmpKvStore(appName = "OSKit-Example-App") } + single { KmpSettingsScreenOpener() } bind IKmpSettingsScreenOpener::class } \ No newline at end of file diff --git a/composeApp/src/iosMain/kotlin/PlatformDI.kt b/composeApp/src/iosMain/kotlin/PlatformDI.kt index 35ae286..e8118cb 100644 --- a/composeApp/src/iosMain/kotlin/PlatformDI.kt +++ b/composeApp/src/iosMain/kotlin/PlatformDI.kt @@ -1,4 +1,6 @@ import com.outsidesource.oskitkmp.storage.KmpKvStore +import com.outsidesource.oskitkmp.systemui.IKmpSettingsScreenOpener +import com.outsidesource.oskitkmp.systemui.KmpSettingsScreenOpener import org.koin.dsl.bind import org.koin.dsl.module import service.swift.ISwiftExampleService @@ -11,6 +13,7 @@ private val koin = initKoin( actual fun platformModule(platformContext: PlatformContext) = module { single { KmpKvStore() } + single { KmpSettingsScreenOpener() } bind IKmpSettingsScreenOpener::class } fun loadKoinSwiftModules( diff --git a/composeApp/src/wasmJsMain/kotlin/PlatformDI.kt b/composeApp/src/wasmJsMain/kotlin/PlatformDI.kt index a76078e..8e662bf 100644 --- a/composeApp/src/wasmJsMain/kotlin/PlatformDI.kt +++ b/composeApp/src/wasmJsMain/kotlin/PlatformDI.kt @@ -1,5 +1,7 @@ import com.outsidesource.oskitkmp.storage.KmpKvStore import com.outsidesource.oskitkmp.storage.WasmKmpKvStoreType +import com.outsidesource.oskitkmp.systemui.IKmpSettingsScreenOpener +import com.outsidesource.oskitkmp.systemui.KmpSettingsScreenOpener import org.koin.dsl.bind import org.koin.dsl.module import service.swift.ISwiftExampleService @@ -10,4 +12,5 @@ actual object PlatformContext actual fun platformModule(platformContext: PlatformContext) = module { single { NoOpSwiftExampleService() } bind ISwiftExampleService::class single { KmpKvStore(type = WasmKmpKvStoreType.LocalStorage) } + single { KmpSettingsScreenOpener() } bind IKmpSettingsScreenOpener::class } \ No newline at end of file