android: add basic screens
This commit is contained in:
@@ -5,6 +5,7 @@ plugins {
|
|||||||
alias(libs.plugins.androidApplication)
|
alias(libs.plugins.androidApplication)
|
||||||
alias(libs.plugins.composeMultiplatform)
|
alias(libs.plugins.composeMultiplatform)
|
||||||
alias(libs.plugins.composeCompiler)
|
alias(libs.plugins.composeCompiler)
|
||||||
|
kotlin("plugin.serialization") version libs.versions.kotlin.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
@@ -18,6 +19,8 @@ kotlin {
|
|||||||
androidMain.dependencies {
|
androidMain.dependencies {
|
||||||
implementation(libs.compose.uiToolingPreview)
|
implementation(libs.compose.uiToolingPreview)
|
||||||
implementation(libs.androidx.activity.compose)
|
implementation(libs.androidx.activity.compose)
|
||||||
|
implementation("androidx.navigation:navigation-compose:2.8.8")
|
||||||
|
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.8.0")
|
||||||
implementation("androidx.datastore:datastore-preferences:1.2.1")
|
implementation("androidx.datastore:datastore-preferences:1.2.1")
|
||||||
implementation("androidx.datastore:datastore-preferences-core:1.2.1")
|
implementation("androidx.datastore:datastore-preferences-core:1.2.1")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,48 +1,83 @@
|
|||||||
package su.reya.coop
|
package su.reya.coop
|
||||||
|
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
import android.content.Context
|
||||||
import androidx.compose.foundation.Image
|
|
||||||
import androidx.compose.foundation.background
|
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.layout.safeContentPadding
|
|
||||||
import androidx.compose.material3.Button
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import org.jetbrains.compose.resources.painterResource
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.datastore.core.DataStore
|
||||||
|
import androidx.datastore.preferences.core.Preferences
|
||||||
|
import androidx.datastore.preferences.core.booleanPreferencesKey
|
||||||
|
import androidx.datastore.preferences.core.edit
|
||||||
|
import androidx.datastore.preferences.preferencesDataStore
|
||||||
|
import androidx.navigation.compose.NavHost
|
||||||
|
import androidx.navigation.compose.composable
|
||||||
|
import androidx.navigation.compose.rememberNavController
|
||||||
|
import androidx.navigation.toRoute
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
import coop.composeapp.generated.resources.Res
|
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "settings")
|
||||||
import coop.composeapp.generated.resources.compose_multiplatform
|
private val FIRST_TIME_KEY = booleanPreferencesKey("first_time")
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@Preview
|
|
||||||
fun App() {
|
fun App() {
|
||||||
MaterialTheme {
|
MaterialTheme {
|
||||||
var showContent by remember { mutableStateOf(false) }
|
val context = LocalContext.current
|
||||||
Column(
|
val scope = rememberCoroutineScope()
|
||||||
modifier = Modifier
|
val navController = rememberNavController()
|
||||||
.background(MaterialTheme.colorScheme.primaryContainer)
|
|
||||||
.safeContentPadding()
|
val isFirstTimeFlow = remember {
|
||||||
.fillMaxSize(),
|
context.dataStore.data.map { preferences ->
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
preferences[FIRST_TIME_KEY] ?: true
|
||||||
) {
|
|
||||||
Button(onClick = { showContent = !showContent }) {
|
|
||||||
Text("Click me!")
|
|
||||||
}
|
}
|
||||||
AnimatedVisibility(showContent) {
|
|
||||||
val greeting = remember { Greeting().greet() }
|
|
||||||
Column(
|
|
||||||
modifier = Modifier.fillMaxWidth(),
|
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
|
||||||
) {
|
|
||||||
Image(painterResource(Res.drawable.compose_multiplatform), null)
|
|
||||||
Text("Compose: $greeting")
|
|
||||||
}
|
}
|
||||||
|
val isFirstTime by isFirstTimeFlow.collectAsState(initial = null)
|
||||||
|
|
||||||
|
if (isFirstTime == null) {
|
||||||
|
// Loading state
|
||||||
|
return@MaterialTheme
|
||||||
|
}
|
||||||
|
|
||||||
|
NavHost(
|
||||||
|
navController = navController,
|
||||||
|
startDestination = if (isFirstTime == true) Screen.Welcome else Screen.Home
|
||||||
|
) {
|
||||||
|
composable<Screen.Welcome> { backStackEntry ->
|
||||||
|
WelcomeScreen(onContinue = {
|
||||||
|
scope.launch {
|
||||||
|
context.dataStore.edit { settings ->
|
||||||
|
settings[FIRST_TIME_KEY] = false
|
||||||
|
}
|
||||||
|
navController.navigate(Screen.Home) {
|
||||||
|
popUpTo<Screen.Welcome> { inclusive = true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
composable<Screen.Home> { backStackEntry ->
|
||||||
|
HomeScreen(
|
||||||
|
onOpenChat = { id -> navController.navigate(Screen.Chat(id)) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
composable<Screen.Chat> { backStackEntry ->
|
||||||
|
val chat: Screen.Chat = backStackEntry.toRoute()
|
||||||
|
ChatScreen(id = chat.id)
|
||||||
|
}
|
||||||
|
composable<Screen.Onboarding> { backStackEntry ->
|
||||||
|
OnboardingScreen(
|
||||||
|
onOpenImport = { navController.navigate(Screen.Import) },
|
||||||
|
onOpenNew = { navController.navigate(Screen.New) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
composable<Screen.Import> { backStackEntry ->
|
||||||
|
ImportScreen()
|
||||||
|
}
|
||||||
|
composable<Screen.New> { backStackEntry ->
|
||||||
|
NewScreen()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ class MainActivity : ComponentActivity() {
|
|||||||
setContent {
|
setContent {
|
||||||
App()
|
App()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
98
composeApp/src/androidMain/kotlin/su/reya/coop/Screens.kt
Normal file
98
composeApp/src/androidMain/kotlin/su/reya/coop/Screens.kt
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
package su.reya.coop
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
sealed interface Screen {
|
||||||
|
@Serializable
|
||||||
|
data object Welcome : Screen
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data object Home : Screen
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class Chat(val id: String) : Screen
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data object Onboarding : Screen
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data object Import : Screen
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data object New : Screen
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun WelcomeScreen(onContinue: () -> Unit) {
|
||||||
|
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||||
|
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||||
|
Text("Welcome Screen")
|
||||||
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
Button(onClick = onContinue) {
|
||||||
|
Text("Get Started")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun HomeScreen(onOpenChat: (String) -> Unit) {
|
||||||
|
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||||
|
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||||
|
Text("Home Screen")
|
||||||
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
Button(onClick = { onOpenChat("123") }) {
|
||||||
|
Text("Open Chat 123")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ChatScreen(id: String) {
|
||||||
|
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||||
|
Text("Chat Screen (ID: $id)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun OnboardingScreen(onOpenImport: () -> Unit, onOpenNew: () -> Unit) {
|
||||||
|
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||||
|
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||||
|
Text("Onboarding Screen")
|
||||||
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
Button(onClick = onOpenImport) {
|
||||||
|
Text("Import")
|
||||||
|
}
|
||||||
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
Button(onClick = onOpenNew) {
|
||||||
|
Text("New")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ImportScreen() {
|
||||||
|
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||||
|
Text("Import Screen")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun NewScreen() {
|
||||||
|
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||||
|
Text("New Screen")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,10 +8,12 @@ androidx-appcompat = "1.7.1"
|
|||||||
androidx-core = "1.18.0"
|
androidx-core = "1.18.0"
|
||||||
androidx-espresso = "3.7.0"
|
androidx-espresso = "3.7.0"
|
||||||
androidx-lifecycle = "2.10.0"
|
androidx-lifecycle = "2.10.0"
|
||||||
|
androidx-navigation = "2.8.8"
|
||||||
androidx-testExt = "1.3.0"
|
androidx-testExt = "1.3.0"
|
||||||
composeMultiplatform = "1.10.3"
|
composeMultiplatform = "1.10.3"
|
||||||
junit = "4.13.2"
|
junit = "4.13.2"
|
||||||
kotlin = "2.3.20"
|
kotlin = "2.3.20"
|
||||||
|
kotlinx-serialization = "1.8.0"
|
||||||
material3 = "1.10.0-alpha05"
|
material3 = "1.10.0-alpha05"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
@@ -23,6 +25,8 @@ androidx-testExt-junit = { module = "androidx.test.ext:junit", version.ref = "an
|
|||||||
androidx-espresso-core = { module = "androidx.test.espresso:espresso-core", version.ref = "androidx-espresso" }
|
androidx-espresso-core = { module = "androidx.test.espresso:espresso-core", version.ref = "androidx-espresso" }
|
||||||
androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "androidx-appcompat" }
|
androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "androidx-appcompat" }
|
||||||
androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activity" }
|
androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activity" }
|
||||||
|
androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "androidx-navigation" }
|
||||||
|
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx-serialization" }
|
||||||
compose-uiTooling = { module = "org.jetbrains.compose.ui:ui-tooling", version.ref = "composeMultiplatform" }
|
compose-uiTooling = { module = "org.jetbrains.compose.ui:ui-tooling", version.ref = "composeMultiplatform" }
|
||||||
androidx-lifecycle-viewmodelCompose = { module = "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "androidx-lifecycle" }
|
androidx-lifecycle-viewmodelCompose = { module = "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "androidx-lifecycle" }
|
||||||
androidx-lifecycle-runtimeCompose = { module = "org.jetbrains.androidx.lifecycle:lifecycle-runtime-compose", version.ref = "androidx-lifecycle" }
|
androidx-lifecycle-runtimeCompose = { module = "org.jetbrains.androidx.lifecycle:lifecycle-runtime-compose", version.ref = "androidx-lifecycle" }
|
||||||
|
|||||||
Reference in New Issue
Block a user