simple navigation with Voyager

This commit is contained in:
2024-08-05 02:11:03 +03:00
parent bf6b55aab9
commit 471af18f5e
15 changed files with 190 additions and 90 deletions
+1 -1
View File
@@ -62,6 +62,7 @@ kotlin {
implementation(libs.coil.network.ktor)
implementation(libs.kotlinx.coroutines.core)
implementation(libs.ktor.core)
implementation(libs.ktor.client.cio)
implementation(libs.kotlinx.serialization.json)
implementation(libs.multiplatformSettings)
implementation(libs.koin.core)
@@ -94,7 +95,6 @@ kotlin {
iosMain.dependencies {
implementation(libs.ktor.client.darwin)
}
}
}
@@ -1,78 +1,19 @@
package dev.meloda.overseerr
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import dev.meloda.overseerr.model.Platform
import cafe.adriel.voyager.navigator.Navigator
import dev.meloda.overseerr.screens.url.presentation.UrlScreen
import dev.meloda.overseerr.theme.AppTheme
import org.koin.compose.KoinContext
import org.koin.compose.koinInject
@OptIn(ExperimentalMaterial3Api::class)
@Composable
internal fun App() = KoinContext {
val platform: Platform = koinInject()
AppTheme {
var loginValue by rememberSaveable {
mutableStateOf("")
}
var passwordValue by rememberSaveable {
mutableStateOf("")
}
Scaffold(
topBar = {
TopAppBar(
title = {
Text(text = "Log in")
}
)
Text(
text = "Current platform: ${platform.name}",
style = MaterialTheme.typography.displayLarge
)
}
) { padding ->
Column(
modifier = Modifier.fillMaxSize()
.padding(padding),
horizontalAlignment = Alignment.CenterHorizontally
) {
TextField(
modifier = Modifier.fillMaxWidth(0.9f),
value = loginValue,
onValueChange = { newText -> loginValue = newText },
placeholder = { Text(text = "Login") }
)
Spacer(modifier = Modifier.height(16.dp))
TextField(
modifier = Modifier.fillMaxWidth(0.9f),
value = passwordValue,
onValueChange = { newText -> passwordValue = newText },
placeholder = { Text(text = "Password") }
)
Spacer(modifier = Modifier.height(16.dp))
Button(
onClick = {
}
) {
Text(text = "Authorize")
}
}
Surface(modifier = Modifier.fillMaxSize()) {
Navigator(UrlScreen())
}
}
}
@@ -0,0 +1,18 @@
package dev.meloda.overseerr.di
import dev.meloda.overseerr.model.Platform
import dev.meloda.overseerr.network.di.networkModule
import dev.meloda.overseerr.screens.login.di.loginModule
import dev.meloda.overseerr.screens.url.di.urlModule
import org.koin.core.module.dsl.singleOf
import org.koin.dsl.module
val appModule = module {
singleOf(::Platform)
includes(
networkModule,
loginModule,
urlModule
)
}
@@ -1,9 +0,0 @@
package dev.meloda.overseerr.di
import dev.meloda.overseerr.model.Platform
import org.koin.core.module.dsl.singleOf
import org.koin.dsl.module
val appModule = module {
singleOf(::Platform)
}
@@ -1,4 +0,0 @@
package dev.meloda.overseerr.login.model
class LoginScreenState {
}
@@ -1,10 +0,0 @@
package dev.meloda.overseerr.login.presentation
import androidx.compose.runtime.Composable
import dev.icerock.moko.mvvm.compose.getViewModel
import dev.meloda.overseerr.login.LoginViewModel
@Composable
fun LoginScreen(viewModel: LoginViewModel) {
}
@@ -0,0 +1,13 @@
package dev.meloda.overseerr.network.di
import io.ktor.client.*
import io.ktor.client.engine.cio.*
import org.koin.dsl.module
val networkModule = module {
single {
HttpClient(CIO) {
}
}
}
@@ -1,4 +1,4 @@
package dev.meloda.overseerr.login
package dev.meloda.overseerr.screens.login
import dev.icerock.moko.mvvm.viewmodel.ViewModel
@@ -0,0 +1,9 @@
package dev.meloda.overseerr.screens.login.di
import dev.icerock.moko.mvvm.compose.viewModelFactory
import dev.meloda.overseerr.screens.login.LoginViewModel
import org.koin.dsl.module
val loginModule = module {
viewModelFactory(::LoginViewModel)
}
@@ -0,0 +1,4 @@
package dev.meloda.overseerr.screens.login.model
class LoginScreenState {
}
@@ -0,0 +1,87 @@
package dev.meloda.overseerr.screens.login.presentation
import androidx.compose.foundation.layout.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.rounded.ArrowBack
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import cafe.adriel.voyager.core.screen.Screen
import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.currentOrThrow
class LoginScreen : Screen {
@OptIn(ExperimentalMaterial3Api::class)
@Composable
override fun Content() {
val navigator = LocalNavigator.currentOrThrow
var loginValue by rememberSaveable {
mutableStateOf("")
}
var passwordValue by rememberSaveable {
mutableStateOf("")
}
Scaffold(
topBar = {
TopAppBar(
title = {
Text(text = "Log in")
},
navigationIcon = {
IconButton(
onClick = navigator::pop
) {
Icon(
imageVector = Icons.AutoMirrored.Rounded.ArrowBack,
contentDescription = null
)
}
}
)
}
) { padding ->
Column(
modifier = Modifier.fillMaxSize()
.padding(padding),
horizontalAlignment = Alignment.CenterHorizontally
) {
TextField(
modifier = Modifier.fillMaxWidth(0.9f),
value = loginValue,
onValueChange = { newText -> loginValue = newText },
placeholder = { Text(text = "Login") }
)
Spacer(modifier = Modifier.height(16.dp))
TextField(
modifier = Modifier.fillMaxWidth(0.9f),
value = passwordValue,
onValueChange = { newText -> passwordValue = newText },
placeholder = { Text(text = "Password") }
)
Spacer(modifier = Modifier.height(16.dp))
Button(
onClick = {
}
) {
Text(text = "Authorize")
}
}
}
}
}
@@ -0,0 +1,6 @@
package dev.meloda.overseerr.screens.url
import dev.icerock.moko.mvvm.viewmodel.ViewModel
class UrlViewModel : ViewModel() {
}
@@ -0,0 +1,11 @@
package dev.meloda.overseerr.screens.url.di
import dev.icerock.moko.mvvm.compose.viewModelFactory
import dev.meloda.overseerr.screens.url.UrlViewModel
import org.koin.dsl.module
val urlModule = module {
viewModelFactory {
UrlViewModel()
}
}
@@ -0,0 +1,33 @@
package dev.meloda.overseerr.screens.url.presentation
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Button
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import cafe.adriel.voyager.core.screen.Screen
import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.currentOrThrow
import dev.meloda.overseerr.screens.login.presentation.LoginScreen
class UrlScreen : Screen {
@Composable
override fun Content() {
val navigator = LocalNavigator.currentOrThrow
Scaffold(modifier = Modifier.fillMaxSize()) {
Column(modifier = Modifier.fillMaxSize()) {
Text(text = "Input url screen")
Button(
onClick = {
navigator.push(LoginScreen())
}
) {
Text(text = "Next")
}
}
}
}
}