From 655e8424e5316aab7625377001dacae887642f0f Mon Sep 17 00:00:00 2001 From: michael Date: Mon, 24 Apr 2023 19:58:46 +0300 Subject: [PATCH] =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=20=D1=81=D0=BF=D0=BE=D1=81=D0=BE=D0=B1=20=D0=B8=D0=BD?= =?UTF-8?q?=D0=B6=D0=B5=D0=BA=D1=82=D0=B0=20=D0=B2=20ViewModel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/ru/megboyzz/dnevnik/MainActivity.kt | 5 ++ .../authorization/AuthorizationStatus.kt | 3 +- .../ru/megboyzz/dnevnik/di/AppComponent.kt | 12 +++-- .../dnevnik/di/modules/DatabaseModule.kt | 4 +- .../megboyzz/dnevnik/navigation/AppNavHost.kt | 18 ++++--- .../megboyzz/dnevnik/screens/LoginScreen.kt | 24 ++++++---- .../dnevnik/screens/ui/main/Drawer.kt | 48 ++++++++++--------- .../megboyzz/dnevnik/service/MarksService.kt | 8 ++++ .../viewmodel/AuthorizationViewModel.kt | 25 +++++----- .../dnevnik/viewmodel/ProfileViewModel.kt | 20 ++------ .../viewmodel/core/ViewModelFactory.kt | 8 +--- .../viewmodel/subscreen/LastMarksViewModel.kt | 16 ++++--- 12 files changed, 107 insertions(+), 84 deletions(-) create mode 100644 app/src/main/java/ru/megboyzz/dnevnik/service/MarksService.kt diff --git a/app/src/main/java/ru/megboyzz/dnevnik/MainActivity.kt b/app/src/main/java/ru/megboyzz/dnevnik/MainActivity.kt index 773aa47..61cfeda 100644 --- a/app/src/main/java/ru/megboyzz/dnevnik/MainActivity.kt +++ b/app/src/main/java/ru/megboyzz/dnevnik/MainActivity.kt @@ -3,13 +3,17 @@ package ru.megboyzz.dnevnik import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent +import androidx.activity.viewModels import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material.Surface import androidx.compose.ui.Modifier +import androidx.lifecycle.ViewModel import ru.megboyzz.dnevnik.db.dao.CredentialsDao import ru.megboyzz.dnevnik.db.dao.GlobalUserContextDao import ru.megboyzz.dnevnik.navigation.AppNavHost import ru.megboyzz.dnevnik.ui.theme.lightGray +import ru.megboyzz.dnevnik.viewmodel.AuthorizationViewModel +import ru.megboyzz.dnevnik.viewmodel.core.ViewModelFactory import javax.inject.Inject import kotlin.concurrent.thread @@ -27,6 +31,7 @@ class MainActivity : ComponentActivity() { super.onCreate(savedInstanceState) this.app = application as App app.appComponent.inject(this) + setContent { Surface( diff --git a/app/src/main/java/ru/megboyzz/dnevnik/authorization/AuthorizationStatus.kt b/app/src/main/java/ru/megboyzz/dnevnik/authorization/AuthorizationStatus.kt index 60591fd..e3e72f6 100644 --- a/app/src/main/java/ru/megboyzz/dnevnik/authorization/AuthorizationStatus.kt +++ b/app/src/main/java/ru/megboyzz/dnevnik/authorization/AuthorizationStatus.kt @@ -9,6 +9,7 @@ enum class AuthorizationStatus { MAINTAIN, CREDENTIALS_LOADING, NOTHING, - UNKNOWN_ERROR + UNKNOWN_ERROR, + LOGOUT } \ No newline at end of file diff --git a/app/src/main/java/ru/megboyzz/dnevnik/di/AppComponent.kt b/app/src/main/java/ru/megboyzz/dnevnik/di/AppComponent.kt index 607f351..2bfd2c3 100644 --- a/app/src/main/java/ru/megboyzz/dnevnik/di/AppComponent.kt +++ b/app/src/main/java/ru/megboyzz/dnevnik/di/AppComponent.kt @@ -10,6 +10,7 @@ import ru.megboyzz.dnevnik.authorization.AuthorizationManager import ru.megboyzz.dnevnik.db.dao.CredentialsDao import ru.megboyzz.dnevnik.db.dao.GlobalUserContextDao import ru.megboyzz.dnevnik.di.modules.AppModule +import ru.megboyzz.dnevnik.entities.db.Credentials import ru.megboyzz.dnevnik.viewmodel.AuthorizationViewModel import ru.megboyzz.dnevnik.viewmodel.ProfileViewModel import javax.inject.Singleton @@ -19,13 +20,16 @@ import javax.inject.Singleton @Component(modules = [AppModule::class]) interface AppComponent { - fun inject(viewModel: AuthorizationViewModel) + val authViewModel: AuthorizationViewModel + + val profileViewModel: ProfileViewModel + + val credentialsDao: CredentialsDao + + val globalUserContextDao: GlobalUserContextDao fun inject(viewModel: ProfileViewModel) fun inject(activity: MainActivity) - fun getCredentialsDao(): CredentialsDao - fun getGlobalUserContextDao(): GlobalUserContextDao - @Component.Builder interface Builder { fun appModule(appModule: AppModule): Builder // add this diff --git a/app/src/main/java/ru/megboyzz/dnevnik/di/modules/DatabaseModule.kt b/app/src/main/java/ru/megboyzz/dnevnik/di/modules/DatabaseModule.kt index 5e3de5d..dc16859 100644 --- a/app/src/main/java/ru/megboyzz/dnevnik/di/modules/DatabaseModule.kt +++ b/app/src/main/java/ru/megboyzz/dnevnik/di/modules/DatabaseModule.kt @@ -4,10 +4,13 @@ import android.content.Context import androidx.room.Room import dagger.Module import dagger.Provides +import kotlinx.coroutines.coroutineScope import ru.megboyzz.dnevnik.db.AppDataBase import ru.megboyzz.dnevnik.db.dao.CredentialsDao import ru.megboyzz.dnevnik.db.dao.GlobalUserContextDao +import ru.megboyzz.dnevnik.entities.db.Credentials import javax.inject.Singleton +import kotlin.coroutines.coroutineContext @Module class DatabaseModule { @@ -27,5 +30,4 @@ class DatabaseModule { @Provides fun provideGlobalUserContextDao(dataBase: AppDataBase): GlobalUserContextDao = dataBase.globalUserContextDao() - } \ No newline at end of file diff --git a/app/src/main/java/ru/megboyzz/dnevnik/navigation/AppNavHost.kt b/app/src/main/java/ru/megboyzz/dnevnik/navigation/AppNavHost.kt index 6d81459..1850866 100644 --- a/app/src/main/java/ru/megboyzz/dnevnik/navigation/AppNavHost.kt +++ b/app/src/main/java/ru/megboyzz/dnevnik/navigation/AppNavHost.kt @@ -1,10 +1,10 @@ package ru.megboyzz.dnevnik.navigation +import android.util.Log import androidx.compose.material.CircularProgressIndicator import androidx.compose.material.rememberScaffoldState import androidx.compose.runtime.Composable import androidx.compose.ui.platform.LocalContext -import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController @@ -14,7 +14,8 @@ import ru.megboyzz.dnevnik.collectAsMutableState import ru.megboyzz.dnevnik.screens.* import ru.megboyzz.dnevnik.viewmodel.AuthorizationViewModel import ru.megboyzz.dnevnik.navigate -import ru.megboyzz.dnevnik.viewmodel.AuthorizationViewModelFactory +import androidx.activity.viewModels +import ru.megboyzz.dnevnik.appComponent import ru.megboyzz.dnevnik.viewmodel.core.ViewModelFactory sealed class BaseNavRote(open val route: String) @@ -33,14 +34,19 @@ sealed class AppNavRoute(override val route: String): BaseNavRote(route){ @Composable fun AppNavHost(){ + Log.i("AppNavHost", "Called") + val scaffoldState = rememberScaffoldState() val navController = rememberNavController() - val app = (LocalContext.current as MainActivity).app + val mainActivity = LocalContext.current as MainActivity - val authorizationViewModel: AuthorizationViewModel = viewModel( - factory = AuthorizationViewModelFactory(app) - ) + val authorizationViewModel: AuthorizationViewModel by mainActivity.viewModels{ + ViewModelFactory{ + Log.i("AuthorizationViewModel", "i am created!") + mainActivity.appComponent.authViewModel + } + } val loginStatus = authorizationViewModel.loginStatus.collectAsMutableState() diff --git a/app/src/main/java/ru/megboyzz/dnevnik/screens/LoginScreen.kt b/app/src/main/java/ru/megboyzz/dnevnik/screens/LoginScreen.kt index 54164c9..9fd1d44 100644 --- a/app/src/main/java/ru/megboyzz/dnevnik/screens/LoginScreen.kt +++ b/app/src/main/java/ru/megboyzz/dnevnik/screens/LoginScreen.kt @@ -1,8 +1,9 @@ package ru.megboyzz.dnevnik.screens +import android.util.Log +import androidx.activity.viewModels import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.material.Button import androidx.compose.material.CircularProgressIndicator @@ -10,10 +11,8 @@ import androidx.compose.material.Text import androidx.compose.runtime.* import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp -import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavController import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.launch import ru.megboyzz.dnevnik.MainActivity import ru.megboyzz.dnevnik.appComponent @@ -24,14 +23,21 @@ import ru.megboyzz.dnevnik.navigation.AppNavRoute import ru.megboyzz.dnevnik.screens.ui.AlertMessageBox import ru.megboyzz.dnevnik.screens.ui.LoginScreenContent import ru.megboyzz.dnevnik.viewmodel.AuthorizationViewModel +import ru.megboyzz.dnevnik.viewmodel.core.ViewModelFactory //TODO Переверстать экран входа @Composable fun LoginScreen(navController: NavController) { - val context = LocalContext.current + Log.i("LoginScreen", "Called") - val authorizationViewModel: AuthorizationViewModel = viewModel() + val activity = LocalContext.current as MainActivity + + val authorizationViewModel: AuthorizationViewModel by activity.viewModels { + ViewModelFactory{ + activity.appComponent.authViewModel + } + } val login = authorizationViewModel.login.collectAsMutableState() @@ -67,8 +73,10 @@ fun LoginScreen(navController: NavController) { ) } - if(loginStatus.value == AuthorizationStatus.LOGGED) + if(loginStatus.value == AuthorizationStatus.LOGGED) { + Log.i("loginStatus", "logged") navController.navigate(AppNavRoute.Marks) + } Box(){ LoginScreenContent( @@ -109,8 +117,8 @@ fun LoginScreen(navController: NavController) { val scope = rememberCoroutineScope() var isRemoving by remember{ mutableStateOf(false) } Button(onClick = { - val globalUserContextDao = context.appComponent.getGlobalUserContextDao() - val credentialsDao = context.appComponent.getCredentialsDao() + val globalUserContextDao = activity.appComponent.globalUserContextDao + val credentialsDao = activity.appComponent.credentialsDao scope.launch(Dispatchers.IO) { isRemoving = true globalUserContextDao.deleteGlobalUserContext() diff --git a/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/main/Drawer.kt b/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/main/Drawer.kt index 458d42b..a221e20 100644 --- a/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/main/Drawer.kt +++ b/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/main/Drawer.kt @@ -1,6 +1,7 @@ package ru.megboyzz.dnevnik.screens.ui.main -import android.annotation.SuppressLint +import android.util.Log +import androidx.activity.viewModels import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.layout.* @@ -11,20 +12,9 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.shadow -import androidx.compose.ui.geometry.CornerRadius -import androidx.compose.ui.geometry.Rect -import androidx.compose.ui.geometry.RoundRect -import androidx.compose.ui.geometry.Size import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.ImageBitmap -import androidx.compose.ui.graphics.Outline -import androidx.compose.ui.graphics.Shape -import androidx.compose.ui.graphics.painter.BitmapPainter import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.imageResource -import androidx.compose.ui.unit.Density -import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.dp import androidx.compose.ui.zIndex import androidx.lifecycle.viewmodel.compose.viewModel @@ -38,12 +28,11 @@ import ru.megboyzz.dnevnik.screens.ui.AlmostOutlinedText import ru.megboyzz.dnevnik.screens.ui.LeaveAlert import ru.megboyzz.dnevnik.screens.ui.ProfileCard import ru.megboyzz.dnevnik.ui.theme.H2 -import ru.megboyzz.dnevnik.ui.theme.Shapes import ru.megboyzz.dnevnik.ui.theme.mainBlue import ru.megboyzz.dnevnik.ui.theme.white +import ru.megboyzz.dnevnik.viewmodel.AuthorizationViewModel import ru.megboyzz.dnevnik.viewmodel.ProfileViewModel -import ru.megboyzz.dnevnik.viewmodel.ProfileViewModelFactory -import ru.megboyzz.dnevnik.viewmodel.model.UserProfileModel +import ru.megboyzz.dnevnik.viewmodel.core.ViewModelFactory @Composable @@ -83,15 +72,27 @@ fun DrawerContent( scaffoldState: ScaffoldState ) { - val app = (LocalContext.current as MainActivity).app + Log.i("DrawerContent", "Called") - val profileViewModel: ProfileViewModel = viewModel( - factory = ProfileViewModelFactory(app) - ) + val activity = LocalContext.current as MainActivity + + val profileViewModel: ProfileViewModel by activity.viewModels{ + ViewModelFactory{ + activity.appComponent.profileViewModel + } + } + + val authorizationViewModel: AuthorizationViewModel by activity.viewModels { + ViewModelFactory{ + activity.appComponent.authViewModel + } + } val profile = profileViewModel.profile.collectAsState() - val dao = LocalContext.current.appComponent.getCredentialsDao() + val credentialsDao = activity.appComponent.credentialsDao + val globalUserContextDao = activity.appComponent.globalUserContextDao + var leaveAlertIsOpened by remember { @@ -110,11 +111,12 @@ fun DrawerContent( onAgree = { scope.launch(Dispatchers.IO) { isLeavingProcess = true - dao.deleteCredentials() + credentialsDao.deleteCredentials() + globalUserContextDao.deleteGlobalUserContext() leaveAlertIsOpened = false - this.launch(Dispatchers.Main) { navController.navigate(AppNavRoute.Login) } - scaffoldState.drawerState.close() } + authorizationViewModel.resetAuth() + navController.navigate(AppNavRoute.Login) }, onCancel = { leaveAlertIsOpened = false } ) diff --git a/app/src/main/java/ru/megboyzz/dnevnik/service/MarksService.kt b/app/src/main/java/ru/megboyzz/dnevnik/service/MarksService.kt new file mode 100644 index 0000000..a2687f4 --- /dev/null +++ b/app/src/main/java/ru/megboyzz/dnevnik/service/MarksService.kt @@ -0,0 +1,8 @@ +package ru.megboyzz.dnevnik.service + +//Сервис для последних оценок +interface MarksService { + + + +} \ No newline at end of file diff --git a/app/src/main/java/ru/megboyzz/dnevnik/viewmodel/AuthorizationViewModel.kt b/app/src/main/java/ru/megboyzz/dnevnik/viewmodel/AuthorizationViewModel.kt index 2e2b7cb..49a3110 100644 --- a/app/src/main/java/ru/megboyzz/dnevnik/viewmodel/AuthorizationViewModel.kt +++ b/app/src/main/java/ru/megboyzz/dnevnik/viewmodel/AuthorizationViewModel.kt @@ -14,19 +14,18 @@ import ru.megboyzz.dnevnik.authorization.AuthorizationStatus import java.lang.IllegalArgumentException import javax.inject.Inject -class AuthorizationViewModel(val application: App): AndroidViewModel(application) { +class AuthorizationViewModel @Inject constructor( + private val authManager: AuthorizationManager +): ViewModel() { val login = MutableStateFlow("") val password = MutableStateFlow("") val rememberMe = MutableStateFlow(false) - @Inject - lateinit var authManager: AuthorizationManager - val loginStatus = MutableStateFlow(AuthorizationStatus.CREDENTIALS_LOADING) init { - application.appComponent.inject(this) + Log.i("AuthorizationViewModel", "AuthorizationViewModel in constructor") viewModelScope.launch(Dispatchers.IO) { loginStatus.emit(authManager.checkCredentials()) } @@ -45,14 +44,12 @@ class AuthorizationViewModel(val application: App): AndroidViewModel(application } -} - -class AuthorizationViewModelFactory(private val application: App) : ViewModelProvider.Factory { - - override fun create(modelClass: Class): T { - if (modelClass.isAssignableFrom(AuthorizationViewModel::class.java)) - return AuthorizationViewModel(application) as T - throw IllegalArgumentException("Unknown ViewModel Class") + fun resetAuth(){ + viewModelScope.launch(Dispatchers.IO) { + loginStatus.emit(AuthorizationStatus.LOGOUT) + login.emit("") + password.emit("") + } } -} \ No newline at end of file +} diff --git a/app/src/main/java/ru/megboyzz/dnevnik/viewmodel/ProfileViewModel.kt b/app/src/main/java/ru/megboyzz/dnevnik/viewmodel/ProfileViewModel.kt index 485fee9..2787248 100644 --- a/app/src/main/java/ru/megboyzz/dnevnik/viewmodel/ProfileViewModel.kt +++ b/app/src/main/java/ru/megboyzz/dnevnik/viewmodel/ProfileViewModel.kt @@ -1,5 +1,6 @@ package ru.megboyzz.dnevnik.viewmodel +import android.util.Log import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider @@ -16,15 +17,14 @@ import ru.megboyzz.dnevnik.viewmodel.model.UserProfileModel import java.lang.IllegalArgumentException import javax.inject.Inject -class ProfileViewModel(val application: App) : AndroidViewModel(application) { +class ProfileViewModel @Inject constructor( + val userContextDao: GlobalUserContextDao +) : ViewModel() { val profile = MutableStateFlow(null) - @Inject - lateinit var userContextDao: GlobalUserContextDao - init{ - application.appComponent.inject(this) + Log.i("ProfileViewModel", "i am created!") viewModelScope.launch(Dispatchers.IO) { val globalUserContext = userContextDao.getGlobalUserContext() val convertedProfile = convertGlobalUserContextToProfile(globalUserContext) @@ -56,14 +56,4 @@ class ProfileViewModel(val application: App) : AndroidViewModel(application) { ) } -} - -class ProfileViewModelFactory(private val application: App) : ViewModelProvider.Factory { - - override fun create(modelClass: Class): T { - if (modelClass.isAssignableFrom(ProfileViewModel::class.java)) - return ProfileViewModel(application) as T - throw IllegalArgumentException("Unknown ViewModel Class") - } - } \ No newline at end of file diff --git a/app/src/main/java/ru/megboyzz/dnevnik/viewmodel/core/ViewModelFactory.kt b/app/src/main/java/ru/megboyzz/dnevnik/viewmodel/core/ViewModelFactory.kt index f8bf27c..ef58f75 100644 --- a/app/src/main/java/ru/megboyzz/dnevnik/viewmodel/core/ViewModelFactory.kt +++ b/app/src/main/java/ru/megboyzz/dnevnik/viewmodel/core/ViewModelFactory.kt @@ -5,10 +5,6 @@ import androidx.lifecycle.ViewModelProvider import ru.megboyzz.dnevnik.App import java.lang.IllegalArgumentException -class ViewModelFactory(private val application: App): ViewModelProvider.Factory { - override fun create(modelClass: Class): T { - if (modelClass.isAssignableFrom(ViewModel::class.java)) - return modelClass.getConstructor().newInstance(application) - throw IllegalArgumentException("Unknown ViewModel Class") - } +class ViewModelFactory(private val create: () -> T) : ViewModelProvider.Factory { + override fun create(modelClass: Class): T = create.invoke() as T } \ No newline at end of file diff --git a/app/src/main/java/ru/megboyzz/dnevnik/viewmodel/subscreen/LastMarksViewModel.kt b/app/src/main/java/ru/megboyzz/dnevnik/viewmodel/subscreen/LastMarksViewModel.kt index 9445f8a..43b761f 100644 --- a/app/src/main/java/ru/megboyzz/dnevnik/viewmodel/subscreen/LastMarksViewModel.kt +++ b/app/src/main/java/ru/megboyzz/dnevnik/viewmodel/subscreen/LastMarksViewModel.kt @@ -1,18 +1,20 @@ package ru.megboyzz.dnevnik.viewmodel.subscreen -import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.ViewModel -import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.viewModelScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.launch -import ru.megboyzz.dnevnik.App +import ru.megboyzz.dnevnik.db.dao.CredentialsDao +import ru.megboyzz.dnevnik.db.dao.GlobalUserContextDao import ru.megboyzz.dnevnik.entities.response.UserContext import ru.megboyzz.dnevnik.screens.subscreens.viewmodel.model.MarkModel -import java.lang.IllegalArgumentException +import javax.inject.Inject -class LastMarksViewModel(apiUserContext: UserContext): ViewModel() { +class LastMarksViewModel @Inject constructor( + globalUserContextDao: GlobalUserContextDao, + credentialsDao: CredentialsDao +): ViewModel() { val lastMarksList = MutableStateFlow(listOf()) val isLoading = MutableStateFlow(true) @@ -20,9 +22,11 @@ class LastMarksViewModel(apiUserContext: UserContext): ViewModel() { init{ viewModelScope.launch(Dispatchers.IO) { - + globalUserContextDao.globalUserContextIsExists() } } + + } \ No newline at end of file