Sukurk AuthViewModel.kt — prisijungimo ekranas
Kodo stulpelyje — AuthViewModel.kt. Ta pati MVI forma kaip krepšelyje (3 pamoka): nekintanti būsena, vienas onEvent(), _uiState.update { it.copy(...) }. Gudrybė — vienas ekranas atlieka ir prisijungimą, ir registraciją: isLoginMode nusprendžia, kurį serverio metodą kviesti.
MVI kontraktas ir būsena:
sealed interface AuthEvent {
data class EmailChanged(val value: String) : AuthEvent
data class PasswordChanged(val value: String) : AuthEvent
data object Submit : AuthEvent // vienas mygtukas; veiksmą lemia režimas
data object ToggleMode : AuthEvent // login ↔ register
}
data class AuthUiState(
val email: String = "", val password: String = "",
val isLoading: Boolean = false, val error: String? = null,
val isLoggedIn: Boolean = false,
val isLoginMode: Boolean = true // true = Log in, false = Sign up
)
LoginScreen — du OutlinedTextField (email, password su PasswordVisualTransformation), vienas mygtukas (užrašas priklauso nuo režimo) ir LaunchedEffect(state.isLoggedIn), kuris pavykus nuveda toliau:
LaunchedEffect(state.isLoggedIn) {
if (state.isLoggedIn) onLoginSuccess() // → į meniu
}
Kur pradeda programa? StartupViewModel paleidime patikrina žetoną ir nusprendžia pradinį ekraną:
sealed interface StartupState { data object Checking; data object LoggedIn; data object LoggedOut }
// init { if (repository.isLoggedIn()) LoggedIn else LoggedOut }
// nav: Checking → splash; LoggedIn → Screen.Menu; LoggedOut → Screen.Login
Ir Koin (auth modulis; subsetas — be TableSession, kuri ateis 10 pamokoje):
val authModule = module {
single { AuthRepository(get(), get()) } // get() = PicaApi, get() = TokenStorage
viewModel { AuthViewModel(get()) }
viewModel { StartupViewModel(get()) }
}
Patikrink. Paleisk backendą ir programėlę:
1. Pirmas startas → LoggedOut → Login ekranas.
2. „Sign up", įvedi el. paštą + slaptažodį → POST /register → gauni žetoną → meniu.
3. Uždarai ir atidarai programėlę → StartupViewModel randa galiojantį žetoną → iškart meniu (be prisijungimo).
Spąstai (Koin).
AuthRepository(get(), get())antramget()reikiaTokenStorage. JeicoreModule(6 pamoka) jos neregistruoja, programa nulūžta pirmą kartą jungiantis:org.koin.core.error.NoBeanDefFoundException: No definition found for type 'TokenStorage'Sprendimas — pridėk į
coreModule:single<TokenStorage> { SecureTokenStorage(get()) }. Naujas priklausomybes visada užregistruok modulyje, kitaip Koinas nežino, kaip jas pastatyti.