Tema
/
Mobiliosios programėlės KOTLIN
Pamoka 8 / 14 Autentifikacija I: el. paštas ~50 min

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()) antram get() reikia TokenStorage. Jei coreModule (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.