Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
7be3938
Change UI according to the latest adjustments
alperozturk96 Dec 2, 2024
e2fc6a7
Add task actions
alperozturk96 Dec 2, 2024
9de9f0d
add TaskActions
alperozturk96 Dec 2, 2024
b8055bc
add actions
alperozturk96 Dec 2, 2024
623ff84
clear unnecessary logic
alperozturk96 Dec 2, 2024
a4c36f1
complete more actions
alperozturk96 Dec 2, 2024
8f71899
add more actions to the detail view
alperozturk96 Dec 2, 2024
bab98b4
modal bottom sheet appereance fix
alperozturk96 Dec 2, 2024
baba9e0
Handle states better
alperozturk96 Dec 3, 2024
d620123
Add time completion to the task status
alperozturk96 Dec 3, 2024
f7bfaa5
adopt latest api changes
alperozturk96 Dec 3, 2024
ded9384
only use text context
alperozturk96 Dec 3, 2024
312e793
fix add operation
alperozturk96 Dec 3, 2024
4796b67
remove combined click
alperozturk96 Dec 3, 2024
ac3c735
Use task types for create operation
alperozturk96 Dec 4, 2024
21ef735
use response key for id
alperozturk96 Dec 4, 2024
2ca151d
Fix bottom sheet title appereance
alperozturk96 Dec 4, 2024
51b5add
Fix code analytics
alperozturk96 Dec 4, 2024
8f69816
update library
alperozturk96 Dec 4, 2024
92c99b2
decouple business logic from the ui
alperozturk96 Dec 4, 2024
3cffeee
update tests
alperozturk96 Dec 4, 2024
8d4a34c
Create DateFormatter extract date related logic from Task extensions
alperozturk96 Dec 4, 2024
06af708
Get rid of unncessary state for task view
alperozturk96 Dec 4, 2024
fb087b5
remove unused keys
alperozturk96 Dec 4, 2024
e0ac903
remove unused icon for assistant (lint warning)
alperozturk96 Dec 4, 2024
41b06cc
fix code analytics
alperozturk96 Dec 4, 2024
561c6d1
use native tab layout
alperozturk96 Dec 4, 2024
0d53be7
fix colors
alperozturk96 Dec 4, 2024
98529dc
fix colors
alperozturk96 Dec 4, 2024
54cc4f8
fix code analytics
alperozturk96 Dec 4, 2024
06b8db9
update library
alperozturk96 Dec 9, 2024
2d53e53
use input and output together for share and copy
alperozturk96 Dec 9, 2024
9801624
change title of the add new task
alperozturk96 Dec 9, 2024
ddcd223
update ss
alperozturk96 Dec 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ package com.nextcloud.client.assistant

import com.nextcloud.client.assistant.repository.AssistantRepository
import com.owncloud.android.AbstractOnServerIT
import com.owncloud.android.lib.resources.assistant.model.TaskTypeData
import com.owncloud.android.lib.resources.status.NextcloudVersion
import org.junit.Assert.assertTrue
import org.junit.Before
Expand All @@ -35,7 +36,7 @@ class AssistantRepositoryTests : AbstractOnServerIT() {
val result = sut?.getTaskTypes()
assertTrue(result?.isSuccess == true)

val taskTypes = result?.resultData?.types
val taskTypes = result?.resultData
assertTrue(taskTypes?.isNotEmpty() == true)
}

Expand Down Expand Up @@ -63,8 +64,14 @@ class AssistantRepositoryTests : AbstractOnServerIT() {
}

val input = "Give me some random output for test purpose"
val type = "OCP\\TextProcessing\\FreePromptTaskType"
val result = sut?.createTask(input, type)
val taskType = TaskTypeData(
"core:text2text",
"Free text to text prompt",
"Runs an arbitrary prompt through a language model that returns a reply",
null,
null
)
val result = sut?.createTask(input, taskType)
assertTrue(result?.isSuccess == true)
}

Expand Down
127 changes: 53 additions & 74 deletions app/src/main/java/com/nextcloud/client/assistant/AssistantViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,129 +7,122 @@
*/
package com.nextcloud.client.assistant

import android.content.Context
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.nextcloud.client.assistant.model.ScreenOverlayState
import com.nextcloud.client.assistant.model.ScreenState
import com.nextcloud.client.assistant.repository.AssistantRepositoryType
import com.owncloud.android.R
import com.owncloud.android.lib.resources.assistant.model.Task
import com.owncloud.android.lib.resources.assistant.model.TaskType
import com.owncloud.android.lib.resources.assistant.model.TaskTypeData
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import java.lang.ref.WeakReference

class AssistantViewModel(
private val repository: AssistantRepositoryType,
private val context: WeakReference<Context>
private val repository: AssistantRepositoryType
) : ViewModel() {

sealed class State {
data object Idle : State()
data object Loading : State()
data class Error(val messageId: Int) : State()
data class TaskCreated(val messageId: Int) : State()
data class TaskDeleted(val messageId: Int) : State()
}
private val _screenState = MutableStateFlow<ScreenState?>(null)
val screenState: StateFlow<ScreenState?> = _screenState

private val _screenOverlayState = MutableStateFlow<ScreenOverlayState?>(null)
val screenOverlayState: StateFlow<ScreenOverlayState?> = _screenOverlayState

private val _state = MutableStateFlow<State>(State.Loading)
val state: StateFlow<State> = _state
private val _snackbarMessageId = MutableStateFlow<Int?>(null)
val snackbarMessageId: StateFlow<Int?> = _snackbarMessageId

private val _selectedTaskType = MutableStateFlow<TaskType?>(null)
val selectedTaskType: StateFlow<TaskType?> = _selectedTaskType
private val _selectedTaskType = MutableStateFlow<TaskTypeData?>(null)
val selectedTaskType: StateFlow<TaskTypeData?> = _selectedTaskType

private val _taskTypes = MutableStateFlow<List<TaskType>?>(null)
val taskTypes: StateFlow<List<TaskType>?> = _taskTypes
private val _taskTypes = MutableStateFlow<List<TaskTypeData>?>(null)
val taskTypes: StateFlow<List<TaskTypeData>?> = _taskTypes

private var taskList: List<Task>? = null

private val _filteredTaskList = MutableStateFlow<List<Task>?>(null)
val filteredTaskList: StateFlow<List<Task>?> = _filteredTaskList

private val _isRefreshing = MutableStateFlow(false)
val isRefreshing: StateFlow<Boolean> = _isRefreshing

init {
fetchTaskTypes()
fetchTaskList()
}

@Suppress("MagicNumber")
fun createTask(input: String, type: String) {
fun createTask(input: String, taskType: TaskTypeData) {
viewModelScope.launch(Dispatchers.IO) {
val result = repository.createTask(input, type)
val result = repository.createTask(input, taskType)

val messageId = if (result.isSuccess) {
R.string.assistant_screen_task_create_success_message
} else {
R.string.assistant_screen_task_create_fail_message
}

_state.update {
State.TaskCreated(messageId)
}
updateSnackbarMessage(messageId)

delay(2000L)
fetchTaskList()
}
}

fun selectTaskType(task: TaskType) {
fun selectTaskType(task: TaskTypeData) {
_selectedTaskType.update {
filterTaskList(task.id)
task
}

fetchTaskList()
}

private fun fetchTaskTypes() {
viewModelScope.launch(Dispatchers.IO) {
val allTaskType = context.get()?.getString(R.string.assistant_screen_all_task_type)
val excludedIds = listOf("OCA\\ContextChat\\TextProcessing\\ContextChatTaskType")
val result = arrayListOf(TaskType(null, allTaskType, null))
val taskTypesResult = repository.getTaskTypes()

if (taskTypesResult.isSuccess) {
val excludedTaskTypes = taskTypesResult.resultData.types.filter { item -> item.id !in excludedIds }
result.addAll(excludedTaskTypes)
val result = taskTypesResult.resultData
_taskTypes.update {
result.toList()
result
}

selectTaskType(result.first())
} else {
_state.update {
State.Error(R.string.assistant_screen_task_types_error_state_message)
}
updateSnackbarMessage(R.string.assistant_screen_task_types_error_state_message)
}
}
}

fun fetchTaskList(appId: String = "assistant") {
fun fetchTaskList() {
viewModelScope.launch(Dispatchers.IO) {
_isRefreshing.update {
true
_screenState.update {
ScreenState.Refreshing
}

val result = repository.getTaskList(appId)
val taskType = _selectedTaskType.value?.id ?: return@launch
val result = repository.getTaskList(taskType)
if (result.isSuccess) {
taskList = result.resultData.tasks

filterTaskList(_selectedTaskType.value?.id)

_state.update {
State.Idle
taskList = result.resultData.tasks.filter { it.appId == "assistant" }
_filteredTaskList.update {
taskList?.sortedByDescending { task ->
task.id
}
}
updateSnackbarMessage(null)
} else {
_state.update {
State.Error(R.string.assistant_screen_task_list_error_state_message)
}
updateSnackbarMessage(R.string.assistant_screen_task_list_error_state_message)
}

_isRefreshing.update {
false
updateScreenState()
}
}

private fun updateScreenState() {
_screenState.update {
if (_filteredTaskList.value?.isEmpty() == true) {
ScreenState.EmptyContent
} else {
ScreenState.Content
}
}
}
Expand All @@ -144,37 +137,23 @@ class AssistantViewModel(
R.string.assistant_screen_task_delete_fail_message
}

_state.update {
State.TaskDeleted(messageId)
}
updateSnackbarMessage(messageId)

if (result.isSuccess) {
removeTaskFromList(id)
}
}
}

fun resetState() {
_state.update {
State.Idle
fun updateSnackbarMessage(value: Int?) {
_snackbarMessageId.update {
value
}
}

private fun filterTaskList(taskTypeId: String?) {
if (taskTypeId == null) {
_filteredTaskList.update {
taskList
}
} else {
_filteredTaskList.update {
taskList?.filter { it.type == taskTypeId }
}
}

_filteredTaskList.update {
it?.sortedByDescending { task ->
task.id
}
fun updateScreenState(value: ScreenOverlayState?) {
_screenOverlayState.update {
value
}
}

Expand Down
Loading
Loading