diff --git a/wearos/src/main/AndroidManifest.xml b/wearos/src/main/AndroidManifest.xml index 0e6bed31a..a821035ac 100644 --- a/wearos/src/main/AndroidManifest.xml +++ b/wearos/src/main/AndroidManifest.xml @@ -37,6 +37,7 @@ + \ No newline at end of file diff --git a/wearos/src/main/java/com/habitrpg/wearos/habitica/models/DisplayedError.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/models/DisplayedError.kt new file mode 100644 index 000000000..0626da42b --- /dev/null +++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/models/DisplayedError.kt @@ -0,0 +1,3 @@ +package com.habitrpg.wearos.habitica.models + +data class DisplayedError(val title: String) \ No newline at end of file diff --git a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/AvatarActivity.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/AvatarActivity.kt index c6473abde..525698f29 100644 --- a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/AvatarActivity.kt +++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/AvatarActivity.kt @@ -7,8 +7,8 @@ import com.habitrpg.wearos.habitica.ui.viewmodels.AvatarViewModel import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint -class AvatarActivity: BaseActivity() { - val viewModel: AvatarViewModel by viewModels() +class AvatarActivity: BaseActivity() { + override val viewModel: AvatarViewModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { binding = ActivityAvatarBinding.inflate(layoutInflater) diff --git a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/BaseActivity.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/BaseActivity.kt index 1b4b30da7..707eae5f0 100644 --- a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/BaseActivity.kt +++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/BaseActivity.kt @@ -1,14 +1,27 @@ package com.habitrpg.wearos.habitica.ui.activities +import android.content.Intent import android.os.Bundle import androidx.activity.ComponentActivity import androidx.viewbinding.ViewBinding +import androidx.wear.activity.ConfirmationActivity +import com.habitrpg.wearos.habitica.ui.viewmodels.BaseViewModel -open class BaseActivity : ComponentActivity() { +abstract class BaseActivity : ComponentActivity() { protected lateinit var binding: B + abstract val viewModel: VM override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(binding.root) + + viewModel.errorValues.observe(this) { + val intent = Intent(this, ConfirmationActivity::class.java).apply { + putExtra(ConfirmationActivity.EXTRA_ANIMATION_TYPE, ConfirmationActivity.FAILURE_ANIMATION) + putExtra(ConfirmationActivity.EXTRA_MESSAGE, it.title) + putExtra(ConfirmationActivity.EXTRA_ANIMATION_DURATION_MILLIS, 3000) + } + startActivity(intent) + } } } \ No newline at end of file diff --git a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/MainActivity.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/MainActivity.kt index 1ddca6f42..f31e7cc9c 100644 --- a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/MainActivity.kt +++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/MainActivity.kt @@ -26,8 +26,8 @@ data class MenuItem( ) @AndroidEntryPoint -class MainActivity : BaseActivity() { - val viewModel: MainViewModel by viewModels() +class MainActivity : BaseActivity() { + override val viewModel: MainViewModel by viewModels() private val adapter = HubAdapter() diff --git a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/TaskListActivity.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/TaskListActivity.kt index a65da21d0..c7f82d1de 100644 --- a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/TaskListActivity.kt +++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/TaskListActivity.kt @@ -11,9 +11,9 @@ import com.habitrpg.wearos.habitica.ui.viewmodels.TaskListViewModel import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint -class TaskListActivity: BaseActivity() { +class TaskListActivity: BaseActivity() { private val adapter = TaskListAdapter() - private val viewModel: TaskListViewModel by viewModels() + override val viewModel: TaskListViewModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { binding = ActivityTasklistBinding.inflate(layoutInflater) 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 36cf02489..685606f1c 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 @@ -5,17 +5,24 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope 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 -class AvatarViewModel @Inject constructor(userRepository: UserRepository) : BaseViewModel(userRepository) { +class AvatarViewModel @Inject constructor( + userRepository: UserRepository, + exceptionBuilder: ExceptionHandlerBuilder +) : BaseViewModel( + userRepository, + exceptionBuilder +) { val _user = MutableLiveData() val user: LiveData = _user init { - viewModelScope.launch { + viewModelScope.launch(exceptionBuilder.userFacing(this)) { _user.value = userRepository.retrieveUser() } } diff --git a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/viewmodels/BaseViewModel.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/viewmodels/BaseViewModel.kt index 747aaa515..2130e1980 100644 --- a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/viewmodels/BaseViewModel.kt +++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/viewmodels/BaseViewModel.kt @@ -1,6 +1,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.models.DisplayedError +import com.habitrpg.wearos.habitica.util.ErrorPresenter +import com.habitrpg.wearos.habitica.util.ExceptionHandlerBuilder -open class BaseViewModel(val userRepository: UserRepository): ViewModel() \ No newline at end of file +open class BaseViewModel( + val userRepository: UserRepository, + val exceptionBuilder: ExceptionHandlerBuilder +): ViewModel(), ErrorPresenter { + override val errorValues = MutableLiveData() +} \ 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 997c6f6c9..649111ff9 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 @@ -5,17 +5,21 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope 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 -class MainViewModel @Inject constructor(userRepository: UserRepository) : BaseViewModel(userRepository) { +class MainViewModel @Inject constructor( + userRepository: UserRepository, + exceptionBuilder: ExceptionHandlerBuilder +) : BaseViewModel(userRepository, exceptionBuilder) { val _user = MutableLiveData() val user: LiveData = _user init { - viewModelScope.launch { + viewModelScope.launch(exceptionBuilder.userFacing(this)) { _user.value = userRepository.retrieveUser() } } 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 12dae28ad..50d786ca8 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 @@ -8,6 +8,7 @@ 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 @@ -16,15 +17,16 @@ import javax.inject.Inject class TaskListViewModel @Inject constructor( savedStateHandle: SavedStateHandle, private val taskRepository: TaskRepository, - userRepository: UserRepository -) : BaseViewModel(userRepository) { + userRepository: UserRepository, + exceptionBuilder: ExceptionHandlerBuilder +) : BaseViewModel(userRepository, exceptionBuilder) { val _tasks = MutableLiveData>() val tasks: LiveData> = _tasks val taskType = TaskType.from(savedStateHandle.get("task_type")) init { - viewModelScope.launch { + viewModelScope.launch(exceptionBuilder.userFacing(this)) { _tasks.value = taskRepository.retrieveTasks()?.tasks?.values?.filter { it.type == taskType }?.toList() diff --git a/wearos/src/main/java/com/habitrpg/wearos/habitica/data/DateJSONAdapter.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/util/DateJSONAdapter.kt similarity index 100% rename from wearos/src/main/java/com/habitrpg/wearos/habitica/data/DateJSONAdapter.kt rename to wearos/src/main/java/com/habitrpg/wearos/habitica/util/DateJSONAdapter.kt diff --git a/wearos/src/main/java/com/habitrpg/wearos/habitica/util/ErrorPresenter.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/util/ErrorPresenter.kt new file mode 100644 index 000000000..1383598e9 --- /dev/null +++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/util/ErrorPresenter.kt @@ -0,0 +1,8 @@ +package com.habitrpg.wearos.habitica.util + +import androidx.lifecycle.MutableLiveData +import com.habitrpg.wearos.habitica.models.DisplayedError + +interface ErrorPresenter { + val errorValues: MutableLiveData +} diff --git a/wearos/src/main/java/com/habitrpg/wearos/habitica/util/HabiticaCoroutineExceptionhandler.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/util/HabiticaCoroutineExceptionhandler.kt new file mode 100644 index 000000000..5351ba9d3 --- /dev/null +++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/util/HabiticaCoroutineExceptionhandler.kt @@ -0,0 +1,22 @@ +package com.habitrpg.wearos.habitica.util + +import android.util.Log +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() { + fun silent(): CoroutineExceptionHandler { + return CoroutineExceptionHandler { context, throwable -> + Log.e(context.toString(), "Error: ${throwable.cause}", throwable) + } + } + + fun userFacing(errorPresenter: ErrorPresenter): CoroutineExceptionHandler { + return CoroutineExceptionHandler { _, throwable -> + errorPresenter.errorValues.value = throwable.message?.let { DisplayedError(it) } + } + } +} \ No newline at end of file