AssistantViewModel.kt 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. /*
  2. * Nextcloud - Android Client
  3. *
  4. * SPDX-FileCopyrightText: 2024 Alper Ozturk <alper_ozturk@proton.me>
  5. * SPDX-FileCopyrightText: 2024 Nextcloud GmbH
  6. * SPDX-License-Identifier: AGPL-3.0-or-later
  7. */
  8. package com.nextcloud.client.assistant
  9. import android.content.Context
  10. import androidx.lifecycle.ViewModel
  11. import androidx.lifecycle.viewModelScope
  12. import com.nextcloud.client.assistant.repository.AssistantRepositoryType
  13. import com.owncloud.android.R
  14. import com.owncloud.android.lib.resources.assistant.model.Task
  15. import com.owncloud.android.lib.resources.assistant.model.TaskType
  16. import kotlinx.coroutines.Dispatchers
  17. import kotlinx.coroutines.delay
  18. import kotlinx.coroutines.flow.MutableStateFlow
  19. import kotlinx.coroutines.flow.StateFlow
  20. import kotlinx.coroutines.flow.update
  21. import kotlinx.coroutines.launch
  22. import java.lang.ref.WeakReference
  23. class AssistantViewModel(
  24. private val repository: AssistantRepositoryType,
  25. private val context: WeakReference<Context>
  26. ) : ViewModel() {
  27. sealed class State {
  28. data object Idle : State()
  29. data object Loading : State()
  30. data class Error(val messageId: Int) : State()
  31. data class TaskCreated(val messageId: Int) : State()
  32. data class TaskDeleted(val messageId: Int) : State()
  33. }
  34. private val _state = MutableStateFlow<State>(State.Loading)
  35. val state: StateFlow<State> = _state
  36. private val _selectedTaskType = MutableStateFlow<TaskType?>(null)
  37. val selectedTaskType: StateFlow<TaskType?> = _selectedTaskType
  38. private val _taskTypes = MutableStateFlow<List<TaskType>?>(null)
  39. val taskTypes: StateFlow<List<TaskType>?> = _taskTypes
  40. private var _taskList: List<Task>? = null
  41. private val _filteredTaskList = MutableStateFlow<List<Task>?>(null)
  42. val filteredTaskList: StateFlow<List<Task>?> = _filteredTaskList
  43. init {
  44. fetchTaskTypes()
  45. fetchTaskList()
  46. }
  47. @Suppress("MagicNumber")
  48. fun createTask(
  49. input: String,
  50. type: String
  51. ) {
  52. viewModelScope.launch(Dispatchers.IO) {
  53. val result = repository.createTask(input, type)
  54. val messageId = if (result.isSuccess) {
  55. R.string.assistant_screen_task_create_success_message
  56. } else {
  57. R.string.assistant_screen_task_create_fail_message
  58. }
  59. _state.update {
  60. State.TaskCreated(messageId)
  61. }
  62. delay(2000L)
  63. fetchTaskList()
  64. }
  65. }
  66. fun selectTaskType(task: TaskType) {
  67. _selectedTaskType.update {
  68. filterTaskList(task.id)
  69. task
  70. }
  71. }
  72. private fun fetchTaskTypes() {
  73. viewModelScope.launch(Dispatchers.IO) {
  74. val allTaskType = context.get()?.getString(R.string.assistant_screen_all_task_type)
  75. val excludedIds = listOf("OCA\\ContextChat\\TextProcessing\\ContextChatTaskType")
  76. val result = arrayListOf(TaskType(null, allTaskType, null))
  77. val taskTypesResult = repository.getTaskTypes()
  78. if (taskTypesResult.isSuccess) {
  79. val excludedTaskTypes = taskTypesResult.resultData.types.filter { item -> item.id !in excludedIds }
  80. result.addAll(excludedTaskTypes)
  81. _taskTypes.update {
  82. result.toList()
  83. }
  84. selectTaskType(result.first())
  85. } else {
  86. _state.update {
  87. State.Error(R.string.assistant_screen_task_types_error_state_message)
  88. }
  89. }
  90. }
  91. }
  92. fun fetchTaskList(appId: String = "assistant", onCompleted: () -> Unit = {}) {
  93. viewModelScope.launch(Dispatchers.IO) {
  94. val result = repository.getTaskList(appId)
  95. if (result.isSuccess) {
  96. _taskList = result.resultData.tasks
  97. filterTaskList(_selectedTaskType.value?.id)
  98. _state.update {
  99. State.Idle
  100. }
  101. onCompleted()
  102. } else {
  103. _state.update {
  104. State.Error(R.string.assistant_screen_task_list_error_state_message)
  105. }
  106. }
  107. }
  108. }
  109. fun deleteTask(id: Long) {
  110. viewModelScope.launch(Dispatchers.IO) {
  111. val result = repository.deleteTask(id)
  112. val messageId = if (result.isSuccess) {
  113. R.string.assistant_screen_task_delete_success_message
  114. } else {
  115. R.string.assistant_screen_task_delete_fail_message
  116. }
  117. _state.update {
  118. State.TaskDeleted(messageId)
  119. }
  120. if (result.isSuccess) {
  121. removeTaskFromList(id)
  122. }
  123. }
  124. }
  125. fun resetState() {
  126. _state.update {
  127. State.Idle
  128. }
  129. }
  130. private fun filterTaskList(taskTypeId: String?) {
  131. if (taskTypeId == null) {
  132. _filteredTaskList.update {
  133. _taskList
  134. }
  135. } else {
  136. _filteredTaskList.update {
  137. _taskList?.filter { it.type == taskTypeId }
  138. }
  139. }
  140. _filteredTaskList.update {
  141. it?.sortedByDescending { task ->
  142. task.id
  143. }
  144. }
  145. }
  146. private fun removeTaskFromList(id: Long) {
  147. _filteredTaskList.update { currentList ->
  148. currentList?.filter { it.id != id }
  149. }
  150. }
  151. }