Improve how loading is displayed

This commit is contained in:
Phillip Thelen 2022-06-24 10:29:28 +02:00
parent cf2e46d199
commit 31c16eb6ca
17 changed files with 84 additions and 35 deletions

View file

@ -0,0 +1,20 @@
package com.habitrpg.wearos.habitica.managers
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class LoadingManager @Inject constructor() {
private val _isLoading = MutableLiveData<Boolean>()
val isLoading: LiveData<Boolean> = _isLoading
fun startLoading() {
_isLoading.value = true
}
fun endLoading() {
_isLoading.value = false
}
}

View file

@ -14,12 +14,17 @@ import com.google.android.gms.wearable.CapabilityClient
import com.google.android.gms.wearable.MessageClient
import com.google.android.gms.wearable.Wearable
import com.habitrpg.android.habitica.databinding.ActivityWrapperBinding
import com.habitrpg.wearos.habitica.managers.LoadingManager
import com.habitrpg.wearos.habitica.ui.viewmodels.BaseViewModel
import com.habitrpg.wearos.habitica.ui.views.IndeterminateProgressView
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import javax.inject.Inject
abstract class BaseActivity<B: ViewBinding, VM: BaseViewModel> : ComponentActivity() {
@Inject
lateinit var loadingManager: LoadingManager
val messageClient: MessageClient by lazy { Wearable.getMessageClient(this) }
val capabilityClient: CapabilityClient by lazy { Wearable.getCapabilityClient(this) }
companion object {
@ -45,6 +50,14 @@ abstract class BaseActivity<B: ViewBinding, VM: BaseViewModel> : ComponentActivi
}
startActivity(intent)
}
loadingManager.isLoading.observe(this) {
if (it) {
startAnimatingProgress()
} else {
stopAnimatingProgress()
}
}
}
override fun onResume() {

View file

@ -2,6 +2,7 @@ package com.habitrpg.wearos.habitica.ui.viewmodels
import androidx.lifecycle.asLiveData
import com.habitrpg.wearos.habitica.data.repositories.UserRepository
import com.habitrpg.wearos.habitica.managers.LoadingManager
import com.habitrpg.wearos.habitica.util.ExceptionHandlerBuilder
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
@ -9,10 +10,10 @@ import javax.inject.Inject
@HiltViewModel
class AvatarViewModel @Inject constructor(
userRepository: UserRepository,
exceptionBuilder: ExceptionHandlerBuilder
exceptionBuilder: ExceptionHandlerBuilder, loadingManager: LoadingManager
) : BaseViewModel(
userRepository,
exceptionBuilder
exceptionBuilder, loadingManager
) {
var user = userRepository.getUser().asLiveData()
}

View file

@ -3,18 +3,15 @@ package com.habitrpg.wearos.habitica.ui.viewmodels
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.habitrpg.wearos.habitica.data.repositories.UserRepository
import com.habitrpg.wearos.habitica.managers.LoadingManager
import com.habitrpg.wearos.habitica.models.DisplayedError
import com.habitrpg.wearos.habitica.models.user.User
import com.habitrpg.wearos.habitica.util.ErrorPresenter
import com.habitrpg.wearos.habitica.util.ExceptionHandlerBuilder
open class BaseViewModel(
val userRepository: UserRepository,
val exceptionBuilder: ExceptionHandlerBuilder
val exceptionBuilder: ExceptionHandlerBuilder,
val loadingManager: LoadingManager
): ViewModel(), ErrorPresenter {
suspend fun retrieveUser(): User? {
return userRepository.retrieveUser()
}
override val errorValues = MutableLiveData<DisplayedError>()
}

View file

@ -1,14 +1,15 @@
package com.habitrpg.wearos.habitica.ui.viewmodels
import com.habitrpg.wearos.habitica.data.repositories.UserRepository
import com.habitrpg.wearos.habitica.managers.LoadingManager
import com.habitrpg.wearos.habitica.util.ExceptionHandlerBuilder
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
@HiltViewModel
class FaintViewModel @Inject constructor(userRepository: UserRepository,
exceptionBuilder: ExceptionHandlerBuilder
) : BaseViewModel(userRepository, exceptionBuilder) {
exceptionBuilder: ExceptionHandlerBuilder, loadingManager: LoadingManager
) : BaseViewModel(userRepository, exceptionBuilder, loadingManager) {
suspend fun revive() {
userRepository.revive()
}

View file

@ -6,6 +6,7 @@ import androidx.lifecycle.viewModelScope
import com.habitrpg.common.habitica.models.responses.TaskDirection
import com.habitrpg.wearos.habitica.data.repositories.TaskRepository
import com.habitrpg.wearos.habitica.data.repositories.UserRepository
import com.habitrpg.wearos.habitica.managers.LoadingManager
import com.habitrpg.wearos.habitica.util.ExceptionHandlerBuilder
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
@ -16,8 +17,8 @@ class HabitDrectionViewModel @Inject constructor(
savedStateHandle: SavedStateHandle,
userRepository: UserRepository,
val taskRepository: TaskRepository,
exceptionBuilder: ExceptionHandlerBuilder
) : BaseViewModel(userRepository, exceptionBuilder) {
exceptionBuilder: ExceptionHandlerBuilder, loadingManager: LoadingManager
) : BaseViewModel(userRepository, exceptionBuilder, loadingManager) {
val taskID = savedStateHandle.get<String>("task_id")
val task = taskRepository.getTask(taskID).asLiveData()

View file

@ -23,6 +23,7 @@ import com.habitrpg.common.habitica.models.auth.UserAuthResponse
import com.habitrpg.common.habitica.models.auth.UserAuthSocial
import com.habitrpg.wearos.habitica.data.ApiClient
import com.habitrpg.wearos.habitica.data.repositories.UserRepository
import com.habitrpg.wearos.habitica.managers.LoadingManager
import com.habitrpg.wearos.habitica.util.ExceptionHandlerBuilder
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
@ -34,8 +35,8 @@ class LoginViewModel @Inject constructor(userRepository: UserRepository,
exceptionBuilder: ExceptionHandlerBuilder,
val keyHelper: KeyHelper?,
val sharedPreferences: SharedPreferences,
val apiClient: ApiClient
) : BaseViewModel(userRepository, exceptionBuilder) {
val apiClient: ApiClient, loadingManager: LoadingManager
) : BaseViewModel(userRepository, exceptionBuilder, loadingManager) {
lateinit var onLoginCompleted: () -> Unit
var googleEmail: String? = null
@ -133,7 +134,7 @@ class LoginViewModel @Inject constructor(userRepository: UserRepository,
saveTokens(userAuthResponse.apiToken, userAuthResponse.id)
} catch (e: Exception) {
}
retrieveUser()
userRepository.retrieveUser()
onLoginCompleted()
}

View file

@ -4,6 +4,7 @@ import androidx.lifecycle.asLiveData
import androidx.lifecycle.viewModelScope
import com.habitrpg.wearos.habitica.data.repositories.TaskRepository
import com.habitrpg.wearos.habitica.data.repositories.UserRepository
import com.habitrpg.wearos.habitica.managers.LoadingManager
import com.habitrpg.wearos.habitica.util.ExceptionHandlerBuilder
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
@ -13,14 +14,16 @@ import javax.inject.Inject
class MainViewModel @Inject constructor(
userRepository: UserRepository,
val taskRepository: TaskRepository,
exceptionBuilder: ExceptionHandlerBuilder
) : BaseViewModel(userRepository, exceptionBuilder) {
exceptionBuilder: ExceptionHandlerBuilder, loadingManager: LoadingManager
) : BaseViewModel(userRepository, exceptionBuilder, loadingManager) {
var user = userRepository.getUser().asLiveData()
init {
viewModelScope.launch(exceptionBuilder.userFacing(this)) {
loadingManager.startLoading()
userRepository.retrieveUser()
taskRepository.retrieveTasks()
loadingManager.endLoading()
}
}
}

View file

@ -6,6 +6,7 @@ import com.habitrpg.common.habitica.models.responses.TaskDirection
import com.habitrpg.common.habitica.models.tasks.TaskType
import com.habitrpg.wearos.habitica.data.repositories.TaskRepository
import com.habitrpg.wearos.habitica.data.repositories.UserRepository
import com.habitrpg.wearos.habitica.managers.LoadingManager
import com.habitrpg.wearos.habitica.models.tasks.Task
import com.habitrpg.wearos.habitica.util.ExceptionHandlerBuilder
import dagger.hilt.android.lifecycle.HiltViewModel
@ -16,8 +17,8 @@ import javax.inject.Inject
class RYAViewModel @Inject constructor(
userRepository: UserRepository,
val taskRepository: TaskRepository,
exceptionBuilder: ExceptionHandlerBuilder
) : BaseViewModel(userRepository, exceptionBuilder) {
exceptionBuilder: ExceptionHandlerBuilder, loadingManager: LoadingManager
) : BaseViewModel(userRepository, exceptionBuilder, loadingManager) {
val tasks = taskRepository.getTasks(TaskType.DAILY).asLiveData()
private val tasksToComplete = mutableListOf<Task>()
@ -38,12 +39,14 @@ class RYAViewModel @Inject constructor(
fun runCron(function: (Boolean) -> Unit) {
viewModelScope.launch(exceptionBuilder.userFacing(this)) {
loadingManager.startLoading()
for (task in tasksToComplete) {
taskRepository.scoreTask(null, task, TaskDirection.UP)
}
userRepository.runCron()
userRepository.retrieveUser()
function(true)
loadingManager.endLoading()
}
}
}

View file

@ -4,6 +4,7 @@ import android.content.SharedPreferences
import androidx.core.content.edit
import com.habitrpg.wearos.habitica.data.ApiClient
import com.habitrpg.wearos.habitica.data.repositories.UserRepository
import com.habitrpg.wearos.habitica.managers.LoadingManager
import com.habitrpg.wearos.habitica.util.ExceptionHandlerBuilder
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
@ -12,8 +13,8 @@ import javax.inject.Inject
class SettingsViewModel @Inject constructor(userRepository: UserRepository,
exceptionBuilder: ExceptionHandlerBuilder,
private val apiClient: ApiClient,
private val sharedPreferences: SharedPreferences
) : BaseViewModel(userRepository, exceptionBuilder) {
private val sharedPreferences: SharedPreferences, loadingManager: LoadingManager
) : BaseViewModel(userRepository, exceptionBuilder, loadingManager) {
fun logout() {
sharedPreferences.edit {

View file

@ -9,6 +9,7 @@ import com.habitrpg.common.habitica.api.HostConfig
import com.habitrpg.common.habitica.helpers.KeyHelper
import com.habitrpg.wearos.habitica.data.ApiClient
import com.habitrpg.wearos.habitica.data.repositories.UserRepository
import com.habitrpg.wearos.habitica.managers.LoadingManager
import com.habitrpg.wearos.habitica.util.ExceptionHandlerBuilder
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
@ -20,8 +21,8 @@ class SplashViewModel @Inject constructor(userRepository: UserRepository,
val hostConfig: HostConfig,
val apiClient: ApiClient,
val sharedPreferences: SharedPreferences,
val keyHelper: KeyHelper?
) : BaseViewModel(userRepository, exceptionBuilder), MessageClient.OnMessageReceivedListener {
val keyHelper: KeyHelper?, loadingManager: LoadingManager
) : BaseViewModel(userRepository, exceptionBuilder, loadingManager), MessageClient.OnMessageReceivedListener {
lateinit var onLoginCompleted: (Boolean) -> Unit
val hasAuthentication: Boolean
get() {
@ -43,7 +44,7 @@ class SplashViewModel @Inject constructor(userRepository: UserRepository,
onLoginCompleted(false)
return@launch
}
retrieveUser()
userRepository.retrieveUser()
onLoginCompleted(true)
}
}

View file

@ -3,6 +3,7 @@ package com.habitrpg.wearos.habitica.ui.viewmodels
import androidx.lifecycle.LiveData
import androidx.lifecycle.asLiveData
import com.habitrpg.wearos.habitica.data.repositories.UserRepository
import com.habitrpg.wearos.habitica.managers.LoadingManager
import com.habitrpg.wearos.habitica.models.user.User
import com.habitrpg.wearos.habitica.util.ExceptionHandlerBuilder
import dagger.hilt.android.lifecycle.HiltViewModel
@ -10,8 +11,8 @@ import javax.inject.Inject
@HiltViewModel
class StatsViewModel @Inject constructor(userRepository: UserRepository,
exceptionBuilder: ExceptionHandlerBuilder
) : BaseViewModel(userRepository, exceptionBuilder) {
exceptionBuilder: ExceptionHandlerBuilder, loadingManager: LoadingManager
) : BaseViewModel(userRepository, exceptionBuilder, loadingManager) {
var user: LiveData<User> = userRepository.getUser().asLiveData()

View file

@ -4,6 +4,7 @@ import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.asLiveData
import com.habitrpg.wearos.habitica.data.repositories.TaskRepository
import com.habitrpg.wearos.habitica.data.repositories.UserRepository
import com.habitrpg.wearos.habitica.managers.LoadingManager
import com.habitrpg.wearos.habitica.util.ExceptionHandlerBuilder
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
@ -13,8 +14,8 @@ class TaskDetailViewModel @Inject constructor(
savedStateHandle: SavedStateHandle,
taskRepository: TaskRepository,
userRepository: UserRepository,
exceptionBuilder: ExceptionHandlerBuilder
) : BaseViewModel(userRepository, exceptionBuilder) {
exceptionBuilder: ExceptionHandlerBuilder, loadingManager: LoadingManager
) : BaseViewModel(userRepository, exceptionBuilder, loadingManager) {
val taskID = savedStateHandle.get<String>("task_id")
val task = taskRepository.getTask(taskID).asLiveData()
}

View file

@ -4,6 +4,7 @@ import com.habitrpg.common.habitica.models.tasks.Frequency
import com.habitrpg.common.habitica.models.tasks.TaskType
import com.habitrpg.wearos.habitica.data.repositories.TaskRepository
import com.habitrpg.wearos.habitica.data.repositories.UserRepository
import com.habitrpg.wearos.habitica.managers.LoadingManager
import com.habitrpg.wearos.habitica.models.tasks.Task
import com.habitrpg.wearos.habitica.util.ExceptionHandlerBuilder
import dagger.hilt.android.lifecycle.HiltViewModel
@ -13,8 +14,8 @@ import javax.inject.Inject
class TaskFormViewModel @Inject constructor(
userRepository: UserRepository,
val taskRepository: TaskRepository,
exceptionBuilder: ExceptionHandlerBuilder
) : BaseViewModel(userRepository, exceptionBuilder) {
exceptionBuilder: ExceptionHandlerBuilder, loadingManager: LoadingManager
) : BaseViewModel(userRepository, exceptionBuilder, loadingManager) {
suspend fun saveTask(text: CharSequence?, taskType: TaskType?) {
if (text?.isNotBlank() != true || taskType == null) {
return

View file

@ -8,6 +8,7 @@ import com.habitrpg.common.habitica.models.responses.TaskScoringResult
import com.habitrpg.common.habitica.models.tasks.TaskType
import com.habitrpg.wearos.habitica.data.repositories.TaskRepository
import com.habitrpg.wearos.habitica.data.repositories.UserRepository
import com.habitrpg.wearos.habitica.managers.LoadingManager
import com.habitrpg.wearos.habitica.models.tasks.Task
import com.habitrpg.wearos.habitica.util.ExceptionHandlerBuilder
import dagger.hilt.android.lifecycle.HiltViewModel
@ -19,8 +20,8 @@ class TaskListViewModel @Inject constructor(
savedStateHandle: SavedStateHandle,
private val taskRepository: TaskRepository,
userRepository: UserRepository,
exceptionBuilder: ExceptionHandlerBuilder
) : BaseViewModel(userRepository, exceptionBuilder) {
exceptionBuilder: ExceptionHandlerBuilder, loadingManager: LoadingManager
) : BaseViewModel(userRepository, exceptionBuilder, loadingManager) {
val taskType = TaskType.from(savedStateHandle.get<String>("task_type"))
val tasks = taskRepository.getTasks(taskType ?: TaskType.HABIT).asLiveData()
val user = userRepository.getUser()

View file

@ -3,14 +3,15 @@ package com.habitrpg.wearos.habitica.ui.viewmodels
import androidx.lifecycle.SavedStateHandle
import com.habitrpg.common.habitica.models.responses.TaskScoringResult
import com.habitrpg.wearos.habitica.data.repositories.UserRepository
import com.habitrpg.wearos.habitica.managers.LoadingManager
import com.habitrpg.wearos.habitica.util.ExceptionHandlerBuilder
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
@HiltViewModel
class TaskResultViewModel @Inject constructor(savedStateHandle: SavedStateHandle, userRepository: UserRepository,
exceptionBuilder: ExceptionHandlerBuilder
) : BaseViewModel(userRepository, exceptionBuilder) {
exceptionBuilder: ExceptionHandlerBuilder, loadingManager: LoadingManager
) : BaseViewModel(userRepository, exceptionBuilder, loadingManager) {
val hasDrop: Boolean
get() {
return result?.drop?.key?.isNotBlank() == true || (result?.questItemsFound ?: 0) > 0

View file

@ -1,13 +1,14 @@
package com.habitrpg.wearos.habitica.util
import android.util.Log
import com.habitrpg.wearos.habitica.managers.LoadingManager
import com.habitrpg.wearos.habitica.models.DisplayedError
import dagger.hilt.android.scopes.ViewModelScoped
import kotlinx.coroutines.CoroutineExceptionHandler
import javax.inject.Inject
@ViewModelScoped
class ExceptionHandlerBuilder @Inject constructor() {
class ExceptionHandlerBuilder @Inject constructor(val loadingManager: LoadingManager) {
fun silent(): CoroutineExceptionHandler {
return CoroutineExceptionHandler { context, throwable ->
Log.e(context.toString(), "Error: ${throwable.cause}", throwable)
@ -18,6 +19,7 @@ class ExceptionHandlerBuilder @Inject constructor() {
return CoroutineExceptionHandler { _, throwable ->
Log.e("Coroutine Error", "Error: ${throwable.cause}", throwable)
errorPresenter.errorValues.value = throwable.message?.let { DisplayedError(it) }
loadingManager.endLoading()
}
}
}