android: add basic screens

This commit is contained in:
2026-04-23 14:42:35 +07:00
parent fc0d6b6057
commit 8c6b70304d
5 changed files with 176 additions and 37 deletions

View File

@@ -1,48 +1,83 @@
package su.reya.coop
import androidx.compose.animation.AnimatedVisibility
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 android.content.Context
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import org.jetbrains.compose.resources.painterResource
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
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
import coop.composeapp.generated.resources.compose_multiplatform
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "settings")
private val FIRST_TIME_KEY = booleanPreferencesKey("first_time")
@Composable
@Preview
fun App() {
MaterialTheme {
var showContent by remember { mutableStateOf(false) }
Column(
modifier = Modifier
.background(MaterialTheme.colorScheme.primaryContainer)
.safeContentPadding()
.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Button(onClick = { showContent = !showContent }) {
Text("Click me!")
val context = LocalContext.current
val scope = rememberCoroutineScope()
val navController = rememberNavController()
val isFirstTimeFlow = remember {
context.dataStore.data.map { preferences ->
preferences[FIRST_TIME_KEY] ?: true
}
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()
}
}
}

View File

@@ -32,7 +32,6 @@ class MainActivity : ComponentActivity() {
setContent {
App()
}
}
}

View 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")
}
}