From b090ac537be6a9b97d0e3fda08369f134de391cf Mon Sep 17 00:00:00 2001 From: Phillip Thelen Date: Fri, 3 Jun 2022 16:05:24 +0200 Subject: [PATCH] start using local repositories --- wearos/build.gradle | 2 + .../wearos/habitica/data/ApiClient.kt | 26 ++++++++----- .../wearos/habitica/data/ApiService.kt | 2 +- .../data/repositories/TaskLocalRepository.kt | 38 ++++++++++++++++++- .../data/repositories/TaskRepository.kt | 16 +++++++- .../data/repositories/UserLocalRepository.kt | 17 ++++++++- .../data/repositories/UserRepository.kt | 15 +++++++- .../habitica/ui/viewmodels/AvatarViewModel.kt | 11 ++---- .../habitica/ui/viewmodels/MainViewModel.kt | 13 ++++--- .../ui/viewmodels/TaskListViewModel.kt | 14 ++----- 10 files changed, 114 insertions(+), 40 deletions(-) diff --git a/wearos/build.gradle b/wearos/build.gradle index 7b13587ab..05a13943c 100644 --- a/wearos/build.gradle +++ b/wearos/build.gradle @@ -37,9 +37,11 @@ dependencies { implementation 'androidx.recyclerview:recyclerview:1.2.1' implementation 'androidx.wear:wear:1.2.0' implementation "androidx.wear:wear-input:1.1.0" + //Networking implementation 'com.squareup.okhttp3:okhttp:4.9.1' implementation 'com.squareup.okhttp3:logging-interceptor:4.9.1' + //REST API handling implementation('com.squareup.retrofit2:retrofit:2.9.0') { exclude module: 'okhttp' diff --git a/wearos/src/main/java/com/habitrpg/wearos/habitica/data/ApiClient.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/data/ApiClient.kt index d8cf7410f..c41a84c8b 100644 --- a/wearos/src/main/java/com/habitrpg/wearos/habitica/data/ApiClient.kt +++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/data/ApiClient.kt @@ -6,6 +6,7 @@ import com.habitrpg.common.habitica.api.HostConfig import com.habitrpg.common.habitica.api.Server import com.habitrpg.common.habitica.models.auth.UserAuth import com.habitrpg.common.habitica.models.auth.UserAuthSocial +import com.habitrpg.wearos.habitica.models.WearableHabitResponse import okhttp3.Cache import okhttp3.OkHttpClient import okhttp3.Request @@ -84,18 +85,23 @@ class ApiClient @Inject constructor( this.apiService = retrofitAdapter.create(ApiService::class.java) } - suspend fun getUser() = apiService.getUser().data - suspend fun updateUser(data: Map) = apiService.updateUser(data).data - suspend fun sleep() = apiService.sleep().data - suspend fun revive() = apiService.revive().data + private fun process(response: WearableHabitResponse): T? { + return response.data + } - suspend fun loginLocal(auth: UserAuth) = apiService.connectLocal(auth).data - suspend fun loginSocial(auth: UserAuthSocial) = apiService.connectSocial(auth).data + suspend fun getUser() = process(apiService.getUser()) + suspend fun updateUser(data: Map) = process(apiService.updateUser(data)) + suspend fun sleep() = process(apiService.sleep()) + suspend fun revive() = process(apiService.revive()) - suspend fun addPushDevice(data: Map) = apiService.addPushDevice(data).data - suspend fun removePushDevice(id: String) = apiService.removePushDevice(id).data + suspend fun loginLocal(auth: UserAuth) = process(apiService.connectLocal(auth)) + suspend fun loginSocial(auth: UserAuthSocial) = process(apiService.connectSocial(auth)) - suspend fun runCron() = apiService.runCron().data + suspend fun addPushDevice(data: Map) = process(apiService.addPushDevice(data)) + suspend fun removePushDevice(id: String) = process(apiService.removePushDevice(id)) - suspend fun getTasks() = apiService.getTasks().data + suspend fun runCron() = process(apiService.runCron()) + + suspend fun getTasks() = process(apiService.getTasks()) + suspend fun scoreTask(id: String, direction: String) = process(apiService.scoreTask(id, direction)) } \ No newline at end of file diff --git a/wearos/src/main/java/com/habitrpg/wearos/habitica/data/ApiService.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/data/ApiService.kt index 85eab155d..91fbaf93d 100644 --- a/wearos/src/main/java/com/habitrpg/wearos/habitica/data/ApiService.kt +++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/data/ApiService.kt @@ -41,7 +41,7 @@ interface ApiService { suspend fun getTask(@Path("id") id: String): WearableHabitResponse @POST("tasks/{id}/score/{direction}") - suspend fun postTaskDirection(@Path("id") id: String, @Path("direction") direction: String): WearableHabitResponse + suspend fun scoreTask(@Path("id") id: String, @Path("direction") direction: String): WearableHabitResponse @POST("tasks/bulk-score") suspend fun bulkScoreTasks(@Body data: List>): WearableHabitResponse diff --git a/wearos/src/main/java/com/habitrpg/wearos/habitica/data/repositories/TaskLocalRepository.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/data/repositories/TaskLocalRepository.kt index 89db1807e..5650d5687 100644 --- a/wearos/src/main/java/com/habitrpg/wearos/habitica/data/repositories/TaskLocalRepository.kt +++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/data/repositories/TaskLocalRepository.kt @@ -1,5 +1,41 @@ package com.habitrpg.wearos.habitica.data.repositories +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.asFlow +import com.habitrpg.common.habitica.models.tasks.TaskType +import com.habitrpg.wearos.habitica.models.tasks.Task +import com.habitrpg.wearos.habitica.models.tasks.TaskList +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.emptyFlow import javax.inject.Inject +import javax.inject.Singleton -class TaskLocalRepository @Inject constructor() \ No newline at end of file +@Singleton +class TaskLocalRepository @Inject constructor() { + private val tasks = mapOf( + TaskType.HABIT to MutableLiveData>(), + TaskType.DAILY to MutableLiveData>(), + TaskType.TODO to MutableLiveData>(), + TaskType.REWARD to MutableLiveData>() + ) + fun getTasks(type: TaskType): Flow> { + return tasks[type]?.asFlow() ?: emptyFlow() + } + + fun saveTasks(tasks: TaskList) { + val taskMap = mutableMapOf( + TaskType.HABIT to mutableListOf(), + TaskType.DAILY to mutableListOf(), + TaskType.TODO to mutableListOf(), + TaskType.REWARD to mutableListOf() + ) + for (task in tasks.tasks) { + if (task.value.type != null) { + taskMap[task.value.type]?.add(task.value) + } + } + for (type in taskMap) { + this.tasks[type.key]?.value = type.value + } + } +} \ No newline at end of file diff --git a/wearos/src/main/java/com/habitrpg/wearos/habitica/data/repositories/TaskRepository.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/data/repositories/TaskRepository.kt index d1cec8e7d..c26419fbf 100644 --- a/wearos/src/main/java/com/habitrpg/wearos/habitica/data/repositories/TaskRepository.kt +++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/data/repositories/TaskRepository.kt @@ -1,10 +1,24 @@ package com.habitrpg.wearos.habitica.data.repositories +import com.habitrpg.common.habitica.models.responses.TaskDirection +import com.habitrpg.common.habitica.models.tasks.TaskType import com.habitrpg.wearos.habitica.data.ApiClient +import com.habitrpg.wearos.habitica.models.tasks.Task +import com.habitrpg.wearos.habitica.models.tasks.TaskList +import kotlinx.coroutines.flow.Flow import javax.inject.Inject class TaskRepository @Inject constructor(val apiClient: ApiClient, val localRepository: TaskLocalRepository) { - suspend fun retrieveTasks() = apiClient.getTasks() + suspend fun retrieveTasks(): TaskList? { + val tasks = apiClient.getTasks() + tasks?.let { localRepository.saveTasks(tasks) } + return tasks + } + fun getTasks(taskType: TaskType): Flow> = localRepository.getTasks(taskType) + suspend fun scoreTask(task: Task, direction: TaskDirection) { + val id = task.id ?: return + val response = apiClient.scoreTask(id, direction.text) + } } \ No newline at end of file diff --git a/wearos/src/main/java/com/habitrpg/wearos/habitica/data/repositories/UserLocalRepository.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/data/repositories/UserLocalRepository.kt index 1ea26465b..475082f7f 100644 --- a/wearos/src/main/java/com/habitrpg/wearos/habitica/data/repositories/UserLocalRepository.kt +++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/data/repositories/UserLocalRepository.kt @@ -1,5 +1,20 @@ package com.habitrpg.wearos.habitica.data.repositories +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.asFlow +import com.habitrpg.wearos.habitica.models.User +import kotlinx.coroutines.flow.Flow import javax.inject.Inject +import javax.inject.Singleton -class UserLocalRepository @Inject constructor() \ No newline at end of file +@Singleton +class UserLocalRepository @Inject constructor() { + private val user = MutableLiveData() + fun getUser(): Flow { + return user.asFlow() + } + + fun saveUser(user: User) { + this.user.value = user + } +} \ No newline at end of file diff --git a/wearos/src/main/java/com/habitrpg/wearos/habitica/data/repositories/UserRepository.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/data/repositories/UserRepository.kt index 57f62aaa8..e238f9b7b 100644 --- a/wearos/src/main/java/com/habitrpg/wearos/habitica/data/repositories/UserRepository.kt +++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/data/repositories/UserRepository.kt @@ -1,12 +1,23 @@ package com.habitrpg.wearos.habitica.data.repositories import com.habitrpg.wearos.habitica.data.ApiClient +import com.habitrpg.wearos.habitica.models.User import javax.inject.Inject class UserRepository @Inject constructor(val apiClient: ApiClient, val localRepository: UserLocalRepository) { - suspend fun retrieveUser() = apiClient.getUser() - suspend fun updateUser(data: Map) = apiClient.updateUser(data) + fun getUser() = localRepository.getUser() + + suspend fun retrieveUser(): User? { + val user = apiClient.getUser() + user?.let { localRepository.saveUser(it) } + return user + } + suspend fun updateUser(data: Map): User? { + val user = apiClient.updateUser(data) + user?.let { localRepository.saveUser(it) } + return user + } suspend fun sleep() = apiClient.sleep() suspend fun revive() = apiClient.revive() diff --git a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/viewmodels/AvatarViewModel.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/viewmodels/AvatarViewModel.kt index 685606f1c..4abac961d 100644 --- a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/viewmodels/AvatarViewModel.kt +++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/viewmodels/AvatarViewModel.kt @@ -1,13 +1,11 @@ package com.habitrpg.wearos.habitica.ui.viewmodels import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.viewModelScope +import androidx.lifecycle.asLiveData import com.habitrpg.wearos.habitica.data.repositories.UserRepository import com.habitrpg.wearos.habitica.models.User import com.habitrpg.wearos.habitica.util.ExceptionHandlerBuilder import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel @@ -18,12 +16,9 @@ class AvatarViewModel @Inject constructor( userRepository, exceptionBuilder ) { - val _user = MutableLiveData() - val user: LiveData = _user + var user: LiveData init { - viewModelScope.launch(exceptionBuilder.userFacing(this)) { - _user.value = userRepository.retrieveUser() - } + user = userRepository.getUser().asLiveData() } } \ No newline at end of file diff --git a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/viewmodels/MainViewModel.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/viewmodels/MainViewModel.kt index 649111ff9..ae7f66e65 100644 --- a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/viewmodels/MainViewModel.kt +++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/viewmodels/MainViewModel.kt @@ -1,8 +1,9 @@ package com.habitrpg.wearos.habitica.ui.viewmodels import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData +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.models.User import com.habitrpg.wearos.habitica.util.ExceptionHandlerBuilder @@ -13,14 +14,16 @@ import javax.inject.Inject @HiltViewModel class MainViewModel @Inject constructor( userRepository: UserRepository, + val taskRepository: TaskRepository, exceptionBuilder: ExceptionHandlerBuilder ) : BaseViewModel(userRepository, exceptionBuilder) { - val _user = MutableLiveData() - val user: LiveData = _user + var user: LiveData init { - viewModelScope.launch(exceptionBuilder.userFacing(this)) { - _user.value = userRepository.retrieveUser() + user = userRepository.getUser().asLiveData() + viewModelScope.launch { + userRepository.retrieveUser() + taskRepository.retrieveTasks() } } } \ No newline at end of file diff --git a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/viewmodels/TaskListViewModel.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/viewmodels/TaskListViewModel.kt index 50d786ca8..716a36442 100644 --- a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/viewmodels/TaskListViewModel.kt +++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/viewmodels/TaskListViewModel.kt @@ -1,16 +1,14 @@ package com.habitrpg.wearos.habitica.ui.viewmodels import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData import androidx.lifecycle.SavedStateHandle -import androidx.lifecycle.viewModelScope +import androidx.lifecycle.asLiveData 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.models.tasks.Task import com.habitrpg.wearos.habitica.util.ExceptionHandlerBuilder import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel @@ -20,16 +18,10 @@ class TaskListViewModel @Inject constructor( userRepository: UserRepository, exceptionBuilder: ExceptionHandlerBuilder ) : BaseViewModel(userRepository, exceptionBuilder) { - val _tasks = MutableLiveData>() - val tasks: LiveData> = _tasks - + var tasks: LiveData> val taskType = TaskType.from(savedStateHandle.get("task_type")) init { - viewModelScope.launch(exceptionBuilder.userFacing(this)) { - _tasks.value = taskRepository.retrieveTasks()?.tasks?.values?.filter { - it.type == taskType - }?.toList() - } + tasks = taskRepository.getTasks(taskType ?: TaskType.HABIT).asLiveData() } } \ No newline at end of file