diff --git a/build.gradle.kts b/build.gradle.kts
index ec93b69..4064277 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -7,4 +7,5 @@ plugins {
alias(libs.plugins.compose.compiler) apply false
alias(libs.plugins.kotlinJvm) apply false
alias(libs.plugins.kotlinMultiplatform) apply false
-}
\ No newline at end of file
+ alias(libs.plugins.jetbrains.kotlin.android) apply false
+}
diff --git a/composeApp/build.gradle.kts b/composeApp/build.gradle.kts
index 64ae6af..e7df99f 100644
--- a/composeApp/build.gradle.kts
+++ b/composeApp/build.gradle.kts
@@ -64,6 +64,9 @@ kotlin {
implementation(compose.components.resources)
implementation(compose.components.uiToolingPreview)
implementation(projects.shared)
+ implementation(libs.voyager.navigator)
+ implementation(libs.voyager.navigator.transitions)
+ implementation(libs.voyager.screenmodel)
}
desktopMain.dependencies {
implementation(compose.desktop.currentOs)
diff --git a/composeApp/src/androidMain/AndroidManifest.xml b/composeApp/src/androidMain/AndroidManifest.xml
index c5db0b1..ff9ccec 100644
--- a/composeApp/src/androidMain/AndroidManifest.xml
+++ b/composeApp/src/androidMain/AndroidManifest.xml
@@ -2,6 +2,7 @@
+ android:exported="true">
@@ -20,4 +21,4 @@
-
\ No newline at end of file
+
diff --git a/composeApp/src/androidMain/kotlin/com/app/academy/notes/MainActivity.kt b/composeApp/src/androidMain/kotlin/com/app/academy/notes/MainActivity.kt
index 67eba90..eb4b60f 100644
--- a/composeApp/src/androidMain/kotlin/com/app/academy/notes/MainActivity.kt
+++ b/composeApp/src/androidMain/kotlin/com/app/academy/notes/MainActivity.kt
@@ -1,6 +1,6 @@
package com.app.academy.notes
-import App
+import com.app.academy.App
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
@@ -21,4 +21,4 @@ class MainActivity : ComponentActivity() {
@Composable
fun AppAndroidPreview() {
App()
-}
\ No newline at end of file
+}
diff --git a/composeApp/src/androidMain/kotlin/com/app/academy/notes/NotesAppApplication.kt b/composeApp/src/androidMain/kotlin/com/app/academy/notes/NotesAppApplication.kt
new file mode 100644
index 0000000..ada24db
--- /dev/null
+++ b/composeApp/src/androidMain/kotlin/com/app/academy/notes/NotesAppApplication.kt
@@ -0,0 +1,10 @@
+package app.architect.notes
+
+import android.app.Application
+
+class NotesAppApplication : Application() {
+
+ override fun onCreate() {
+ super.onCreate()
+ }
+}
diff --git a/composeApp/src/commonMain/kotlin/com/app/academy/App.kt b/composeApp/src/commonMain/kotlin/com/app/academy/App.kt
new file mode 100644
index 0000000..ff6da52
--- /dev/null
+++ b/composeApp/src/commonMain/kotlin/com/app/academy/App.kt
@@ -0,0 +1,31 @@
+package com.app.academy
+
+import androidx.compose.animation.AnimatedVisibility
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.isSystemInDarkTheme
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.material.Button
+import androidx.compose.material.MaterialTheme
+import androidx.compose.material.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import app.architect.notes.utils.Greeting
+import com.app.academy.theme.NotesAppTheme
+import kmpnotes.composeapp.generated.resources.Res
+import kmpnotes.composeapp.generated.resources.compose_multiplatform
+import org.jetbrains.compose.resources.painterResource
+import org.jetbrains.compose.ui.tooling.preview.Preview
+
+@Composable
+@Preview
+fun App() {
+ NotesAppTheme {
+ NotesAppNavigation()
+ }
+}
diff --git a/composeApp/src/commonMain/kotlin/App.kt b/composeApp/src/commonMain/kotlin/com/app/academy/DemoScreen.kt
similarity index 83%
rename from composeApp/src/commonMain/kotlin/App.kt
rename to composeApp/src/commonMain/kotlin/com/app/academy/DemoScreen.kt
index 5877753..d496f58 100644
--- a/composeApp/src/commonMain/kotlin/App.kt
+++ b/composeApp/src/commonMain/kotlin/com/app/academy/DemoScreen.kt
@@ -1,10 +1,10 @@
+package com.app.academy
+
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.Image
-import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material.Button
-import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
@@ -14,21 +14,18 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import app.architect.notes.utils.Greeting
+import cafe.adriel.voyager.core.screen.Screen
import kmpnotes.composeapp.generated.resources.Res
import kmpnotes.composeapp.generated.resources.compose_multiplatform
import org.jetbrains.compose.resources.painterResource
-import org.jetbrains.compose.ui.tooling.preview.Preview
-
-@Composable
-@Preview
-fun App() {
- val darkEnabled = isSystemInDarkTheme()
- MaterialTheme() {
+object DemoScreen : Screen {
+ @Composable
+ override fun Content() {
var showContent by remember { mutableStateOf(false) }
Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {
Button(onClick = { showContent = !showContent }) {
- Text("Click me! - $darkEnabled")
+ Text("Click me!")
}
AnimatedVisibility(showContent) {
val greeting = remember { Greeting().greet() }
@@ -43,4 +40,5 @@ fun App() {
}
}
}
+
}
diff --git a/composeApp/src/commonMain/kotlin/com/app/academy/HomeScreen.kt b/composeApp/src/commonMain/kotlin/com/app/academy/HomeScreen.kt
new file mode 100644
index 0000000..9dd6b6e
--- /dev/null
+++ b/composeApp/src/commonMain/kotlin/com/app/academy/HomeScreen.kt
@@ -0,0 +1,21 @@
+package com.app.academy
+
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.material.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import cafe.adriel.voyager.core.screen.Screen
+
+object HomeScreen : Screen {
+ @Composable
+ override fun Content() {
+ Box(
+ modifier = Modifier.fillMaxSize(),
+ contentAlignment = Alignment.Center
+ ) {
+ Text(text = "To be built")
+ }
+ }
+}
diff --git a/composeApp/src/commonMain/kotlin/com/app/academy/NotesNavigation.kt b/composeApp/src/commonMain/kotlin/com/app/academy/NotesNavigation.kt
new file mode 100644
index 0000000..569eea6
--- /dev/null
+++ b/composeApp/src/commonMain/kotlin/com/app/academy/NotesNavigation.kt
@@ -0,0 +1,12 @@
+package com.app.academy
+
+import androidx.compose.runtime.Composable
+import cafe.adriel.voyager.navigator.Navigator
+import cafe.adriel.voyager.transitions.SlideTransition
+
+@Composable
+fun NotesAppNavigation() {
+ Navigator(screen = HomeScreen) {
+ SlideTransition(navigator = it)
+ }
+}
diff --git a/composeApp/src/commonMain/kotlin/com/app/academy/theme/NotesAppTheme.kt b/composeApp/src/commonMain/kotlin/com/app/academy/theme/NotesAppTheme.kt
new file mode 100644
index 0000000..b8500b3
--- /dev/null
+++ b/composeApp/src/commonMain/kotlin/com/app/academy/theme/NotesAppTheme.kt
@@ -0,0 +1,13 @@
+package com.app.academy.theme
+
+import androidx.compose.material.MaterialTheme
+import androidx.compose.runtime.Composable
+
+@Composable
+fun NotesAppTheme(
+ content: @Composable () -> Unit
+) {
+ MaterialTheme(
+ content = content
+ )
+}
diff --git a/composeApp/src/desktopMain/kotlin/main.kt b/composeApp/src/desktopMain/kotlin/main.kt
index 48836f5..b495c5f 100644
--- a/composeApp/src/desktopMain/kotlin/main.kt
+++ b/composeApp/src/desktopMain/kotlin/main.kt
@@ -1,5 +1,6 @@
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.application
+import com.app.academy.App
fun main() = application {
Window(
@@ -8,4 +9,4 @@ fun main() = application {
) {
App()
}
-}
\ No newline at end of file
+}
diff --git a/composeApp/src/iosMain/kotlin/MainViewController.kt b/composeApp/src/iosMain/kotlin/MainViewController.kt
index fa143d4..f3b94c5 100644
--- a/composeApp/src/iosMain/kotlin/MainViewController.kt
+++ b/composeApp/src/iosMain/kotlin/MainViewController.kt
@@ -1,3 +1,4 @@
import androidx.compose.ui.window.ComposeUIViewController
+import com.app.academy.App
-fun MainViewController() = ComposeUIViewController { App() }
\ No newline at end of file
+fun MainViewController() = ComposeUIViewController { App() }
diff --git a/composeApp/src/wasmJsMain/kotlin/main.kt b/composeApp/src/wasmJsMain/kotlin/main.kt
index d2fd60c..b2f0a13 100644
--- a/composeApp/src/wasmJsMain/kotlin/main.kt
+++ b/composeApp/src/wasmJsMain/kotlin/main.kt
@@ -1,5 +1,6 @@
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.window.ComposeViewport
+import com.app.academy.App
import kotlinx.browser.document
@OptIn(ExperimentalComposeUiApi::class)
@@ -7,4 +8,4 @@ fun main() {
ComposeViewport(document.body!!) {
App()
}
-}
\ No newline at end of file
+}
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 5640fcd..14af02e 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -29,7 +29,8 @@ sqlDelight = "2.0.1"
material3Android = "1.2.1"
lifecycleViewmodelCompose = "2.7.0"
material3 = "1.2.1"
-
+kotlinVersion = "2.0.0"
+voyager = "1.0.0"
[libraries]
androidx-core = { module = "androidx.test:core", version.ref = "core" }
@@ -59,6 +60,9 @@ kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-c
native-driver-v200 = { module = "app.cash.sqldelight:native-driver", version.ref = "nativeDriver" }
androidx-lifecycle-viewmodel-compose = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-compose", version.ref = "lifecycleViewmodelCompose" }
runtime-v200 = { module = "app.cash.sqldelight:runtime", version.ref = "runtime" }
+voyager-navigator = { module = "cafe.adriel.voyager:voyager-navigator", version.ref = "voyager" }
+voyager-navigator-transitions = { module = "cafe.adriel.voyager:voyager-transitions", version.ref = "voyager" }
+voyager-screenmodel = { module = "cafe.adriel.voyager:voyager-screenmodel", version.ref = "voyager" }
[plugins]
androidApplication = { id = "com.android.application", version.ref = "agp" }
@@ -70,3 +74,4 @@ ktor = { id = "io.ktor.plugin", version.ref = "ktor" }
kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
kotlinxSerialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
sqldelight = { id = "app.cash.sqldelight", version.ref = "sqlDelight" }
+jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlinVersion" }
diff --git a/iosApp/iosApp/ui/home/HomeScreen.swift b/iosApp/iosApp/ui/home/HomeScreen.swift
new file mode 100644
index 0000000..bda93f9
--- /dev/null
+++ b/iosApp/iosApp/ui/home/HomeScreen.swift
@@ -0,0 +1,7 @@
+import Foundation
+import SwiftUI
+import shared
+
+struct HomeScreen : View {
+
+}
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 78efe06..535a1b3 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -30,5 +30,4 @@ dependencyResolutionManagement {
include(":composeApp")
include(":server")
-include(":androidApp")
include(":shared")
diff --git a/shared/src/androidMain/kotlin/app/architect/notes/utils/NativeStateFlow.android.kt b/shared/src/androidMain/kotlin/app/architect/notes/utils/NativeStateFlow.android.kt
new file mode 100644
index 0000000..ec2d70d
--- /dev/null
+++ b/shared/src/androidMain/kotlin/app/architect/notes/utils/NativeStateFlow.android.kt
@@ -0,0 +1,9 @@
+package app.architect.notes.utils
+
+import kotlinx.coroutines.flow.StateFlow
+
+/**
+ * A cross platform implementation of [StateFlow].
+ */
+actual class NativeStateFlow actual constructor(source: StateFlow) :
+ StateFlow by source
diff --git a/shared/src/commonMain/kotlin/app/architect/notes/utils/NativeStateFlow.kt b/shared/src/commonMain/kotlin/app/architect/notes/utils/NativeStateFlow.kt
index 1808fb3..4c05dbd 100644
--- a/shared/src/commonMain/kotlin/app/architect/notes/utils/NativeStateFlow.kt
+++ b/shared/src/commonMain/kotlin/app/architect/notes/utils/NativeStateFlow.kt
@@ -1,6 +1,5 @@
-package com.example.notes.utils
+package app.architect.notes.utils
-import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
/**
@@ -11,4 +10,4 @@ expect class NativeStateFlow(source: StateFlow) : StateFlow
/**
* Used to convert a [StateFlow] to a [NativeStateFlow]
*/
-fun StateFlow.asNativeStateFlow() = NativeStateFlow(this)
\ No newline at end of file
+fun StateFlow.asNativeStateFlow() = NativeStateFlow(this)
diff --git a/shared/src/iosMain/kotlin/app/architect/notes/utils/NativeStateFlow.ios.kt b/shared/src/iosMain/kotlin/app/architect/notes/utils/NativeStateFlow.ios.kt
new file mode 100644
index 0000000..c1eb2fd
--- /dev/null
+++ b/shared/src/iosMain/kotlin/app/architect/notes/utils/NativeStateFlow.ios.kt
@@ -0,0 +1,21 @@
+package app.architect.notes.utils
+
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.DisposableHandle
+import kotlinx.coroutines.MainScope
+import kotlinx.coroutines.cancel
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.launch
+
+/**
+ * A cross platform implementation of [StateFlow].
+ */
+actual class NativeStateFlow actual constructor(source: StateFlow) : StateFlow by source {
+
+ fun subscribe(onCollect: (T) -> Unit): DisposableHandle {
+ val scope = MainScope().apply {
+ launch(Dispatchers.Main) { collect(onCollect) }
+ }
+ return DisposableHandle { scope.cancel() }
+ }
+}