Merge pull request #1815 from Hafizzle/Hafiz/todo-wear-fixes

Show all to-dos and reset after cron
This commit is contained in:
Phillip Thelen 2022-08-02 16:55:26 +02:00 committed by GitHub
commit 95ec04bd70
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 102 additions and 27 deletions

View file

@ -45,19 +45,24 @@ class AppModule {
}
@Provides
fun providesConverterFactory(): Converter.Factory {
fun providesConverterFactory(moshi: Moshi): Converter.Factory {
return MoshiConverterFactory.create(
Moshi.Builder()
.add(WrappedTasklistAdapter())
.add(customDateAdapter)
.add(FrequencyAdapter())
.add(TaskTypeAdapter())
.add(AttributeAdapter())
.addLast(KotlinJsonAdapterFactory())
.build()
moshi
).asLenient()
}
@Provides
fun providesMoshi(): Moshi {
return Moshi.Builder()
.add(WrappedTasklistAdapter())
.add(customDateAdapter)
.add(FrequencyAdapter())
.add(TaskTypeAdapter())
.add(AttributeAdapter())
.addLast(KotlinJsonAdapterFactory())
.build()
}
@Provides
@Singleton
fun providesApiHClient(

View file

@ -67,7 +67,9 @@ class TaskListActivity : BaseActivity<ActivityTasklistBinding, TaskListViewModel
}
viewModel.tasks.observe(this) {
adapter.data = it
if (!it.isNullOrEmpty()) {
adapter.data = it
}
}
viewModel.taskCount.observe(this) {
adapter.title = getTitle(it)

View file

@ -1,5 +1,7 @@
package com.habitrpg.wearos.habitica.ui.viewmodels
import android.content.SharedPreferences
import androidx.core.content.edit
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.habitrpg.common.habitica.models.responses.TaskDirection
@ -19,6 +21,7 @@ import javax.inject.Inject
class RYAViewModel @Inject constructor(
userRepository: UserRepository,
taskRepository: TaskRepository,
val sharedPreferences: SharedPreferences,
exceptionBuilder: ExceptionHandlerBuilder, appStateManager: AppStateManager
) : BaseViewModel(userRepository, taskRepository, exceptionBuilder, appStateManager) {
var hasRunCron: Boolean = false
@ -50,6 +53,8 @@ class RYAViewModel @Inject constructor(
}
fun runCron(function: (Boolean) -> Unit) {
//Clear shared pref values for saved to-do tasks
sharedPreferences.edit { putString("to_do_tasks", null) }
viewModelScope.launch(exceptionBuilder.userFacing(this)) {
appStateManager.startLoading()
for (task in tasksToComplete) {

View file

@ -1,5 +1,7 @@
package com.habitrpg.wearos.habitica.ui.viewmodels
import android.content.SharedPreferences
import androidx.core.content.edit
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.asLiveData
@ -12,11 +14,15 @@ import com.habitrpg.wearos.habitica.data.repositories.UserRepository
import com.habitrpg.wearos.habitica.managers.AppStateManager
import com.habitrpg.wearos.habitica.models.tasks.Task
import com.habitrpg.wearos.habitica.util.ExceptionHandlerBuilder
import com.squareup.moshi.JsonAdapter
import com.squareup.moshi.Moshi
import com.squareup.moshi.Types
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import java.lang.reflect.Type
import javax.inject.Inject
@HiltViewModel
@ -24,26 +30,27 @@ class TaskListViewModel @Inject constructor(
savedStateHandle: SavedStateHandle,
taskRepository: TaskRepository,
userRepository: UserRepository,
val sharedPreferences: SharedPreferences,
moshi: Moshi,
exceptionBuilder: ExceptionHandlerBuilder, appStateManager: AppStateManager
) : BaseViewModel(userRepository, taskRepository, exceptionBuilder, appStateManager) {
var type: Type = Types.newParameterizedType(
MutableList::class.java,
Task::class.java
)
private val moshiAdapter: JsonAdapter<MutableList<Task>> = moshi.adapter(type)
val taskType = TaskType.from(savedStateHandle.get<String>("task_type"))
val taskCount = MutableLiveData(0)
val completedToDos: MutableList<Task> by lazy {
val tasksString = sharedPreferences.getString("to_do_tasks", null) ?: return@lazy mutableListOf()
return@lazy moshiAdapter.fromJson(tasksString) ?: mutableListOf()
}
val tasks = taskRepository.getTasks(taskType ?: TaskType.HABIT)
.map {
if (taskType == TaskType.DAILY || taskType == TaskType.TODO) {
val taskList: MutableList<Any> = it.filter { it.isDue == true || it.type == TaskType.TODO }.sortedBy { it.completed }.toMutableList()
val firstCompletedIndex = taskList.indexOfFirst { it is Task && it.completed }
if (firstCompletedIndex >= 0) {
// since this is the index of the first completed task, this is also the number of incomplete tasks
taskCount.value = firstCompletedIndex
taskList.add(firstCompletedIndex, "Done today")
} else {
taskCount.value = taskList.size
}
taskList
} else {
taskCount.value = it.size
it
when(taskType) {
TaskType.DAILY -> mapDaily(it)
TaskType.TODO -> mapTodos(it)
else -> map(it)
}
}
.asLiveData()
@ -51,7 +58,22 @@ class TaskListViewModel @Inject constructor(
.asLiveData()
fun scoreTask(task: Task, direction: TaskDirection, onResult: (TaskScoringResult?) -> Unit) {
viewModelScope.launch(exceptionBuilder.userFacing(this)) {
if (taskType == TaskType.TODO) {
if (direction == TaskDirection.UP) {
completedToDos.add(task)
} else {
completedToDos.remove(task)
}
}
viewModelScope.launch(exceptionBuilder.userFacing(this) {
if (taskType == TaskType.TODO) {
if (direction == TaskDirection.UP) {
completedToDos.remove(task)
} else {
completedToDos.add(task)
}
}
}) {
val result = taskRepository.scoreTask(
userRepository.getUser().first(),
task,
@ -65,4 +87,45 @@ class TaskListViewModel @Inject constructor(
onResult(result)
}
}
private fun map(tasks: List<Task>): List<Task> {
taskCount.value = tasks.size
return tasks
}
private fun mapDaily(tasks: List<Task>): MutableList<Any> {
val taskList: MutableList<Any> = tasks.filter { it.isDue == true || it.type == TaskType.TODO }.sortedBy { it.completed }.toMutableList()
val firstCompletedIndex = taskList.indexOfFirst { it is Task && it.completed }
if (firstCompletedIndex >= 0) {
// since this is the index of the first completed task, this is also the number of incomplete tasks
taskCount.value = firstCompletedIndex
taskList.add(firstCompletedIndex, "Done today")
} else {
taskCount.value = taskList.size
}
return taskList
}
override fun onCleared() {
saveCurrentToDos()
super.onCleared()
}
private fun mapTodos(tasks: List<Task>): List<Any> {
val taskList: MutableList<Any> = tasks.filter { !it.completed }.toMutableList()
taskCount.value = taskList.size
if (completedToDos.isNotEmpty()) {
taskList.add("Done today")
taskList.addAll(completedToDos)
}
return taskList
}
private fun saveCurrentToDos() {
sharedPreferences.edit {
putString("to_do_tasks", moshiAdapter.toJson(completedToDos))
}
}
}

View file

@ -18,7 +18,7 @@ class ExceptionHandlerBuilder @Inject constructor(val appStateManager: AppStateM
}
}
fun userFacing(errorPresenter: ErrorPresenter): CoroutineExceptionHandler {
fun userFacing(errorPresenter: ErrorPresenter, handler: ((Throwable) -> Unit)? = null): CoroutineExceptionHandler {
return CoroutineExceptionHandler { _, throwable ->
Log.e("Coroutine Error", "Error: ${throwable.cause}", throwable)
if (throwable is IOException) {
@ -30,7 +30,7 @@ class ExceptionHandlerBuilder @Inject constructor(val appStateManager: AppStateM
DisplayedError(R.drawable.error, it)
}
}
handler?.invoke(throwable)
appStateManager.endLoading()
}
}