Browse Source

@fun: Data with State

bai 2 years ago
parent
commit
7df48d635d

+ 7 - 0
app/src/main/java/com/ys/bdtp/adm/mvvm/model/Data.kt

@@ -66,3 +66,10 @@ fun <ResultType, RequestType> data(
     emitAll(flow)
 }
 
+/**
+ * Flow<T> 转换为带状态 Flow<Data<T>>
+ */
+fun <T> Flow<T>.toStateFlow(): Flow<Data<T>> = flow {
+    emit(Data.loading())
+    emitAll(this@toStateFlow.map { Data.success(it) })
+}

+ 16 - 3
app/src/main/java/com/ys/bdtp/adm/mvvm/ui/screen/login/LoginContent.kt

@@ -18,15 +18,16 @@ import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.sp
 import androidx.core.content.edit
 import com.ys.bdtp.adm.R
-import com.ys.bdtp.adm.app.Password
 import com.ys.bdtp.adm.app.Token
 import com.ys.bdtp.adm.app.theme.blueColor
 import com.ys.bdtp.adm.app.theme.grayColor
 import com.ys.bdtp.adm.app.theme.textBlackColor
+import com.ys.bdtp.adm.app.tools.md5
 import com.ys.bdtp.adm.mvvm.model.vo.request.Login
 import com.ys.bdtp.adm.mvvm.ui.screen.main.LocalNavHostController
 import com.ys.bdtp.adm.mvvm.ui.screen.main.loginToProject
 import com.ys.bdtp.adm.mvvm.vm.login.LoginViewModel
+import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.launch
 import org.kodein.di.compose.rememberInstance
 import org.kodein.di.compose.rememberViewModel
@@ -201,8 +202,20 @@ fun LoginContent() {
                     ),
                     success = { token ->
                         sp.edit { putString(Token, token) }
-                        sp.edit { putString(Password, password) }
-                        nav.loginToProject()
+                        vm.requestAccount(
+                            password = password.md5(),
+                            success = {
+                                scope.launch(Dispatchers.Main) {
+                                    nav.loginToProject()
+                                }
+                            },
+                            failure = { fail ->
+                                scope.launch {
+                                    snackbarHostState
+                                        .showSnackbar(message = fail.message)
+                                }
+                            }
+                        )
                     },
                     failure = { fail ->
                         scope.launch {

+ 14 - 0
app/src/main/java/com/ys/bdtp/adm/mvvm/ui/screen/main/Route.kt

@@ -53,3 +53,17 @@ fun NavHostController.loginToProject() {
     }
 
 }
+
+/**
+ * Project  跳转到 Login 界面
+ */
+fun NavHostController.projectToLogin() {
+    navigate(Route.Login) {
+        launchSingleTop = true
+        popUpTo(Route.Project) {
+            inclusive = true
+        }
+    }
+
+}
+

+ 25 - 16
app/src/main/java/com/ys/bdtp/adm/mvvm/ui/screen/project/Project.kt

@@ -2,7 +2,6 @@ package com.ys.bdtp.adm.mvvm.ui.screen.project
 
 import android.content.SharedPreferences
 import android.net.ConnectivityManager
-import android.util.Log
 import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.background
 import androidx.compose.foundation.layout.Column
@@ -16,12 +15,13 @@ import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.dp
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.flowWithLifecycle
-import com.ys.bdtp.adm.app.Password
 import com.ys.bdtp.adm.app.theme.underColor
 import com.ys.bdtp.adm.app.tools.isNet
+import com.ys.bdtp.adm.mvvm.model.Data
+import com.ys.bdtp.adm.mvvm.model.State
 import com.ys.bdtp.adm.mvvm.ui.compose.*
 import com.ys.bdtp.adm.mvvm.ui.screen.main.LocalNavHostController
-import com.ys.bdtp.adm.mvvm.ui.screen.main.Route
+import com.ys.bdtp.adm.mvvm.ui.screen.main.projectToLogin
 import com.ys.bdtp.adm.mvvm.vm.project.ProjectViewModel
 import kotlinx.coroutines.launch
 import org.kodein.di.compose.rememberInstance
@@ -45,16 +45,16 @@ fun Project() {
         vm.userWithsProjects.flowWithLifecycle(lifecycleOwner.lifecycle, Lifecycle.State.STARTED)
     }
 
-    val userWithsProjects = userFlowLifecycleAware.collectAsState(null)
+    val dataState = userFlowLifecycleAware.collectAsState(Data.loading())
 
     LaunchedEffect(Unit) {
         // isNet 联网,token 进行网络通信, 发起请求, 更新数据.
         if (isNet(cm)) {
-            val password = sp.getString(Password, "") ?: ""
+            /*val password = sp.getString(Password, "") ?: ""
             vm.requestAccount(password) { fail ->
                 // 不同 code 进行不同操作
                 Log.d("Project", "Project requestAccount fail :${fail}")
-            }
+            }*/
         }
     }
 
@@ -82,11 +82,6 @@ fun Project() {
                         vm.logout()
                     }
                     popupState = false
-                    nav.navigate(Route.Login) {
-                        popUpTo(Route.Project) {
-                            inclusive = true
-                        }
-                    }
                 }
             )
         }
@@ -99,11 +94,25 @@ fun Project() {
                 .background(underColor)
                 .padding(horizontal = 32.dp, vertical = 40.dp)
         ) {
-            val projects = userWithsProjects.value?.projects
-            if (projects.isNullOrEmpty())
-                Blank()
-            else
-                ProjectContent(projects)
+            val userWithProjects = dataState.value
+            when (userWithProjects.state) {
+                is State.Loading -> {
+                    // TODO 给与加载提示
+                }
+                is State.Success -> {
+                    val uwp = userWithProjects.data
+                    if (uwp == null) {
+                        nav.projectToLogin()
+                    } else if (uwp.projects.isEmpty()) {
+                        Blank()
+                    } else {
+                        ProjectContent(uwp.projects)
+                    }
+                }
+                is State.Failure -> {
+                    // TODO 给与失败提示
+                }
+            }
         }
     }
 }

+ 37 - 1
app/src/main/java/com/ys/bdtp/adm/mvvm/vm/login/LoginRepository.kt

@@ -1,15 +1,18 @@
 package com.ys.bdtp.adm.mvvm.vm.login
 
+import android.util.Log
 import com.ys.bdtp.adm.mvvm.model.nt.Response
 import com.ys.bdtp.adm.mvvm.model.db.AdmDatabase
+import com.ys.bdtp.adm.mvvm.model.db.entity.UserEntity
 import com.ys.bdtp.adm.mvvm.model.nt.Api
+import com.ys.bdtp.adm.mvvm.model.nt.Fail
 import com.ys.bdtp.adm.mvvm.model.nt.request
 import com.ys.bdtp.adm.mvvm.model.vo.request.Login
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.withContext
 
 /**
- * Login 存储仓库
+ * LoginRepository
  *
  * @author bai
  *
@@ -27,4 +30,37 @@ class LoginRepository(private val api: Api, private val db: AdmDatabase) {
             }
         }
     }
+
+    /**
+     * 获取账号信息
+     */
+    suspend fun requestAccount(password: String, success: () -> Unit, failure: (Fail) -> Unit) {
+        request(
+            request = { api.getAccount() },
+            success = { account ->
+                val user = UserEntity(
+                    password = password,
+                    state = 1,
+                    id = account.id,
+                    account = account.account,
+                    deptId = account.deptId,
+                    email = account.email,
+                    phone = account.phone,
+                    name = account.name,
+                )
+                val users = db.userDao().getUsers().onEach { u -> u.state = 0 }.toMutableList()
+                users.add(user)
+                db.userDao().insUsers(users)
+                account.projects.forEach { it.userId = user.id }
+                db.projectDao().insProjects(account.projects)
+                success()
+                Log.d("requestAccount", "login requestAccount success")
+            },
+            failure = { fail ->
+                failure(fail)
+                Log.d("requestAccount", "login requestAccount failure : $fail")
+            }
+        )
+    }
+
 }

+ 10 - 0
app/src/main/java/com/ys/bdtp/adm/mvvm/vm/login/LoginViewModel.kt

@@ -33,4 +33,14 @@ class LoginViewModel(private val repo: LoginRepository) : ViewModel() {
             }
         }
     }
+
+
+    /**
+     * 获取账号信息
+     */
+    fun requestAccount(password: String, success: () -> Unit, failure: (Fail) -> Unit) {
+        viewModelScope.launch {
+            repo.requestAccount(password, success, failure)
+        }
+    }
 }

+ 10 - 6
app/src/main/java/com/ys/bdtp/adm/mvvm/vm/project/ProjectRepository.kt

@@ -1,14 +1,17 @@
 package com.ys.bdtp.adm.mvvm.vm.project
 
 import android.util.Log
+import com.ys.bdtp.adm.mvvm.model.Data
 import com.ys.bdtp.adm.mvvm.model.db.AdmDatabase
 import com.ys.bdtp.adm.mvvm.model.db.entity.UserEntity
 import com.ys.bdtp.adm.mvvm.model.db.entity.relation.UserWithProjects
 import com.ys.bdtp.adm.mvvm.model.nt.Api
 import com.ys.bdtp.adm.mvvm.model.nt.Fail
 import com.ys.bdtp.adm.mvvm.model.nt.request
+import com.ys.bdtp.adm.mvvm.model.toStateFlow
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.collect
 import kotlinx.coroutines.withContext
 
 /**
@@ -53,16 +56,17 @@ class ProjectRepository(private val api: Api, private val db: AdmDatabase) {
     /**
      *  获取用户以及用户项目
      */
-    fun getUserWithProjects(): Flow<UserWithProjects> {
-        return db.userDao().getUserWithProjects()
+    fun getUserWithProjects(): Flow<Data<UserWithProjects>> {
+        return db.userDao().getUserWithProjects().toStateFlow()
     }
 
     suspend fun logout() {
         withContext(Dispatchers.IO) {
-            val user = db.userDao().currentUser()
-            if (user != null) {
-                user.state = 0
-                db.userDao().updUser(user)
+            db.userDao().getUser().collect {
+                it?.let {
+                    it.state = 0
+                    db.userDao().updUser(it)
+                }
             }
         }
     }

+ 2 - 1
app/src/main/java/com/ys/bdtp/adm/mvvm/vm/project/ProjectViewModel.kt

@@ -2,6 +2,7 @@ package com.ys.bdtp.adm.mvvm.vm.project
 
 import androidx.lifecycle.ViewModel
 import androidx.lifecycle.viewModelScope
+import com.ys.bdtp.adm.mvvm.model.Data
 import com.ys.bdtp.adm.mvvm.model.nt.Fail
 import kotlinx.coroutines.flow.SharingStarted.Companion.WhileSubscribed
 import kotlinx.coroutines.flow.stateIn
@@ -22,7 +23,7 @@ class ProjectViewModel(private val repo: ProjectRepository) : ViewModel() {
     val userWithsProjects = repo.getUserWithProjects().stateIn(
         scope = viewModelScope,
         started = WhileSubscribed(5000),
-        initialValue = null
+        initialValue = Data.loading()
     )
 
     /**