diff --git a/android/app/src/main/java/by/eapp/musicroom/navigation/NavHost.kt b/android/app/src/main/java/by/eapp/musicroom/navigation/NavHost.kt index 1c4ed9e..17f7f2f 100644 --- a/android/app/src/main/java/by/eapp/musicroom/navigation/NavHost.kt +++ b/android/app/src/main/java/by/eapp/musicroom/navigation/NavHost.kt @@ -1,6 +1,7 @@ package by.eapp.musicroom.navigation +import MainScreen import RegistrationScreen import androidx.compose.animation.AnimatedContentTransitionScope import androidx.compose.animation.core.LinearOutSlowInEasing @@ -9,15 +10,32 @@ import androidx.compose.runtime.Composable import androidx.navigation.NavHostController import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable +import by.eapp.musicroom.screens.AuthorizationViewModel @Composable fun NavHostController( navController: NavHostController, ) { + val viewModel = AuthorizationViewModel NavHost( navController = navController, startDestination = Screens.RegistrationScreen.route ) { + + composable( + route = Screens.MainScreen.route, + enterTransition = { + slideIntoContainer( + AnimatedContentTransitionScope.SlideDirection.Left, + animationSpec = tween( + durationMillis = 500, + easing = LinearOutSlowInEasing + ) + ) + } + ) { + MainScreen(navController = navController, viewModel = viewModel) + } composable( route = Screens.RegistrationScreen.route, enterTransition = { diff --git a/android/app/src/main/java/by/eapp/musicroom/navigation/Screens.kt b/android/app/src/main/java/by/eapp/musicroom/navigation/Screens.kt index ffb47ec..3c19eee 100644 --- a/android/app/src/main/java/by/eapp/musicroom/navigation/Screens.kt +++ b/android/app/src/main/java/by/eapp/musicroom/navigation/Screens.kt @@ -6,4 +6,5 @@ sealed class Screens( data object RegistrationScreen: Screens("registration") data object LoginScreen: Screens("login") data object MainScreen: Screens("main") + data object SubmitCode : Screens("submit_code") } \ No newline at end of file diff --git a/android/app/src/main/java/by/eapp/musicroom/screens/AuthorizationViewModel.kt b/android/app/src/main/java/by/eapp/musicroom/screens/AuthorizationViewModel.kt index 2f864ed..560896c 100644 --- a/android/app/src/main/java/by/eapp/musicroom/screens/AuthorizationViewModel.kt +++ b/android/app/src/main/java/by/eapp/musicroom/screens/AuthorizationViewModel.kt @@ -1,6 +1,8 @@ package by.eapp.musicroom.screens +import android.content.Context import android.util.Log +import android.widget.Toast import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import by.eapp.musicroom.data.login.repo.AuthAuthenticator @@ -8,6 +10,7 @@ import by.eapp.musicroom.domain.model.LoginData import by.eapp.musicroom.domain.model.RegistrationData import by.eapp.musicroom.domain.model.SubmitData import by.eapp.musicroom.domain.repo.login.AuthorizationService +import dagger.hilt.android.internal.Contexts.getApplication import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay @@ -75,7 +78,7 @@ class AuthorizationViewModel @Inject constructor( is LoginScreenAction.LoginUser -> loginUser(action.loginData) is LoginScreenAction.RegisterUser -> registerUser(action.registrationData) is LoginScreenAction.SubmitCode -> submitCode(action.submitData) - LoginScreenAction.NavigateToSubmitCode -> TODO() + is LoginScreenAction.ShowError -> showToast(action.text, context = action.context) } } @@ -84,13 +87,38 @@ class AuthorizationViewModel @Inject constructor( const val TAG = "AuthorizationViewModel" } + sealed class Effect(private var isHandled: Boolean = false) { + fun runIfNotHandled(action: (Effect) -> Unit) { + if (!isHandled) { + action(this) + isHandled = true + } + } + + class Exit : Effect(false) + class None : Effect(true) + } + + fun showToast(text: String, context: Context) { + Toast.makeText(getApplication(context), text, Toast.LENGTH_SHORT).show() + } + + fun enableButton( + email: String, + password: String, + repeatPassword: String, + nickname: String, + ): Boolean { + return (email.isNotEmpty() && password.isNotEmpty() && repeatPassword.isNotEmpty() && nickname.isNotEmpty()) + } + } sealed interface LoginScreenAction { - data object NavigateToSubmitCode : LoginScreenAction data class LoginUser(val loginData: LoginData) : LoginScreenAction data class RegisterUser(val registrationData: RegistrationData) : LoginScreenAction data class SubmitCode(val submitData: SubmitData) : LoginScreenAction + data class ShowError(val text: String, val context: Context) : LoginScreenAction } sealed interface LoginScreenState { diff --git a/android/app/src/main/java/by/eapp/musicroom/screens/view/registration/RegistrationScreen.kt b/android/app/src/main/java/by/eapp/musicroom/screens/view/registration/RegistrationScreen.kt index 164e023..42b8e11 100644 --- a/android/app/src/main/java/by/eapp/musicroom/screens/view/registration/RegistrationScreen.kt +++ b/android/app/src/main/java/by/eapp/musicroom/screens/view/registration/RegistrationScreen.kt @@ -7,6 +7,7 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -23,24 +24,52 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.navigation.NavHostController import by.eapp.musicroom.R +import by.eapp.musicroom.domain.model.RegistrationData import by.eapp.musicroom.navigation.Screens +import by.eapp.musicroom.screens.AuthorizationViewModel +import by.eapp.musicroom.screens.LoginScreenAction +import by.eapp.musicroom.screens.LoginScreenState +import by.eapp.musicroom.screens.components.LoadingScreen import by.eapp.musicroom.screens.components.LogInButton import by.eapp.musicroom.screens.components.PasswordTextInputField import by.eapp.musicroom.screens.components.TextInputField +@Composable +fun MainScreen( + navController: NavHostController, + viewModel: AuthorizationViewModel, +) { + val stateUi by viewModel.stateUi.collectAsState() + when (stateUi) { + LoginScreenState.Init -> LoadingScreen() + LoginScreenState.Loading -> LoadingScreen() + LoginScreenState.Success -> RegistrationScreen(navController, viewModel) + is LoginScreenState.Error -> { + viewModel.showToast( + "Error: ${(stateUi as LoginScreenState.Error).error?.message}", + LocalContext.current + ) + } + } +} + @Composable fun RegistrationScreen( - navController: NavHostController + navController: NavHostController, + viewModel: AuthorizationViewModel, ) { var nickname by rememberSaveable { mutableStateOf("") } var email by rememberSaveable { mutableStateOf("") } - var password by remember { mutableStateOf("") } - var repeatPassword by remember { mutableStateOf("") } - var showPassword by remember { mutableStateOf(false) } - var showRepeatPassword by remember { mutableStateOf(false) } + var password by rememberSaveable { mutableStateOf("") } + var repeatPassword by rememberSaveable { mutableStateOf("") } + var showPassword by rememberSaveable { mutableStateOf(false) } + var showRepeatPassword by rememberSaveable { mutableStateOf(false) } + + val state by viewModel.stateUi.collectAsState() + val context = LocalContext.current Column( modifier = Modifier .fillMaxSize() @@ -80,11 +109,13 @@ fun RegistrationScreen( ) //passwords Spacer(modifier = Modifier.height(20.dp)) + Text( text = "Password", modifier = Modifier.padding(bottom = 5.dp), color = Color.White ) + PasswordTextInputField( password = password, onPasswordChange = { password = it }, @@ -94,21 +125,50 @@ fun RegistrationScreen( // Repeat password field Spacer(modifier = Modifier.height(20.dp)) + Text( text = stringResource(R.string.mr_repeat_password), modifier = Modifier.padding(bottom = 5.dp), color = Color.White ) + PasswordTextInputField( password = repeatPassword, onPasswordChange = { repeatPassword = it }, showPassword = showRepeatPassword, onShowPasswordChange = { showRepeatPassword = it } ) + Spacer(modifier = Modifier.height(40.dp)) + LogInButton( - enabled = true, - onClick = {} + enabled = viewModel.enableButton( + nickname = nickname, + email = email, + password = password, + repeatPassword = repeatPassword + ), + onClick = { + if (password == repeatPassword) { + viewModel.dispatch( + LoginScreenAction.RegisterUser( + RegistrationData( + nickname = nickname, + email = email, + password = password + ) + ) + ) + } else { + viewModel.dispatch( + LoginScreenAction.ShowError( + context.getString(R.string.mr_passwords_dont_match), + context + ) + ) + } + + } ) Spacer(modifier = Modifier.height(40.dp)) @@ -144,5 +204,5 @@ fun PasswordTextInputFieldPreview() { @Preview @Composable fun RegistrationScreenPreview() { - RegistrationScreen(navController = NavHostController(context = LocalContext.current)) + // RegistrationScreen(navController = NavHostController(context = LocalContext.current)) } diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index f28625e..5904854 100644 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -9,5 +9,6 @@ nastix123 Repeat password Already have an account? - Подтвердите код + Submit code + Passwords don\'t match \ No newline at end of file