Переглянути джерело

separate dao in different files by entities
refactoring splash feature - prepare for load additional entities such as measure types

MrOzOn 5 роки тому
батько
коміт
b6995e20d6

+ 7 - 3
app/src/main/java/com/mrozon/healthdiary/data/UserRepositoryImp.kt

@@ -6,16 +6,20 @@ import com.mrozon.core_api.db.HealthDiaryDao
 import com.mrozon.core_api.entity.User
 import com.mrozon.core_api.mapper.UserToUserDbMapper
 import com.mrozon.core_api.security.SecurityTokenService
+import com.mrozon.utils.network.Result
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.firstOrNull
+import kotlinx.coroutines.flow.flow
 import javax.inject.Inject
 
 class UserRepositoryImp @Inject constructor(
-    private val healthDiaryDao: HealthDiaryDao,
+    private val dao: HealthDiaryDao,
     private val mapper: UserToUserDbMapper,
     private val securityTokenService: SecurityTokenService
 ): UserRepository {
 
     override fun getLocalUser(): LiveData<User> {
-        val userDb = healthDiaryDao.getUser()
+        val userDb = dao.getLiveUser()
         return Transformations.map(userDb) {
             mapper.reverseMap(it)
         }
@@ -25,7 +29,7 @@ class UserRepositoryImp @Inject constructor(
         securityTokenService.clearAccessToken()
         val userDb = mapper.map(user)
             userDb?.let {
-                healthDiaryDao.deleteUser(userDb)
+                dao.deleteUser(userDb)
         }
     }
 

+ 15 - 6
app/src/main/java/com/mrozon/healthdiary/presentation/main/MainActivity.kt

@@ -12,15 +12,18 @@ import androidx.lifecycle.Observer
 import androidx.lifecycle.ViewModelProvider
 import androidx.navigation.NavController
 import androidx.navigation.findNavController
+import androidx.navigation.fragment.findNavController
 import androidx.navigation.ui.AppBarConfiguration
 import androidx.navigation.ui.navigateUp
 import androidx.navigation.ui.setupActionBarWithNavController
 import com.google.android.material.navigation.NavigationView
+import com.mrozon.core_api.entity.User
 import com.mrozon.core_api.providers.AppWithFacade
 import com.mrozon.healthdiary.R
 import com.mrozon.healthdiary.databinding.ActivityMainBinding
 import com.mrozon.healthdiary.di.main.MainActivityComponent
 import com.mrozon.utils.base.BaseActivity
+import com.mrozon.utils.network.Result
 import timber.log.Timber
 import javax.inject.Inject
 
@@ -94,13 +97,19 @@ class MainActivity : BaseActivity<ActivityMainBinding>(){
             }
         })
 
+
         viewModel.currentUser.observe(this, Observer { user ->
-            val headerView = binding.navView.getHeaderView(0)
-            val tvUserEmail = headerView.findViewById<TextView>(R.id.tvUserEmail)
-            val tvUserName = headerView.findViewById<TextView>(R.id.tvUserName)
-            val ivLogout = headerView.findViewById<ImageView>(R.id.ivLogout)
+            showUserProfile(user)
+        })
+    }
 
-            if (user == null) {
+    private fun showUserProfile(user: User?) {
+        val headerView = binding.navView.getHeaderView(0)
+        val tvUserEmail = headerView.findViewById<TextView>(R.id.tvUserEmail)
+        val tvUserName = headerView.findViewById<TextView>(R.id.tvUserName)
+        val ivLogout = headerView.findViewById<ImageView>(R.id.ivLogout)
+
+        if (user == null) {
                 Timber.d("user is null")
                 supportActionBar?.hide()
                 drawerLayout.setDrawerLockMode(LOCK_MODE_LOCKED_CLOSED)
@@ -116,8 +125,8 @@ class MainActivity : BaseActivity<ActivityMainBinding>(){
                         drawerLayout.closeDrawer(GravityCompat.START)
                     }
                     viewModel.logoutUser(user)
+                    showUserProfile(null)
                 }
             }
-        })
     }
 }

+ 10 - 5
app/src/main/java/com/mrozon/healthdiary/presentation/main/MainActivityViewModel.kt

@@ -3,31 +3,36 @@ package com.mrozon.healthdiary.presentation.main
 import androidx.lifecycle.LiveData
 import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
 import com.mrozon.core_api.entity.User
+import com.mrozon.core_api.providers.CoroutineContextProvider
 import com.mrozon.healthdiary.data.UserRepository
 import com.mrozon.utils.Event
+import com.mrozon.utils.network.Result
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.withContext
 import kotlinx.coroutines.CoroutineExceptionHandler
+import kotlinx.coroutines.flow.collect
 import timber.log.Timber
 import javax.inject.Inject
 
 class MainActivityViewModel @Inject constructor(
-    private val userRepository: UserRepository
+    private val repository: UserRepository,
+    private val coroutineContextProvider: CoroutineContextProvider
 ): ViewModel() {
 
-    val currentUser = userRepository.getLocalUser()
+    val currentUser = repository.getLocalUser()
 
     private val _cleared = MutableLiveData<Event<Unit>>()
     val cleared: LiveData<Event<Unit>>
         get() = _cleared
 
     fun logoutUser(user: User) {
-        CoroutineScope(Dispatchers.IO).launch(getJobErrorHandler()) {
-            userRepository.clearLocalUser(user)
-            withContext(Dispatchers.Main){
+        CoroutineScope(coroutineContextProvider.IO).launch(getJobErrorHandler()) {
+            repository.clearLocalUser(user)
+            withContext(coroutineContextProvider.Main){
                 _cleared.value = Event(Unit)
             }
         }

+ 4 - 46
core_api/src/main/java/com/mrozon/core_api/db/HealthDiaryDao.kt

@@ -1,50 +1,8 @@
 package com.mrozon.core_api.db
 
-import androidx.lifecycle.LiveData
-import androidx.room.*
-import com.mrozon.core_api.db.model.PersonDb
-import com.mrozon.core_api.db.model.UserDb
-import kotlinx.coroutines.flow.Flow
+import androidx.room.Dao
+import com.mrozon.core_api.db.dao.PersonDao
+import com.mrozon.core_api.db.dao.UserDao
 
 @Dao
-interface HealthDiaryDao {
-
-    // USER
-    @Query("SELECT * FROM user_table LIMIT 1")
-    fun getUser(): LiveData<UserDb>
-
-    @Insert(onConflict = OnConflictStrategy.REPLACE)
-    suspend fun insertUser(userDb: UserDb)
-
-    @Delete
-    suspend fun deleteUser(userDb: UserDb)
-
-//    // TOKEN
-//    @Query("SELECT user_token from user_table LIMIT 1")
-//    fun getAccessToken(): String
-
-    // PERSON
-    @Query("SELECT * FROM person_table")
-    fun getPersons(): Flow<List<PersonDb>>
-
-    @Query("SELECT * FROM person_table WHERE person_id=:id LIMIT 1")
-    suspend fun getPerson(id: Long): PersonDb
-
-    @Insert(onConflict = OnConflictStrategy.REPLACE)
-    suspend fun insertAllPerson(persons: List<PersonDb>)
-
-    @Insert(onConflict = OnConflictStrategy.REPLACE)
-    suspend fun insertPerson(person: PersonDb)
-
-    @Query("DELETE FROM person_table WHERE person_id=:id")
-    suspend fun deletePerson(id: Long)
-
-    @Query("DELETE FROM person_table")
-    suspend fun deleteAllPerson()
-
-    @Transaction
-    suspend fun reloadPersons(persons: List<PersonDb>) {
-        deleteAllPerson()
-        insertAllPerson(persons)
-    }
-}
+interface HealthDiaryDao: UserDao, PersonDao

+ 32 - 0
core_api/src/main/java/com/mrozon/core_api/db/dao/PersonDao.kt

@@ -0,0 +1,32 @@
+package com.mrozon.core_api.db.dao
+
+import androidx.room.*
+import com.mrozon.core_api.db.model.PersonDb
+import kotlinx.coroutines.flow.Flow
+
+@Dao
+interface PersonDao {
+    @Query("SELECT * FROM person_table")
+    fun getPersons(): Flow<List<PersonDb>>
+
+    @Query("SELECT * FROM person_table WHERE person_id=:id LIMIT 1")
+    suspend fun getPerson(id: Long): PersonDb
+
+    @Insert(onConflict = OnConflictStrategy.REPLACE)
+    suspend fun insertAllPerson(persons: List<PersonDb>)
+
+    @Insert(onConflict = OnConflictStrategy.REPLACE)
+    suspend fun insertPerson(person: PersonDb)
+
+    @Query("DELETE FROM person_table WHERE person_id=:id")
+    suspend fun deletePerson(id: Long)
+
+    @Query("DELETE FROM person_table")
+    suspend fun deleteAllPerson()
+
+    @Transaction
+    suspend fun reloadPersons(persons: List<PersonDb>) {
+        deleteAllPerson()
+        insertAllPerson(persons)
+    }
+}

+ 22 - 0
core_api/src/main/java/com/mrozon/core_api/db/dao/UserDao.kt

@@ -0,0 +1,22 @@
+package com.mrozon.core_api.db.dao
+
+import androidx.lifecycle.LiveData
+import androidx.room.*
+import com.mrozon.core_api.db.model.UserDb
+import kotlinx.coroutines.flow.Flow
+
+@Dao
+interface UserDao {
+
+    @Query("SELECT * FROM user_table LIMIT 1")
+    fun getUser(): Flow<UserDb>
+
+    @Query("SELECT * FROM user_table LIMIT 1")
+    fun getLiveUser(): LiveData<UserDb>
+
+    @Insert(onConflict = OnConflictStrategy.REPLACE)
+    suspend fun insertUser(userDb: UserDb)
+
+    @Delete
+    suspend fun deleteUser(userDb: UserDb)
+}

+ 3 - 1
feature_splash/src/main/java/com/mrozon/feature_splash/data/PreloadDataRepository.kt

@@ -2,8 +2,10 @@ package com.mrozon.feature_splash.data
 
 import androidx.lifecycle.LiveData
 import com.mrozon.core_api.entity.User
+import com.mrozon.utils.network.Result
+import kotlinx.coroutines.flow.Flow
 
 interface PreloadDataRepository {
 
-    fun getLocalUser(): LiveData<User>
+    fun getLocalUser(): Flow<Result<User?>>
 }

+ 21 - 5
feature_splash/src/main/java/com/mrozon/feature_splash/data/PreloadDataRepositoryImp.kt

@@ -5,17 +5,33 @@ import androidx.lifecycle.Transformations
 import com.mrozon.core_api.db.HealthDiaryDao
 import com.mrozon.core_api.entity.User
 import com.mrozon.core_api.mapper.UserToUserDbMapper
+import com.mrozon.core_api.network.model.toPerson
+import com.mrozon.utils.network.Result
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.firstOrNull
+import kotlinx.coroutines.flow.flow
 import javax.inject.Inject
+import javax.inject.Singleton
 
+@Singleton
 class PreloadDataRepositoryImp @Inject constructor(
-    private val healthDiaryDao: HealthDiaryDao,
+    private val dao: HealthDiaryDao,
     private val mapper: UserToUserDbMapper
 ): PreloadDataRepository {
 
-    override fun getLocalUser(): LiveData<User> {
-        val userDb = healthDiaryDao.getUser()
-        return Transformations.map(userDb) {
-            mapper.reverseMap(it)
+    override fun getLocalUser(): Flow<Result<User?>> {
+        return flow {
+            emit(Result.loading())
+            val query = dao.getUser()
+            val userDb = query.firstOrNull()
+            if(userDb==null){
+                emit(Result.success(null))
+            }
+            else
+            {
+                //TODO load additional entities from network - measure types
+                emit(Result.success(mapper.reverseMap(userDb)))
+            }
         }
     }
 

+ 18 - 8
feature_splash/src/main/java/com/mrozon/feature_splash/presentation/SplashFragment.kt

@@ -16,6 +16,8 @@ import com.mrozon.feature_splash.R
 import com.mrozon.feature_splash.databinding.FragmentSplashBinding
 import com.mrozon.feature_splash.di.SplashFragmentComponent
 import com.mrozon.utils.base.BaseFragment
+import com.mrozon.utils.extension.visible
+import com.mrozon.utils.network.Result
 import timber.log.Timber
 import javax.inject.Inject
 
@@ -39,14 +41,22 @@ class SplashFragment : BaseFragment<FragmentSplashBinding>() {
     }
 
     override fun subscribeUi() {
-        viewModel.currentUser.observe(viewLifecycleOwner, Observer {
-            if(it==null){
-                //auth user
-                navigator.navigateToAuth(findNavController())
-            }
-            else
-            {
-                navigator.navigateToListPerson(findNavController())
+        viewModel.currentUser.observe(viewLifecycleOwner, Observer { event ->
+            event.peekContent().let { result ->
+                when (result.status) {
+                    Result.Status.SUCCESS -> {
+                        if(result.data==null){
+                            navigator.navigateToAuth(findNavController())
+                        }
+                        else
+                        {
+                            navigator.navigateToListPerson(findNavController())
+                        }
+                    }
+                    else -> {
+
+                    }
+                }
             }
         })
     }

+ 27 - 2
feature_splash/src/main/java/com/mrozon/feature_splash/presentation/SplashFragmentViewModel.kt

@@ -1,13 +1,38 @@
 package com.mrozon.feature_splash.presentation
 
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.viewModelScope
+import com.mrozon.core_api.entity.Person
+import com.mrozon.core_api.entity.User
+import com.mrozon.core_api.providers.CoroutineContextProvider
 import com.mrozon.feature_splash.data.PreloadDataRepository
+import com.mrozon.utils.Event
 import com.mrozon.utils.base.BaseViewModel
+import com.mrozon.utils.network.Result
+import kotlinx.coroutines.flow.collect
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+import timber.log.Timber
 import javax.inject.Inject
 
 class SplashFragmentViewModel @Inject constructor(
-    localUser: PreloadDataRepository
+    repository: PreloadDataRepository,
+    private val coroutineContextProvider: CoroutineContextProvider
 ): BaseViewModel() {
 
-    val currentUser = localUser.getLocalUser()
+    private val _currentUser = MutableLiveData<Event<Result<User?>>>()
+    val currentUser: LiveData<Event<Result<User?>>>
+        get() = _currentUser
+
+    init {
+        viewModelScope.launch(coroutineContextProvider.IO){
+            repository.getLocalUser().collect {
+                withContext(coroutineContextProvider.Main) {
+                    _currentUser.value = Event(it)
+                }
+            }
+        }
+    }
 
 }