From 7be3938798853e5b3095b3a18c20b4b9ef3fd855 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Mon, 2 Dec 2024 13:37:08 +0100 Subject: [PATCH 01/34] Change UI according to the latest adjustments Signed-off-by: alperozturk --- .../client/assistant/task/TaskView.kt | 80 ++++++++++++------- .../assistant/task/TaskViewBottomSheetType.kt | 12 +++ 2 files changed, 65 insertions(+), 27 deletions(-) create mode 100644 app/src/main/java/com/nextcloud/client/assistant/task/TaskViewBottomSheetType.kt diff --git a/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt b/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt index cdc5c28476..ea4469e78f 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt @@ -17,8 +17,8 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -29,12 +29,13 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.nextcloud.client.assistant.taskDetail.TaskDetailBottomSheet import com.nextcloud.ui.composeComponents.bottomSheet.MoreActionsBottomSheet -import com.nextcloud.utils.extensions.getRandomString import com.owncloud.android.R import com.owncloud.android.lib.resources.assistant.model.Task @@ -42,20 +43,19 @@ import com.owncloud.android.lib.resources.assistant.model.Task @Suppress("LongMethod", "MagicNumber") @Composable fun TaskView(task: Task, showDeleteTaskAlertDialog: (Long) -> Unit) { - var showTaskDetailBottomSheet by remember { mutableStateOf(false) } - var showMoreActionsBottomSheet by remember { mutableStateOf(false) } + var bottomSheetType by remember { mutableStateOf(null) } Column( modifier = Modifier .fillMaxWidth() - .clip(RoundedCornerShape(16.dp)) + .clip(RoundedCornerShape(8.dp)) .background(MaterialTheme.colorScheme.primary) .combinedClickable(onClick = { - showTaskDetailBottomSheet = true + bottomSheetType = TaskViewBottomSheetType.Detail }, onLongClick = { - showMoreActionsBottomSheet = true + bottomSheetType = TaskViewBottomSheetType.MoreAction }) - .padding(start = 8.dp) + .padding(16.dp) ) { Spacer(modifier = Modifier.height(8.dp)) @@ -63,21 +63,28 @@ fun TaskView(task: Task, showDeleteTaskAlertDialog: (Long) -> Unit) { Text( text = it, color = Color.White, - fontSize = 18.sp + fontSize = 18.sp, + textAlign = TextAlign.Left, + fontWeight = FontWeight.Bold, + modifier = Modifier.width(300.dp) ) } - Spacer(modifier = Modifier.height(16.dp)) + Spacer(modifier = Modifier.height(12.dp)) task.output?.let { - HorizontalDivider(modifier = Modifier.padding(horizontal = 4.dp, vertical = 8.dp)) + val output = if (it.length >= 100) { + it.take(100) + "..." + } else { + it + } Text( - text = it.take(100), - fontSize = 12.sp, + text = output, + fontSize = 18.sp, color = Color.White, + textAlign = TextAlign.Left, modifier = Modifier - .height(100.dp) .animateContentSize( animationSpec = spring( dampingRatio = Spring.DampingRatioLowBouncy, @@ -89,28 +96,48 @@ fun TaskView(task: Task, showDeleteTaskAlertDialog: (Long) -> Unit) { TaskStatus(task, foregroundColor = Color.White) - if (showMoreActionsBottomSheet) { + bottomSheetType?.let { + TaskViewBottomSheet(it, task, showDeleteTaskAlertDialog = { + showDeleteTaskAlertDialog(task.id) + }, dismiss = { + bottomSheetType = null + }) + } + } +} + +@Composable +private fun TaskViewBottomSheet( + bottomSheetType: TaskViewBottomSheetType, + task: Task, + showDeleteTaskAlertDialog: () -> Unit, + dismiss: () -> Unit +) { + when (bottomSheetType) { + TaskViewBottomSheetType.Detail -> { + TaskDetailBottomSheet(task) { + dismiss() + } + } + + TaskViewBottomSheetType.MoreAction -> { val bottomSheetAction = listOf( Triple( R.drawable.ic_delete, R.string.assistant_screen_task_more_actions_bottom_sheet_delete_action ) { - showDeleteTaskAlertDialog(task.id) + showDeleteTaskAlertDialog() } ) MoreActionsBottomSheet( title = task.input, actions = bottomSheetAction, - dismiss = { showMoreActionsBottomSheet = false } + dismiss = { + dismiss() + } ) } - - if (showTaskDetailBottomSheet) { - TaskDetailBottomSheet(task) { - showTaskDetailBottomSheet = false - } - } } } @@ -118,8 +145,6 @@ fun TaskView(task: Task, showDeleteTaskAlertDialog: (Long) -> Unit) { @Preview @Composable private fun TaskViewPreview() { - val output = "Lorem".getRandomString(100) - TaskView( task = Task( 1, @@ -127,8 +152,9 @@ private fun TaskViewPreview() { 0, "1", "1", - "Give me text", - output, + "What about other promising tokens like", + "Several tokens show promise for future growth in the" + + "cryptocurrency market", "", "" ) diff --git a/app/src/main/java/com/nextcloud/client/assistant/task/TaskViewBottomSheetType.kt b/app/src/main/java/com/nextcloud/client/assistant/task/TaskViewBottomSheetType.kt new file mode 100644 index 0000000000..0a2412f028 --- /dev/null +++ b/app/src/main/java/com/nextcloud/client/assistant/task/TaskViewBottomSheetType.kt @@ -0,0 +1,12 @@ +/* + * Nextcloud - Android Client + * + * SPDX-FileCopyrightText: 2024 Alper Ozturk + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package com.nextcloud.client.assistant.task + +enum class TaskViewBottomSheetType { + Detail, MoreAction +} From e2fc6a74d89237c0420c5e1735c37919717b9834 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Mon, 2 Dec 2024 14:14:31 +0100 Subject: [PATCH 02/34] Add task actions Signed-off-by: alperozturk --- .../client/assistant/AsssistantScreen.kt | 7 +- .../client/assistant/task/TaskView.kt | 133 ++++++++++-------- 2 files changed, 84 insertions(+), 56 deletions(-) diff --git a/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt b/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt index 70c85cae91..d95d68aa9f 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt @@ -207,7 +207,12 @@ private fun AssistantContent( } items(taskList) { task -> - TaskView(task, showDeleteTaskAlertDialog = { showDeleteTaskAlertDialog(task.id) }) + TaskView(task, + showDeleteTaskAlertDialog = { showDeleteTaskAlertDialog(task.id) }, + showTaskActions = { + + } + ) Spacer(modifier = Modifier.height(8.dp)) } } diff --git a/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt b/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt index ea4469e78f..d96d62e1ee 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt @@ -12,6 +12,7 @@ import androidx.compose.animation.core.spring import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background import androidx.compose.foundation.combinedClickable +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth @@ -19,6 +20,10 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.MoreVert +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -26,6 +31,7 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color @@ -42,66 +48,80 @@ import com.owncloud.android.lib.resources.assistant.model.Task @OptIn(ExperimentalFoundationApi::class) @Suppress("LongMethod", "MagicNumber") @Composable -fun TaskView(task: Task, showDeleteTaskAlertDialog: (Long) -> Unit) { +fun TaskView(task: Task, showDeleteTaskAlertDialog: (Long) -> Unit, showTaskActions: () -> Unit) { var bottomSheetType by remember { mutableStateOf(null) } - Column( - modifier = Modifier - .fillMaxWidth() - .clip(RoundedCornerShape(8.dp)) - .background(MaterialTheme.colorScheme.primary) - .combinedClickable(onClick = { - bottomSheetType = TaskViewBottomSheetType.Detail - }, onLongClick = { - bottomSheetType = TaskViewBottomSheetType.MoreAction - }) - .padding(16.dp) - ) { - Spacer(modifier = Modifier.height(8.dp)) + Box { + Column( + modifier = Modifier + .fillMaxWidth() + .clip(RoundedCornerShape(8.dp)) + .background(MaterialTheme.colorScheme.primary) + .combinedClickable(onClick = { + bottomSheetType = TaskViewBottomSheetType.Detail + }, onLongClick = { + bottomSheetType = TaskViewBottomSheetType.MoreAction + }) + .padding(16.dp) + ) { + Spacer(modifier = Modifier.height(8.dp)) - task.input?.let { - Text( - text = it, - color = Color.White, - fontSize = 18.sp, - textAlign = TextAlign.Left, - fontWeight = FontWeight.Bold, - modifier = Modifier.width(300.dp) - ) - } - - Spacer(modifier = Modifier.height(12.dp)) - - task.output?.let { - val output = if (it.length >= 100) { - it.take(100) + "..." - } else { - it + task.input?.let { + Text( + text = it, + color = Color.White, + fontSize = 18.sp, + textAlign = TextAlign.Left, + fontWeight = FontWeight.Bold, + modifier = Modifier.width(300.dp) + ) } - Text( - text = output, - fontSize = 18.sp, - color = Color.White, - textAlign = TextAlign.Left, - modifier = Modifier - .animateContentSize( - animationSpec = spring( - dampingRatio = Spring.DampingRatioLowBouncy, - stiffness = Spring.StiffnessLow + Spacer(modifier = Modifier.height(12.dp)) + + task.output?.let { + val output = if (it.length >= 100) { + it.take(100) + "..." + } else { + it + } + + Text( + text = output, + fontSize = 18.sp, + color = Color.White, + textAlign = TextAlign.Left, + modifier = Modifier + .animateContentSize( + animationSpec = spring( + dampingRatio = Spring.DampingRatioLowBouncy, + stiffness = Spring.StiffnessLow + ) ) - ) - ) + ) + } + + TaskStatus(task, foregroundColor = Color.White) + + bottomSheetType?.let { + TaskViewBottomSheet(it, task, showDeleteTaskAlertDialog = { + showDeleteTaskAlertDialog(task.id) + }, dismiss = { + bottomSheetType = null + }) + } } - TaskStatus(task, foregroundColor = Color.White) - - bottomSheetType?.let { - TaskViewBottomSheet(it, task, showDeleteTaskAlertDialog = { - showDeleteTaskAlertDialog(task.id) - }, dismiss = { - bottomSheetType = null - }) + IconButton( + modifier = Modifier.align(Alignment.TopEnd), + onClick = showTaskActions + ) + { + Icon( + imageVector = Icons.Filled.MoreVert, + contentDescription = "More button", + tint = Color.White + ) } } } @@ -157,7 +177,10 @@ private fun TaskViewPreview() { "cryptocurrency market", "", "" - ) - ) { - } + ), showTaskActions = { + + }, showDeleteTaskAlertDialog = { + + } + ) } From 9de9f0d0f5bd935eafa87b883a42dc180a999051 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Mon, 2 Dec 2024 15:00:21 +0100 Subject: [PATCH 03/34] add TaskActions Signed-off-by: alperozturk --- .../client/assistant/AssistantViewModel.kt | 74 ++++++++---- .../client/assistant/AsssistantScreen.kt | 107 ++++++++++-------- .../task/{TaskStatus.kt => TaskStatusView.kt} | 2 +- .../client/assistant/task/TaskView.kt | 3 +- .../{ => model}/TaskViewBottomSheetType.kt | 2 +- .../taskDetail/TaskDetailBottomSheet.kt | 4 +- 6 files changed, 118 insertions(+), 74 deletions(-) rename app/src/main/java/com/nextcloud/client/assistant/task/{TaskStatus.kt => TaskStatusView.kt} (97%) rename app/src/main/java/com/nextcloud/client/assistant/task/{ => model}/TaskViewBottomSheetType.kt (81%) diff --git a/app/src/main/java/com/nextcloud/client/assistant/AssistantViewModel.kt b/app/src/main/java/com/nextcloud/client/assistant/AssistantViewModel.kt index b7894b6d12..797bb15cdd 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/AssistantViewModel.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/AssistantViewModel.kt @@ -27,16 +27,24 @@ class AssistantViewModel( private val context: WeakReference ) : 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() + sealed class MessageState { + data object Loading : MessageState() + data class Error(val messageId: Int) : MessageState() + data class TaskCreated(val messageId: Int) : MessageState() + data class TaskDeleted(val messageId: Int) : MessageState() } - private val _state = MutableStateFlow(State.Loading) - val state: StateFlow = _state + sealed class ScreenState { + data class DeleteTask(val id: Long): ScreenState() + data class AddTask(val taskType: TaskType): ScreenState() + data class TaskActions(val task: Task): ScreenState() + } + + private val _screenState = MutableStateFlow(null) + val screenState: StateFlow = _screenState + + private val _messageState = MutableStateFlow(MessageState.Loading) + val messageState: StateFlow = _messageState private val _selectedTaskType = MutableStateFlow(null) val selectedTaskType: StateFlow = _selectedTaskType @@ -68,8 +76,8 @@ class AssistantViewModel( R.string.assistant_screen_task_create_fail_message } - _state.update { - State.TaskCreated(messageId) + _messageState.update { + MessageState.TaskCreated(messageId) } delay(2000L) @@ -100,8 +108,8 @@ class AssistantViewModel( selectTaskType(result.first()) } else { - _state.update { - State.Error(R.string.assistant_screen_task_types_error_state_message) + _messageState.update { + MessageState.Error(R.string.assistant_screen_task_types_error_state_message) } } } @@ -119,12 +127,12 @@ class AssistantViewModel( filterTaskList(_selectedTaskType.value?.id) - _state.update { - State.Idle + _messageState.update { + null } } else { - _state.update { - State.Error(R.string.assistant_screen_task_list_error_state_message) + _messageState.update { + MessageState.Error(R.string.assistant_screen_task_list_error_state_message) } } @@ -144,8 +152,8 @@ class AssistantViewModel( R.string.assistant_screen_task_delete_fail_message } - _state.update { - State.TaskDeleted(messageId) + _messageState.update { + MessageState.TaskDeleted(messageId) } if (result.isSuccess) { @@ -154,9 +162,33 @@ class AssistantViewModel( } } - fun resetState() { - _state.update { - State.Idle + fun resetMessageState() { + _messageState.update { + null + } + } + + fun resetAlertDialogState() { + _screenState.update { + null + } + } + + fun showDeleteTaskAlertDialog(id: Long) { + _screenState.update { + ScreenState.DeleteTask(id) + } + } + + fun showAddTaskAlertDialog(taskType: TaskType) { + _screenState.update { + ScreenState.AddTask(taskType) + } + } + + fun showTaskActionsBottomSheet(task: Task) { + _screenState.update { + ScreenState.TaskActions(task) } } diff --git a/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt b/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt index d95d68aa9f..8c32b60460 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt @@ -30,10 +30,7 @@ import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext @@ -47,6 +44,7 @@ import com.nextcloud.client.assistant.task.TaskView import com.nextcloud.client.assistant.taskTypes.TaskTypesRow import com.nextcloud.ui.composeActivity.ComposeActivity import com.nextcloud.ui.composeComponents.alertDialog.SimpleAlertDialog +import com.nextcloud.ui.composeComponents.bottomSheet.MoreActionsBottomSheet import com.owncloud.android.R import com.owncloud.android.lib.resources.assistant.model.Task import com.owncloud.android.lib.resources.assistant.model.TaskType @@ -59,16 +57,13 @@ import java.lang.ref.WeakReference @OptIn(ExperimentalMaterial3Api::class) @Composable fun AssistantScreen(viewModel: AssistantViewModel, activity: Activity) { - val state by viewModel.state.collectAsState() + val messageState by viewModel.messageState.collectAsState() + val alertDialogState by viewModel.screenState.collectAsState() + val selectedTaskType by viewModel.selectedTaskType.collectAsState() val filteredTaskList by viewModel.filteredTaskList.collectAsState() val isRefreshing by viewModel.isRefreshing.collectAsState() val taskTypes by viewModel.taskTypes.collectAsState() - var showAddTaskAlertDialog by remember { mutableStateOf(false) } - var showDeleteTaskAlertDialog by remember { mutableStateOf(false) } - var taskIdToDeleted: Long? by remember { - mutableStateOf(null) - } val scope = rememberCoroutineScope() val pullRefreshState = rememberPullToRefreshState() @@ -81,7 +76,7 @@ fun AssistantScreen(viewModel: AssistantViewModel, activity: Activity) { } }) ) { - if (state == AssistantViewModel.State.Loading || isRefreshing) { + if (messageState == AssistantViewModel.MessageState.Loading || isRefreshing) { CenterText(text = stringResource(id = R.string.assistant_screen_loading)) } else { if (filteredTaskList.isNullOrEmpty()) { @@ -91,11 +86,7 @@ fun AssistantScreen(viewModel: AssistantViewModel, activity: Activity) { filteredTaskList!!, taskTypes, selectedTaskType, - viewModel, - showDeleteTaskAlertDialog = { taskId -> - taskIdToDeleted = taskId - showDeleteTaskAlertDialog = true - } + viewModel ) } } @@ -115,7 +106,9 @@ fun AssistantScreen(viewModel: AssistantViewModel, activity: Activity) { .align(Alignment.BottomEnd) .padding(16.dp), onClick = { - showAddTaskAlertDialog = true + selectedTaskType?.let { + viewModel.showAddTaskAlertDialog(it) + } } ) { Icon(Icons.Filled.Add, "Add Task Icon") @@ -123,49 +116,70 @@ fun AssistantScreen(viewModel: AssistantViewModel, activity: Activity) { } } - ScreenState(state, activity, viewModel) + HandleMessageState(messageState, activity, viewModel) + ScreenState(alertDialogState, viewModel) +} - if (showDeleteTaskAlertDialog) { - taskIdToDeleted?.let { id -> - SimpleAlertDialog( - title = stringResource(id = R.string.assistant_screen_delete_task_alert_dialog_title), - description = stringResource(id = R.string.assistant_screen_delete_task_alert_dialog_description), - dismiss = { showDeleteTaskAlertDialog = false }, - onComplete = { viewModel.deleteTask(id) } - ) - } - } - - if (showAddTaskAlertDialog) { - selectedTaskType?.let { taskType -> +@Composable +private fun ScreenState(state: AssistantViewModel.ScreenState?, viewModel: AssistantViewModel) { + when(state) { + is AssistantViewModel.ScreenState.AddTask -> { AddTaskAlertDialog( - title = taskType.name, - description = taskType.description, + title = state.taskType.name, + description = state.taskType.description, addTask = { input -> - taskType.id?.let { + state.taskType.id?.let { viewModel.createTask(input = input, type = it) } }, dismiss = { - showAddTaskAlertDialog = false + viewModel.resetAlertDialogState() } ) } + + is AssistantViewModel.ScreenState.DeleteTask -> { + SimpleAlertDialog( + title = stringResource(id = R.string.assistant_screen_delete_task_alert_dialog_title), + description = stringResource(id = R.string.assistant_screen_delete_task_alert_dialog_description), + dismiss = { viewModel.resetAlertDialogState() }, + onComplete = { viewModel.deleteTask(state.id) } + ) + } + + is AssistantViewModel.ScreenState.TaskActions -> { + val bottomSheetAction = listOf( + Triple( + R.drawable.ic_delete, + R.string.assistant_screen_task_more_actions_bottom_sheet_delete_action + ) { + + } + ) + + MoreActionsBottomSheet( + title = state.task.input, + actions = bottomSheetAction, + dismiss = { viewModel.resetAlertDialogState() } + ) + } + + else -> Unit } } @Composable -private fun ScreenState(state: AssistantViewModel.State, activity: Activity, viewModel: AssistantViewModel) { - val messageId: Int? = when (state) { - is AssistantViewModel.State.Error -> { +private fun HandleMessageState(state: AssistantViewModel.MessageState?, activity: Activity, viewModel: AssistantViewModel) { + val messageStateId: Int? = when (state) { + is AssistantViewModel.MessageState.Error -> { state.messageId } - is AssistantViewModel.State.TaskCreated -> { + is AssistantViewModel.MessageState.TaskCreated -> { state.messageId } - is AssistantViewModel.State.TaskDeleted -> { + is AssistantViewModel.MessageState.TaskDeleted -> { state.messageId } @@ -174,13 +188,13 @@ private fun ScreenState(state: AssistantViewModel.State, activity: Activity, vie } } - messageId?.let { + messageStateId?.let { DisplayUtils.showSnackMessage( activity, - stringResource(id = messageId) + stringResource(id = messageStateId) ) - viewModel.resetState() + viewModel.resetMessageState() } } @@ -190,8 +204,7 @@ private fun AssistantContent( taskList: List, taskTypes: List?, selectedTaskType: TaskType?, - viewModel: AssistantViewModel, - showDeleteTaskAlertDialog: (Long) -> Unit + viewModel: AssistantViewModel ) { LazyColumn( modifier = Modifier @@ -208,10 +221,8 @@ private fun AssistantContent( items(taskList) { task -> TaskView(task, - showDeleteTaskAlertDialog = { showDeleteTaskAlertDialog(task.id) }, - showTaskActions = { - - } + showDeleteTaskAlertDialog = { viewModel.showDeleteTaskAlertDialog(task.id) }, + showTaskActions = { viewModel.showTaskActionsBottomSheet(task) } ) Spacer(modifier = Modifier.height(8.dp)) } diff --git a/app/src/main/java/com/nextcloud/client/assistant/task/TaskStatus.kt b/app/src/main/java/com/nextcloud/client/assistant/task/TaskStatusView.kt similarity index 97% rename from app/src/main/java/com/nextcloud/client/assistant/task/TaskStatus.kt rename to app/src/main/java/com/nextcloud/client/assistant/task/TaskStatusView.kt index f3de443b42..6cc8c81183 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/task/TaskStatus.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/task/TaskStatusView.kt @@ -27,7 +27,7 @@ import com.nextcloud.client.assistant.extensions.statusData import com.owncloud.android.lib.resources.assistant.model.Task @Composable -fun TaskStatus(task: Task, foregroundColor: Color) { +fun TaskStatusView(task: Task, foregroundColor: Color) { Row( modifier = Modifier .fillMaxWidth() diff --git a/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt b/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt index d96d62e1ee..5d960b934f 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt @@ -40,6 +40,7 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import com.nextcloud.client.assistant.task.model.TaskViewBottomSheetType import com.nextcloud.client.assistant.taskDetail.TaskDetailBottomSheet import com.nextcloud.ui.composeComponents.bottomSheet.MoreActionsBottomSheet import com.owncloud.android.R @@ -101,7 +102,7 @@ fun TaskView(task: Task, showDeleteTaskAlertDialog: (Long) -> Unit, showTaskActi ) } - TaskStatus(task, foregroundColor = Color.White) + TaskStatusView(task, foregroundColor = Color.White) bottomSheetType?.let { TaskViewBottomSheet(it, task, showDeleteTaskAlertDialog = { diff --git a/app/src/main/java/com/nextcloud/client/assistant/task/TaskViewBottomSheetType.kt b/app/src/main/java/com/nextcloud/client/assistant/task/model/TaskViewBottomSheetType.kt similarity index 81% rename from app/src/main/java/com/nextcloud/client/assistant/task/TaskViewBottomSheetType.kt rename to app/src/main/java/com/nextcloud/client/assistant/task/model/TaskViewBottomSheetType.kt index 0a2412f028..9df4c13aeb 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/task/TaskViewBottomSheetType.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/task/model/TaskViewBottomSheetType.kt @@ -5,7 +5,7 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ -package com.nextcloud.client.assistant.task +package com.nextcloud.client.assistant.task.model enum class TaskViewBottomSheetType { Detail, MoreAction diff --git a/app/src/main/java/com/nextcloud/client/assistant/taskDetail/TaskDetailBottomSheet.kt b/app/src/main/java/com/nextcloud/client/assistant/taskDetail/TaskDetailBottomSheet.kt index 5912b332dc..dcd03dde6c 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/taskDetail/TaskDetailBottomSheet.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/taskDetail/TaskDetailBottomSheet.kt @@ -40,7 +40,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import com.nextcloud.client.assistant.task.TaskStatus +import com.nextcloud.client.assistant.task.TaskStatusView import com.nextcloud.utils.extensions.getRandomString import com.owncloud.android.R import com.owncloud.android.lib.resources.assistant.model.Task @@ -113,7 +113,7 @@ fun TaskDetailBottomSheet(task: Task, dismiss: () -> Unit) { ) } - TaskStatus(task, foregroundColor = MaterialTheme.colorScheme.onPrimaryContainer) + TaskStatusView(task, foregroundColor = MaterialTheme.colorScheme.onPrimaryContainer) Spacer(modifier = Modifier.height(32.dp)) } From b8055bcf6501e80b78ff6f3741c2371398563375 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Mon, 2 Dec 2024 15:38:00 +0100 Subject: [PATCH 04/34] add actions Signed-off-by: alperozturk --- .../client/assistant/AssistantViewModel.kt | 53 ++++------------ .../client/assistant/AsssistantScreen.kt | 61 +++++++++++++++---- .../assistant/component/AddTaskAlertDialog.kt | 10 ++- .../bottomSheet/MoreActionsBottomSheet.kt | 8 ++- 4 files changed, 75 insertions(+), 57 deletions(-) diff --git a/app/src/main/java/com/nextcloud/client/assistant/AssistantViewModel.kt b/app/src/main/java/com/nextcloud/client/assistant/AssistantViewModel.kt index 797bb15cdd..de075f05aa 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/AssistantViewModel.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/AssistantViewModel.kt @@ -36,7 +36,7 @@ class AssistantViewModel( sealed class ScreenState { data class DeleteTask(val id: Long): ScreenState() - data class AddTask(val taskType: TaskType): ScreenState() + data class AddTask(val taskType: TaskType, val input: String): ScreenState() data class TaskActions(val task: Task): ScreenState() } @@ -76,9 +76,8 @@ class AssistantViewModel( R.string.assistant_screen_task_create_fail_message } - _messageState.update { - MessageState.TaskCreated(messageId) - } + val message = MessageState.TaskCreated(messageId) + updateMessageState(message) delay(2000L) fetchTaskList() @@ -108,9 +107,8 @@ class AssistantViewModel( selectTaskType(result.first()) } else { - _messageState.update { - MessageState.Error(R.string.assistant_screen_task_types_error_state_message) - } + val message = MessageState.Error(R.string.assistant_screen_task_types_error_state_message) + updateMessageState(message) } } } @@ -124,16 +122,11 @@ class AssistantViewModel( val result = repository.getTaskList(appId) if (result.isSuccess) { taskList = result.resultData.tasks - filterTaskList(_selectedTaskType.value?.id) - - _messageState.update { - null - } + updateMessageState(null) } else { - _messageState.update { - MessageState.Error(R.string.assistant_screen_task_list_error_state_message) - } + val message = MessageState.Error(R.string.assistant_screen_task_list_error_state_message) + updateMessageState(message) } _isRefreshing.update { @@ -152,9 +145,7 @@ class AssistantViewModel( R.string.assistant_screen_task_delete_fail_message } - _messageState.update { - MessageState.TaskDeleted(messageId) - } + updateMessageState(MessageState.TaskDeleted(messageId)) if (result.isSuccess) { removeTaskFromList(id) @@ -162,33 +153,15 @@ class AssistantViewModel( } } - fun resetMessageState() { + fun updateMessageState(value: MessageState?) { _messageState.update { - null + value } } - fun resetAlertDialogState() { + fun updateScreenState(value: ScreenState?) { _screenState.update { - null - } - } - - fun showDeleteTaskAlertDialog(id: Long) { - _screenState.update { - ScreenState.DeleteTask(id) - } - } - - fun showAddTaskAlertDialog(taskType: TaskType) { - _screenState.update { - ScreenState.AddTask(taskType) - } - } - - fun showTaskActionsBottomSheet(task: Task) { - _screenState.update { - ScreenState.TaskActions(task) + value } } diff --git a/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt b/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt index 8c32b60460..412618c7c0 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt @@ -8,6 +8,7 @@ package com.nextcloud.client.assistant import android.app.Activity +import android.content.Intent import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -48,6 +49,7 @@ import com.nextcloud.ui.composeComponents.bottomSheet.MoreActionsBottomSheet 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.utils.ClipboardUtil import com.owncloud.android.utils.DisplayUtils import kotlinx.coroutines.delay import kotlinx.coroutines.launch @@ -107,7 +109,9 @@ fun AssistantScreen(viewModel: AssistantViewModel, activity: Activity) { .padding(16.dp), onClick = { selectedTaskType?.let { - viewModel.showAddTaskAlertDialog(it) + val newState = + AssistantViewModel.ScreenState.AddTask(it, "") + viewModel.updateScreenState(newState) } } ) { @@ -117,23 +121,27 @@ fun AssistantScreen(viewModel: AssistantViewModel, activity: Activity) { } HandleMessageState(messageState, activity, viewModel) - ScreenState(alertDialogState, viewModel) + ScreenState(alertDialogState, activity, viewModel) } @Composable -private fun ScreenState(state: AssistantViewModel.ScreenState?, viewModel: AssistantViewModel) { +private fun ScreenState( + state: AssistantViewModel.ScreenState?, + activity: Activity, + viewModel: AssistantViewModel +) { when(state) { is AssistantViewModel.ScreenState.AddTask -> { AddTaskAlertDialog( title = state.taskType.name, description = state.taskType.description, addTask = { input -> - state.taskType.id?.let { - viewModel.createTask(input = input, type = it) + state.taskType.id?.let { taskTypeId -> + viewModel.createTask(input = input, type = taskTypeId) } }, dismiss = { - viewModel.resetAlertDialogState() + viewModel.updateScreenState(null) } ) } @@ -142,7 +150,7 @@ private fun ScreenState(state: AssistantViewModel.ScreenState?, viewModel: Assis SimpleAlertDialog( title = stringResource(id = R.string.assistant_screen_delete_task_alert_dialog_title), description = stringResource(id = R.string.assistant_screen_delete_task_alert_dialog_description), - dismiss = { viewModel.resetAlertDialogState() }, + dismiss = { viewModel.updateScreenState(null) }, onComplete = { viewModel.deleteTask(state.id) } ) } @@ -150,17 +158,38 @@ private fun ScreenState(state: AssistantViewModel.ScreenState?, viewModel: Assis is AssistantViewModel.ScreenState.TaskActions -> { val bottomSheetAction = listOf( Triple( - R.drawable.ic_delete, - R.string.assistant_screen_task_more_actions_bottom_sheet_delete_action + R.drawable.ic_share, + R.string.common_share ) { + val sendIntent = Intent(Intent.ACTION_SEND).apply { + putExtra(Intent.EXTRA_TEXT, state.task.output) + type = "text/plain" + } + val shareIntent = Intent.createChooser(sendIntent, null) + activity.startActivity(shareIntent) + }, + Triple( + R.drawable.ic_content_copy, + R.string.common_copy + ) { + ClipboardUtil.copyToClipboard(activity, state.task.output) + }, + Triple( + R.drawable.ic_edit, + R.string.action_edit + ) { + val taskType = TaskType(state.task.type, "", "") + val newState = + AssistantViewModel.ScreenState.AddTask(taskType, state.task.output ?: "") + viewModel.updateScreenState(newState) } ) MoreActionsBottomSheet( title = state.task.input, actions = bottomSheetAction, - dismiss = { viewModel.resetAlertDialogState() } + dismiss = { viewModel.updateScreenState(null) } ) } @@ -194,7 +223,7 @@ private fun HandleMessageState(state: AssistantViewModel.MessageState?, activity stringResource(id = messageStateId) ) - viewModel.resetMessageState() + viewModel.updateMessageState(null) } } @@ -221,8 +250,14 @@ private fun AssistantContent( items(taskList) { task -> TaskView(task, - showDeleteTaskAlertDialog = { viewModel.showDeleteTaskAlertDialog(task.id) }, - showTaskActions = { viewModel.showTaskActionsBottomSheet(task) } + showDeleteTaskAlertDialog = { + val newState = AssistantViewModel.ScreenState.DeleteTask(task.id) + viewModel.updateScreenState(newState) + }, + showTaskActions = { + val newState = AssistantViewModel.ScreenState.TaskActions(task) + viewModel.updateScreenState(newState) + } ) Spacer(modifier = Modifier.height(8.dp)) } diff --git a/app/src/main/java/com/nextcloud/client/assistant/component/AddTaskAlertDialog.kt b/app/src/main/java/com/nextcloud/client/assistant/component/AddTaskAlertDialog.kt index 9dfdae0465..d6a4aa2dce 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/component/AddTaskAlertDialog.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/component/AddTaskAlertDialog.kt @@ -22,9 +22,15 @@ import com.nextcloud.ui.composeComponents.alertDialog.SimpleAlertDialog import com.owncloud.android.R @Composable -fun AddTaskAlertDialog(title: String?, description: String?, addTask: (String) -> Unit, dismiss: () -> Unit) { +fun AddTaskAlertDialog( + title: String?, + description: String?, + defaultInput: String = "", + addTask: (String) -> Unit, + dismiss: () -> Unit +) { var input by remember { - mutableStateOf("") + mutableStateOf(defaultInput) } SimpleAlertDialog( diff --git a/app/src/main/java/com/nextcloud/ui/composeComponents/bottomSheet/MoreActionsBottomSheet.kt b/app/src/main/java/com/nextcloud/ui/composeComponents/bottomSheet/MoreActionsBottomSheet.kt index 16131db380..07db2701ab 100644 --- a/app/src/main/java/com/nextcloud/ui/composeComponents/bottomSheet/MoreActionsBottomSheet.kt +++ b/app/src/main/java/com/nextcloud/ui/composeComponents/bottomSheet/MoreActionsBottomSheet.kt @@ -37,7 +37,11 @@ import kotlinx.coroutines.launch @SuppressLint("ResourceAsColor") @OptIn(ExperimentalMaterial3Api::class) @Composable -fun MoreActionsBottomSheet(title: String? = null, actions: List Unit>>, dismiss: () -> Unit) { +fun MoreActionsBottomSheet( + title: String? = null, + actions: List Unit>>, + dismiss: () -> Unit +) { val sheetState = rememberModalBottomSheetState() val scope = rememberCoroutineScope() @@ -72,8 +76,8 @@ fun MoreActionsBottomSheet(title: String? = null, actions: List Date: Mon, 2 Dec 2024 15:48:01 +0100 Subject: [PATCH 05/34] clear unnecessary logic Signed-off-by: alperozturk --- .../client/assistant/AssistantViewModel.kt | 28 ++++------ .../client/assistant/AsssistantScreen.kt | 54 +++++-------------- .../utils/extensions/ActivityExtensions.kt | 12 +++++ 3 files changed, 34 insertions(+), 60 deletions(-) diff --git a/app/src/main/java/com/nextcloud/client/assistant/AssistantViewModel.kt b/app/src/main/java/com/nextcloud/client/assistant/AssistantViewModel.kt index de075f05aa..b41019052b 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/AssistantViewModel.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/AssistantViewModel.kt @@ -27,13 +27,6 @@ class AssistantViewModel( private val context: WeakReference ) : ViewModel() { - sealed class MessageState { - data object Loading : MessageState() - data class Error(val messageId: Int) : MessageState() - data class TaskCreated(val messageId: Int) : MessageState() - data class TaskDeleted(val messageId: Int) : MessageState() - } - sealed class ScreenState { data class DeleteTask(val id: Long): ScreenState() data class AddTask(val taskType: TaskType, val input: String): ScreenState() @@ -43,8 +36,8 @@ class AssistantViewModel( private val _screenState = MutableStateFlow(null) val screenState: StateFlow = _screenState - private val _messageState = MutableStateFlow(MessageState.Loading) - val messageState: StateFlow = _messageState + private val _messageId = MutableStateFlow(R.string.assistant_screen_loading) + val messageId: StateFlow = _messageId private val _selectedTaskType = MutableStateFlow(null) val selectedTaskType: StateFlow = _selectedTaskType @@ -76,8 +69,7 @@ class AssistantViewModel( R.string.assistant_screen_task_create_fail_message } - val message = MessageState.TaskCreated(messageId) - updateMessageState(message) + updateMessageId(messageId) delay(2000L) fetchTaskList() @@ -107,8 +99,7 @@ class AssistantViewModel( selectTaskType(result.first()) } else { - val message = MessageState.Error(R.string.assistant_screen_task_types_error_state_message) - updateMessageState(message) + updateMessageId(R.string.assistant_screen_task_types_error_state_message) } } } @@ -123,10 +114,9 @@ class AssistantViewModel( if (result.isSuccess) { taskList = result.resultData.tasks filterTaskList(_selectedTaskType.value?.id) - updateMessageState(null) + updateMessageId(null) } else { - val message = MessageState.Error(R.string.assistant_screen_task_list_error_state_message) - updateMessageState(message) + updateMessageId(R.string.assistant_screen_task_list_error_state_message) } _isRefreshing.update { @@ -145,7 +135,7 @@ class AssistantViewModel( R.string.assistant_screen_task_delete_fail_message } - updateMessageState(MessageState.TaskDeleted(messageId)) + updateMessageId(messageId) if (result.isSuccess) { removeTaskFromList(id) @@ -153,8 +143,8 @@ class AssistantViewModel( } } - fun updateMessageState(value: MessageState?) { - _messageState.update { + fun updateMessageId(value: Int?) { + _messageId.update { value } } diff --git a/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt b/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt index 412618c7c0..3c01e5bb94 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt @@ -8,7 +8,6 @@ package com.nextcloud.client.assistant import android.app.Activity -import android.content.Intent import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -46,6 +45,7 @@ import com.nextcloud.client.assistant.taskTypes.TaskTypesRow import com.nextcloud.ui.composeActivity.ComposeActivity import com.nextcloud.ui.composeComponents.alertDialog.SimpleAlertDialog import com.nextcloud.ui.composeComponents.bottomSheet.MoreActionsBottomSheet +import com.nextcloud.utils.extensions.showShareIntent import com.owncloud.android.R import com.owncloud.android.lib.resources.assistant.model.Task import com.owncloud.android.lib.resources.assistant.model.TaskType @@ -59,7 +59,7 @@ import java.lang.ref.WeakReference @OptIn(ExperimentalMaterial3Api::class) @Composable fun AssistantScreen(viewModel: AssistantViewModel, activity: Activity) { - val messageState by viewModel.messageState.collectAsState() + val messageId by viewModel.messageId.collectAsState() val alertDialogState by viewModel.screenState.collectAsState() val selectedTaskType by viewModel.selectedTaskType.collectAsState() @@ -78,7 +78,7 @@ fun AssistantScreen(viewModel: AssistantViewModel, activity: Activity) { } }) ) { - if (messageState == AssistantViewModel.MessageState.Loading || isRefreshing) { + if (messageId == R.string.assistant_screen_loading || isRefreshing) { CenterText(text = stringResource(id = R.string.assistant_screen_loading)) } else { if (filteredTaskList.isNullOrEmpty()) { @@ -120,7 +120,15 @@ fun AssistantScreen(viewModel: AssistantViewModel, activity: Activity) { } } - HandleMessageState(messageState, activity, viewModel) + messageId?.let { + DisplayUtils.showSnackMessage( + activity, + activity.getString(it) + ) + + viewModel.updateMessageId(null) + } + ScreenState(alertDialogState, activity, viewModel) } @@ -161,13 +169,7 @@ private fun ScreenState( R.drawable.ic_share, R.string.common_share ) { - val sendIntent = Intent(Intent.ACTION_SEND).apply { - putExtra(Intent.EXTRA_TEXT, state.task.output) - type = "text/plain" - } - - val shareIntent = Intent.createChooser(sendIntent, null) - activity.startActivity(shareIntent) + activity.showShareIntent(state.task.output) }, Triple( R.drawable.ic_content_copy, @@ -197,36 +199,6 @@ private fun ScreenState( } } -@Composable -private fun HandleMessageState(state: AssistantViewModel.MessageState?, activity: Activity, viewModel: AssistantViewModel) { - val messageStateId: Int? = when (state) { - is AssistantViewModel.MessageState.Error -> { - state.messageId - } - - is AssistantViewModel.MessageState.TaskCreated -> { - state.messageId - } - - is AssistantViewModel.MessageState.TaskDeleted -> { - state.messageId - } - - else -> { - null - } - } - - messageStateId?.let { - DisplayUtils.showSnackMessage( - activity, - stringResource(id = messageStateId) - ) - - viewModel.updateMessageState(null) - } -} - @OptIn(ExperimentalFoundationApi::class) @Composable private fun AssistantContent( diff --git a/app/src/main/java/com/nextcloud/utils/extensions/ActivityExtensions.kt b/app/src/main/java/com/nextcloud/utils/extensions/ActivityExtensions.kt index 0bdbbbd0cb..bba32fe392 100644 --- a/app/src/main/java/com/nextcloud/utils/extensions/ActivityExtensions.kt +++ b/app/src/main/java/com/nextcloud/utils/extensions/ActivityExtensions.kt @@ -7,6 +7,8 @@ package com.nextcloud.utils.extensions +import android.app.Activity +import android.content.Intent import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.Fragment @@ -17,3 +19,13 @@ fun AppCompatActivity.isActive(): Boolean = !isFinishing && !isDestroyed fun AppCompatActivity.fragments(): List = supportFragmentManager.fragments fun AppCompatActivity.lastFragment(): Fragment = fragments().last() + +fun Activity.showShareIntent(text: String?) { + val sendIntent = Intent(Intent.ACTION_SEND).apply { + putExtra(Intent.EXTRA_TEXT, text) + type = "text/plain" + } + + val shareIntent = Intent.createChooser(sendIntent, null) + startActivity(shareIntent) +} From a4c36f180bc93d28adb0d1fae086df3876ebf652 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Mon, 2 Dec 2024 15:56:47 +0100 Subject: [PATCH 06/34] complete more actions Signed-off-by: alperozturk --- .../com/nextcloud/client/assistant/AsssistantScreen.kt | 9 +++++++-- app/src/main/res/values/strings.xml | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt b/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt index 3c01e5bb94..d0d0777e47 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt @@ -143,6 +143,7 @@ private fun ScreenState( AddTaskAlertDialog( title = state.taskType.name, description = state.taskType.description, + defaultInput = state.input, addTask = { input -> state.taskType.id?.let { taskTypeId -> viewModel.createTask(input = input, type = taskTypeId) @@ -181,9 +182,13 @@ private fun ScreenState( R.drawable.ic_edit, R.string.action_edit ) { - val taskType = TaskType(state.task.type, "", "") + val taskType = TaskType( + state.task.type, + activity.getString(R.string.assistant_screen_add_task_alert_dialog_title), + null + ) val newState = - AssistantViewModel.ScreenState.AddTask(taskType, state.task.output ?: "") + AssistantViewModel.ScreenState.AddTask(taskType, state.task.input ?: "") viewModel.updateScreenState(newState) } ) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e48003d717..ce17c01b2d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -55,6 +55,7 @@ No task available for %s task type, you can create a new task from bottom right. Delete Task Are you sure you want to delete this task? + Add New Task Delete Task From 8f718995ea347fd3952e94fcd225f207c993e3ab Mon Sep 17 00:00:00 2001 From: alperozturk Date: Mon, 2 Dec 2024 16:07:15 +0100 Subject: [PATCH 07/34] add more actions to the detail view Signed-off-by: alperozturk --- .../client/assistant/task/TaskView.kt | 7 ++- .../taskDetail/TaskDetailBottomSheet.kt | 51 +++++++++++++++---- 2 files changed, 45 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt b/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt index 5d960b934f..5011821d8a 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt @@ -109,7 +109,7 @@ fun TaskView(task: Task, showDeleteTaskAlertDialog: (Long) -> Unit, showTaskActi showDeleteTaskAlertDialog(task.id) }, dismiss = { bottomSheetType = null - }) + }, showTaskActions = showTaskActions) } } @@ -131,12 +131,15 @@ fun TaskView(task: Task, showDeleteTaskAlertDialog: (Long) -> Unit, showTaskActi private fun TaskViewBottomSheet( bottomSheetType: TaskViewBottomSheetType, task: Task, + showTaskActions: () -> Unit, showDeleteTaskAlertDialog: () -> Unit, dismiss: () -> Unit ) { when (bottomSheetType) { TaskViewBottomSheetType.Detail -> { - TaskDetailBottomSheet(task) { + TaskDetailBottomSheet(task, showTaskActions = { + showTaskActions() + }) { dismiss() } } diff --git a/app/src/main/java/com/nextcloud/client/assistant/taskDetail/TaskDetailBottomSheet.kt b/app/src/main/java/com/nextcloud/client/assistant/taskDetail/TaskDetailBottomSheet.kt index dcd03dde6c..bc1ec78dda 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/taskDetail/TaskDetailBottomSheet.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/taskDetail/TaskDetailBottomSheet.kt @@ -22,9 +22,13 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.MoreVert import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.ModalBottomSheet import androidx.compose.material3.Text @@ -35,6 +39,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview @@ -48,7 +53,7 @@ import com.owncloud.android.lib.resources.assistant.model.Task @Suppress("LongMethod") @OptIn(ExperimentalFoundationApi::class, ExperimentalMaterial3Api::class) @Composable -fun TaskDetailBottomSheet(task: Task, dismiss: () -> Unit) { +fun TaskDetailBottomSheet(task: Task, showTaskActions: () -> Unit, dismiss: () -> Unit) { var showInput by remember { mutableStateOf(true) } val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true) @@ -58,13 +63,31 @@ fun TaskDetailBottomSheet(task: Task, dismiss: () -> Unit) { onDismissRequest = { dismiss() }, sheetState = sheetState ) { - LazyColumn(modifier = Modifier.fillMaxSize().padding(16.dp)) { + LazyColumn(modifier = Modifier + .fillMaxSize() + .padding(16.dp)) { stickyHeader { Row( - modifier = Modifier.fillMaxWidth().background( - color = colorResource(id = R.color.light_grey), - shape = RoundedCornerShape(8.dp) - ) + modifier = Modifier.fillMaxWidth() + ) { + Spacer(modifier = Modifier.weight(1f)) + + IconButton(onClick = showTaskActions) { + Icon( + imageVector = Icons.Filled.MoreVert, + contentDescription = "More button", + tint = Color.White + ) + } + } + + Row( + modifier = Modifier + .fillMaxWidth() + .background( + color = colorResource(id = R.color.light_grey), + shape = RoundedCornerShape(8.dp) + ) ) { TextInputSelectButton( Modifier.weight(1f), @@ -90,10 +113,13 @@ fun TaskDetailBottomSheet(task: Task, dismiss: () -> Unit) { Spacer(modifier = Modifier.height(16.dp)) Column( - modifier = Modifier.fillMaxSize().background( - color = MaterialTheme.colorScheme.secondaryContainer, - shape = RoundedCornerShape(8.dp) - ).padding(16.dp) + modifier = Modifier + .fillMaxSize() + .background( + color = MaterialTheme.colorScheme.secondaryContainer, + shape = RoundedCornerShape(8.dp) + ) + .padding(16.dp) ) { Text( text = if (showInput) { @@ -154,7 +180,10 @@ private fun TaskDetailScreenPreview() { "output".getRandomString(300), "", "" - ) + ), + showTaskActions = { + + } ) { } } From bab98b4213e3f7b8c0649451d71f2214bdc8f6c0 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Mon, 2 Dec 2024 16:16:55 +0100 Subject: [PATCH 08/34] modal bottom sheet appereance fix Signed-off-by: alperozturk --- .../java/com/nextcloud/client/assistant/task/TaskView.kt | 5 ++++- .../composeComponents/bottomSheet/MoreActionsBottomSheet.kt | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt b/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt index 5011821d8a..48d7ea602b 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt @@ -109,7 +109,9 @@ fun TaskView(task: Task, showDeleteTaskAlertDialog: (Long) -> Unit, showTaskActi showDeleteTaskAlertDialog(task.id) }, dismiss = { bottomSheetType = null - }, showTaskActions = showTaskActions) + }, showTaskActions = { + showTaskActions() + }) } } @@ -138,6 +140,7 @@ private fun TaskViewBottomSheet( when (bottomSheetType) { TaskViewBottomSheetType.Detail -> { TaskDetailBottomSheet(task, showTaskActions = { + dismiss() showTaskActions() }) { dismiss() diff --git a/app/src/main/java/com/nextcloud/ui/composeComponents/bottomSheet/MoreActionsBottomSheet.kt b/app/src/main/java/com/nextcloud/ui/composeComponents/bottomSheet/MoreActionsBottomSheet.kt index 07db2701ab..4b106433da 100644 --- a/app/src/main/java/com/nextcloud/ui/composeComponents/bottomSheet/MoreActionsBottomSheet.kt +++ b/app/src/main/java/com/nextcloud/ui/composeComponents/bottomSheet/MoreActionsBottomSheet.kt @@ -47,6 +47,7 @@ fun MoreActionsBottomSheet( ModalBottomSheet( modifier = Modifier.padding(top = 32.dp), + containerColor = colorScheme.surface, onDismissRequest = { dismiss() }, From baba9e04556160003ac30709a9e22eee00ddbab1 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Tue, 3 Dec 2024 10:13:59 +0100 Subject: [PATCH 09/34] Handle states better Signed-off-by: alperozturk --- .../client/assistant/AssistantViewModel.kt | 54 +++---- .../client/assistant/AsssistantScreen.kt | 136 +++++++++++------- .../assistant/model/ScreenOverlayState.kt | 17 +++ .../client/assistant/model/ScreenState.kt | 12 ++ 4 files changed, 147 insertions(+), 72 deletions(-) create mode 100644 app/src/main/java/com/nextcloud/client/assistant/model/ScreenOverlayState.kt create mode 100644 app/src/main/java/com/nextcloud/client/assistant/model/ScreenState.kt diff --git a/app/src/main/java/com/nextcloud/client/assistant/AssistantViewModel.kt b/app/src/main/java/com/nextcloud/client/assistant/AssistantViewModel.kt index b41019052b..4ec4601a96 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/AssistantViewModel.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/AssistantViewModel.kt @@ -10,6 +10,8 @@ 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 @@ -27,17 +29,14 @@ class AssistantViewModel( private val context: WeakReference ) : ViewModel() { - sealed class ScreenState { - data class DeleteTask(val id: Long): ScreenState() - data class AddTask(val taskType: TaskType, val input: String): ScreenState() - data class TaskActions(val task: Task): ScreenState() - } - private val _screenState = MutableStateFlow(null) val screenState: StateFlow = _screenState - private val _messageId = MutableStateFlow(R.string.assistant_screen_loading) - val messageId: StateFlow = _messageId + private val _screenOverlayState = MutableStateFlow(null) + val screenOverlayState: StateFlow = _screenOverlayState + + private val _snackbarMessageId = MutableStateFlow(null) + val snackbarMessageId: StateFlow = _snackbarMessageId private val _selectedTaskType = MutableStateFlow(null) val selectedTaskType: StateFlow = _selectedTaskType @@ -50,9 +49,6 @@ class AssistantViewModel( private val _filteredTaskList = MutableStateFlow?>(null) val filteredTaskList: StateFlow?> = _filteredTaskList - private val _isRefreshing = MutableStateFlow(false) - val isRefreshing: StateFlow = _isRefreshing - init { fetchTaskTypes() fetchTaskList() @@ -69,7 +65,7 @@ class AssistantViewModel( R.string.assistant_screen_task_create_fail_message } - updateMessageId(messageId) + updateSnackbarMessage(messageId) delay(2000L) fetchTaskList() @@ -81,6 +77,8 @@ class AssistantViewModel( filterTaskList(task.id) task } + + updateScreenState() } private fun fetchTaskTypes() { @@ -99,28 +97,36 @@ class AssistantViewModel( selectTaskType(result.first()) } else { - updateMessageId(R.string.assistant_screen_task_types_error_state_message) + updateSnackbarMessage(R.string.assistant_screen_task_types_error_state_message) } } } fun fetchTaskList(appId: String = "assistant") { viewModelScope.launch(Dispatchers.IO) { - _isRefreshing.update { - true + _screenState.update { + ScreenState.Refreshing } val result = repository.getTaskList(appId) if (result.isSuccess) { taskList = result.resultData.tasks filterTaskList(_selectedTaskType.value?.id) - updateMessageId(null) + updateSnackbarMessage(null) } else { - updateMessageId(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 } } } @@ -135,7 +141,7 @@ class AssistantViewModel( R.string.assistant_screen_task_delete_fail_message } - updateMessageId(messageId) + updateSnackbarMessage(messageId) if (result.isSuccess) { removeTaskFromList(id) @@ -143,14 +149,14 @@ class AssistantViewModel( } } - fun updateMessageId(value: Int?) { - _messageId.update { + fun updateSnackbarMessage(value: Int?) { + _snackbarMessageId.update { value } } - fun updateScreenState(value: ScreenState?) { - _screenState.update { + fun updateScreenState(value: ScreenOverlayState?) { + _screenOverlayState.update { value } } diff --git a/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt b/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt index d0d0777e47..f308ece63a 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt @@ -25,6 +25,7 @@ import androidx.compose.material3.FloatingActionButton import androidx.compose.material3.Icon import androidx.compose.material3.LinearProgressIndicator import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.pulltorefresh.PullToRefreshState import androidx.compose.material3.pulltorefresh.pullToRefresh import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState import androidx.compose.runtime.Composable @@ -39,6 +40,8 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.nextcloud.client.assistant.component.AddTaskAlertDialog import com.nextcloud.client.assistant.component.CenterText +import com.nextcloud.client.assistant.model.ScreenOverlayState +import com.nextcloud.client.assistant.model.ScreenState import com.nextcloud.client.assistant.repository.AssistantMockRepository import com.nextcloud.client.assistant.task.TaskView import com.nextcloud.client.assistant.taskTypes.TaskTypesRow @@ -59,87 +62,124 @@ import java.lang.ref.WeakReference @OptIn(ExperimentalMaterial3Api::class) @Composable fun AssistantScreen(viewModel: AssistantViewModel, activity: Activity) { - val messageId by viewModel.messageId.collectAsState() - val alertDialogState by viewModel.screenState.collectAsState() + val messageId by viewModel.snackbarMessageId.collectAsState() + val screenOverlayState by viewModel.screenOverlayState.collectAsState() val selectedTaskType by viewModel.selectedTaskType.collectAsState() val filteredTaskList by viewModel.filteredTaskList.collectAsState() - val isRefreshing by viewModel.isRefreshing.collectAsState() + val screenState by viewModel.screenState.collectAsState() val taskTypes by viewModel.taskTypes.collectAsState() val scope = rememberCoroutineScope() val pullRefreshState = rememberPullToRefreshState() @Suppress("MagicNumber") Box( - modifier = Modifier.pullToRefresh(isRefreshing, pullRefreshState, onRefresh = { + modifier = Modifier.pullToRefresh( + screenState == ScreenState.Refreshing, + pullRefreshState, + onRefresh = { scope.launch { delay(1500) viewModel.fetchTaskList() } }) ) { - if (messageId == R.string.assistant_screen_loading || isRefreshing) { - CenterText(text = stringResource(id = R.string.assistant_screen_loading)) - } else { - if (filteredTaskList.isNullOrEmpty()) { - EmptyTaskList(selectedTaskType, taskTypes, viewModel) - } else { - AssistantContent( - filteredTaskList!!, - taskTypes, - selectedTaskType, - viewModel - ) - } - } + ShowScreenState(screenState, selectedTaskType, taskTypes, viewModel, filteredTaskList) - if (isRefreshing) { - LinearProgressIndicator(modifier = Modifier.fillMaxWidth()) - } else { - LinearProgressIndicator( - progress = { pullRefreshState.distanceFraction }, - modifier = Modifier.fillMaxWidth() - ) - } + ShowLinearProgressIndicator(screenState, pullRefreshState) if (selectedTaskType?.name != stringResource(id = R.string.assistant_screen_all_task_type)) { - FloatingActionButton( + AddFloatingActionButton( modifier = Modifier .align(Alignment.BottomEnd) .padding(16.dp), - onClick = { - selectedTaskType?.let { - val newState = - AssistantViewModel.ScreenState.AddTask(it, "") - viewModel.updateScreenState(newState) - } - } - ) { - Icon(Icons.Filled.Add, "Add Task Icon") - } + selectedTaskType, + viewModel + ) } } + showSnackBarMessage(messageId, activity, viewModel) + ShowOverlayState(screenOverlayState, activity, viewModel) +} + +@Composable +private fun ShowScreenState( + screenState: ScreenState?, + selectedTaskType: TaskType?, + taskTypes: List?, + viewModel: AssistantViewModel, + filteredTaskList: List? +) { + when(screenState) { + ScreenState.Refreshing -> { + CenterText(text = stringResource(id = R.string.assistant_screen_loading)) + } + + ScreenState.EmptyContent -> { + EmptyTaskList(selectedTaskType, taskTypes, viewModel) + } + + ScreenState.Content -> { + AssistantContent( + filteredTaskList!!, + taskTypes, + selectedTaskType, + viewModel + ) + } + + null -> Unit + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +private fun ShowLinearProgressIndicator(screenState: ScreenState?, pullToRefreshState: PullToRefreshState) { + if (screenState == ScreenState.Refreshing) { + LinearProgressIndicator(modifier = Modifier.fillMaxWidth()) + } else { + LinearProgressIndicator( + progress = { pullToRefreshState.distanceFraction }, + modifier = Modifier.fillMaxWidth() + ) + } +} + +@Composable +private fun AddFloatingActionButton(modifier: Modifier, selectedTaskType: TaskType?, viewModel: AssistantViewModel) { + FloatingActionButton( + modifier = modifier, + onClick = { + selectedTaskType?.let { + val newState = ScreenOverlayState.AddTask(it, "") + viewModel.updateScreenState(newState) + } + } + ) { + Icon(Icons.Filled.Add, "Add Task Icon") + } +} + +private fun showSnackBarMessage(messageId: Int?, activity: Activity, viewModel: AssistantViewModel) { messageId?.let { DisplayUtils.showSnackMessage( activity, activity.getString(it) ) - viewModel.updateMessageId(null) + viewModel.updateSnackbarMessage(null) } - - ScreenState(alertDialogState, activity, viewModel) } @Composable -private fun ScreenState( - state: AssistantViewModel.ScreenState?, +private fun ShowOverlayState( + state: ScreenOverlayState?, activity: Activity, viewModel: AssistantViewModel ) { when(state) { - is AssistantViewModel.ScreenState.AddTask -> { + is ScreenOverlayState.AddTask -> { AddTaskAlertDialog( title = state.taskType.name, description = state.taskType.description, @@ -155,7 +195,7 @@ private fun ScreenState( ) } - is AssistantViewModel.ScreenState.DeleteTask -> { + is ScreenOverlayState.DeleteTask -> { SimpleAlertDialog( title = stringResource(id = R.string.assistant_screen_delete_task_alert_dialog_title), description = stringResource(id = R.string.assistant_screen_delete_task_alert_dialog_description), @@ -164,7 +204,7 @@ private fun ScreenState( ) } - is AssistantViewModel.ScreenState.TaskActions -> { + is ScreenOverlayState.TaskActions -> { val bottomSheetAction = listOf( Triple( R.drawable.ic_share, @@ -188,7 +228,7 @@ private fun ScreenState( null ) val newState = - AssistantViewModel.ScreenState.AddTask(taskType, state.task.input ?: "") + ScreenOverlayState.AddTask(taskType, state.task.input ?: "") viewModel.updateScreenState(newState) } ) @@ -228,11 +268,11 @@ private fun AssistantContent( items(taskList) { task -> TaskView(task, showDeleteTaskAlertDialog = { - val newState = AssistantViewModel.ScreenState.DeleteTask(task.id) + val newState = ScreenOverlayState.DeleteTask(task.id) viewModel.updateScreenState(newState) }, showTaskActions = { - val newState = AssistantViewModel.ScreenState.TaskActions(task) + val newState = ScreenOverlayState.TaskActions(task) viewModel.updateScreenState(newState) } ) diff --git a/app/src/main/java/com/nextcloud/client/assistant/model/ScreenOverlayState.kt b/app/src/main/java/com/nextcloud/client/assistant/model/ScreenOverlayState.kt new file mode 100644 index 0000000000..23c6c44af7 --- /dev/null +++ b/app/src/main/java/com/nextcloud/client/assistant/model/ScreenOverlayState.kt @@ -0,0 +1,17 @@ +/* + * Nextcloud - Android Client + * + * SPDX-FileCopyrightText: 2024 Alper Ozturk + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package com.nextcloud.client.assistant.model + +import com.owncloud.android.lib.resources.assistant.model.Task +import com.owncloud.android.lib.resources.assistant.model.TaskType + +sealed class ScreenOverlayState { + data class DeleteTask(val id: Long): ScreenOverlayState() + data class AddTask(val taskType: TaskType, val input: String): ScreenOverlayState() + data class TaskActions(val task: Task): ScreenOverlayState() +} diff --git a/app/src/main/java/com/nextcloud/client/assistant/model/ScreenState.kt b/app/src/main/java/com/nextcloud/client/assistant/model/ScreenState.kt new file mode 100644 index 0000000000..d7c42dcf99 --- /dev/null +++ b/app/src/main/java/com/nextcloud/client/assistant/model/ScreenState.kt @@ -0,0 +1,12 @@ +/* + * Nextcloud - Android Client + * + * SPDX-FileCopyrightText: 2024 Alper Ozturk + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package com.nextcloud.client.assistant.model + +enum class ScreenState { + Refreshing, EmptyContent, Content +} From d620123e3e035019e54a44650fd4cf1c5a95ec88 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Tue, 3 Dec 2024 11:59:48 +0100 Subject: [PATCH 10/34] Add time completion to the task status Signed-off-by: alperozturk --- .../client/assistant/AsssistantScreen.kt | 10 +- .../assistant/extensions/TaskExtensions.kt | 78 +++++++++--- .../repository/AssistantMockRepository.kt | 79 ++---------- .../client/assistant/task/TaskStatusView.kt | 113 +++++++++++++++--- .../client/assistant/task/TaskView.kt | 23 ++-- .../taskDetail/TaskDetailBottomSheet.kt | 19 +-- app/src/main/res/values/strings.xml | 16 +++ 7 files changed, 219 insertions(+), 119 deletions(-) diff --git a/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt b/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt index f308ece63a..e21fad6f46 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt @@ -122,7 +122,7 @@ private fun ShowScreenState( ScreenState.Content -> { AssistantContent( - filteredTaskList!!, + filteredTaskList ?: listOf(), taskTypes, selectedTaskType, viewModel @@ -210,13 +210,13 @@ private fun ShowOverlayState( R.drawable.ic_share, R.string.common_share ) { - activity.showShareIntent(state.task.output) + activity.showShareIntent(state.task.output?.output) }, Triple( R.drawable.ic_content_copy, R.string.common_copy ) { - ClipboardUtil.copyToClipboard(activity, state.task.output) + ClipboardUtil.copyToClipboard(activity, state.task.output?.output) }, Triple( R.drawable.ic_edit, @@ -228,13 +228,13 @@ private fun ShowOverlayState( null ) val newState = - ScreenOverlayState.AddTask(taskType, state.task.input ?: "") + ScreenOverlayState.AddTask(taskType, state.task.input?.input ?: "") viewModel.updateScreenState(newState) } ) MoreActionsBottomSheet( - title = state.task.input, + title = state.task.input?.input, actions = bottomSheetAction, dismiss = { viewModel.updateScreenState(null) } ) diff --git a/app/src/main/java/com/nextcloud/client/assistant/extensions/TaskExtensions.kt b/app/src/main/java/com/nextcloud/client/assistant/extensions/TaskExtensions.kt index 4df63f69a9..bdb00c20a0 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/extensions/TaskExtensions.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/extensions/TaskExtensions.kt @@ -9,34 +9,82 @@ package com.nextcloud.client.assistant.extensions +import android.content.Context +import android.icu.text.SimpleDateFormat import com.owncloud.android.R import com.owncloud.android.lib.resources.assistant.model.Task +import java.util.Date +import java.util.Locale +import java.util.concurrent.TimeUnit @Suppress("MagicNumber") -fun Task.statusData(): Pair { +fun Task.getStatusIcon(): Int { return when (status) { - 0L -> { - Pair(R.drawable.ic_unknown, R.string.assistant_screen_unknown_task_status_text) + "STATUS_UNKNOWN" -> { + R.drawable.ic_unknown } - 1L -> { - Pair(R.drawable.ic_clock, R.string.assistant_screen_scheduled_task_status_text) + "STATUS_SCHEDULED" -> { + R.drawable.ic_clock } - 2L -> { - Pair(R.drawable.ic_modification_desc, R.string.assistant_screen_running_task_text) + "STATUS_RUNNING" -> { + R.drawable.ic_modification_desc } - 3L -> { - Pair(R.drawable.ic_info, R.string.assistant_screen_successful_task_text) + "STATUS_SUCCESSFUL" -> { + R.drawable.ic_check_circle_outline } - 4L -> { - Pair(R.drawable.image_fail, R.string.assistant_screen_failed_task_text) + "STATUS_FAILED" -> { + R.drawable.image_fail } else -> { - Pair(R.drawable.ic_unknown, R.string.assistant_screen_unknown_task_status_text) + R.drawable.ic_unknown } } } -// TODO add -fun Task.completionDateRepresentation(): String { - return completionExpectedAt ?: "TODO IMPLEMENT IT" +fun Task.getModifiedAtRepresentation(context: Context): String? { + if (lastUpdated == null) { + return null + } + + val modifiedAt = lastUpdated!!.toLong() + val currentTime = System.currentTimeMillis() / 1000 + val timeDifference = (currentTime - modifiedAt).toInt() + val timeDifferenceInMinutes = (timeDifference / 60) + val timeDifferenceInHours = (timeDifference / 3600) + + return when { + timeDifference == 0 -> { + context.getString(R.string.common_now) + } + + timeDifference < TimeUnit.MINUTES.toSeconds(1) -> { + context.resources.getQuantityString(R.plurals.time_seconds_ago, timeDifference, timeDifference) + } + + timeDifference < TimeUnit.HOURS.toSeconds(1) -> { + context.resources.getQuantityString( + R.plurals.time_minutes_ago, + timeDifferenceInMinutes, + timeDifferenceInMinutes + ) + } + + timeDifference < TimeUnit.DAYS.toSeconds(1) -> { + context.resources.getQuantityString( + R.plurals.time_hours_ago, + timeDifferenceInHours, + timeDifferenceInHours + ) + } + + else -> { + convertToDateFormat(modifiedAt) + } + } +} + +private fun convertToDateFormat(timestamp: Long): String { + val date = Date(timestamp * 1000) + val format = SimpleDateFormat("MMM d", Locale.getDefault()) + return format.format(date) } diff --git a/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantMockRepository.kt b/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantMockRepository.kt index d1c4b6172f..a4066b746b 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantMockRepository.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantMockRepository.kt @@ -10,7 +10,9 @@ package com.nextcloud.client.assistant.repository import com.nextcloud.utils.extensions.getRandomString import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.lib.resources.assistant.model.Task +import com.owncloud.android.lib.resources.assistant.model.TaskInput import com.owncloud.android.lib.resources.assistant.model.TaskList +import com.owncloud.android.lib.resources.assistant.model.TaskOutput import com.owncloud.android.lib.resources.assistant.model.TaskType import com.owncloud.android.lib.resources.assistant.model.TaskTypes @@ -44,76 +46,15 @@ class AssistantMockRepository(private val giveEmptyTasks: Boolean = false) : Ass null, "12", "", - "Give me some long text 1", - "Lorem ipsum".getRandomString(100), - "" + TaskInput("Give me some long text 1"), + TaskOutput("Lorem ipsum".getRandomString(100)), + 1707692337, + 1707692337, + 1707692337, + 1707692337, + 1707692337, ), - Task( - 2, - "GenerateHeadline", - null, - "12", - "", - "Give me some text 2", - "Lorem".getRandomString(100), - "", - "" - ), - Task( - 3, - "FreePrompt", - null, - "12", - "", - "Give me some text 3", - "Lorem".getRandomString(300), - "", - "" - ), - Task( - 4, - "FreePrompt", - null, - "12", - "", - "Give me some text 4", - "Lorem".getRandomString(300), - "", - "" - ), - Task( - 5, - "FreePrompt", - null, - "12", - "", - "Give me some text 5", - "Lorem".getRandomString(300), - "", - "" - ), - Task( - 6, - "FreePrompt", - null, - "12", - "", - "Give me some text 6", - "Lorem".getRandomString(300), - "", - "" - ), - Task( - 7, - "FreePrompt", - null, - "12", - "", - "Give me some text 7", - "Lorem".getRandomString(300), - "", - "" - ) + ) ) } diff --git a/app/src/main/java/com/nextcloud/client/assistant/task/TaskStatusView.kt b/app/src/main/java/com/nextcloud/client/assistant/task/TaskStatusView.kt index 6cc8c81183..79ec51a6bf 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/task/TaskStatusView.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/task/TaskStatusView.kt @@ -14,27 +14,37 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.ColorFilter +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import com.nextcloud.client.assistant.extensions.statusData +import com.nextcloud.client.assistant.extensions.getModifiedAtRepresentation +import com.nextcloud.client.assistant.extensions.getStatusIcon import com.owncloud.android.lib.resources.assistant.model.Task +import com.owncloud.android.lib.resources.assistant.model.TaskInput +import com.owncloud.android.lib.resources.assistant.model.TaskOutput +import java.util.concurrent.TimeUnit @Composable fun TaskStatusView(task: Task, foregroundColor: Color) { + val context = LocalContext.current + Row( modifier = Modifier .fillMaxWidth() .padding(vertical = 16.dp), verticalAlignment = Alignment.CenterVertically ) { - val (iconId, descriptionId) = task.statusData() + val iconId = task.getStatusIcon() + val description = task.getModifiedAtRepresentation(context) Image( painter = painterResource(id = iconId), @@ -43,16 +53,91 @@ fun TaskStatusView(task: Task, foregroundColor: Color) { contentDescription = "status icon" ) - Spacer(modifier = Modifier.width(6.dp)) - - Text(text = stringResource(id = descriptionId), color = foregroundColor) - - /* - Spacer(modifier = Modifier.weight(1f)) - - Text(text = task.completionDateRepresentation(), color = foregroundColor) - - Spacer(modifier = Modifier.width(6.dp)) - */ + description?.let { + Spacer(modifier = Modifier.width(6.dp)) + Text(text = description, color = foregroundColor) + } + } +} + +@Composable +@Preview +private fun TaskStatusViewPreview() { + val currentTime = System.currentTimeMillis() / 1000 + + val tasks = listOf( + Task( + id = 1L, + type = "type1", + status = "STATUS_RUNNING", + userId = "user1", + appId = "app1", + input = TaskInput("input1"), + output = TaskOutput("output1"), + scheduledAt = currentTime.toInt(), + lastUpdated = currentTime.toInt() + ), + + Task( + id = 2L, + type = "type2", + status = "STATUS_SUCCESSFUL", + userId = "user2", + appId = "app2", + input = TaskInput("input2"), + output = TaskOutput("output2"), + lastUpdated = (currentTime - TimeUnit.MINUTES.toSeconds(5)).toInt() + ), + + Task( + id = 3L, + type = "type3", + status = "STATUS_RUNNING", + userId = "user3", + appId = "app3", + input = TaskInput("input3"), + output = TaskOutput("output3"), + lastUpdated = (currentTime - TimeUnit.HOURS.toSeconds(5)).toInt() + ), + + Task( + id = 4L, + type = "type4", + status = "STATUS_SUCCESSFUL", + userId = "user4", + appId = "app4", + input = TaskInput("input4"), + output = TaskOutput("output4"), + lastUpdated = (currentTime - TimeUnit.DAYS.toSeconds(5)).toInt() + ), + + Task( + id = 5L, + type = "type5", + status = "STATUS_SUCCESSFUL", + userId = "user5", + appId = "app5", + input = TaskInput("input5"), + output = TaskOutput("output5"), + lastUpdated = (currentTime - TimeUnit.DAYS.toSeconds(60)).toInt() + ), + + Task( + id = 7L, + type = "type7", + status = "STATUS_UNKNOWN", + userId = "user7", + appId = "app7", + input = TaskInput("input7"), + output = TaskOutput("output7"), + scheduledAt = null, + lastUpdated = null + ) + ) + + LazyColumn { + items(tasks) { + TaskStatusView(it, foregroundColor = Color.White) + } } } diff --git a/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt b/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt index 48d7ea602b..9bbddba27a 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt @@ -45,6 +45,8 @@ import com.nextcloud.client.assistant.taskDetail.TaskDetailBottomSheet import com.nextcloud.ui.composeComponents.bottomSheet.MoreActionsBottomSheet import com.owncloud.android.R import com.owncloud.android.lib.resources.assistant.model.Task +import com.owncloud.android.lib.resources.assistant.model.TaskInput +import com.owncloud.android.lib.resources.assistant.model.TaskOutput @OptIn(ExperimentalFoundationApi::class) @Suppress("LongMethod", "MagicNumber") @@ -67,7 +69,7 @@ fun TaskView(task: Task, showDeleteTaskAlertDialog: (Long) -> Unit, showTaskActi ) { Spacer(modifier = Modifier.height(8.dp)) - task.input?.let { + task.input?.input?.let { Text( text = it, color = Color.White, @@ -80,7 +82,7 @@ fun TaskView(task: Task, showDeleteTaskAlertDialog: (Long) -> Unit, showTaskActi Spacer(modifier = Modifier.height(12.dp)) - task.output?.let { + task.output?.output?.let { val output = if (it.length >= 100) { it.take(100) + "..." } else { @@ -158,7 +160,7 @@ private fun TaskViewBottomSheet( ) MoreActionsBottomSheet( - title = task.input, + title = task.input?.input, actions = bottomSheetAction, dismiss = { dismiss() @@ -176,14 +178,17 @@ private fun TaskViewPreview() { task = Task( 1, "Free Prompt", - 0, + "STATUS_COMPLETED", "1", "1", - "What about other promising tokens like", - "Several tokens show promise for future growth in the" + - "cryptocurrency market", - "", - "" + TaskInput("What about other promising tokens like"), + TaskOutput("Several tokens show promise for future growth in the" + + "cryptocurrency market"), + 1707692337, + 1707692337, + 1707692337, + 1707692337, + 1707692337, ), showTaskActions = { }, showDeleteTaskAlertDialog = { diff --git a/app/src/main/java/com/nextcloud/client/assistant/taskDetail/TaskDetailBottomSheet.kt b/app/src/main/java/com/nextcloud/client/assistant/taskDetail/TaskDetailBottomSheet.kt index bc1ec78dda..aa02421eb9 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/taskDetail/TaskDetailBottomSheet.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/taskDetail/TaskDetailBottomSheet.kt @@ -49,6 +49,8 @@ import com.nextcloud.client.assistant.task.TaskStatusView import com.nextcloud.utils.extensions.getRandomString import com.owncloud.android.R import com.owncloud.android.lib.resources.assistant.model.Task +import com.owncloud.android.lib.resources.assistant.model.TaskInput +import com.owncloud.android.lib.resources.assistant.model.TaskOutput @Suppress("LongMethod") @OptIn(ExperimentalFoundationApi::class, ExperimentalMaterial3Api::class) @@ -123,9 +125,9 @@ fun TaskDetailBottomSheet(task: Task, showTaskActions: () -> Unit, dismiss: () - ) { Text( text = if (showInput) { - task.input ?: "" + task.input?.input ?: "" } else { - task.output ?: stringResource(R.string.assistant_screen_task_output_empty_text) + task.output?.output ?: stringResource(R.string.assistant_screen_task_output_empty_text) }, fontSize = 12.sp, color = MaterialTheme.colorScheme.onPrimaryContainer, @@ -173,13 +175,16 @@ private fun TaskDetailScreenPreview() { task = Task( 1, "Free Prompt", - 0, + null, "1", "1", - "Give me text".getRandomString(100), - "output".getRandomString(300), - "", - "" + TaskInput("Give me text".getRandomString(100)), + TaskOutput("output".getRandomString(300)), + 1707692337, + 1707692337, + 1707692337, + 1707692337, + 1707692337, ), showTaskActions = { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ce17c01b2d..c3ccd3a745 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -135,6 +135,21 @@ %d minutes + + 1 second ago + %d seconds ago + + + + 1 minute ago + %d minutes ago + + + + 1 hour ago + %d hours ago + + Try %1$s on your device! I want to invite you to use %1$s on your device.\nDownload here: %2$s %1$s or %2$s @@ -191,6 +206,7 @@ Yes No OK + Now Cancel sync Cancel Back From f7bfaa5ba1ebd27e864d29eb0d069ee3561de065 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Tue, 3 Dec 2024 13:29:43 +0100 Subject: [PATCH 11/34] adopt latest api changes Signed-off-by: alperozturk --- .../client/assistant/AssistantViewModel.kt | 59 ++++++------------- .../client/assistant/AsssistantScreen.kt | 56 +++++++----------- .../assistant/model/ScreenOverlayState.kt | 4 +- .../repository/AssistantMockRepository.kt | 12 +--- .../repository/AssistantRepository.kt | 4 +- .../repository/AssistantRepositoryType.kt | 2 +- .../assistant/taskTypes/TaskTypesRow.kt | 4 +- .../taskTypes/model/AssistantTaskType.kt | 30 ++++++++++ .../ui/composeActivity/ComposeActivity.kt | 4 +- app/src/main/res/values-ar/strings.xml | 1 - app/src/main/res/values-ast/strings.xml | 1 - app/src/main/res/values-b+en+001/strings.xml | 1 - app/src/main/res/values-bg-rBG/strings.xml | 1 - app/src/main/res/values-br/strings.xml | 1 - app/src/main/res/values-ca/strings.xml | 1 - app/src/main/res/values-cs-rCZ/strings.xml | 1 - app/src/main/res/values-da/strings.xml | 1 - app/src/main/res/values-de/strings.xml | 1 - app/src/main/res/values-el/strings.xml | 1 - app/src/main/res/values-eo/strings.xml | 1 - app/src/main/res/values-es-rAR/strings.xml | 1 - app/src/main/res/values-es-rCL/strings.xml | 1 - app/src/main/res/values-es-rCO/strings.xml | 1 - app/src/main/res/values-es-rDO/strings.xml | 1 - app/src/main/res/values-es-rEC/strings.xml | 1 - app/src/main/res/values-es-rMX/strings.xml | 1 - app/src/main/res/values-es/strings.xml | 1 - app/src/main/res/values-eu/strings.xml | 1 - app/src/main/res/values-fa/strings.xml | 1 - app/src/main/res/values-fi-rFI/strings.xml | 1 - app/src/main/res/values-fr/strings.xml | 1 - app/src/main/res/values-ga/strings.xml | 1 - app/src/main/res/values-gl/strings.xml | 1 - app/src/main/res/values-hr/strings.xml | 1 - app/src/main/res/values-hu-rHU/strings.xml | 1 - app/src/main/res/values-in/strings.xml | 1 - app/src/main/res/values-is/strings.xml | 1 - app/src/main/res/values-it/strings.xml | 1 - app/src/main/res/values-iw/strings.xml | 1 - app/src/main/res/values-ja-rJP/strings.xml | 1 - app/src/main/res/values-ka/strings.xml | 1 - app/src/main/res/values-ko/strings.xml | 1 - app/src/main/res/values-lt-rLT/strings.xml | 1 - app/src/main/res/values-lv/strings.xml | 1 - app/src/main/res/values-mk/strings.xml | 1 - app/src/main/res/values-nb-rNO/strings.xml | 1 - app/src/main/res/values-nl/strings.xml | 1 - app/src/main/res/values-pl/strings.xml | 1 - app/src/main/res/values-pt-rBR/strings.xml | 1 - app/src/main/res/values-pt-rPT/strings.xml | 1 - app/src/main/res/values-ro/strings.xml | 1 - app/src/main/res/values-ru/strings.xml | 1 - app/src/main/res/values-sc/strings.xml | 1 - app/src/main/res/values-sk-rSK/strings.xml | 1 - app/src/main/res/values-sl/strings.xml | 1 - app/src/main/res/values-sq/strings.xml | 1 - app/src/main/res/values-sr-rSP/strings.xml | 1 - app/src/main/res/values-sr/strings.xml | 1 - app/src/main/res/values-sv/strings.xml | 1 - app/src/main/res/values-th-rTH/strings.xml | 1 - app/src/main/res/values-tr/strings.xml | 1 - app/src/main/res/values-ug/strings.xml | 1 - app/src/main/res/values-uk/strings.xml | 1 - app/src/main/res/values-vi/strings.xml | 1 - app/src/main/res/values-zh-rCN/strings.xml | 1 - app/src/main/res/values-zh-rHK/strings.xml | 1 - app/src/main/res/values-zh-rTW/strings.xml | 1 - app/src/main/res/values/strings.xml | 2 - 68 files changed, 80 insertions(+), 155 deletions(-) create mode 100644 app/src/main/java/com/nextcloud/client/assistant/taskTypes/model/AssistantTaskType.kt diff --git a/app/src/main/java/com/nextcloud/client/assistant/AssistantViewModel.kt b/app/src/main/java/com/nextcloud/client/assistant/AssistantViewModel.kt index 4ec4601a96..579e0233a8 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/AssistantViewModel.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/AssistantViewModel.kt @@ -7,26 +7,24 @@ */ 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.nextcloud.client.assistant.taskTypes.model.AssistantTaskType +import com.nextcloud.client.assistant.taskTypes.model.toAssistantTaskTypeList import com.owncloud.android.R import com.owncloud.android.lib.resources.assistant.model.Task -import com.owncloud.android.lib.resources.assistant.model.TaskType 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 ) : ViewModel() { private val _screenState = MutableStateFlow(null) @@ -38,11 +36,11 @@ class AssistantViewModel( private val _snackbarMessageId = MutableStateFlow(null) val snackbarMessageId: StateFlow = _snackbarMessageId - private val _selectedTaskType = MutableStateFlow(null) - val selectedTaskType: StateFlow = _selectedTaskType + private val _selectedTaskType = MutableStateFlow(null) + val selectedTaskType: StateFlow = _selectedTaskType - private val _taskTypes = MutableStateFlow?>(null) - val taskTypes: StateFlow?> = _taskTypes + private val _taskTypes = MutableStateFlow?>(null) + val taskTypes: StateFlow?> = _taskTypes private var taskList: List? = null @@ -51,7 +49,6 @@ class AssistantViewModel( init { fetchTaskTypes() - fetchTaskList() } @Suppress("MagicNumber") @@ -72,27 +69,22 @@ class AssistantViewModel( } } - fun selectTaskType(task: TaskType) { + fun selectTaskType(task: AssistantTaskType) { _selectedTaskType.update { - filterTaskList(task.id) task } - updateScreenState() + 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.toAssistantTaskTypeList() _taskTypes.update { - result.toList() + result } selectTaskType(result.first()) @@ -102,16 +94,21 @@ class AssistantViewModel( } } - fun fetchTaskList(appId: String = "assistant") { + fun fetchTaskList() { viewModelScope.launch(Dispatchers.IO) { _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) + taskList = result.resultData.tasks.filter { it.appId == "assistant" } + _filteredTaskList.update { + taskList?.sortedByDescending { task -> + task.id + } + } updateSnackbarMessage(null) } else { updateSnackbarMessage(R.string.assistant_screen_task_list_error_state_message) @@ -161,24 +158,6 @@ class AssistantViewModel( } } - 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 - } - } - } - private fun removeTaskFromList(id: Long) { _filteredTaskList.update { currentList -> currentList?.filter { it.id != id } diff --git a/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt b/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt index e21fad6f46..45c14c38dc 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt @@ -34,7 +34,6 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp @@ -45,18 +44,17 @@ import com.nextcloud.client.assistant.model.ScreenState import com.nextcloud.client.assistant.repository.AssistantMockRepository import com.nextcloud.client.assistant.task.TaskView import com.nextcloud.client.assistant.taskTypes.TaskTypesRow +import com.nextcloud.client.assistant.taskTypes.model.AssistantTaskType import com.nextcloud.ui.composeActivity.ComposeActivity import com.nextcloud.ui.composeComponents.alertDialog.SimpleAlertDialog import com.nextcloud.ui.composeComponents.bottomSheet.MoreActionsBottomSheet import com.nextcloud.utils.extensions.showShareIntent 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.utils.ClipboardUtil import com.owncloud.android.utils.DisplayUtils import kotlinx.coroutines.delay import kotlinx.coroutines.launch -import java.lang.ref.WeakReference @Suppress("LongMethod") @OptIn(ExperimentalMaterial3Api::class) @@ -88,15 +86,13 @@ fun AssistantScreen(viewModel: AssistantViewModel, activity: Activity) { ShowLinearProgressIndicator(screenState, pullRefreshState) - if (selectedTaskType?.name != stringResource(id = R.string.assistant_screen_all_task_type)) { - AddFloatingActionButton( - modifier = Modifier - .align(Alignment.BottomEnd) - .padding(16.dp), - selectedTaskType, - viewModel - ) - } + AddFloatingActionButton( + modifier = Modifier + .align(Alignment.BottomEnd) + .padding(16.dp), + selectedTaskType, + viewModel + ) } showSnackBarMessage(messageId, activity, viewModel) @@ -106,8 +102,8 @@ fun AssistantScreen(viewModel: AssistantViewModel, activity: Activity) { @Composable private fun ShowScreenState( screenState: ScreenState?, - selectedTaskType: TaskType?, - taskTypes: List?, + selectedTaskType: AssistantTaskType?, + taskTypes: List?, viewModel: AssistantViewModel, filteredTaskList: List? ) { @@ -147,7 +143,7 @@ private fun ShowLinearProgressIndicator(screenState: ScreenState?, pullToRefresh } @Composable -private fun AddFloatingActionButton(modifier: Modifier, selectedTaskType: TaskType?, viewModel: AssistantViewModel) { +private fun AddFloatingActionButton(modifier: Modifier, selectedTaskType: AssistantTaskType?, viewModel: AssistantViewModel) { FloatingActionButton( modifier = modifier, onClick = { @@ -222,7 +218,7 @@ private fun ShowOverlayState( R.drawable.ic_edit, R.string.action_edit ) { - val taskType = TaskType( + val taskType = AssistantTaskType( state.task.type, activity.getString(R.string.assistant_screen_add_task_alert_dialog_title), null @@ -248,8 +244,8 @@ private fun ShowOverlayState( @Composable private fun AssistantContent( taskList: List, - taskTypes: List?, - selectedTaskType: TaskType?, + taskTypes: List?, + selectedTaskType: AssistantTaskType?, viewModel: AssistantViewModel ) { LazyColumn( @@ -282,15 +278,11 @@ private fun AssistantContent( } @Composable -private fun EmptyTaskList(selectedTaskType: TaskType?, taskTypes: List?, viewModel: AssistantViewModel) { - val text = if (selectedTaskType?.name == stringResource(id = R.string.assistant_screen_all_task_type)) { - stringResource(id = R.string.assistant_screen_no_task_available_for_all_task_filter_text) - } else { - stringResource( - id = R.string.assistant_screen_no_task_available_text, - selectedTaskType?.name ?: "" - ) - } +private fun EmptyTaskList(selectedTaskType: AssistantTaskType?, taskTypes: List?, viewModel: AssistantViewModel) { + val text = stringResource( + id = R.string.assistant_screen_no_task_available_text, + selectedTaskType?.name ?: "" + ) Column( modifier = Modifier @@ -314,10 +306,7 @@ private fun AssistantScreenPreview() { MaterialTheme( content = { AssistantScreen( - viewModel = AssistantViewModel( - repository = mockRepository, - context = WeakReference(LocalContext.current) - ), + viewModel = AssistantViewModel(repository = mockRepository), activity = ComposeActivity() ) } @@ -331,10 +320,7 @@ private fun AssistantEmptyScreenPreview() { MaterialTheme( content = { AssistantScreen( - viewModel = AssistantViewModel( - repository = mockRepository, - context = WeakReference(LocalContext.current) - ), + viewModel = AssistantViewModel(repository = mockRepository), activity = ComposeActivity() ) } diff --git a/app/src/main/java/com/nextcloud/client/assistant/model/ScreenOverlayState.kt b/app/src/main/java/com/nextcloud/client/assistant/model/ScreenOverlayState.kt index 23c6c44af7..8ef3410d76 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/model/ScreenOverlayState.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/model/ScreenOverlayState.kt @@ -7,11 +7,11 @@ package com.nextcloud.client.assistant.model +import com.nextcloud.client.assistant.taskTypes.model.AssistantTaskType import com.owncloud.android.lib.resources.assistant.model.Task -import com.owncloud.android.lib.resources.assistant.model.TaskType sealed class ScreenOverlayState { data class DeleteTask(val id: Long): ScreenOverlayState() - data class AddTask(val taskType: TaskType, val input: String): ScreenOverlayState() + data class AddTask(val taskType: AssistantTaskType, val input: String): ScreenOverlayState() data class TaskActions(val task: Task): ScreenOverlayState() } diff --git a/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantMockRepository.kt b/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantMockRepository.kt index a4066b746b..cf2e14e7b7 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantMockRepository.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantMockRepository.kt @@ -13,19 +13,13 @@ import com.owncloud.android.lib.resources.assistant.model.Task import com.owncloud.android.lib.resources.assistant.model.TaskInput import com.owncloud.android.lib.resources.assistant.model.TaskList import com.owncloud.android.lib.resources.assistant.model.TaskOutput -import com.owncloud.android.lib.resources.assistant.model.TaskType import com.owncloud.android.lib.resources.assistant.model.TaskTypes @Suppress("MagicNumber") class AssistantMockRepository(private val giveEmptyTasks: Boolean = false) : AssistantRepositoryType { override fun getTaskTypes(): RemoteOperationResult { return RemoteOperationResult(RemoteOperationResult.ResultCode.OK).apply { - resultData = TaskTypes( - listOf( - TaskType("1", "FreePrompt", "You can create free prompt text"), - TaskType("2", "Generate Headline", "You can create generate headline text") - ) - ) + resultData = null } } @@ -33,8 +27,7 @@ class AssistantMockRepository(private val giveEmptyTasks: Boolean = false) : Ass return RemoteOperationResult(RemoteOperationResult.ResultCode.OK) } - @Suppress("LongMethod") - override fun getTaskList(appId: String): RemoteOperationResult { + override fun getTaskList(taskType: String): RemoteOperationResult { val taskList = if (giveEmptyTasks) { TaskList(listOf()) } else { @@ -54,7 +47,6 @@ class AssistantMockRepository(private val giveEmptyTasks: Boolean = false) : Ass 1707692337, 1707692337, ), - ) ) } diff --git a/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantRepository.kt b/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantRepository.kt index 1cb32ff43c..1689ac021f 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantRepository.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantRepository.kt @@ -26,8 +26,8 @@ class AssistantRepository(private val client: NextcloudClient) : AssistantReposi return CreateTaskRemoteOperation(input, type).execute(client) } - override fun getTaskList(appId: String): RemoteOperationResult { - return GetTaskListRemoteOperation(appId).execute(client) + override fun getTaskList(taskType: String): RemoteOperationResult { + return GetTaskListRemoteOperation(taskType).execute(client) } override fun deleteTask(id: Long): RemoteOperationResult { diff --git a/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantRepositoryType.kt b/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantRepositoryType.kt index 8bb9808863..e8a0d2fb67 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantRepositoryType.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantRepositoryType.kt @@ -16,7 +16,7 @@ interface AssistantRepositoryType { fun createTask(input: String, type: String): RemoteOperationResult - fun getTaskList(appId: String): RemoteOperationResult + fun getTaskList(taskType: String): RemoteOperationResult fun deleteTask(id: Long): RemoteOperationResult } diff --git a/app/src/main/java/com/nextcloud/client/assistant/taskTypes/TaskTypesRow.kt b/app/src/main/java/com/nextcloud/client/assistant/taskTypes/TaskTypesRow.kt index db7e2ac2eb..976d8603c9 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/taskTypes/TaskTypesRow.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/taskTypes/TaskTypesRow.kt @@ -20,10 +20,10 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp -import com.owncloud.android.lib.resources.assistant.model.TaskType +import com.nextcloud.client.assistant.taskTypes.model.AssistantTaskType @Composable -fun TaskTypesRow(selectedTaskType: TaskType?, data: List?, selectTaskType: (TaskType) -> Unit) { +fun TaskTypesRow(selectedTaskType: AssistantTaskType?, data: List?, selectTaskType: (AssistantTaskType) -> Unit) { Row( modifier = Modifier .fillMaxWidth() diff --git a/app/src/main/java/com/nextcloud/client/assistant/taskTypes/model/AssistantTaskType.kt b/app/src/main/java/com/nextcloud/client/assistant/taskTypes/model/AssistantTaskType.kt new file mode 100644 index 0000000000..8ac2af7bc4 --- /dev/null +++ b/app/src/main/java/com/nextcloud/client/assistant/taskTypes/model/AssistantTaskType.kt @@ -0,0 +1,30 @@ +/* + * Nextcloud - Android Client + * + * SPDX-FileCopyrightText: 2024 Alper Ozturk + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package com.nextcloud.client.assistant.taskTypes.model + +import com.owncloud.android.lib.resources.assistant.model.TaskTypes + +data class AssistantTaskType( + val id: String?, + val name: String?, + val description: String? +) + +fun TaskTypes.toAssistantTaskTypeList(): List { + return arrayListOf().apply { + add(AssistantTaskType("core:text2text", types.coreText2text.name, types.coreText2text.description)) + add(AssistantTaskType("core:text2text:topics", types.coreText2textTopics.name, types.coreText2textTopics.description)) + add(AssistantTaskType("core:text2text:headline", types.coreText2textHeadline.name, types.coreText2textHeadline.description)) + add(AssistantTaskType("core:text2text:summary", types.coreText2textSummary.name, types.coreText2textSummary.description)) + add(AssistantTaskType("core:text2text:translate", types.coreText2textTranslate.name, types.coreText2textTranslate.description)) + add(AssistantTaskType("core:text2image", types.coreText2image.name, types.coreText2image.description)) + add(AssistantTaskType("core:audio2text", types.coreAudio2text.name, types.coreAudio2text.description)) + add(AssistantTaskType("core:contextwrite", types.coreContextwrite.name, types.coreContextwrite.description)) + add(AssistantTaskType("context_chat:context_chat", types.contextChatContextChat.name, types.contextChatContextChat.description)) + } +} diff --git a/app/src/main/java/com/nextcloud/ui/composeActivity/ComposeActivity.kt b/app/src/main/java/com/nextcloud/ui/composeActivity/ComposeActivity.kt index d341769208..d310e6e37c 100644 --- a/app/src/main/java/com/nextcloud/ui/composeActivity/ComposeActivity.kt +++ b/app/src/main/java/com/nextcloud/ui/composeActivity/ComposeActivity.kt @@ -31,7 +31,6 @@ import com.owncloud.android.lib.common.utils.Log_OC import com.owncloud.android.ui.activity.DrawerActivity import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext -import java.lang.ref.WeakReference class ComposeActivity : DrawerActivity() { @@ -88,8 +87,7 @@ class ComposeActivity : DrawerActivity() { nextcloudClient?.let { client -> AssistantScreen( viewModel = AssistantViewModel( - repository = AssistantRepository(client), - context = WeakReference(this) + repository = AssistantRepository(client) ), activity = this ) diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index b5be74127c..7e3c5a29b8 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -46,7 +46,6 @@ منفذ البروكسي عرض أداة واحدة من لوحة القيادة بحث في %s - الكل أكتُب أيَّ نص هل أنت متأكد أنك ترغب بحذف هذه المهمة؟ حذف مهمة diff --git a/app/src/main/res/values-ast/strings.xml b/app/src/main/res/values-ast/strings.xml index 024a3b1fe2..2609787a47 100644 --- a/app/src/main/res/values-ast/strings.xml +++ b/app/src/main/res/values-ast/strings.xml @@ -24,7 +24,6 @@ URL base Puertu del proxy Buscar en: %s - Too Escribi daqué Falló Planificóse diff --git a/app/src/main/res/values-b+en+001/strings.xml b/app/src/main/res/values-b+en+001/strings.xml index 9d2a448b6f..783c6802b1 100644 --- a/app/src/main/res/values-b+en+001/strings.xml +++ b/app/src/main/res/values-b+en+001/strings.xml @@ -46,7 +46,6 @@ Proxy Port Shows one widget from dashboard Search in %s - All Type some text Are you sure you want to delete this task? Delete Task diff --git a/app/src/main/res/values-bg-rBG/strings.xml b/app/src/main/res/values-bg-rBG/strings.xml index f3bf9cd3d3..54250c33a4 100644 --- a/app/src/main/res/values-bg-rBG/strings.xml +++ b/app/src/main/res/values-bg-rBG/strings.xml @@ -36,7 +36,6 @@ Порт на прокси сървъра Показва един изпълним модул от таблото за управление Търсене в %s - Всички Неуспешно Планирано Завършен diff --git a/app/src/main/res/values-br/strings.xml b/app/src/main/res/values-br/strings.xml index 038992b03c..035c93b1fc 100644 --- a/app/src/main/res/values-br/strings.xml +++ b/app/src/main/res/values-br/strings.xml @@ -37,7 +37,6 @@ Porzh Proksi Diskouez a ra ur widget dre daolenn-vourzh Klask e %s - Pep tra Skrivañ un tamm testenn Ha sur oc\'h e fell deoc\'h dilemel an trevell-mañ ? Dilemel an trevell diff --git a/app/src/main/res/values-ca/strings.xml b/app/src/main/res/values-ca/strings.xml index b233effbdb..8fe134b9b8 100644 --- a/app/src/main/res/values-ca/strings.xml +++ b/app/src/main/res/values-ca/strings.xml @@ -45,7 +45,6 @@ Port del proxy Mostra un giny del tauler Cerca a %s - Totes Escriu una mica de text Segur que voleu suprimir aquesta tasca? Suprimeix la tasca diff --git a/app/src/main/res/values-cs-rCZ/strings.xml b/app/src/main/res/values-cs-rCZ/strings.xml index 1558ecf62f..f6ca3a448d 100644 --- a/app/src/main/res/values-cs-rCZ/strings.xml +++ b/app/src/main/res/values-cs-rCZ/strings.xml @@ -46,7 +46,6 @@ Port proxy Zobrazuje jeden ovládací prvek z nástěnky Hledat v %s - Vše Zadejte nějaký text Opravdu chcete tuto úlohu smazat? Smazat úkol diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml index 4d9ce7958f..710f2598ee 100644 --- a/app/src/main/res/values-da/strings.xml +++ b/app/src/main/res/values-da/strings.xml @@ -36,7 +36,6 @@ Tillad videredeling Viser én widget fra dashboard Søg i %s - Alle Skriv noget tekst Er du sikker på du vil slette denne opgave? Slet opgave diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index f35eab33c8..ceffb6541b 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -46,7 +46,6 @@ Proxy-Port Zeigt ein Widget aus dem Dashboard an Suche in %s - Alle Bitte einen Text eingeben Möchten Sie diese Aufgabe wirklich löschen? Aufgabe löschen diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index da9cd10d30..9e3e09020b 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -35,7 +35,6 @@ Θύρα διαμεσολαβητή Εμφάνιση ενός γραφικού στοιχείου από τον πίνακα ελέγχου Αναζήτηση στο %s - \'Ολα Πληκτρολογήστε κάποιο κείμενο Απέτυχε Ολοκληρωμένες diff --git a/app/src/main/res/values-eo/strings.xml b/app/src/main/res/values-eo/strings.xml index 41aa8b73d2..a0655d9b8d 100644 --- a/app/src/main/res/values-eo/strings.xml +++ b/app/src/main/res/values-eo/strings.xml @@ -31,7 +31,6 @@ Detalaj agordoj Permesi rekunhavigon Serĉi en 1%s - Ĉiuj Plenumita Nekonata Aliro malsukcesis: %1$s diff --git a/app/src/main/res/values-es-rAR/strings.xml b/app/src/main/res/values-es-rAR/strings.xml index 39e68285ea..47318ff136 100644 --- a/app/src/main/res/values-es-rAR/strings.xml +++ b/app/src/main/res/values-es-rAR/strings.xml @@ -37,7 +37,6 @@ Puerto del Proxy Muestra un widget del panel Buscar en %s - Todos Escriba un texto ¿Está seguro que desea eliminar esta tarea? Eliminar tarea diff --git a/app/src/main/res/values-es-rCL/strings.xml b/app/src/main/res/values-es-rCL/strings.xml index d10f842d9e..47e61d6816 100644 --- a/app/src/main/res/values-es-rCL/strings.xml +++ b/app/src/main/res/values-es-rCL/strings.xml @@ -37,7 +37,6 @@ Puerto del Proxy Muestra un widget del panel de control Buscar en %s - Todos Escribe un texto ¿Está seguro que desea eliminar esta tarea? Tarea eliminada diff --git a/app/src/main/res/values-es-rCO/strings.xml b/app/src/main/res/values-es-rCO/strings.xml index 6df403977b..e76eb967bd 100644 --- a/app/src/main/res/values-es-rCO/strings.xml +++ b/app/src/main/res/values-es-rCO/strings.xml @@ -31,7 +31,6 @@ Configuración avanzada Permitir volver a compartir Buscar en %s - Todos Completado Desconocido ¡No se encontró la cuenta asociada! diff --git a/app/src/main/res/values-es-rDO/strings.xml b/app/src/main/res/values-es-rDO/strings.xml index 852854810a..8db8c1ea8a 100644 --- a/app/src/main/res/values-es-rDO/strings.xml +++ b/app/src/main/res/values-es-rDO/strings.xml @@ -30,7 +30,6 @@ Agregar a %1$s Permitir volver a compartir Buscar en %s - Todos Completado Desconocido ¡Cuenta asociada no encontrada! diff --git a/app/src/main/res/values-es-rEC/strings.xml b/app/src/main/res/values-es-rEC/strings.xml index 03317462ae..7cd2a4d521 100644 --- a/app/src/main/res/values-es-rEC/strings.xml +++ b/app/src/main/res/values-es-rEC/strings.xml @@ -36,7 +36,6 @@ Puerto del proxy Muestra un widget del panel de control Compartir en %s - Todos Error Programado Completado diff --git a/app/src/main/res/values-es-rMX/strings.xml b/app/src/main/res/values-es-rMX/strings.xml index 49ba3ae57f..ee2be0d136 100644 --- a/app/src/main/res/values-es-rMX/strings.xml +++ b/app/src/main/res/values-es-rMX/strings.xml @@ -37,7 +37,6 @@ Puerto del proxy Muestra un widget del panel Buscar en %s - Todos Escriba algo de texto ¿Está seguro de eliminar esta tarea? Eliminar tarea diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index c4a9bc5307..89e05e5790 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -38,7 +38,6 @@ Puerto del proxy Muestra un widget del tablero Buscar en %s - Todo Escriba algo de texto ¿Está seguro de querer eliminar esta tarea? Eliminar tarea diff --git a/app/src/main/res/values-eu/strings.xml b/app/src/main/res/values-eu/strings.xml index ae0cdf9d98..307763c273 100644 --- a/app/src/main/res/values-eu/strings.xml +++ b/app/src/main/res/values-eu/strings.xml @@ -46,7 +46,6 @@ Proxy-ataka Paneleko trepeta bat erakusten du Bilatu %s(e)n - Denak Idatzi testu bat Ziur zeregin hau ezabatu nahi duzula? Ezabatu zeregina diff --git a/app/src/main/res/values-fa/strings.xml b/app/src/main/res/values-fa/strings.xml index d5e324ea28..11b1f451d1 100644 --- a/app/src/main/res/values-fa/strings.xml +++ b/app/src/main/res/values-fa/strings.xml @@ -38,7 +38,6 @@ پورت پروکسی نمایش یک ابزارک از پیشخوان جستجو در %s - همه مقداری متن را تایپ کنید Failed Scheduled diff --git a/app/src/main/res/values-fi-rFI/strings.xml b/app/src/main/res/values-fi-rFI/strings.xml index 4c917c8e5f..a7a30c9f8d 100644 --- a/app/src/main/res/values-fi-rFI/strings.xml +++ b/app/src/main/res/values-fi-rFI/strings.xml @@ -36,7 +36,6 @@ Välityspalvelimen portti Näyttää yhden pienoissovelluksen konsolista Etsi kohteesta %s - Kaikki Syötä tekstiä Haluatko varmasti poistaa tämän tehtävän? Poista tehtävä diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 20021336b1..d8928562be 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -46,7 +46,6 @@ Port Proxy Affiche un widget du tableau de bord Recherche dans %s - Tout Tapez du texte Êtes-vous sûr de vouloir supprimer cette tâche ? Supprimer la tâche diff --git a/app/src/main/res/values-ga/strings.xml b/app/src/main/res/values-ga/strings.xml index c2ea1c2992..0f913d68f3 100644 --- a/app/src/main/res/values-ga/strings.xml +++ b/app/src/main/res/values-ga/strings.xml @@ -46,7 +46,6 @@ Port Seachfhreastalaí Taispeáin giuirléid amháin ón deais Cuardaigh i %s - Gach Clóscríobh roinnt téacs An bhfuil tú cinnte gur mhaith leat an tasc seo a scriosadh? Scrios Tasc diff --git a/app/src/main/res/values-gl/strings.xml b/app/src/main/res/values-gl/strings.xml index 67f1549dfb..0d98dbf37c 100644 --- a/app/src/main/res/values-gl/strings.xml +++ b/app/src/main/res/values-gl/strings.xml @@ -46,7 +46,6 @@ Porto do proxy Amosa un trebello do taboleiro Buscar en %s - Todo Escriba algún texto Confirma que quere eliminar esta tarefa? Eliminar tarefa diff --git a/app/src/main/res/values-hr/strings.xml b/app/src/main/res/values-hr/strings.xml index 53f588a9f8..dab66b27c0 100644 --- a/app/src/main/res/values-hr/strings.xml +++ b/app/src/main/res/values-hr/strings.xml @@ -34,7 +34,6 @@ Osnovni URL Proxy port Traži u %s - Sve Završeno Nepoznata pogreška Pripadajući račun nije pronađen! diff --git a/app/src/main/res/values-hu-rHU/strings.xml b/app/src/main/res/values-hu-rHU/strings.xml index f95ab65b84..dce31e6544 100644 --- a/app/src/main/res/values-hu-rHU/strings.xml +++ b/app/src/main/res/values-hu-rHU/strings.xml @@ -40,7 +40,6 @@ Proxy portja Egy modult jelenít meg a irányítópultról Keresés itt: %s - Összes Gépeljen be szöveget Sikertelen Ütemezve diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index a67029d9b9..55097e8359 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -35,7 +35,6 @@ Izinkan pembagian ulang Menampilkan satu gawit dari dasbor Cari dalam %s - Semua Tulis beberapa teks Apakah Anda yakin ingin menghapus tugas ini? Hapus Tugas diff --git a/app/src/main/res/values-is/strings.xml b/app/src/main/res/values-is/strings.xml index e15d7d88c0..db2c3fd041 100644 --- a/app/src/main/res/values-is/strings.xml +++ b/app/src/main/res/values-is/strings.xml @@ -35,7 +35,6 @@ Gátt milliþjóns Sýnir einn viðmótshluta af stjórnborði Leita í %s - Allt Lokið Óþekkt Tengdur notandaaðgangur fannst ekki! diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 3ec6517f45..69f70ee415 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -46,7 +46,6 @@ Porta proxy Mostra un widget dal cruscotto Cerca in %s - Tutti Aggiungi del testo Sei sicuro di voler rimuovere questa attività? Elimina attività diff --git a/app/src/main/res/values-iw/strings.xml b/app/src/main/res/values-iw/strings.xml index 4cb19df0ce..9a7768e510 100644 --- a/app/src/main/res/values-iw/strings.xml +++ b/app/src/main/res/values-iw/strings.xml @@ -35,7 +35,6 @@ פתחת מתווך מצג וידג׳ט אחד מלוח הבקרה חפש ב %s - הכול הושלם לא ידוע לא נמצא חשבון משויך! diff --git a/app/src/main/res/values-ja-rJP/strings.xml b/app/src/main/res/values-ja-rJP/strings.xml index ee616d46ed..235a4284ea 100644 --- a/app/src/main/res/values-ja-rJP/strings.xml +++ b/app/src/main/res/values-ja-rJP/strings.xml @@ -46,7 +46,6 @@ プロキシポート ダッシュボードから一つのウィジェットを表示 %s の中を検索 - すべて テキストを入力 本当にこのタスクを削除しますか? タスクを削除 diff --git a/app/src/main/res/values-ka/strings.xml b/app/src/main/res/values-ka/strings.xml index 0bf9ee5e44..b5214708f1 100644 --- a/app/src/main/res/values-ka/strings.xml +++ b/app/src/main/res/values-ka/strings.xml @@ -35,7 +35,6 @@ Allow resharing Shows one widget from dashboard Search in %s - All Failed Completed Unknown diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index e84e072565..2cafec7609 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -38,7 +38,6 @@ 프록시 포트 대시보드에 위젯 하나만 표시 %s에서 검색 - 모두 텍스트 입력 이 작업을 삭제하시겠습니까? 작업 삭제 diff --git a/app/src/main/res/values-lt-rLT/strings.xml b/app/src/main/res/values-lt-rLT/strings.xml index d1638648c0..1767c1c6c8 100644 --- a/app/src/main/res/values-lt-rLT/strings.xml +++ b/app/src/main/res/values-lt-rLT/strings.xml @@ -37,7 +37,6 @@ Įgaliotojo serverio prievadas Rodo vieną valdiklį iš skydelio Ieškoti %s - Visos Įrašykite kokį nors tekstą Ar tikrai norite ištrinti šią užduotį? Ištrinti užduotį diff --git a/app/src/main/res/values-lv/strings.xml b/app/src/main/res/values-lv/strings.xml index 467e141b95..858f100224 100644 --- a/app/src/main/res/values-lv/strings.xml +++ b/app/src/main/res/values-lv/strings.xml @@ -33,7 +33,6 @@ Atļaut atkārtotu koplietošanu Starpniekservera ports Meklēt %s - Visi Dzēst uzdevumu Neizdevās Pabeigts diff --git a/app/src/main/res/values-mk/strings.xml b/app/src/main/res/values-mk/strings.xml index 7c14988bff..f09707c6f9 100644 --- a/app/src/main/res/values-mk/strings.xml +++ b/app/src/main/res/values-mk/strings.xml @@ -34,7 +34,6 @@ Proxy порта Прикажува еден виџет од контролната табла Барај во %s - Сите Неуспешно Завршено Непознат diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml index 37d886a278..59c1d93b8e 100644 --- a/app/src/main/res/values-nb-rNO/strings.xml +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -38,7 +38,6 @@ Proxy-port Viser en widget fra dashbordet Søk i %s - Alle Skriv inn litt tekst Er du sikker på at du vil slette denne oppgaven? Slett oppgave diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 19b6a387b4..642dbf6bfe 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -46,7 +46,6 @@ Proxy poort Toont één widget van dashboard Zoeken in %s - Alle Geef wat tekst in Bent u zeker dat u deze taak wilt verwijderen? Verwijder taak diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 8c164208ef..543ddc096d 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -45,7 +45,6 @@ Port proxy Pokazuje jeden widżet z pulpitu nawigacyjnego Szukaj w %s - Wszystkie Wpisz jakiś tekst Czy na pewno chcesz usunąć to zadanie? Usuń zadanie diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 69cf7f5e18..3ab79e4221 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -39,7 +39,6 @@ Porta do Proxy Mostra um widget do painel Pesquisar em %s - Tudos Digite algum texto Tem certeza de que deseja excluir esta tarefa? Excluir tarefa diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index 3a666664cd..2bc8f8053d 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -34,7 +34,6 @@ Permitir repartilha Mostra um \'\'widget\'\' do painel Procurar em %s - Todos Concluída Desconhecido Conta associada não encontrada! diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index 823c07aa0c..9517775ac3 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -37,7 +37,6 @@ Port proxy Arată un singur widget din panoul principal Caută in %s - Toate Tastează un text Sigur doriți să ștergeți acest task? Şterge task diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index ccceed196e..ec579c1ba8 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -38,7 +38,6 @@ Порт прокси Показывает один виджет с главного экрана. Искать в %s - Все Наберите какой-то текст Вы уверены, что хотите удалить эту задачу? Удалить задачу diff --git a/app/src/main/res/values-sc/strings.xml b/app/src/main/res/values-sc/strings.xml index 4f72789c87..b270eef792 100644 --- a/app/src/main/res/values-sc/strings.xml +++ b/app/src/main/res/values-sc/strings.xml @@ -35,7 +35,6 @@ URL de base Port serbidore intermèdiu Chirca in %s - Totu Peruna faina a disponimentu. Seletziona sa genia de faina pro nde creare una noa. Peruna faina a disponimentu pro sa genia %s. Nde podes creare una noa dae su cugione in bassu a dereta. Cumpletadu diff --git a/app/src/main/res/values-sk-rSK/strings.xml b/app/src/main/res/values-sk-rSK/strings.xml index 26132f0f3e..a2daa96479 100644 --- a/app/src/main/res/values-sk-rSK/strings.xml +++ b/app/src/main/res/values-sk-rSK/strings.xml @@ -46,7 +46,6 @@ Brána proxy Zobrazí jeden widget z hlavného panela Hľadať v %s - Všetko Napíšte nejaký text Naozaj chcete vymazať túto úlohu? Vymazať Úlohu diff --git a/app/src/main/res/values-sl/strings.xml b/app/src/main/res/values-sl/strings.xml index 886464bb71..2508769f87 100644 --- a/app/src/main/res/values-sl/strings.xml +++ b/app/src/main/res/values-sl/strings.xml @@ -38,7 +38,6 @@ Vrata posredniškega strežnika Pokaži en gradnik iz nadzorne plošče Poišči v %s - Vse Opravilo je spodletelo! Načrtovano Končano diff --git a/app/src/main/res/values-sq/strings.xml b/app/src/main/res/values-sq/strings.xml index ce77e5b62b..d3ea0bb766 100644 --- a/app/src/main/res/values-sq/strings.xml +++ b/app/src/main/res/values-sq/strings.xml @@ -29,7 +29,6 @@ Cilësime të Avancuara Lejo rindarje Kërkoni në %s - Të gjithë Të plotësuara I panjohur Llogaria e lidhur nuk u gjet! diff --git a/app/src/main/res/values-sr-rSP/strings.xml b/app/src/main/res/values-sr-rSP/strings.xml index 652431135b..73ea5112a4 100644 --- a/app/src/main/res/values-sr-rSP/strings.xml +++ b/app/src/main/res/values-sr-rSP/strings.xml @@ -30,7 +30,6 @@ Dodaj u %1$s Napredna podešavanja Pretraga u %s - Sve Da li ste sigurni da želite da izbrišete ovaj zadatak? Izbriši zadatak Nije uspelo diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml index e89f8d589d..1d0410059b 100644 --- a/app/src/main/res/values-sr/strings.xml +++ b/app/src/main/res/values-sr/strings.xml @@ -46,7 +46,6 @@ Прокси порт Приказује један виџет са контролне табле Тражи у %s - Све Откуцајте неки текст Да ли сте сигурни да желите да обришете овај задатак? Обриши задатак diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 8299cc8578..fd394d3d07 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -46,7 +46,6 @@ Proxyport Visa en widget från dashboard Sök i %s - Alla Skriv någon text Är du säker på att du vill ta bort den här uppgiften? Ta bort uppgift diff --git a/app/src/main/res/values-th-rTH/strings.xml b/app/src/main/res/values-th-rTH/strings.xml index 848d04a9de..dc25210656 100644 --- a/app/src/main/res/values-th-rTH/strings.xml +++ b/app/src/main/res/values-th-rTH/strings.xml @@ -34,7 +34,6 @@ อนุญาตให้แชร์ซ้ำ แสดงหนึ่งวิดเจ็ตจากแดชบอร์ด ค้นหาใน %s - ทั้งหมด พิมพ์ข้อความของคุณ อยู่ระหว่างการดำเนินการ เสร็จแล้ว diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 395832b90d..37485f0d17 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -38,7 +38,6 @@ Vekil sunucu bağlantı noktası Panodan bir pano bileşeni görüntüler %s içinde arama - Tümü Bir şeyler yazın Bu görevi silmek istediğinize emin misiniz? Görevi sil diff --git a/app/src/main/res/values-ug/strings.xml b/app/src/main/res/values-ug/strings.xml index bb64d4b20f..dec44b5e36 100644 --- a/app/src/main/res/values-ug/strings.xml +++ b/app/src/main/res/values-ug/strings.xml @@ -38,7 +38,6 @@ ۋاكالەتچى ئېغىز باشقۇرۇش تاختىسىدىكى بىر كىچىك قورالنى كۆرسىتىدۇ % S دىن ئىزدەڭ - ھەممىسى بەزى تېكىستلەرنى كىرگۈزۈڭ بۇ ۋەزىپىنى ئۆچۈرمەكچىمۇ؟ ۋەزىپىنى ئۆچۈرۈڭ diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index f6ba502de8..27555b0e6f 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -46,7 +46,6 @@ Порт проксі-сервера Показувати один віджет з панелі віджетів Пошук у %s - Всі Вставте будь-який текст Дійсно вилучити це завдання? Вилучити завдання diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index 703030f62c..bc49e11974 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -33,7 +33,6 @@ Cho phép chia sẻ lại Hiện thị lối tắt từ dashboard Tìm kiếm trong %s - Tất cả Lên kế hoạch Hoàn thành Không xác định diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 30efb9373d..625773c3b7 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -46,7 +46,6 @@ 代理端口 显示仪表盘中的一个小部件 在 %s 中搜索 - 所有 输入一些文字 您确定要删除这些任务吗? 删除任务 diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml index a3ccd239a3..4d78a0a6af 100644 --- a/app/src/main/res/values-zh-rHK/strings.xml +++ b/app/src/main/res/values-zh-rHK/strings.xml @@ -46,7 +46,6 @@ proxy代理伺服器連接埠 顯示儀表板中的一個小部件 %s內搜尋 - 全部 輸入一些文字 您確定要刪除此工作項目嗎? 刪除任務 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index c85a54adb4..12aa410724 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -46,7 +46,6 @@ proxy代理伺服器連接埠 顯示儀表板中的一個小工具 搜尋 %s - 全部 輸入一些文字 您確定要刪除此工作項目嗎? 刪除工作項目 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c3ccd3a745..41a1d29e3a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -76,8 +76,6 @@ Input Output - All - Assistant All files Personal files From ded93848a4f029a63032e1f8af35046c83a9960f Mon Sep 17 00:00:00 2001 From: alperozturk Date: Tue, 3 Dec 2024 13:36:10 +0100 Subject: [PATCH 12/34] only use text context Signed-off-by: alperozturk --- .../client/assistant/taskTypes/model/AssistantTaskType.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/src/main/java/com/nextcloud/client/assistant/taskTypes/model/AssistantTaskType.kt b/app/src/main/java/com/nextcloud/client/assistant/taskTypes/model/AssistantTaskType.kt index 8ac2af7bc4..1bfc3c3079 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/taskTypes/model/AssistantTaskType.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/taskTypes/model/AssistantTaskType.kt @@ -22,8 +22,6 @@ fun TaskTypes.toAssistantTaskTypeList(): List { add(AssistantTaskType("core:text2text:headline", types.coreText2textHeadline.name, types.coreText2textHeadline.description)) add(AssistantTaskType("core:text2text:summary", types.coreText2textSummary.name, types.coreText2textSummary.description)) add(AssistantTaskType("core:text2text:translate", types.coreText2textTranslate.name, types.coreText2textTranslate.description)) - add(AssistantTaskType("core:text2image", types.coreText2image.name, types.coreText2image.description)) - add(AssistantTaskType("core:audio2text", types.coreAudio2text.name, types.coreAudio2text.description)) add(AssistantTaskType("core:contextwrite", types.coreContextwrite.name, types.coreContextwrite.description)) add(AssistantTaskType("context_chat:context_chat", types.contextChatContextChat.name, types.contextChatContextChat.description)) } From 312e793fb2ffb9317cc8a0d8d9baf228e9c73b42 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Tue, 3 Dec 2024 14:50:36 +0100 Subject: [PATCH 13/34] fix add operation Signed-off-by: alperozturk --- .../client/assistant/extensions/TaskExtensions.kt | 2 +- .../assistant/taskTypes/model/AssistantTaskType.kt | 12 +++++------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/nextcloud/client/assistant/extensions/TaskExtensions.kt b/app/src/main/java/com/nextcloud/client/assistant/extensions/TaskExtensions.kt index bdb00c20a0..845e410ab8 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/extensions/TaskExtensions.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/extensions/TaskExtensions.kt @@ -53,7 +53,7 @@ fun Task.getModifiedAtRepresentation(context: Context): String? { val timeDifferenceInHours = (timeDifference / 3600) return when { - timeDifference == 0 -> { + timeDifference < 0 -> { context.getString(R.string.common_now) } diff --git a/app/src/main/java/com/nextcloud/client/assistant/taskTypes/model/AssistantTaskType.kt b/app/src/main/java/com/nextcloud/client/assistant/taskTypes/model/AssistantTaskType.kt index 1bfc3c3079..2da8192465 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/taskTypes/model/AssistantTaskType.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/taskTypes/model/AssistantTaskType.kt @@ -7,6 +7,7 @@ package com.nextcloud.client.assistant.taskTypes.model +import com.owncloud.android.lib.resources.assistant.model.TaskIds import com.owncloud.android.lib.resources.assistant.model.TaskTypes data class AssistantTaskType( @@ -17,12 +18,9 @@ data class AssistantTaskType( fun TaskTypes.toAssistantTaskTypeList(): List { return arrayListOf().apply { - add(AssistantTaskType("core:text2text", types.coreText2text.name, types.coreText2text.description)) - add(AssistantTaskType("core:text2text:topics", types.coreText2textTopics.name, types.coreText2textTopics.description)) - add(AssistantTaskType("core:text2text:headline", types.coreText2textHeadline.name, types.coreText2textHeadline.description)) - add(AssistantTaskType("core:text2text:summary", types.coreText2textSummary.name, types.coreText2textSummary.description)) - add(AssistantTaskType("core:text2text:translate", types.coreText2textTranslate.name, types.coreText2textTranslate.description)) - add(AssistantTaskType("core:contextwrite", types.coreContextwrite.name, types.coreContextwrite.description)) - add(AssistantTaskType("context_chat:context_chat", types.contextChatContextChat.name, types.contextChatContextChat.description)) + add(AssistantTaskType(TaskIds.GenerateText.id, types.generateText.name, types.generateText.description)) + add(AssistantTaskType(TaskIds.ExtractTopics.id, types.extractTopics.name, types.extractTopics.description)) + add(AssistantTaskType(TaskIds.GenerateHeadline.id, types.generateHeadline.name, types.generateHeadline.description)) + add(AssistantTaskType(TaskIds.Summarize.id, types.summarize.name, types.summarize.description)) } } From 4796b679430a73fbf85c2fa4421ec25c5f8b4db2 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Tue, 3 Dec 2024 14:58:13 +0100 Subject: [PATCH 14/34] remove combined click Signed-off-by: alperozturk --- .../client/assistant/AsssistantScreen.kt | 14 ++++--- .../client/assistant/task/TaskView.kt | 40 +++---------------- .../task/model/TaskViewBottomSheetType.kt | 2 +- 3 files changed, 15 insertions(+), 41 deletions(-) diff --git a/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt b/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt index 45c14c38dc..97bb8b2649 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt @@ -226,7 +226,15 @@ private fun ShowOverlayState( val newState = ScreenOverlayState.AddTask(taskType, state.task.input?.input ?: "") viewModel.updateScreenState(newState) - } + }, + Triple( + R.drawable.ic_delete, + R.string.assistant_screen_task_more_actions_bottom_sheet_delete_action + ) { + val newState = + ScreenOverlayState.DeleteTask(state.task.id) + viewModel.updateScreenState(newState) + }, ) MoreActionsBottomSheet( @@ -263,10 +271,6 @@ private fun AssistantContent( items(taskList) { task -> TaskView(task, - showDeleteTaskAlertDialog = { - val newState = ScreenOverlayState.DeleteTask(task.id) - viewModel.updateScreenState(newState) - }, showTaskActions = { val newState = ScreenOverlayState.TaskActions(task) viewModel.updateScreenState(newState) diff --git a/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt b/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt index 9bbddba27a..49dc4f3ee5 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt @@ -9,9 +9,8 @@ package com.nextcloud.client.assistant.task import androidx.compose.animation.animateContentSize import androidx.compose.animation.core.Spring import androidx.compose.animation.core.spring -import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background -import androidx.compose.foundation.combinedClickable +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer @@ -42,16 +41,13 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.nextcloud.client.assistant.task.model.TaskViewBottomSheetType import com.nextcloud.client.assistant.taskDetail.TaskDetailBottomSheet -import com.nextcloud.ui.composeComponents.bottomSheet.MoreActionsBottomSheet -import com.owncloud.android.R import com.owncloud.android.lib.resources.assistant.model.Task import com.owncloud.android.lib.resources.assistant.model.TaskInput import com.owncloud.android.lib.resources.assistant.model.TaskOutput -@OptIn(ExperimentalFoundationApi::class) @Suppress("LongMethod", "MagicNumber") @Composable -fun TaskView(task: Task, showDeleteTaskAlertDialog: (Long) -> Unit, showTaskActions: () -> Unit) { +fun TaskView(task: Task, showTaskActions: () -> Unit) { var bottomSheetType by remember { mutableStateOf(null) } Box { @@ -60,11 +56,9 @@ fun TaskView(task: Task, showDeleteTaskAlertDialog: (Long) -> Unit, showTaskActi .fillMaxWidth() .clip(RoundedCornerShape(8.dp)) .background(MaterialTheme.colorScheme.primary) - .combinedClickable(onClick = { + .clickable { bottomSheetType = TaskViewBottomSheetType.Detail - }, onLongClick = { - bottomSheetType = TaskViewBottomSheetType.MoreAction - }) + } .padding(16.dp) ) { Spacer(modifier = Modifier.height(8.dp)) @@ -107,9 +101,7 @@ fun TaskView(task: Task, showDeleteTaskAlertDialog: (Long) -> Unit, showTaskActi TaskStatusView(task, foregroundColor = Color.White) bottomSheetType?.let { - TaskViewBottomSheet(it, task, showDeleteTaskAlertDialog = { - showDeleteTaskAlertDialog(task.id) - }, dismiss = { + TaskViewBottomSheet(it, task, dismiss = { bottomSheetType = null }, showTaskActions = { showTaskActions() @@ -136,7 +128,6 @@ private fun TaskViewBottomSheet( bottomSheetType: TaskViewBottomSheetType, task: Task, showTaskActions: () -> Unit, - showDeleteTaskAlertDialog: () -> Unit, dismiss: () -> Unit ) { when (bottomSheetType) { @@ -148,25 +139,6 @@ private fun TaskViewBottomSheet( dismiss() } } - - TaskViewBottomSheetType.MoreAction -> { - val bottomSheetAction = listOf( - Triple( - R.drawable.ic_delete, - R.string.assistant_screen_task_more_actions_bottom_sheet_delete_action - ) { - showDeleteTaskAlertDialog() - } - ) - - MoreActionsBottomSheet( - title = task.input?.input, - actions = bottomSheetAction, - dismiss = { - dismiss() - } - ) - } } } @@ -191,8 +163,6 @@ private fun TaskViewPreview() { 1707692337, ), showTaskActions = { - }, showDeleteTaskAlertDialog = { - } ) } diff --git a/app/src/main/java/com/nextcloud/client/assistant/task/model/TaskViewBottomSheetType.kt b/app/src/main/java/com/nextcloud/client/assistant/task/model/TaskViewBottomSheetType.kt index 9df4c13aeb..dd531126f9 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/task/model/TaskViewBottomSheetType.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/task/model/TaskViewBottomSheetType.kt @@ -8,5 +8,5 @@ package com.nextcloud.client.assistant.task.model enum class TaskViewBottomSheetType { - Detail, MoreAction + Detail } From ac3c735d979476039bd3bf2b96b6f0e204344f78 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 4 Dec 2024 10:21:07 +0100 Subject: [PATCH 15/34] Use task types for create operation Signed-off-by: alperozturk --- .../assistant/AssistantRepositoryTests.kt | 12 ++++++--- .../client/assistant/AssistantViewModel.kt | 20 +++++++------- .../client/assistant/AsssistantScreen.kt | 20 +++++++------- .../assistant/model/ScreenOverlayState.kt | 4 +-- .../repository/AssistantMockRepository.kt | 3 ++- .../repository/AssistantRepository.kt | 5 ++-- .../repository/AssistantRepositoryType.kt | 3 ++- .../assistant/taskTypes/TaskTypesRow.kt | 4 +-- .../taskTypes/model/AssistantTaskType.kt | 26 ------------------- 9 files changed, 40 insertions(+), 57 deletions(-) delete mode 100644 app/src/main/java/com/nextcloud/client/assistant/taskTypes/model/AssistantTaskType.kt diff --git a/app/src/androidTest/java/com/nextcloud/client/assistant/AssistantRepositoryTests.kt b/app/src/androidTest/java/com/nextcloud/client/assistant/AssistantRepositoryTests.kt index aa3eefb8c2..6895f6e3b9 100644 --- a/app/src/androidTest/java/com/nextcloud/client/assistant/AssistantRepositoryTests.kt +++ b/app/src/androidTest/java/com/nextcloud/client/assistant/AssistantRepositoryTests.kt @@ -9,6 +9,8 @@ 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.assistant.model.toTaskTypeDataList import com.owncloud.android.lib.resources.status.NextcloudVersion import org.junit.Assert.assertTrue import org.junit.Before @@ -35,7 +37,7 @@ class AssistantRepositoryTests : AbstractOnServerIT() { val result = sut?.getTaskTypes() assertTrue(result?.isSuccess == true) - val taskTypes = result?.resultData?.types + val taskTypes = result?.resultData?.toTaskTypeDataList() assertTrue(taskTypes?.isNotEmpty() == true) } @@ -63,8 +65,12 @@ 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" + ) + val result = sut?.createTask(input, taskType) assertTrue(result?.isSuccess == true) } diff --git a/app/src/main/java/com/nextcloud/client/assistant/AssistantViewModel.kt b/app/src/main/java/com/nextcloud/client/assistant/AssistantViewModel.kt index 579e0233a8..a314571ae0 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/AssistantViewModel.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/AssistantViewModel.kt @@ -12,10 +12,10 @@ 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.nextcloud.client.assistant.taskTypes.model.AssistantTaskType -import com.nextcloud.client.assistant.taskTypes.model.toAssistantTaskTypeList import com.owncloud.android.R import com.owncloud.android.lib.resources.assistant.model.Task +import com.owncloud.android.lib.resources.assistant.model.TaskTypeData +import com.owncloud.android.lib.resources.assistant.model.toTaskTypeDataList import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow @@ -36,11 +36,11 @@ class AssistantViewModel( private val _snackbarMessageId = MutableStateFlow(null) val snackbarMessageId: StateFlow = _snackbarMessageId - private val _selectedTaskType = MutableStateFlow(null) - val selectedTaskType: StateFlow = _selectedTaskType + private val _selectedTaskType = MutableStateFlow(null) + val selectedTaskType: StateFlow = _selectedTaskType - private val _taskTypes = MutableStateFlow?>(null) - val taskTypes: StateFlow?> = _taskTypes + private val _taskTypes = MutableStateFlow?>(null) + val taskTypes: StateFlow?> = _taskTypes private var taskList: List? = null @@ -52,9 +52,9 @@ class AssistantViewModel( } @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 @@ -69,7 +69,7 @@ class AssistantViewModel( } } - fun selectTaskType(task: AssistantTaskType) { + fun selectTaskType(task: TaskTypeData) { _selectedTaskType.update { task } @@ -82,7 +82,7 @@ class AssistantViewModel( val taskTypesResult = repository.getTaskTypes() if (taskTypesResult.isSuccess) { - val result = taskTypesResult.resultData.toAssistantTaskTypeList() + val result = taskTypesResult.resultData.toTaskTypeDataList() _taskTypes.update { result } diff --git a/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt b/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt index 97bb8b2649..2e8b8c627b 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt @@ -44,13 +44,13 @@ import com.nextcloud.client.assistant.model.ScreenState import com.nextcloud.client.assistant.repository.AssistantMockRepository import com.nextcloud.client.assistant.task.TaskView import com.nextcloud.client.assistant.taskTypes.TaskTypesRow -import com.nextcloud.client.assistant.taskTypes.model.AssistantTaskType import com.nextcloud.ui.composeActivity.ComposeActivity import com.nextcloud.ui.composeComponents.alertDialog.SimpleAlertDialog import com.nextcloud.ui.composeComponents.bottomSheet.MoreActionsBottomSheet import com.nextcloud.utils.extensions.showShareIntent import com.owncloud.android.R import com.owncloud.android.lib.resources.assistant.model.Task +import com.owncloud.android.lib.resources.assistant.model.TaskTypeData import com.owncloud.android.utils.ClipboardUtil import com.owncloud.android.utils.DisplayUtils import kotlinx.coroutines.delay @@ -102,8 +102,8 @@ fun AssistantScreen(viewModel: AssistantViewModel, activity: Activity) { @Composable private fun ShowScreenState( screenState: ScreenState?, - selectedTaskType: AssistantTaskType?, - taskTypes: List?, + selectedTaskType: TaskTypeData?, + taskTypes: List?, viewModel: AssistantViewModel, filteredTaskList: List? ) { @@ -143,7 +143,7 @@ private fun ShowLinearProgressIndicator(screenState: ScreenState?, pullToRefresh } @Composable -private fun AddFloatingActionButton(modifier: Modifier, selectedTaskType: AssistantTaskType?, viewModel: AssistantViewModel) { +private fun AddFloatingActionButton(modifier: Modifier, selectedTaskType: TaskTypeData?, viewModel: AssistantViewModel) { FloatingActionButton( modifier = modifier, onClick = { @@ -181,8 +181,8 @@ private fun ShowOverlayState( description = state.taskType.description, defaultInput = state.input, addTask = { input -> - state.taskType.id?.let { taskTypeId -> - viewModel.createTask(input = input, type = taskTypeId) + state.taskType.let { taskType -> + viewModel.createTask(input = input, taskType = taskType) } }, dismiss = { @@ -218,7 +218,7 @@ private fun ShowOverlayState( R.drawable.ic_edit, R.string.action_edit ) { - val taskType = AssistantTaskType( + val taskType = TaskTypeData( state.task.type, activity.getString(R.string.assistant_screen_add_task_alert_dialog_title), null @@ -252,8 +252,8 @@ private fun ShowOverlayState( @Composable private fun AssistantContent( taskList: List, - taskTypes: List?, - selectedTaskType: AssistantTaskType?, + taskTypes: List?, + selectedTaskType: TaskTypeData?, viewModel: AssistantViewModel ) { LazyColumn( @@ -282,7 +282,7 @@ private fun AssistantContent( } @Composable -private fun EmptyTaskList(selectedTaskType: AssistantTaskType?, taskTypes: List?, viewModel: AssistantViewModel) { +private fun EmptyTaskList(selectedTaskType: TaskTypeData?, taskTypes: List?, viewModel: AssistantViewModel) { val text = stringResource( id = R.string.assistant_screen_no_task_available_text, selectedTaskType?.name ?: "" diff --git a/app/src/main/java/com/nextcloud/client/assistant/model/ScreenOverlayState.kt b/app/src/main/java/com/nextcloud/client/assistant/model/ScreenOverlayState.kt index 8ef3410d76..2b44a4e130 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/model/ScreenOverlayState.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/model/ScreenOverlayState.kt @@ -7,11 +7,11 @@ package com.nextcloud.client.assistant.model -import com.nextcloud.client.assistant.taskTypes.model.AssistantTaskType import com.owncloud.android.lib.resources.assistant.model.Task +import com.owncloud.android.lib.resources.assistant.model.TaskTypeData sealed class ScreenOverlayState { data class DeleteTask(val id: Long): ScreenOverlayState() - data class AddTask(val taskType: AssistantTaskType, val input: String): ScreenOverlayState() + data class AddTask(val taskType: TaskTypeData, val input: String): ScreenOverlayState() data class TaskActions(val task: Task): ScreenOverlayState() } diff --git a/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantMockRepository.kt b/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantMockRepository.kt index cf2e14e7b7..6d40e51e41 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantMockRepository.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantMockRepository.kt @@ -13,6 +13,7 @@ import com.owncloud.android.lib.resources.assistant.model.Task import com.owncloud.android.lib.resources.assistant.model.TaskInput import com.owncloud.android.lib.resources.assistant.model.TaskList import com.owncloud.android.lib.resources.assistant.model.TaskOutput +import com.owncloud.android.lib.resources.assistant.model.TaskTypeData import com.owncloud.android.lib.resources.assistant.model.TaskTypes @Suppress("MagicNumber") @@ -23,7 +24,7 @@ class AssistantMockRepository(private val giveEmptyTasks: Boolean = false) : Ass } } - override fun createTask(input: String, type: String): RemoteOperationResult { + override fun createTask(input: String, taskType: TaskTypeData): RemoteOperationResult { return RemoteOperationResult(RemoteOperationResult.ResultCode.OK) } diff --git a/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantRepository.kt b/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantRepository.kt index 1689ac021f..14d9b86ab5 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantRepository.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantRepository.kt @@ -14,6 +14,7 @@ import com.owncloud.android.lib.resources.assistant.DeleteTaskRemoteOperation import com.owncloud.android.lib.resources.assistant.GetTaskListRemoteOperation import com.owncloud.android.lib.resources.assistant.GetTaskTypesRemoteOperation import com.owncloud.android.lib.resources.assistant.model.TaskList +import com.owncloud.android.lib.resources.assistant.model.TaskTypeData import com.owncloud.android.lib.resources.assistant.model.TaskTypes class AssistantRepository(private val client: NextcloudClient) : AssistantRepositoryType { @@ -22,8 +23,8 @@ class AssistantRepository(private val client: NextcloudClient) : AssistantReposi return GetTaskTypesRemoteOperation().execute(client) } - override fun createTask(input: String, type: String): RemoteOperationResult { - return CreateTaskRemoteOperation(input, type).execute(client) + override fun createTask(input: String, taskType: TaskTypeData): RemoteOperationResult { + return CreateTaskRemoteOperation(input, taskType).execute(client) } override fun getTaskList(taskType: String): RemoteOperationResult { diff --git a/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantRepositoryType.kt b/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantRepositoryType.kt index e8a0d2fb67..c653d47153 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantRepositoryType.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantRepositoryType.kt @@ -9,12 +9,13 @@ package com.nextcloud.client.assistant.repository import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.lib.resources.assistant.model.TaskList +import com.owncloud.android.lib.resources.assistant.model.TaskTypeData import com.owncloud.android.lib.resources.assistant.model.TaskTypes interface AssistantRepositoryType { fun getTaskTypes(): RemoteOperationResult - fun createTask(input: String, type: String): RemoteOperationResult + fun createTask(input: String, taskType: TaskTypeData): RemoteOperationResult fun getTaskList(taskType: String): RemoteOperationResult diff --git a/app/src/main/java/com/nextcloud/client/assistant/taskTypes/TaskTypesRow.kt b/app/src/main/java/com/nextcloud/client/assistant/taskTypes/TaskTypesRow.kt index 976d8603c9..99a336de45 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/taskTypes/TaskTypesRow.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/taskTypes/TaskTypesRow.kt @@ -20,10 +20,10 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp -import com.nextcloud.client.assistant.taskTypes.model.AssistantTaskType +import com.owncloud.android.lib.resources.assistant.model.TaskTypeData @Composable -fun TaskTypesRow(selectedTaskType: AssistantTaskType?, data: List?, selectTaskType: (AssistantTaskType) -> Unit) { +fun TaskTypesRow(selectedTaskType: TaskTypeData?, data: List?, selectTaskType: (TaskTypeData) -> Unit) { Row( modifier = Modifier .fillMaxWidth() diff --git a/app/src/main/java/com/nextcloud/client/assistant/taskTypes/model/AssistantTaskType.kt b/app/src/main/java/com/nextcloud/client/assistant/taskTypes/model/AssistantTaskType.kt deleted file mode 100644 index 2da8192465..0000000000 --- a/app/src/main/java/com/nextcloud/client/assistant/taskTypes/model/AssistantTaskType.kt +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Nextcloud - Android Client - * - * SPDX-FileCopyrightText: 2024 Alper Ozturk - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -package com.nextcloud.client.assistant.taskTypes.model - -import com.owncloud.android.lib.resources.assistant.model.TaskIds -import com.owncloud.android.lib.resources.assistant.model.TaskTypes - -data class AssistantTaskType( - val id: String?, - val name: String?, - val description: String? -) - -fun TaskTypes.toAssistantTaskTypeList(): List { - return arrayListOf().apply { - add(AssistantTaskType(TaskIds.GenerateText.id, types.generateText.name, types.generateText.description)) - add(AssistantTaskType(TaskIds.ExtractTopics.id, types.extractTopics.name, types.extractTopics.description)) - add(AssistantTaskType(TaskIds.GenerateHeadline.id, types.generateHeadline.name, types.generateHeadline.description)) - add(AssistantTaskType(TaskIds.Summarize.id, types.summarize.name, types.summarize.description)) - } -} From 21ef73578a805de29f7451ba66be992f08f2e6d2 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 4 Dec 2024 10:50:14 +0100 Subject: [PATCH 16/34] use response key for id Signed-off-by: alperozturk --- .../com/nextcloud/client/assistant/AssistantViewModel.kt | 3 +-- .../java/com/nextcloud/client/assistant/AsssistantScreen.kt | 2 ++ .../client/assistant/repository/AssistantMockRepository.kt | 5 ++--- .../client/assistant/repository/AssistantRepository.kt | 3 +-- .../client/assistant/repository/AssistantRepositoryType.kt | 2 +- 5 files changed, 7 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/nextcloud/client/assistant/AssistantViewModel.kt b/app/src/main/java/com/nextcloud/client/assistant/AssistantViewModel.kt index a314571ae0..fac81e41eb 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/AssistantViewModel.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/AssistantViewModel.kt @@ -15,7 +15,6 @@ 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.TaskTypeData -import com.owncloud.android.lib.resources.assistant.model.toTaskTypeDataList import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow @@ -82,7 +81,7 @@ class AssistantViewModel( val taskTypesResult = repository.getTaskTypes() if (taskTypesResult.isSuccess) { - val result = taskTypesResult.resultData.toTaskTypeDataList() + val result = taskTypesResult.resultData _taskTypes.update { result } diff --git a/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt b/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt index 2e8b8c627b..21788a2c02 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt @@ -221,6 +221,8 @@ private fun ShowOverlayState( val taskType = TaskTypeData( state.task.type, activity.getString(R.string.assistant_screen_add_task_alert_dialog_title), + null, + null, null ) val newState = diff --git a/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantMockRepository.kt b/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantMockRepository.kt index 6d40e51e41..d6db1c60c5 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantMockRepository.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantMockRepository.kt @@ -14,12 +14,11 @@ import com.owncloud.android.lib.resources.assistant.model.TaskInput import com.owncloud.android.lib.resources.assistant.model.TaskList import com.owncloud.android.lib.resources.assistant.model.TaskOutput import com.owncloud.android.lib.resources.assistant.model.TaskTypeData -import com.owncloud.android.lib.resources.assistant.model.TaskTypes @Suppress("MagicNumber") class AssistantMockRepository(private val giveEmptyTasks: Boolean = false) : AssistantRepositoryType { - override fun getTaskTypes(): RemoteOperationResult { - return RemoteOperationResult(RemoteOperationResult.ResultCode.OK).apply { + override fun getTaskTypes(): RemoteOperationResult> { + return RemoteOperationResult>(RemoteOperationResult.ResultCode.OK).apply { resultData = null } } diff --git a/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantRepository.kt b/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantRepository.kt index 14d9b86ab5..5da5e56473 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantRepository.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantRepository.kt @@ -15,11 +15,10 @@ import com.owncloud.android.lib.resources.assistant.GetTaskListRemoteOperation import com.owncloud.android.lib.resources.assistant.GetTaskTypesRemoteOperation import com.owncloud.android.lib.resources.assistant.model.TaskList import com.owncloud.android.lib.resources.assistant.model.TaskTypeData -import com.owncloud.android.lib.resources.assistant.model.TaskTypes class AssistantRepository(private val client: NextcloudClient) : AssistantRepositoryType { - override fun getTaskTypes(): RemoteOperationResult { + override fun getTaskTypes(): RemoteOperationResult> { return GetTaskTypesRemoteOperation().execute(client) } diff --git a/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantRepositoryType.kt b/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantRepositoryType.kt index c653d47153..ae6020e0eb 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantRepositoryType.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantRepositoryType.kt @@ -13,7 +13,7 @@ import com.owncloud.android.lib.resources.assistant.model.TaskTypeData import com.owncloud.android.lib.resources.assistant.model.TaskTypes interface AssistantRepositoryType { - fun getTaskTypes(): RemoteOperationResult + fun getTaskTypes(): RemoteOperationResult> fun createTask(input: String, taskType: TaskTypeData): RemoteOperationResult From 2ca151d9bcf5dc16c25c8da2de971806bd2a5e48 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 4 Dec 2024 11:02:45 +0100 Subject: [PATCH 17/34] Fix bottom sheet title appereance Signed-off-by: alperozturk --- .../nextcloud/client/assistant/AsssistantScreen.kt | 3 ++- .../client/assistant/extensions/TaskExtensions.kt | 11 +++++++++++ .../assistant/taskDetail/TaskDetailBottomSheet.kt | 1 + 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt b/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt index 21788a2c02..9b73e6f616 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt @@ -39,6 +39,7 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.nextcloud.client.assistant.component.AddTaskAlertDialog import com.nextcloud.client.assistant.component.CenterText +import com.nextcloud.client.assistant.extensions.getInputTitle import com.nextcloud.client.assistant.model.ScreenOverlayState import com.nextcloud.client.assistant.model.ScreenState import com.nextcloud.client.assistant.repository.AssistantMockRepository @@ -240,7 +241,7 @@ private fun ShowOverlayState( ) MoreActionsBottomSheet( - title = state.task.input?.input, + title = state.task.getInputTitle(), actions = bottomSheetAction, dismiss = { viewModel.updateScreenState(null) } ) diff --git a/app/src/main/java/com/nextcloud/client/assistant/extensions/TaskExtensions.kt b/app/src/main/java/com/nextcloud/client/assistant/extensions/TaskExtensions.kt index 845e410ab8..117d5629c9 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/extensions/TaskExtensions.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/extensions/TaskExtensions.kt @@ -17,6 +17,17 @@ import java.util.Date import java.util.Locale import java.util.concurrent.TimeUnit +fun Task.getInputTitle(): String { + val maxTitleLength = 20 + val title = input?.input ?: "" + + return if (title.length > maxTitleLength) { + title.take(maxTitleLength) + "..." + } else { + title + } +} + @Suppress("MagicNumber") fun Task.getStatusIcon(): Int { return when (status) { diff --git a/app/src/main/java/com/nextcloud/client/assistant/taskDetail/TaskDetailBottomSheet.kt b/app/src/main/java/com/nextcloud/client/assistant/taskDetail/TaskDetailBottomSheet.kt index aa02421eb9..7e62b04f4a 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/taskDetail/TaskDetailBottomSheet.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/taskDetail/TaskDetailBottomSheet.kt @@ -68,6 +68,7 @@ fun TaskDetailBottomSheet(task: Task, showTaskActions: () -> Unit, dismiss: () - LazyColumn(modifier = Modifier .fillMaxSize() .padding(16.dp)) { + stickyHeader { Row( modifier = Modifier.fillMaxWidth() From 51b5add1be27f171a42e03914a1cfdc3e5744a41 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 4 Dec 2024 11:06:18 +0100 Subject: [PATCH 18/34] Fix code analytics Signed-off-by: alperozturk --- .../client/assistant/AssistantViewModel.kt | 2 +- .../client/assistant/AsssistantScreen.kt | 41 +++++++++++-------- .../assistant/extensions/TaskExtensions.kt | 5 ++- .../assistant/model/ScreenOverlayState.kt | 6 +-- .../client/assistant/model/ScreenState.kt | 4 +- .../repository/AssistantMockRepository.kt | 4 +- .../repository/AssistantRepositoryType.kt | 1 - .../client/assistant/task/TaskStatusView.kt | 1 + .../client/assistant/task/TaskView.kt | 15 +++---- .../taskDetail/TaskDetailBottomSheet.kt | 12 +++--- .../bottomSheet/MoreActionsBottomSheet.kt | 6 +-- 11 files changed, 53 insertions(+), 44 deletions(-) diff --git a/app/src/main/java/com/nextcloud/client/assistant/AssistantViewModel.kt b/app/src/main/java/com/nextcloud/client/assistant/AssistantViewModel.kt index fac81e41eb..5d9c6156d8 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/AssistantViewModel.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/AssistantViewModel.kt @@ -23,7 +23,7 @@ import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch class AssistantViewModel( - private val repository: AssistantRepositoryType, + private val repository: AssistantRepositoryType ) : ViewModel() { private val _screenState = MutableStateFlow(null) diff --git a/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt b/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt index 9b73e6f616..8b31d54d21 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt @@ -77,11 +77,12 @@ fun AssistantScreen(viewModel: AssistantViewModel, activity: Activity) { screenState == ScreenState.Refreshing, pullRefreshState, onRefresh = { - scope.launch { - delay(1500) - viewModel.fetchTaskList() + scope.launch { + delay(1500) + viewModel.fetchTaskList() + } } - }) + ) ) { ShowScreenState(screenState, selectedTaskType, taskTypes, viewModel, filteredTaskList) @@ -108,7 +109,7 @@ private fun ShowScreenState( viewModel: AssistantViewModel, filteredTaskList: List? ) { - when(screenState) { + when (screenState) { ScreenState.Refreshing -> { CenterText(text = stringResource(id = R.string.assistant_screen_loading)) } @@ -144,7 +145,11 @@ private fun ShowLinearProgressIndicator(screenState: ScreenState?, pullToRefresh } @Composable -private fun AddFloatingActionButton(modifier: Modifier, selectedTaskType: TaskTypeData?, viewModel: AssistantViewModel) { +private fun AddFloatingActionButton( + modifier: Modifier, + selectedTaskType: TaskTypeData?, + viewModel: AssistantViewModel +) { FloatingActionButton( modifier = modifier, onClick = { @@ -169,17 +174,14 @@ private fun showSnackBarMessage(messageId: Int?, activity: Activity, viewModel: } } +@Suppress("LongMethod") @Composable -private fun ShowOverlayState( - state: ScreenOverlayState?, - activity: Activity, - viewModel: AssistantViewModel -) { - when(state) { +private fun ShowOverlayState(state: ScreenOverlayState?, activity: Activity, viewModel: AssistantViewModel) { + when (state) { is ScreenOverlayState.AddTask -> { AddTaskAlertDialog( - title = state.taskType.name, - description = state.taskType.description, + title = state.taskType.name, + description = state.taskType.description, defaultInput = state.input, addTask = { input -> state.taskType.let { taskType -> @@ -237,7 +239,7 @@ private fun ShowOverlayState( val newState = ScreenOverlayState.DeleteTask(state.task.id) viewModel.updateScreenState(newState) - }, + } ) MoreActionsBottomSheet( @@ -273,7 +275,8 @@ private fun AssistantContent( } items(taskList) { task -> - TaskView(task, + TaskView( + task, showTaskActions = { val newState = ScreenOverlayState.TaskActions(task) viewModel.updateScreenState(newState) @@ -285,7 +288,11 @@ private fun AssistantContent( } @Composable -private fun EmptyTaskList(selectedTaskType: TaskTypeData?, taskTypes: List?, viewModel: AssistantViewModel) { +private fun EmptyTaskList( + selectedTaskType: TaskTypeData?, + taskTypes: List?, + viewModel: AssistantViewModel +) { val text = stringResource( id = R.string.assistant_screen_no_task_available_text, selectedTaskType?.name ?: "" diff --git a/app/src/main/java/com/nextcloud/client/assistant/extensions/TaskExtensions.kt b/app/src/main/java/com/nextcloud/client/assistant/extensions/TaskExtensions.kt index 117d5629c9..8186283ed7 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/extensions/TaskExtensions.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/extensions/TaskExtensions.kt @@ -17,6 +17,7 @@ import java.util.Date import java.util.Locale import java.util.concurrent.TimeUnit +@Suppress("MagicNumber") fun Task.getInputTitle(): String { val maxTitleLength = 20 val title = input?.input ?: "" @@ -52,6 +53,7 @@ fun Task.getStatusIcon(): Int { } } +@Suppress("MagicNumber") fun Task.getModifiedAtRepresentation(context: Context): String? { if (lastUpdated == null) { return null @@ -80,7 +82,7 @@ fun Task.getModifiedAtRepresentation(context: Context): String? { ) } - timeDifference < TimeUnit.DAYS.toSeconds(1) -> { + timeDifference < TimeUnit.DAYS.toSeconds(1) -> { context.resources.getQuantityString( R.plurals.time_hours_ago, timeDifferenceInHours, @@ -94,6 +96,7 @@ fun Task.getModifiedAtRepresentation(context: Context): String? { } } +@Suppress("MagicNumber") private fun convertToDateFormat(timestamp: Long): String { val date = Date(timestamp * 1000) val format = SimpleDateFormat("MMM d", Locale.getDefault()) diff --git a/app/src/main/java/com/nextcloud/client/assistant/model/ScreenOverlayState.kt b/app/src/main/java/com/nextcloud/client/assistant/model/ScreenOverlayState.kt index 2b44a4e130..f6459c4d9f 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/model/ScreenOverlayState.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/model/ScreenOverlayState.kt @@ -11,7 +11,7 @@ import com.owncloud.android.lib.resources.assistant.model.Task import com.owncloud.android.lib.resources.assistant.model.TaskTypeData sealed class ScreenOverlayState { - data class DeleteTask(val id: Long): ScreenOverlayState() - data class AddTask(val taskType: TaskTypeData, val input: String): ScreenOverlayState() - data class TaskActions(val task: Task): ScreenOverlayState() + data class DeleteTask(val id: Long) : ScreenOverlayState() + data class AddTask(val taskType: TaskTypeData, val input: String) : ScreenOverlayState() + data class TaskActions(val task: Task) : ScreenOverlayState() } diff --git a/app/src/main/java/com/nextcloud/client/assistant/model/ScreenState.kt b/app/src/main/java/com/nextcloud/client/assistant/model/ScreenState.kt index d7c42dcf99..33e206c9d0 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/model/ScreenState.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/model/ScreenState.kt @@ -8,5 +8,7 @@ package com.nextcloud.client.assistant.model enum class ScreenState { - Refreshing, EmptyContent, Content + Refreshing, + EmptyContent, + Content } diff --git a/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantMockRepository.kt b/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantMockRepository.kt index d6db1c60c5..4821760f15 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantMockRepository.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantMockRepository.kt @@ -45,8 +45,8 @@ class AssistantMockRepository(private val giveEmptyTasks: Boolean = false) : Ass 1707692337, 1707692337, 1707692337, - 1707692337, - ), + 1707692337 + ) ) ) } diff --git a/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantRepositoryType.kt b/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantRepositoryType.kt index ae6020e0eb..2d031a87c4 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantRepositoryType.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/repository/AssistantRepositoryType.kt @@ -10,7 +10,6 @@ package com.nextcloud.client.assistant.repository import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.lib.resources.assistant.model.TaskList import com.owncloud.android.lib.resources.assistant.model.TaskTypeData -import com.owncloud.android.lib.resources.assistant.model.TaskTypes interface AssistantRepositoryType { fun getTaskTypes(): RemoteOperationResult> diff --git a/app/src/main/java/com/nextcloud/client/assistant/task/TaskStatusView.kt b/app/src/main/java/com/nextcloud/client/assistant/task/TaskStatusView.kt index 79ec51a6bf..145ee57c53 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/task/TaskStatusView.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/task/TaskStatusView.kt @@ -60,6 +60,7 @@ fun TaskStatusView(task: Task, foregroundColor: Color) { } } +@Suppress("LongMethod", "MagicNumber") @Composable @Preview private fun TaskStatusViewPreview() { diff --git a/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt b/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt index 49dc4f3ee5..da9d06cf72 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt @@ -112,8 +112,7 @@ fun TaskView(task: Task, showTaskActions: () -> Unit) { IconButton( modifier = Modifier.align(Alignment.TopEnd), onClick = showTaskActions - ) - { + ) { Icon( imageVector = Icons.Filled.MoreVert, contentDescription = "More button", @@ -154,15 +153,17 @@ private fun TaskViewPreview() { "1", "1", TaskInput("What about other promising tokens like"), - TaskOutput("Several tokens show promise for future growth in the" + - "cryptocurrency market"), + TaskOutput( + "Several tokens show promise for future growth in the" + + "cryptocurrency market" + ), 1707692337, 1707692337, 1707692337, 1707692337, - 1707692337, - ), showTaskActions = { - + 1707692337 + ), + showTaskActions = { } ) } diff --git a/app/src/main/java/com/nextcloud/client/assistant/taskDetail/TaskDetailBottomSheet.kt b/app/src/main/java/com/nextcloud/client/assistant/taskDetail/TaskDetailBottomSheet.kt index 7e62b04f4a..7cce23d3e7 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/taskDetail/TaskDetailBottomSheet.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/taskDetail/TaskDetailBottomSheet.kt @@ -65,10 +65,11 @@ fun TaskDetailBottomSheet(task: Task, showTaskActions: () -> Unit, dismiss: () - onDismissRequest = { dismiss() }, sheetState = sheetState ) { - LazyColumn(modifier = Modifier - .fillMaxSize() - .padding(16.dp)) { - + LazyColumn( + modifier = Modifier + .fillMaxSize() + .padding(16.dp) + ) { stickyHeader { Row( modifier = Modifier.fillMaxWidth() @@ -185,10 +186,9 @@ private fun TaskDetailScreenPreview() { 1707692337, 1707692337, 1707692337, - 1707692337, + 1707692337 ), showTaskActions = { - } ) { } diff --git a/app/src/main/java/com/nextcloud/ui/composeComponents/bottomSheet/MoreActionsBottomSheet.kt b/app/src/main/java/com/nextcloud/ui/composeComponents/bottomSheet/MoreActionsBottomSheet.kt index 4b106433da..b3d409aee0 100644 --- a/app/src/main/java/com/nextcloud/ui/composeComponents/bottomSheet/MoreActionsBottomSheet.kt +++ b/app/src/main/java/com/nextcloud/ui/composeComponents/bottomSheet/MoreActionsBottomSheet.kt @@ -37,11 +37,7 @@ import kotlinx.coroutines.launch @SuppressLint("ResourceAsColor") @OptIn(ExperimentalMaterial3Api::class) @Composable -fun MoreActionsBottomSheet( - title: String? = null, - actions: List Unit>>, - dismiss: () -> Unit -) { +fun MoreActionsBottomSheet(title: String? = null, actions: List Unit>>, dismiss: () -> Unit) { val sheetState = rememberModalBottomSheetState() val scope = rememberCoroutineScope() From 8f698167ebb53d469d48fe2c30d2af5c1129973a Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 4 Dec 2024 11:21:41 +0100 Subject: [PATCH 19/34] update library Signed-off-by: alperozturk --- gradle/verification-metadata.xml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 5ed0f83735..754ab87ae3 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -7933,6 +7933,14 @@ + + + + + + + + From 92c99b22332792aa8604b30fbcc3b2a3904c5e6a Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 4 Dec 2024 11:41:47 +0100 Subject: [PATCH 20/34] decouple business logic from the ui Signed-off-by: alperozturk --- .../client/assistant/AsssistantScreen.kt | 46 ++---------- .../assistant/extensions/TaskExtensions.kt | 6 +- .../assistant/model/ScreenOverlayState.kt | 73 ++++++++++++++++++- 3 files changed, 83 insertions(+), 42 deletions(-) diff --git a/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt b/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt index 8b31d54d21..2ff5ab3db7 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt @@ -48,11 +48,9 @@ import com.nextcloud.client.assistant.taskTypes.TaskTypesRow import com.nextcloud.ui.composeActivity.ComposeActivity import com.nextcloud.ui.composeComponents.alertDialog.SimpleAlertDialog import com.nextcloud.ui.composeComponents.bottomSheet.MoreActionsBottomSheet -import com.nextcloud.utils.extensions.showShareIntent import com.owncloud.android.R import com.owncloud.android.lib.resources.assistant.model.Task import com.owncloud.android.lib.resources.assistant.model.TaskTypeData -import com.owncloud.android.utils.ClipboardUtil import com.owncloud.android.utils.DisplayUtils import kotlinx.coroutines.delay import kotlinx.coroutines.launch @@ -204,47 +202,15 @@ private fun ShowOverlayState(state: ScreenOverlayState?, activity: Activity, vie } is ScreenOverlayState.TaskActions -> { - val bottomSheetAction = listOf( - Triple( - R.drawable.ic_share, - R.string.common_share - ) { - activity.showShareIntent(state.task.output?.output) - }, - Triple( - R.drawable.ic_content_copy, - R.string.common_copy - ) { - ClipboardUtil.copyToClipboard(activity, state.task.output?.output) - }, - Triple( - R.drawable.ic_edit, - R.string.action_edit - ) { - val taskType = TaskTypeData( - state.task.type, - activity.getString(R.string.assistant_screen_add_task_alert_dialog_title), - null, - null, - null - ) - val newState = - ScreenOverlayState.AddTask(taskType, state.task.input?.input ?: "") - viewModel.updateScreenState(newState) - }, - Triple( - R.drawable.ic_delete, - R.string.assistant_screen_task_more_actions_bottom_sheet_delete_action - ) { - val newState = - ScreenOverlayState.DeleteTask(state.task.id) - viewModel.updateScreenState(newState) - } - ) + val actions = state.getAction(activity, onEditCompleted = { addTask -> + viewModel.updateScreenState(addTask) + }, onDeleteCompleted = { deleteTask -> + viewModel.updateScreenState(deleteTask) + }) MoreActionsBottomSheet( title = state.task.getInputTitle(), - actions = bottomSheetAction, + actions = actions, dismiss = { viewModel.updateScreenState(null) } ) } diff --git a/app/src/main/java/com/nextcloud/client/assistant/extensions/TaskExtensions.kt b/app/src/main/java/com/nextcloud/client/assistant/extensions/TaskExtensions.kt index 8186283ed7..4654dbecaa 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/extensions/TaskExtensions.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/extensions/TaskExtensions.kt @@ -17,10 +17,14 @@ import java.util.Date import java.util.Locale import java.util.concurrent.TimeUnit +fun Task.getInput(): String? = input?.input + +fun Task.getOutput(): String? = output?.output + @Suppress("MagicNumber") fun Task.getInputTitle(): String { val maxTitleLength = 20 - val title = input?.input ?: "" + val title = getInput() ?: "" return if (title.length > maxTitleLength) { title.take(maxTitleLength) + "..." diff --git a/app/src/main/java/com/nextcloud/client/assistant/model/ScreenOverlayState.kt b/app/src/main/java/com/nextcloud/client/assistant/model/ScreenOverlayState.kt index f6459c4d9f..9dd131cc78 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/model/ScreenOverlayState.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/model/ScreenOverlayState.kt @@ -7,11 +7,82 @@ package com.nextcloud.client.assistant.model +import android.app.Activity +import com.nextcloud.client.assistant.extensions.getInput +import com.nextcloud.client.assistant.extensions.getOutput +import com.nextcloud.utils.extensions.showShareIntent +import com.owncloud.android.R import com.owncloud.android.lib.resources.assistant.model.Task import com.owncloud.android.lib.resources.assistant.model.TaskTypeData +import com.owncloud.android.utils.ClipboardUtil sealed class ScreenOverlayState { data class DeleteTask(val id: Long) : ScreenOverlayState() data class AddTask(val taskType: TaskTypeData, val input: String) : ScreenOverlayState() - data class TaskActions(val task: Task) : ScreenOverlayState() + data class TaskActions(val task: Task) : ScreenOverlayState() { + private fun getInput(): String? = task.getInput() + private fun getOutput(): String? = task.getOutput() + + private fun getCopyToClipboardAction(activity: Activity): Triple Unit> { + return Triple( + R.drawable.ic_content_copy, + R.string.common_copy + ) { + ClipboardUtil.copyToClipboard(activity, getOutput()) + } + } + + private fun getShareAction(activity: Activity): Triple Unit> { + return Triple( + R.drawable.ic_share, + R.string.common_share + ) { + activity.showShareIntent(getOutput()) + } + } + + private fun getEditAction(activity: Activity, onComplete: (AddTask) -> Unit): Triple Unit> { + return Triple( + R.drawable.ic_edit, + R.string.action_edit + ) { + val taskType = TaskTypeData( + task.type, + activity.getString(R.string.assistant_screen_add_task_alert_dialog_title), + null, + null, + null + ) + val newState = AddTask(taskType, getInput() ?: "") + onComplete(newState) + } + } + + private fun getDeleteAction(onComplete: (DeleteTask) -> Unit): Triple Unit> { + return Triple( + R.drawable.ic_delete, + R.string.assistant_screen_task_more_actions_bottom_sheet_delete_action + ) { + val newState = DeleteTask(task.id) + onComplete(newState) + } + } + + fun getAction( + activity: Activity, + onEditCompleted: (AddTask) -> Unit, + onDeleteCompleted: (DeleteTask) -> Unit + ): List Unit>> { + return listOf( + getShareAction(activity), + getCopyToClipboardAction(activity), + getEditAction(activity, onComplete = { + onEditCompleted(it) + }), + getDeleteAction(onComplete = { + onDeleteCompleted(it) + }) + ) + } + } } From 3cffeee863eaac6af1bec6db179a77a30ced81dc Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 4 Dec 2024 11:42:07 +0100 Subject: [PATCH 21/34] update tests Signed-off-by: alperozturk --- .../nextcloud/client/assistant/AssistantRepositoryTests.kt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/src/androidTest/java/com/nextcloud/client/assistant/AssistantRepositoryTests.kt b/app/src/androidTest/java/com/nextcloud/client/assistant/AssistantRepositoryTests.kt index 6895f6e3b9..cd86391620 100644 --- a/app/src/androidTest/java/com/nextcloud/client/assistant/AssistantRepositoryTests.kt +++ b/app/src/androidTest/java/com/nextcloud/client/assistant/AssistantRepositoryTests.kt @@ -10,7 +10,6 @@ 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.assistant.model.toTaskTypeDataList import com.owncloud.android.lib.resources.status.NextcloudVersion import org.junit.Assert.assertTrue import org.junit.Before @@ -37,7 +36,7 @@ class AssistantRepositoryTests : AbstractOnServerIT() { val result = sut?.getTaskTypes() assertTrue(result?.isSuccess == true) - val taskTypes = result?.resultData?.toTaskTypeDataList() + val taskTypes = result?.resultData assertTrue(taskTypes?.isNotEmpty() == true) } @@ -68,7 +67,9 @@ class AssistantRepositoryTests : AbstractOnServerIT() { val taskType = TaskTypeData( "core:text2text", "Free text to text prompt", - "Runs an arbitrary prompt through a language model that returns a reply" + "Runs an arbitrary prompt through a language model that returns a reply", + null, + null ) val result = sut?.createTask(input, taskType) assertTrue(result?.isSuccess == true) From 8d4a34c86a3fa43c2df94d169f5e6de9d851c5a0 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 4 Dec 2024 11:50:41 +0100 Subject: [PATCH 22/34] Create DateFormatter extract date related logic from Task extensions Signed-off-by: alperozturk --- .../assistant/extensions/TaskExtensions.kt | 14 +++------- .../nextcloud/utils/date/DateFormatPattern.kt | 9 +++++-- .../com/nextcloud/utils/date/DateFormatter.kt | 26 +++++++++++++++++++ 3 files changed, 36 insertions(+), 13 deletions(-) create mode 100644 app/src/main/java/com/nextcloud/utils/date/DateFormatter.kt diff --git a/app/src/main/java/com/nextcloud/client/assistant/extensions/TaskExtensions.kt b/app/src/main/java/com/nextcloud/client/assistant/extensions/TaskExtensions.kt index 4654dbecaa..1302b7a522 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/extensions/TaskExtensions.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/extensions/TaskExtensions.kt @@ -10,11 +10,10 @@ package com.nextcloud.client.assistant.extensions import android.content.Context -import android.icu.text.SimpleDateFormat +import com.nextcloud.utils.date.DateFormatPattern +import com.nextcloud.utils.date.DateFormatter import com.owncloud.android.R import com.owncloud.android.lib.resources.assistant.model.Task -import java.util.Date -import java.util.Locale import java.util.concurrent.TimeUnit fun Task.getInput(): String? = input?.input @@ -95,14 +94,7 @@ fun Task.getModifiedAtRepresentation(context: Context): String? { } else -> { - convertToDateFormat(modifiedAt) + DateFormatter.timestampToDateRepresentation(modifiedAt, DateFormatPattern.MonthWithDate) } } } - -@Suppress("MagicNumber") -private fun convertToDateFormat(timestamp: Long): String { - val date = Date(timestamp * 1000) - val format = SimpleDateFormat("MMM d", Locale.getDefault()) - return format.format(date) -} diff --git a/app/src/main/java/com/nextcloud/utils/date/DateFormatPattern.kt b/app/src/main/java/com/nextcloud/utils/date/DateFormatPattern.kt index 38072c3528..a3852d67af 100644 --- a/app/src/main/java/com/nextcloud/utils/date/DateFormatPattern.kt +++ b/app/src/main/java/com/nextcloud/utils/date/DateFormatPattern.kt @@ -9,7 +9,12 @@ package com.nextcloud.utils.date enum class DateFormatPattern(val pattern: String) { /** - * e.g. 10.11.2024 - 12:44 + * 10.11.2024 - 12:44 */ - FullDateWithHours("dd.MM.yyyy - HH:mm") + FullDateWithHours("dd.MM.yyyy - HH:mm"), + + /** + * Aug 3 + */ + MonthWithDate("MMM d") } diff --git a/app/src/main/java/com/nextcloud/utils/date/DateFormatter.kt b/app/src/main/java/com/nextcloud/utils/date/DateFormatter.kt new file mode 100644 index 0000000000..ea43a5a27b --- /dev/null +++ b/app/src/main/java/com/nextcloud/utils/date/DateFormatter.kt @@ -0,0 +1,26 @@ +/* + * Nextcloud - Android Client + * + * SPDX-FileCopyrightText: 2024 Alper Ozturk + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package com.nextcloud.utils.date + +import android.icu.text.SimpleDateFormat +import java.util.Date +import java.util.Locale + +object DateFormatter { + + /** + * Converts a Unix timestamp (in milliseconds) into a formatted date string. + * For example, input 1733309160885 with "MMM d" pattern outputs "Dec 4". + */ + @Suppress("MagicNumber") + fun timestampToDateRepresentation(timestamp: Long, formatPattern: DateFormatPattern): String { + val date = Date(timestamp * 1000) + val format = SimpleDateFormat(formatPattern.pattern, Locale.getDefault()) + return format.format(date) + } +} From 06af70802dbb92c5c262c64ffec3b29376eee0d4 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 4 Dec 2024 12:05:50 +0100 Subject: [PATCH 23/34] Get rid of unncessary state for task view Signed-off-by: alperozturk --- .../client/assistant/AsssistantScreen.kt | 2 +- .../assistant/model/ScreenOverlayState.kt | 2 +- .../client/assistant/task/TaskView.kt | 35 +++++-------------- .../task/model/TaskViewBottomSheetType.kt | 12 ------- 4 files changed, 10 insertions(+), 41 deletions(-) delete mode 100644 app/src/main/java/com/nextcloud/client/assistant/task/model/TaskViewBottomSheetType.kt diff --git a/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt b/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt index 2ff5ab3db7..34b63adcf7 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt @@ -202,7 +202,7 @@ private fun ShowOverlayState(state: ScreenOverlayState?, activity: Activity, vie } is ScreenOverlayState.TaskActions -> { - val actions = state.getAction(activity, onEditCompleted = { addTask -> + val actions = state.getActions(activity, onEditCompleted = { addTask -> viewModel.updateScreenState(addTask) }, onDeleteCompleted = { deleteTask -> viewModel.updateScreenState(deleteTask) diff --git a/app/src/main/java/com/nextcloud/client/assistant/model/ScreenOverlayState.kt b/app/src/main/java/com/nextcloud/client/assistant/model/ScreenOverlayState.kt index 9dd131cc78..6ee8ea6132 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/model/ScreenOverlayState.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/model/ScreenOverlayState.kt @@ -68,7 +68,7 @@ sealed class ScreenOverlayState { } } - fun getAction( + fun getActions( activity: Activity, onEditCompleted: (AddTask) -> Unit, onDeleteCompleted: (DeleteTask) -> Unit diff --git a/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt b/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt index da9d06cf72..1bd8809253 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt @@ -39,7 +39,6 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import com.nextcloud.client.assistant.task.model.TaskViewBottomSheetType import com.nextcloud.client.assistant.taskDetail.TaskDetailBottomSheet import com.owncloud.android.lib.resources.assistant.model.Task import com.owncloud.android.lib.resources.assistant.model.TaskInput @@ -48,7 +47,7 @@ import com.owncloud.android.lib.resources.assistant.model.TaskOutput @Suppress("LongMethod", "MagicNumber") @Composable fun TaskView(task: Task, showTaskActions: () -> Unit) { - var bottomSheetType by remember { mutableStateOf(null) } + var showTaskDetailBottomSheet by remember { mutableStateOf(false) } Box { Column( @@ -57,7 +56,7 @@ fun TaskView(task: Task, showTaskActions: () -> Unit) { .clip(RoundedCornerShape(8.dp)) .background(MaterialTheme.colorScheme.primary) .clickable { - bottomSheetType = TaskViewBottomSheetType.Detail + showTaskDetailBottomSheet = true } .padding(16.dp) ) { @@ -100,12 +99,13 @@ fun TaskView(task: Task, showTaskActions: () -> Unit) { TaskStatusView(task, foregroundColor = Color.White) - bottomSheetType?.let { - TaskViewBottomSheet(it, task, dismiss = { - bottomSheetType = null - }, showTaskActions = { + if (showTaskDetailBottomSheet) { + TaskDetailBottomSheet(task, showTaskActions = { + showTaskDetailBottomSheet = false showTaskActions() - }) + }) { + showTaskDetailBottomSheet = false + } } } @@ -122,25 +122,6 @@ fun TaskView(task: Task, showTaskActions: () -> Unit) { } } -@Composable -private fun TaskViewBottomSheet( - bottomSheetType: TaskViewBottomSheetType, - task: Task, - showTaskActions: () -> Unit, - dismiss: () -> Unit -) { - when (bottomSheetType) { - TaskViewBottomSheetType.Detail -> { - TaskDetailBottomSheet(task, showTaskActions = { - dismiss() - showTaskActions() - }) { - dismiss() - } - } - } -} - @Suppress("MagicNumber") @Preview @Composable diff --git a/app/src/main/java/com/nextcloud/client/assistant/task/model/TaskViewBottomSheetType.kt b/app/src/main/java/com/nextcloud/client/assistant/task/model/TaskViewBottomSheetType.kt deleted file mode 100644 index dd531126f9..0000000000 --- a/app/src/main/java/com/nextcloud/client/assistant/task/model/TaskViewBottomSheetType.kt +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Nextcloud - Android Client - * - * SPDX-FileCopyrightText: 2024 Alper Ozturk - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -package com.nextcloud.client.assistant.task.model - -enum class TaskViewBottomSheetType { - Detail -} From fb087b56ecaa697c2f560eef447e9b06694e0c87 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 4 Dec 2024 12:10:27 +0100 Subject: [PATCH 24/34] remove unused keys Signed-off-by: alperozturk --- app/src/main/res/values-ar/strings.xml | 6 ------ app/src/main/res/values-ast/strings.xml | 4 ---- app/src/main/res/values-b+en+001/strings.xml | 6 ------ app/src/main/res/values-bg-rBG/strings.xml | 4 ---- app/src/main/res/values-br/strings.xml | 6 ------ app/src/main/res/values-ca/strings.xml | 6 ------ app/src/main/res/values-cs-rCZ/strings.xml | 6 ------ app/src/main/res/values-da/strings.xml | 5 ----- app/src/main/res/values-de/strings.xml | 6 ------ app/src/main/res/values-el/strings.xml | 3 --- app/src/main/res/values-eo/strings.xml | 2 -- app/src/main/res/values-es-rAR/strings.xml | 6 ------ app/src/main/res/values-es-rCL/strings.xml | 6 ------ app/src/main/res/values-es-rCO/strings.xml | 2 -- app/src/main/res/values-es-rDO/strings.xml | 2 -- app/src/main/res/values-es-rEC/strings.xml | 4 ---- app/src/main/res/values-es-rMX/strings.xml | 6 ------ app/src/main/res/values-es/strings.xml | 6 ------ app/src/main/res/values-eu/strings.xml | 6 ------ app/src/main/res/values-fa/strings.xml | 4 ---- app/src/main/res/values-fi-rFI/strings.xml | 4 ---- app/src/main/res/values-fr/strings.xml | 6 ------ app/src/main/res/values-ga/strings.xml | 6 ------ app/src/main/res/values-gd/strings.xml | 2 -- app/src/main/res/values-gl/strings.xml | 6 ------ app/src/main/res/values-hr/strings.xml | 2 -- app/src/main/res/values-hu-rHU/strings.xml | 4 ---- app/src/main/res/values-in/strings.xml | 6 ------ app/src/main/res/values-is/strings.xml | 2 -- app/src/main/res/values-it/strings.xml | 6 ------ app/src/main/res/values-iw/strings.xml | 2 -- app/src/main/res/values-ja-rJP/strings.xml | 6 ------ app/src/main/res/values-ka/strings.xml | 3 --- app/src/main/res/values-ko/strings.xml | 6 ------ app/src/main/res/values-lo/strings.xml | 2 -- app/src/main/res/values-lt-rLT/strings.xml | 3 --- app/src/main/res/values-lv/strings.xml | 3 --- app/src/main/res/values-mk/strings.xml | 3 --- app/src/main/res/values-nb-rNO/strings.xml | 6 ------ app/src/main/res/values-nl/strings.xml | 6 ------ app/src/main/res/values-pl/strings.xml | 6 ------ app/src/main/res/values-pt-rBR/strings.xml | 6 ------ app/src/main/res/values-pt-rPT/strings.xml | 2 -- app/src/main/res/values-ro/strings.xml | 6 ------ app/src/main/res/values-ru/strings.xml | 6 ------ app/src/main/res/values-sc/strings.xml | 3 --- app/src/main/res/values-sk-rSK/strings.xml | 6 ------ app/src/main/res/values-sl/strings.xml | 4 ---- app/src/main/res/values-sq/strings.xml | 2 -- app/src/main/res/values-sr-rSP/strings.xml | 5 ----- app/src/main/res/values-sr/strings.xml | 6 ------ app/src/main/res/values-sv/strings.xml | 6 ------ app/src/main/res/values-th-rTH/strings.xml | 3 --- app/src/main/res/values-tk/strings.xml | 2 -- app/src/main/res/values-tr/strings.xml | 6 ------ app/src/main/res/values-ug/strings.xml | 6 ------ app/src/main/res/values-uk/strings.xml | 6 ------ app/src/main/res/values-vi/strings.xml | 3 --- app/src/main/res/values-zh-rCN/strings.xml | 6 ------ app/src/main/res/values-zh-rHK/strings.xml | 6 ------ app/src/main/res/values-zh-rTW/strings.xml | 6 ------ app/src/main/res/values/strings.xml | 7 ------- 62 files changed, 289 deletions(-) diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 7e3c5a29b8..daa3a089de 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -49,13 +49,8 @@ أكتُب أيَّ نص هل أنت متأكد أنك ترغب بحذف هذه المهمة؟ حذف مهمة - فشل يتم الآن تحميل قائمة المهام؛ يرجى الانتظار... - لا توجد أي مهام متوفرة. حدِّد نوع المهمة لإنشاء واحدة جديدة. لا توجد أي مهام متوفرة من النوع %s. يمكنك إنشاء مهمة جديدة من الشريط السفلي الجانبي. - قيد التجهيز - مُجدول - مُكتمل حدث خطأ أثناء إنشاء المهمة تمّ إنشاء المهمة بنجاح حدث خطأ أثناء حذف المهمة @@ -65,7 +60,6 @@ نتيجة المهمة غير جاهة بعدُ. تعذّر جلب أنواع المهام. قم رجاءً بالتحقُّق من اتصالك بالإنترنت. المُساعِد - غير معروف مُدخَلات المُخرَجَات الحساب المرتبط غير موجود! diff --git a/app/src/main/res/values-ast/strings.xml b/app/src/main/res/values-ast/strings.xml index 2609787a47..dc2c545684 100644 --- a/app/src/main/res/values-ast/strings.xml +++ b/app/src/main/res/values-ast/strings.xml @@ -25,13 +25,9 @@ Puertu del proxy Buscar en: %s Escribi daqué - Falló - Planificóse - Completóse Nun ye posible dir en cata de la llista de xeres. Comprueba la conexón a internet. Nun ye posible dir en cata de los tipos de xeres. Comprueba la conexón a internet. Asistente - Desconocí­u Entrada Salida Yá esiste nel preséu una cuenta pal mesmu usuariu y sirvidor diff --git a/app/src/main/res/values-b+en+001/strings.xml b/app/src/main/res/values-b+en+001/strings.xml index 783c6802b1..d997603ae6 100644 --- a/app/src/main/res/values-b+en+001/strings.xml +++ b/app/src/main/res/values-b+en+001/strings.xml @@ -49,13 +49,8 @@ Type some text Are you sure you want to delete this task? Delete Task - Failed Task List are loading, please wait - No task available. Select a task type to create a new task. No task available for %s task type, you can create a new task from bottom right. - In Progress - Scheduled - Completed An error occurred while creating the task Task successfully created An error occurred while deleting the task @@ -65,7 +60,6 @@ The task output is not ready yet. Unable to fetch task types, please check your internet connection. Assistant - Unknown Input Output Associated account not found! diff --git a/app/src/main/res/values-bg-rBG/strings.xml b/app/src/main/res/values-bg-rBG/strings.xml index 54250c33a4..bbb9751a87 100644 --- a/app/src/main/res/values-bg-rBG/strings.xml +++ b/app/src/main/res/values-bg-rBG/strings.xml @@ -36,11 +36,7 @@ Порт на прокси сървъра Показва един изпълним модул от таблото за управление Търсене в %s - Неуспешно - Планирано - Завършен Задачата е успешно изтрита - Неизвестен Свързания профил не е намерен! Достъп неуспешен: %1$s Профилът все още не съществува на устройството diff --git a/app/src/main/res/values-br/strings.xml b/app/src/main/res/values-br/strings.xml index 035c93b1fc..002b61502f 100644 --- a/app/src/main/res/values-br/strings.xml +++ b/app/src/main/res/values-br/strings.xml @@ -40,13 +40,8 @@ Skrivañ un tamm testenn Ha sur oc\'h e fell deoc\'h dilemel an trevell-mañ ? Dilemel an trevell - C\'hwitet O kargañ roll an trevelloù, gortozit ur pennadig - N\'eus trevell ebet evit c\'hoazh. Diuzit ur seurt trevell evit krouiñ unan nevez. N\'eus trevell ebet evit %s seurt trevell, gallout a rit krouiñ unan nevez en traoñ a-zehoùt. - War ar stern - Raktreset - Echu C\'hoarvezet ez eus ur fazi en ur grouiñ an trevell Trevell bet krouet ervat C\'hoarvezet ez eus ur fazi en ur zilemel an trevell @@ -55,7 +50,6 @@ Dilemel an trevell N\'eus ket bet gallet tizhout ar seurtoù trevelloù, gwiriit ho kevreadenn genrouedad. Skoazeller - Dianv Enmont Ezvont N\'eo ket bet kavet ar gont stag ! diff --git a/app/src/main/res/values-ca/strings.xml b/app/src/main/res/values-ca/strings.xml index 8fe134b9b8..509f19d4d2 100644 --- a/app/src/main/res/values-ca/strings.xml +++ b/app/src/main/res/values-ca/strings.xml @@ -48,13 +48,8 @@ Escriu una mica de text Segur que voleu suprimir aquesta tasca? Suprimeix la tasca - Ha fallat S\'està carregant la llista de tasques, espereu - No hi ha cap tasca disponible. Seleccioneu un tipus de tasca per a crear una tasca nova. No hi ha cap tasca disponible per al tipus de tasca %s. Podeu crear una tasca nova des de baix a la dreta. - En curs - Planificat - S\'ha completat S\'ha produït un error en crear la tasca La tasca s\'ha creat correctament S\'ha produït un error en suprimir la tasca @@ -64,7 +59,6 @@ La sortida de la tasca encara no està a punt. No s\'han pogut obtenir els tipus de tasques. Comproveu la connexió a Internet. Assistent - Desconegut Entrada Sortida No s\'ha trobat el compte associat! diff --git a/app/src/main/res/values-cs-rCZ/strings.xml b/app/src/main/res/values-cs-rCZ/strings.xml index f6ca3a448d..c4ef2f725e 100644 --- a/app/src/main/res/values-cs-rCZ/strings.xml +++ b/app/src/main/res/values-cs-rCZ/strings.xml @@ -49,13 +49,8 @@ Zadejte nějaký text Opravdu chcete tuto úlohu smazat? Smazat úkol - Nezdařilo se Načítá se seznam úkolů – vyčkejte - Není k dispozici žádný úkol. Aby bylo možné vytvořit nový úkol, vyberte jeho typ. Pro typ úkolu %s nejsou k dispozici žádné úkoly – nový úkol je možné vytvořit vpravo dole. - Probíhá - Naplánováno - Dokončeno Při vytváření úlohy se vyskytla chyba Úloha byla úspěšně vytvořena Při mazání úlohy se vyskytla chyba @@ -65,7 +60,6 @@ Výstup z úkolu ještě není připraven. Nedaří se získat typy úloh – zkontrolujte připojení k Internetu. Asistent - Neznámé Vstup Výstup Související účet nenalezen! diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml index 710f2598ee..16fe3f3556 100644 --- a/app/src/main/res/values-da/strings.xml +++ b/app/src/main/res/values-da/strings.xml @@ -39,17 +39,12 @@ Skriv noget tekst Er du sikker på du vil slette denne opgave? Slet opgave - Mislykkede Opgavelisten indlæser, vent venligst - I gang - Planlagt - Fuldført Opgaven er oprettet En fejl opstod under sletning af opgaven Opgaven er slettet Slet opgave Assistent - Ukendt Forbundet konto blev ikke fundet! Adgang fejlede: %1$s Kontoen findes endnu ikke på enheden diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index ceffb6541b..4d83c5074d 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -49,13 +49,8 @@ Bitte einen Text eingeben Möchten Sie diese Aufgabe wirklich löschen? Aufgabe löschen - Fehlgeschlagen Aufgabenlisten werden geladen, bitte warten - Keine Aufgabe verfügbar. Aufgabentyp auswählen, um eine neue Aufgabe zu erstellen. Für den Aufgabentyp %s ist keine Aufgabe verfügbar. Sie können unten rechts eine neue Aufgabe erstellen. - In Bearbeitung - Geplant - Fertiggestellt Es ist ein Fehler beim Erstellen der Aufgabe aufgetreten Aufgabe erfolgreich erstellt Es ist ein Fehler beim Löschen der Aufgabe aufgetreten @@ -65,7 +60,6 @@ Die Aufgabenausgabe ist noch nicht fertig. Die Aufgabentypen können nicht abgerufen werden. Bitte überprüfen Sie Ihre Internetverbindung. Assistent - Unbekannt Eingabe Ausgabe Verknüpftes Konto nicht gefunden! diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 9e3e09020b..3c9584738f 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -36,9 +36,6 @@ Εμφάνιση ενός γραφικού στοιχείου από τον πίνακα ελέγχου Αναζήτηση στο %s Πληκτρολογήστε κάποιο κείμενο - Απέτυχε - Ολοκληρωμένες - Άγνωστο Δεν βρέθηκε ο συνδεδεμένος λογαριασμός! Αποτυχία πρόσβασης: %1$s Ο λογαριασμός δεν υπάρχει ακόμα στη συσκευή diff --git a/app/src/main/res/values-eo/strings.xml b/app/src/main/res/values-eo/strings.xml index a0655d9b8d..2f997d4471 100644 --- a/app/src/main/res/values-eo/strings.xml +++ b/app/src/main/res/values-eo/strings.xml @@ -31,8 +31,6 @@ Detalaj agordoj Permesi rekunhavigon Serĉi en 1%s - Plenumita - Nekonata Aliro malsukcesis: %1$s La konto ankoraŭ ne aldoniĝis al tiu ĉi aparato Konto pri samaj uzanto kaj servilo jam ekzistas tiuaparate diff --git a/app/src/main/res/values-es-rAR/strings.xml b/app/src/main/res/values-es-rAR/strings.xml index 47318ff136..f6567d75cd 100644 --- a/app/src/main/res/values-es-rAR/strings.xml +++ b/app/src/main/res/values-es-rAR/strings.xml @@ -40,13 +40,8 @@ Escriba un texto ¿Está seguro que desea eliminar esta tarea? Eliminar tarea - Error Las listas de tareas están cargando, por favor espere - No hay tareas disponibles. Seleccione un tipo de tarea para crear una nueva. No hay tareas del tipo %s, puede crear una nueva tarea desde la parte inferior derecha - En progreso - Programado - Completado Ocurrió un error al crear la tarea Tarea creada exitosamente Ocurrió un error al eliminar la tarea @@ -55,7 +50,6 @@ Eliminar tarea No se pudieron obtener los tipos de tareas, por favor, revise su conexión a internet. Asistente - Desconocido Entrada Salida ¡Cuenta asociada no encontrada! diff --git a/app/src/main/res/values-es-rCL/strings.xml b/app/src/main/res/values-es-rCL/strings.xml index 47e61d6816..135b2548a0 100644 --- a/app/src/main/res/values-es-rCL/strings.xml +++ b/app/src/main/res/values-es-rCL/strings.xml @@ -40,13 +40,8 @@ Escribe un texto ¿Está seguro que desea eliminar esta tarea? Tarea eliminada - Falló Lista de Tareas en lectura, espere por favor. - No hay tareas disponibles. Seleccione un tipo de tarea para crear una nueva. No hay tareas del tipo %s, puede crear una nueva tarea desde la parte inferior derecha - En progreso - Programado - Completado Ocurrió un error mientras creaba la tarea Tarea creada con éxito Ocurrió un error mientras eliminaba la tarea @@ -55,7 +50,6 @@ Tarea eliminada No se puede recuperar los tipos de tareas, comprueba la conexión a Internet. Asistente - Desconocido Entrada Salida ¡Cuenta asociada no encontrada! diff --git a/app/src/main/res/values-es-rCO/strings.xml b/app/src/main/res/values-es-rCO/strings.xml index e76eb967bd..b3350f677e 100644 --- a/app/src/main/res/values-es-rCO/strings.xml +++ b/app/src/main/res/values-es-rCO/strings.xml @@ -31,8 +31,6 @@ Configuración avanzada Permitir volver a compartir Buscar en %s - Completado - Desconocido ¡No se encontró la cuenta asociada! Error de acceso: %1$s La cuenta aún no ha sido agregada a este dispositivo diff --git a/app/src/main/res/values-es-rDO/strings.xml b/app/src/main/res/values-es-rDO/strings.xml index 8db8c1ea8a..12daad5a75 100644 --- a/app/src/main/res/values-es-rDO/strings.xml +++ b/app/src/main/res/values-es-rDO/strings.xml @@ -30,8 +30,6 @@ Agregar a %1$s Permitir volver a compartir Buscar en %s - Completado - Desconocido ¡Cuenta asociada no encontrada! Error de acceso: %1$s La cuenta aún no ha sido agregada a este dispositivo diff --git a/app/src/main/res/values-es-rEC/strings.xml b/app/src/main/res/values-es-rEC/strings.xml index 7cd2a4d521..5e3983ef25 100644 --- a/app/src/main/res/values-es-rEC/strings.xml +++ b/app/src/main/res/values-es-rEC/strings.xml @@ -36,11 +36,7 @@ Puerto del proxy Muestra un widget del panel de control Compartir en %s - Error - Programado - Completado Tarea eliminada con éxito - Desconocido ¡Cuenta asociada no encontrada! Acceso fallido: %1$s La cuenta aún no ha sido agregada a este dispositivo diff --git a/app/src/main/res/values-es-rMX/strings.xml b/app/src/main/res/values-es-rMX/strings.xml index ee2be0d136..f8bc5e50ba 100644 --- a/app/src/main/res/values-es-rMX/strings.xml +++ b/app/src/main/res/values-es-rMX/strings.xml @@ -40,13 +40,8 @@ Escriba algo de texto ¿Está seguro de eliminar esta tarea? Eliminar tarea - Falló Las listas de tareas están cargando, por favor espere - No hay tareas disponibles. Seleccione un tipo de tarea para crear una nueva. No hay tareas disponibles para el tipo de tarea %s, puede crear una nueva tarea abajo a la derecha. - En proceso - Programado - Completado Ocurrió un error al crear la tarea Tarea creada exitosamente Ocurrió un error al eliminar la tarea @@ -55,7 +50,6 @@ Eliminar tarea No se pudieron obtener los tipos de tareas, por favor, revise su conexión a internet. Asistente - Desconocido Entrada Salida ¡No se encontró la cuenta asociada! diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 89e05e5790..1e10ea1519 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -41,13 +41,8 @@ Escriba algo de texto ¿Está seguro de querer eliminar esta tarea? Eliminar tarea - Falló Las listas de tareas están cargando, por favor espere - No hay tareas disponibles. Seleccione un tipo de tarea para crear una nueva. No hay tareas disponibles para el tipo de tarea %s, puede crear una nueva tarea abajo a la derecha. - En progreso - Programado - Completado Ocurrió un error al crear la tarea Tarea creada exitosamente Ocurrió un error al eliminar la tarea @@ -56,7 +51,6 @@ Eliminar tarea No se pudieron obtener los tipos de tareas, por favor, revise su conexión a internet. Asistente - Desconocido Entrada Salida ¡Cuenta asociada no encontrada! diff --git a/app/src/main/res/values-eu/strings.xml b/app/src/main/res/values-eu/strings.xml index 307763c273..73c710dad4 100644 --- a/app/src/main/res/values-eu/strings.xml +++ b/app/src/main/res/values-eu/strings.xml @@ -49,13 +49,8 @@ Idatzi testu bat Ziur zeregin hau ezabatu nahi duzula? Ezabatu zeregina - Huts egin du Zereginen zerrenda kargatzen ari da, itxaron mesedez - Ez dago zereginik. Hautatu zeregin mota bat zeregin berri bat sortzeko. Ez dago zereginik %s zeregin motarako, zeregin berri bat sor dezakezu behean eskuinean. - Abian - Antolatuta - Osatua Errore bat gertatu da zeregina sortzean Zeregina behar bezala sortu da Errore bat gertatu da zeregina ezabatzean @@ -65,7 +60,6 @@ Zereginaren irteera ez dago prest oraindik. Ezin dira zeregin motak eskuratu, egiaztatu Interneteko konexioa. Morroia - Ezezaguna Sarrera Irteera Ez da aurkitu lotutako konturik diff --git a/app/src/main/res/values-fa/strings.xml b/app/src/main/res/values-fa/strings.xml index 11b1f451d1..808928b55f 100644 --- a/app/src/main/res/values-fa/strings.xml +++ b/app/src/main/res/values-fa/strings.xml @@ -39,11 +39,7 @@ نمایش یک ابزارک از پیشخوان جستجو در %s مقداری متن را تایپ کنید - Failed - Scheduled - نکمیل شده Task successfully deleted - ناشناخته حساب مرتبط یافت نشد! دسترسی خطای %1$s حساب به این وسیله اضافه نشده است diff --git a/app/src/main/res/values-fi-rFI/strings.xml b/app/src/main/res/values-fi-rFI/strings.xml index a7a30c9f8d..aa73721eb1 100644 --- a/app/src/main/res/values-fi-rFI/strings.xml +++ b/app/src/main/res/values-fi-rFI/strings.xml @@ -39,10 +39,7 @@ Syötä tekstiä Haluatko varmasti poistaa tämän tehtävän? Poista tehtävä - Epäonnistui Tehtävälista latautuu, odota - Aikataulutettu - Valmistui Tehtävän luonti epäonnistui Tehtävä luotu Tehtävän poisto epäonnistui @@ -51,7 +48,6 @@ Poista tehtävä Tehtävätyyppen haku epäonnistui, tarkista internetyhteytesi. Avustaja - Tuntematon Liitettyä tiliä ei löydy! Pääsy epäonnistui: %1$s Tälle laitteelle ei ole vielä asennettu tiliä. diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index d8928562be..9e457276bb 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -49,13 +49,8 @@ Tapez du texte Êtes-vous sûr de vouloir supprimer cette tâche ? Supprimer la tâche - Échec La liste des tâches charge, veuillez patienter - Aucune tâche disponible. Sélectionner un type de tâche pour créer une nouvelle tâche. Aucune tâche disponible pour le type de tâche %s, vous pouvez créer une nouvelle tâche en bas à droite. - En cours - Planifié - Terminé Une erreur est survenue lors de la création de la tâche La tâche a bien été créée Une erreur est survenue lors de la suppression de la tâche @@ -65,7 +60,6 @@ Le résultat de la tâche n\'est pas encore prêt. Impossible de récupérer les types des tâches, veuillez vérifier votre connexion Internet. Assistant - Inconnu Entrée Sortie Compte associé introuvable ! diff --git a/app/src/main/res/values-ga/strings.xml b/app/src/main/res/values-ga/strings.xml index 0f913d68f3..652ed0d642 100644 --- a/app/src/main/res/values-ga/strings.xml +++ b/app/src/main/res/values-ga/strings.xml @@ -49,13 +49,8 @@ Clóscríobh roinnt téacs An bhfuil tú cinnte gur mhaith leat an tasc seo a scriosadh? Scrios Tasc - Theip Tá an Liosta Tasc á lódáil, fan go fóill, le do thoil - Níl aon tasc ar fáil. Roghnaigh cineál taisc chun tasc nua a chruthú. Níl aon tasc ar fáil do chineál taisc %s, is féidir leat tasc nua a chruthú ón mbun ar dheis. - Ar Siúl - Sceidealta - Críochnaithe Tharla earráid agus an tasc á chruthú D\'éirigh leis an tasc a chruthú Tharla earráid agus an tasc á scriosadh @@ -65,7 +60,6 @@ Níl an t-aschur tasc réidh fós. Ní féidir cineálacha tascanna a fháil, seiceáil do nasc idirlín le do thoil. Cúntóir - Anaithnid Ionchur Aschur Cuntas gaolmhar gan aimsiú! diff --git a/app/src/main/res/values-gd/strings.xml b/app/src/main/res/values-gd/strings.xml index b50dee945c..7e8a048311 100644 --- a/app/src/main/res/values-gd/strings.xml +++ b/app/src/main/res/values-gd/strings.xml @@ -31,8 +31,6 @@ Cuir ri %1$s Ceadaich co-roinneadh às ùr Lorg am broinn %s - Coileanta - Chan eil fhios Cha deach an cunntas co-cheangailte a lorg! Dh’fhàillig leis an inntrigeadh: %1$s Cha deach an cunntas a chur ris air an uidheam seo fhathast diff --git a/app/src/main/res/values-gl/strings.xml b/app/src/main/res/values-gl/strings.xml index 0d98dbf37c..22112df16f 100644 --- a/app/src/main/res/values-gl/strings.xml +++ b/app/src/main/res/values-gl/strings.xml @@ -49,13 +49,8 @@ Escriba algún texto Confirma que quere eliminar esta tarefa? Eliminar tarefa - Fallado Estase a cargar a lista de tarefas, agarde - Non hai ningunha tarefa dispoñíbel. Seleccione un tipo de tarefa para crear unha nova tarefa. Non hai ningunha tarefa dispoñible para o tipo de tarefa %s, pode crear unha nova desde a parte inferior dereita. - En proceso - Programado - Completado Produciuse un erro ao crear a tarefa A tarefa creouse satisfactoriamente Produciuse un erro ao eliminar a tarefa @@ -65,7 +60,6 @@ A saída da tarefa aínda non está preparada. Non é posíbel recuperar os tipos de tarefas. Comprobe a conexión a Internet. Asistente - Descoñecido Entrada Saída Non se atopou unha conta asociada! diff --git a/app/src/main/res/values-hr/strings.xml b/app/src/main/res/values-hr/strings.xml index dab66b27c0..41ef92176f 100644 --- a/app/src/main/res/values-hr/strings.xml +++ b/app/src/main/res/values-hr/strings.xml @@ -34,8 +34,6 @@ Osnovni URL Proxy port Traži u %s - Završeno - Nepoznata pogreška Pripadajući račun nije pronađen! Neuspjeli pristup: %1$s Račun još nije dodan na ovaj uređaj diff --git a/app/src/main/res/values-hu-rHU/strings.xml b/app/src/main/res/values-hu-rHU/strings.xml index dce31e6544..9cea3e1ed9 100644 --- a/app/src/main/res/values-hu-rHU/strings.xml +++ b/app/src/main/res/values-hu-rHU/strings.xml @@ -41,11 +41,7 @@ Egy modult jelenít meg a irányítópultról Keresés itt: %s Gépeljen be szöveget - Sikertelen - Ütemezve - Teljesített Feladat sikeresen törölve - Ismeretlen A kapcsolódó fiók nem található! Hozzáférési hiba: %1$s Az eszközön még nem létezik a fiók diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index 55097e8359..add87fff21 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -38,13 +38,8 @@ Tulis beberapa teks Apakah Anda yakin ingin menghapus tugas ini? Hapus Tugas - Gagal Daftar Tugas sedang dimuat, mohon tunggu - Tidak ada tugas yang tersedia. Pilih jenis tugas untuk membuat tugas baru. Tidak ada tugas yang tersedia untuk jenis tugas %s, Anda dapat membuat tugas baru dari pojok kanan bawah. - Sedang Berlangsung - Dijadwalkan - Selesai Terjadi kesalahan saat membuat tugas Tugas berhasil dibuat Terjadi kesalahan saat menghapus tugas @@ -53,7 +48,6 @@ Hapus Tugas Tidak dapat memperoleh jenis tugas, mohon periksa koneksi internet Anda. Asisten - Tidak diketahui Input Output Akun terkait tidak ditemukan! diff --git a/app/src/main/res/values-is/strings.xml b/app/src/main/res/values-is/strings.xml index db2c3fd041..45087d1b28 100644 --- a/app/src/main/res/values-is/strings.xml +++ b/app/src/main/res/values-is/strings.xml @@ -35,8 +35,6 @@ Gátt milliþjóns Sýnir einn viðmótshluta af stjórnborði Leita í %s - Lokið - Óþekkt Tengdur notandaaðgangur fannst ekki! Aðgangur mistókst: %1$s Aðgangur er ekki ennþá til á tækinu diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 69f70ee415..aa9050e433 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -49,13 +49,8 @@ Aggiungi del testo Sei sicuro di voler rimuovere questa attività? Elimina attività - Non riuscito Lista dei Task in caricamento, si prega di attendere - Nessun task disponibile. Scegli un tipo di Task per crearne uno nuovo. Nessun task disponibile per la tipologia %s, puoi crearne uno nuovo in basso a destra. - In corso - Programmato - Completato Un errore è intercorso durante la creazione del task Task creato con successo Un errore è intercorso durante la cancellazione del task @@ -65,7 +60,6 @@ Il risultato del task non è ancora pronto. Impossibile recuperare i tipi di task, per favore verifica la tua connessione a internet. Assistente - Sconosciuto Input Output Account associato non trovato. diff --git a/app/src/main/res/values-iw/strings.xml b/app/src/main/res/values-iw/strings.xml index 9a7768e510..790d024575 100644 --- a/app/src/main/res/values-iw/strings.xml +++ b/app/src/main/res/values-iw/strings.xml @@ -35,8 +35,6 @@ פתחת מתווך מצג וידג׳ט אחד מלוח הבקרה חפש ב %s - הושלם - לא ידוע לא נמצא חשבון משויך! גישה נכשלה: %1$s החשבון לא נוסף למכשיר הזה עדיין diff --git a/app/src/main/res/values-ja-rJP/strings.xml b/app/src/main/res/values-ja-rJP/strings.xml index 235a4284ea..282cba667c 100644 --- a/app/src/main/res/values-ja-rJP/strings.xml +++ b/app/src/main/res/values-ja-rJP/strings.xml @@ -49,13 +49,8 @@ テキストを入力 本当にこのタスクを削除しますか? タスクを削除 - 失敗 タスクリストを読み込み中です。しばらくお待ちください - 利用可能なタスクがありません。タスクの種類を選択して、新しいタスクを作成してください。 タスクタイプ%sに使用できるタスクがありません。右下から新しいタスクを作成できます。 - 進行中 - スケジュール済 - 完了 タスクの作成中にエラーが発生しました。 タスクは正常に作成されました。 タスクの削除中にエラーが発生しました。 @@ -65,7 +60,6 @@ タスクの出力はまだ準備ができていません。 タスクタイプを取得できません。インターネット接続を確認してください。 アシスタント - 不明 入力 出力 関連付けられたアカウントが見つかりません! diff --git a/app/src/main/res/values-ka/strings.xml b/app/src/main/res/values-ka/strings.xml index b5214708f1..03c8021bd9 100644 --- a/app/src/main/res/values-ka/strings.xml +++ b/app/src/main/res/values-ka/strings.xml @@ -35,9 +35,6 @@ Allow resharing Shows one widget from dashboard Search in %s - Failed - Completed - Unknown Associated account not found! Access failed: %1$s The account is not added on this device yet diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 2cafec7609..0b7925d811 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -41,13 +41,8 @@ 텍스트 입력 이 작업을 삭제하시겠습니까? 작업 삭제 - 실패 작업 목록을 로드하는 중입니다. 잠시 기다려 주세요. - 사용할 수 있는 작업이 없습니다. 새 작업을 생성하려면 작업 유형을 선택하세요. %s작업 유형을 위해 사용 가능한 작업이 없습니다, 오른쪽 하단에서 새 작업을 만들 수 있습니다. - 진행 중 - 예정됨 - 완료됨 작업을 생성하는 중에 오류가 발생했습니다. 작업이 성공적으로 생성됨 작업을 삭제하는 중에 오류가 발생했습니다. @@ -56,7 +51,6 @@ 작업 삭제 작업 유형을 가져올 수 없습니다. 인터넷 연결을 확인하세요. 어시스턴트 - 알 수 없음 입력 출력 관련 계정을 찾을 수 없습니다! diff --git a/app/src/main/res/values-lo/strings.xml b/app/src/main/res/values-lo/strings.xml index 6c63a9645c..0991847461 100644 --- a/app/src/main/res/values-lo/strings.xml +++ b/app/src/main/res/values-lo/strings.xml @@ -34,8 +34,6 @@ ອະນຸຍາດໃຫ້ ການແບ່ງປັນຄືນ ສະແດງໜຶ່ງລາຍການຈາກໜ້າປັດ ຄົ້ນຫາໃນ%s - ສຳເລັດ - ບໍ່ຮູ້ ບໍ່ພົບບັນຊີທີ່ກ່ຽວຂ້ອງ! ການເຂົ້າເຖິງໄດ້ບໍ່ສຳເລັດ%1$s: ຍັງບໍ່ໄດ້ເພີ່ມບັນຊີໃສ່ໃນອຸປະກອນນີ້ diff --git a/app/src/main/res/values-lt-rLT/strings.xml b/app/src/main/res/values-lt-rLT/strings.xml index 1767c1c6c8..82cbd6eee4 100644 --- a/app/src/main/res/values-lt-rLT/strings.xml +++ b/app/src/main/res/values-lt-rLT/strings.xml @@ -40,15 +40,12 @@ Įrašykite kokį nors tekstą Ar tikrai norite ištrinti šią užduotį? Ištrinti užduotį - Nepavyko - Užbaigta Kuriant užduotį, įvyko klaida Užduotis sėkmingai sukurta Ištrinant užduotį, įvyko klaida Užduotis sėkmingai ištrinta Nepavyko gauti užduočių sąrašo, patikrinkite savo interneto ryšį. Ištrinti užduotį - Nežinoma Išvestis Susieta paskyra nerasta! Prieiga nepavyko: %1$s diff --git a/app/src/main/res/values-lv/strings.xml b/app/src/main/res/values-lv/strings.xml index 858f100224..e845fe8114 100644 --- a/app/src/main/res/values-lv/strings.xml +++ b/app/src/main/res/values-lv/strings.xml @@ -34,10 +34,7 @@ Starpniekservera ports Meklēt %s Dzēst uzdevumu - Neizdevās - Pabeigts Dzēst uzdevumu - Nezināms Saistītais konts nav atrasts! Piekļuve neizdevās: %1$s Konts vēl nav pievienots šai iekārtai diff --git a/app/src/main/res/values-mk/strings.xml b/app/src/main/res/values-mk/strings.xml index f09707c6f9..907a2396d7 100644 --- a/app/src/main/res/values-mk/strings.xml +++ b/app/src/main/res/values-mk/strings.xml @@ -34,9 +34,6 @@ Proxy порта Прикажува еден виџет од контролната табла Барај во %s - Неуспешно - Завршено - Непознат Не е пронајдена поврзана сметка! Неуспешен пристап: %1$s Сметката сеуште не е додадена на овој уред diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml index 59c1d93b8e..f3f37c3e97 100644 --- a/app/src/main/res/values-nb-rNO/strings.xml +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -41,13 +41,8 @@ Skriv inn litt tekst Er du sikker på at du vil slette denne oppgaven? Slett oppgave - Mislyktes Oppgaveliste lastes inn, vennligst vent - Ingen oppgave tilgjengelig. Velg en oppgavetype for å opprette en ny oppgave. Ingen oppgave tilgjengelig for %s-oppgavetype, du kan opprette en ny oppgave fra nede til høyre. - Pågår - Planlagt - Ferdig Det oppstod en feil under oppretting av oppgaven Oppgave opprettet Det oppstod en feil under sletting av oppgaven @@ -56,7 +51,6 @@ Slett oppgave Kan ikke hente oppgavetyper, vennligst sjekk internettforbindelsen din. Assistent - Ukjent Inndata Utdata Tilknyttet bruker ikke funnet! diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 642dbf6bfe..572dc4b7ee 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -49,13 +49,8 @@ Geef wat tekst in Bent u zeker dat u deze taak wilt verwijderen? Verwijder taak - Mislukt Takenlijst wordt geladen, even geduld - Geen taak beschikbaar. Selecteer een taaktype om een nieuwe aan te maken. Geen taak beschikbaar voor %s taaktype, u kunt rechts onder een nieuwe taak aanmaken. - Bezig - Ingepland - Voltooid Er is een fout opgetreden bij het aanmaken van de taak Taak succesvol aangemaakt Er is een fout opgetreden bij het verwijderen van de taak @@ -64,7 +59,6 @@ Verwijder taak Kan taken types niet ophalen. Controleer je internetverbinding. Assistent - Onbekend Input Output Bijbehorend account niet gevonden! diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 543ddc096d..28227e7dbd 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -48,13 +48,8 @@ Wpisz jakiś tekst Czy na pewno chcesz usunąć to zadanie? Usuń zadanie - Nie powiodło się Trwa wczytywanie listy zadań. Proszę czekać - Brak dostępnych zadań. Wybierz typ zadania, aby utworzyć nowe zadanie. Brak dostępnych zadań dla typu zadania %s. Możesz utworzyć nowe zadanie w prawym dolnym rogu. - W trakcie - Zaplanowane - Zakończone Wystąpił błąd podczas tworzenia zadania Zadanie pomyślnie utworzone Wystąpił błąd podczas usuwania zadania @@ -64,7 +59,6 @@ Wynik zadanie nie jest jeszcze gotowy Nie można pobrać typów zadań. Sprawdź swoje połączenie internetowe. Asystent - Nieznany Wejście Wyjście Nie znaleziono powiązanego konta! diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 3ab79e4221..fcf9a64743 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -42,13 +42,8 @@ Digite algum texto Tem certeza de que deseja excluir esta tarefa? Excluir tarefa - Falhou A lista de tarefas está carregando, aguarde - Nenhuma tarefa disponível. Selecione um tipo de tarefa para criar uma nova tarefa. Nenhuma tarefa disponível para o tipo de tarefa %s. Você pode criar uma nova tarefa no canto inferior direito. - Em Andamento - Agendada - Finalizado Ocorreu um erro ao criar a tarefa Tarefa criada com sucesso Ocorreu um erro ao excluir a tarefa @@ -58,7 +53,6 @@ O resultado da tarefa ainda não está pronto. Não foi possível buscar os tipos de tarefas. Verifique sua conexão com a Internet. Assistente - Desconhecido Entrada Saída Conta associada não encontrada! diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index 2bc8f8053d..c5abe36ddf 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -34,8 +34,6 @@ Permitir repartilha Mostra um \'\'widget\'\' do painel Procurar em %s - Concluída - Desconhecido Conta associada não encontrada! Acesso falhou: %1$s A conta ainda não foi adicionada a este dispositivo diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index 9517775ac3..c6b7731283 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -40,13 +40,8 @@ Tastează un text Sigur doriți să ștergeți acest task? Şterge task - Eșuat Lista de taskuri se încarcă, așteptați - Nici un task disponibil. Selectați un tip de task pentru a crea unul nou. Niciun task disponibil pentru tipul de task %s, puteți crea un task nou din dreapta jos. - În curs de desfășurare - Programat - Terminat A apărut o eroare la crearea taskului Task creat cu succes A apărut o eroare la ștergerea taskului @@ -55,7 +50,6 @@ Şterge task Nu se pot prelua tipurile taskurilor, vă rugăm să verificați conexiunea la internet. Asistent - Necunoscut Intrare Rezultat Contul asociat nu a fost găsit! diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index ec579c1ba8..98ce1421eb 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -41,13 +41,8 @@ Наберите какой-то текст Вы уверены, что хотите удалить эту задачу? Удалить задачу - Не удалось Список задач загружается, пожалуйста подождите - Нет доступных задач. Выберите тип задачи, чтобы создать новую задачу. Нет доступной задачи для типа задачи %s, вы можете создать новую задачу в правом нижнем углу. - Выполянется - Запланированное - Выполнено Произошла ошибка при создании задачи Задача успешно создана Произошла ошибка во время удаления задачи @@ -56,7 +51,6 @@ Удалить задачу Не удается получить список задач, проверьте ваше подключение к Интернету. Помощник - Неизвестно Ввод Вывод Связанный аккаунт не найден! diff --git a/app/src/main/res/values-sc/strings.xml b/app/src/main/res/values-sc/strings.xml index b270eef792..42d92faafb 100644 --- a/app/src/main/res/values-sc/strings.xml +++ b/app/src/main/res/values-sc/strings.xml @@ -35,10 +35,7 @@ URL de base Port serbidore intermèdiu Chirca in %s - Peruna faina a disponimentu. Seletziona sa genia de faina pro nde creare una noa. Peruna faina a disponimentu pro sa genia %s. Nde podes creare una noa dae su cugione in bassu a dereta. - Cumpletadu - Disconnotu Contu assotziadu no agatadu! Atzessu faddidu: %1$s Su contu non s\'agatat ancora in custu dispositivu diff --git a/app/src/main/res/values-sk-rSK/strings.xml b/app/src/main/res/values-sk-rSK/strings.xml index a2daa96479..02a42ab565 100644 --- a/app/src/main/res/values-sk-rSK/strings.xml +++ b/app/src/main/res/values-sk-rSK/strings.xml @@ -49,13 +49,8 @@ Napíšte nejaký text Naozaj chcete vymazať túto úlohu? Vymazať Úlohu - Zlyhalo Zoznam úloh sa nahráva, prosím čakajte - Žiadne úlohy nie su dostupné. Vyberte typ úlohy pre vytvorenie novej. Pre typ úlohy %s nie je k dispozícii žiadna úloha, môžete vytvoriť novú úlohu vpravo dole. - Prebieha - Naplánované - Dokončené Pri vytváraní úlohy nastala chyba Úloha bola úspešne vytvorená Pri odstraňovaní úlohy nastala chyba @@ -64,7 +59,6 @@ Vymazať Úlohu Nie je možné načítať typy úloh, skontrolujte svoje internetové pripojenie. Asistent - Neznámy Vstup Výstup Priradený účet sa nenašiel diff --git a/app/src/main/res/values-sl/strings.xml b/app/src/main/res/values-sl/strings.xml index 2508769f87..44136a723f 100644 --- a/app/src/main/res/values-sl/strings.xml +++ b/app/src/main/res/values-sl/strings.xml @@ -38,10 +38,6 @@ Vrata posredniškega strežnika Pokaži en gradnik iz nadzorne plošče Poišči v %s - Opravilo je spodletelo! - Načrtovano - Končano - Neznano Povezanega računa ni mogoče najti! Dostop je spodletel: %1$s Račun še ni dodan na to napravo. diff --git a/app/src/main/res/values-sq/strings.xml b/app/src/main/res/values-sq/strings.xml index d3ea0bb766..d726998145 100644 --- a/app/src/main/res/values-sq/strings.xml +++ b/app/src/main/res/values-sq/strings.xml @@ -29,8 +29,6 @@ Cilësime të Avancuara Lejo rindarje Kërkoni në %s - Të plotësuara - I panjohur Llogaria e lidhur nuk u gjet! Hyrja dështoi: %1$s Kjo llogari nuk është shtuar në këtë paisje akoma diff --git a/app/src/main/res/values-sr-rSP/strings.xml b/app/src/main/res/values-sr-rSP/strings.xml index 73ea5112a4..79ee3ef7bb 100644 --- a/app/src/main/res/values-sr-rSP/strings.xml +++ b/app/src/main/res/values-sr-rSP/strings.xml @@ -32,13 +32,8 @@ Pretraga u %s Da li ste sigurni da želite da izbrišete ovaj zadatak? Izbriši zadatak - Nije uspelo Lista zadataka se učitava, molimo sačekajte - Nijedan zadatak nije dostupan. Izaberite tip zadatka da biste kreirali novi zadatak. Nijedan zadatak nije dostupan za %s tip zadatka, možete kreirati novi zadatak dole desno. - U toku - Zakazano - Završeno Izbriši zadatak Pridruženi nalog nije nađen! Neuspeo pristup: %1$s diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml index 1d0410059b..0af0b6b879 100644 --- a/app/src/main/res/values-sr/strings.xml +++ b/app/src/main/res/values-sr/strings.xml @@ -49,13 +49,8 @@ Откуцајте неки текст Да ли сте сигурни да желите да обришете овај задатак? Обриши задатак - Није успело Листа задатака се учитава, молимо вас сачекајте - Не постоји ниједан задатак. Да бисте креирали нови задатак, изаберите тип задатка. Не постоји ниједан задатак типа %s, нови задатак можете да креирате доле десно. - Напредује - Заказано - Завршено Дошло је до грешке током креирања задатка Задатак је успешно креиран Дошло је до грешке током брисања задатка @@ -65,7 +60,6 @@ Излаз задатка још увек није спреман. Не могу да се преузму типови задатака, молимо вас да проверите везу са интернетом. Асистент - Непознато Унос Излаз Придружени налог није нађен! diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index fd394d3d07..f924d8b38d 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -49,13 +49,8 @@ Skriv någon text Är du säker på att du vill ta bort den här uppgiften? Ta bort uppgift - Misslyckades Uppgiftslistan laddas, vänta - Ingen uppgift tillgänglig. Välj en uppgiftstyp för att skapa en ny uppgift. Ingen uppgift tillgänglig för uppgiftstyp %s, du kan skapa en ny uppgift längst ner till höger. - Pågående - Schemalagd - Slutförd Ett fel uppstod när uppgiften skapades Uppgiften har skapats Ett fel uppstod när uppgiften skulle tas bort @@ -65,7 +60,6 @@ Uppgiftens resultat är inte redo än. Det går inte att hämta uppgiftstyper, kontrollera din internetanslutning. Assistent - Okänd Inmatning Utdata Associerat konto kunde inte hittas! diff --git a/app/src/main/res/values-th-rTH/strings.xml b/app/src/main/res/values-th-rTH/strings.xml index dc25210656..a6ee47d653 100644 --- a/app/src/main/res/values-th-rTH/strings.xml +++ b/app/src/main/res/values-th-rTH/strings.xml @@ -35,9 +35,6 @@ แสดงหนึ่งวิดเจ็ตจากแดชบอร์ด ค้นหาใน %s พิมพ์ข้อความของคุณ - อยู่ระหว่างการดำเนินการ - เสร็จแล้ว - ไม่ทราบ ไม่พบบัญชีที่เกี่ยวข้อง! การเข้าถึงล้มเหลว: %1$s บัญชียังไม่ถูกเพิ่มบนอุปกรณ์นี้ diff --git a/app/src/main/res/values-tk/strings.xml b/app/src/main/res/values-tk/strings.xml index 5cff2f37bd..6428f5a6a4 100644 --- a/app/src/main/res/values-tk/strings.xml +++ b/app/src/main/res/values-tk/strings.xml @@ -30,8 +30,6 @@ Goşuň%1$s Täzeden paýlaşmaga rugsat beriň Gözlemek%siçinde - Tamamlanan - Näbelli Baglanyşyk hasaby tapylmady! Şowsuz Giriş%1$s: Akaunt entek bu enjamda goşulmaýar diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 37485f0d17..8bde18db21 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -41,13 +41,8 @@ Bir şeyler yazın Bu görevi silmek istediğinize emin misiniz? Görevi sil - Tamamlanamadı Lütfen görev listesi yüklenirken bekleyin - Herhangi bir görev yok.Yeni bir görev eklemek için bir görev türü seçin. %s türünde bir görev yok. Sağ alttan yeni bir görev ekleyebilirsiniz. - Yapılıyor - Zamanlanmış - Tamamlanmış Görev oluşturulurken bir sorun çıktı Görev oluşturuldu Görev silinirken bir sorun çıktı @@ -56,7 +51,6 @@ Görevi sil Görev türleri alınamadı. Lütfen İnternet bağlantınızı denetleyin. Yardımcı - Bilinmiyor Giriş Çıkış İlişkili hesap bulunamadı! diff --git a/app/src/main/res/values-ug/strings.xml b/app/src/main/res/values-ug/strings.xml index dec44b5e36..1d9ce44c2f 100644 --- a/app/src/main/res/values-ug/strings.xml +++ b/app/src/main/res/values-ug/strings.xml @@ -41,13 +41,8 @@ بەزى تېكىستلەرنى كىرگۈزۈڭ بۇ ۋەزىپىنى ئۆچۈرمەكچىمۇ؟ ۋەزىپىنى ئۆچۈرۈڭ - مەغلۇب بولدى ۋەزىپە تىزىملىكى يۈكلىنىۋاتىدۇ ، ساقلاپ تۇرۇڭ - ھېچقانداق ۋەزىپە يوق. يېڭى ۋەزىپە يارىتىش ئۈچۈن ۋەزىپە تۈرىنى تاللاڭ. % S ۋەزىپە تىپىغا ماس كېلىدىغان ۋەزىپە يوق ، ئاستىدىن ئوڭدىن يېڭى ۋەزىپە قۇرالايسىز. - ئىلگىرىلەۋاتىدۇ - پىلانلانغان - تاماملاندى ۋەزىپە قۇرغاندا خاتالىق كۆرۈلدى ۋەزىپە مۇۋەپپەقىيەتلىك قۇرۇلدى ۋەزىپىنى ئۆچۈرگەندە خاتالىق كۆرۈلدى @@ -56,7 +51,6 @@ ۋەزىپىنى ئۆچۈرۈڭ ۋەزىپە تۈرلىرىنى ئېلىپ كېتەلمىدىڭىز ، تور ئۇلىنىشىڭىزنى تەكشۈرۈپ بېقىڭ. ياردەمچى - نامەلۇم كىرگۈزۈش چىقىرىش بىرلەشمە ھېسابات تېپىلمىدى! diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 27555b0e6f..57876d62dc 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -49,13 +49,8 @@ Вставте будь-який текст Дійсно вилучити це завдання? Вилучити завдання - Не вдалося Отримання переліку завдань, зачекайте - Відсутні завдання. Виберіть вид завдань для додавання нового завдання Відсутні завдання для завдань типу %s. Ви можете додати нове завдання праворуч внизу. - В процесі - Заплановано - Виконано Помилка під час додавання завдання Успішно додано завдання Помилка під час вилучення завдання @@ -65,7 +60,6 @@ Поки неможливо показати завдання Не вдалося отримати типи завдань. Перевірте з\'єднання з мережею. Помічник - Невідомо Введення Виведення Пов\'язаний обліковий запис не знайдено! diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index bc49e11974..d7eb116cd8 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -33,9 +33,6 @@ Cho phép chia sẻ lại Hiện thị lối tắt từ dashboard Tìm kiếm trong %s - Lên kế hoạch - Hoàn thành - Không xác định Không tìm thấy tài khoản được liên kết! Lỗi truy cập: %1$s Tài khoản chưa được thêm vào thiết bị này. diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 625773c3b7..0c34561c3a 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -49,13 +49,8 @@ 输入一些文字 您确定要删除这些任务吗? 删除任务 - 失败了 任务列表加载中,请稍等 - 没有可用任务。选择任务类型以创建新任务。 %s任务类型没有可用任务,你可以从右下角创建新任务。 - 进行中 - 已排程 - 已完成 创建任务时发生错误 任务已创建 删除任务时发生错误 @@ -65,7 +60,6 @@ 任务输出尚未就绪。 无法获取任务类型,请检查您的网络连接。 助手 - 未知 输入 输出结果 相关账号未找到! diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml index 4d78a0a6af..e6ed734ce3 100644 --- a/app/src/main/res/values-zh-rHK/strings.xml +++ b/app/src/main/res/values-zh-rHK/strings.xml @@ -49,13 +49,8 @@ 輸入一些文字 您確定要刪除此工作項目嗎? 刪除任務 - 失敗了 任務清單加載中,請稍候 - 無可用的工作項目。選取工作項目類型以建立新工作項目。 沒有可用於 %s 任務項目類型的任務項目,您可以從右下角建立新任務項目。 - 進行中 - 預定 - 已完成 建立任務項目時發生錯誤 已成功建立任務項目 刪除任務時發生了錯誤 @@ -65,7 +60,6 @@ 任務輸出尚未就緒。 無法擷取任務類型,請檢查您的網際網路連線。 助手 - 不詳 輸入 輸出 無法找到連結帳戶 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 12aa410724..87e90feee2 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -49,13 +49,8 @@ 輸入一些文字 您確定要刪除此工作項目嗎? 刪除工作項目 - 失敗 未載入工作項目清單,請稍候 - 無可用的工作項目。選取工作項目類型以建立新工作項目。 沒有可用於 %s 工作項目類型的工作項目,您可以從右下角建立新工作項目。 - 進行中 - 已安排 - 已完成 建立工作項目時發生錯誤 已成功建立工作項目 刪除工作項目時發生錯誤 @@ -65,7 +60,6 @@ 任務輸出尚未就緒。 無法擷取工作項目類型,請檢查您的網際網路連線。 助理 - 未知 輸入 輸出 找不到相關的帳號! diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 41a1d29e3a..b8d0528dfa 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -51,7 +51,6 @@ Assistant Task List are loading, please wait The task output is not ready yet. - No task available. Select a task type to create a new task. No task available for %s task type, you can create a new task from bottom right. Delete Task Are you sure you want to delete this task? @@ -67,12 +66,6 @@ Type some text - Unknown - Scheduled - Completed - Failed - In Progress - Input Output From e0ac903bceacff52c77dbf646e6a281c0de6041e Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 4 Dec 2024 12:12:09 +0100 Subject: [PATCH 25/34] remove unused icon for assistant (lint warning) Signed-off-by: alperozturk --- app/src/main/res/drawable/ic_info.xml | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 app/src/main/res/drawable/ic_info.xml diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml deleted file mode 100644 index 345147ea17..0000000000 --- a/app/src/main/res/drawable/ic_info.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - From 41b06ccf4e104a9312817cf6cffa842c33bde8de Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 4 Dec 2024 12:12:35 +0100 Subject: [PATCH 26/34] fix code analytics Signed-off-by: alperozturk --- .../java/com/nextcloud/client/assistant/AsssistantScreen.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt b/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt index 34b63adcf7..e956cc2edd 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt @@ -204,7 +204,7 @@ private fun ShowOverlayState(state: ScreenOverlayState?, activity: Activity, vie is ScreenOverlayState.TaskActions -> { val actions = state.getActions(activity, onEditCompleted = { addTask -> viewModel.updateScreenState(addTask) - }, onDeleteCompleted = { deleteTask -> + }, onDeleteCompleted = { deleteTask -> viewModel.updateScreenState(deleteTask) }) From 561c6d1d0beb73e9696fe2666bce376850b07bc6 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 4 Dec 2024 14:32:59 +0100 Subject: [PATCH 27/34] use native tab layout Signed-off-by: alperozturk --- .../client/assistant/AsssistantScreen.kt | 47 ++++++------ .../assistant/taskTypes/TaskTypesRow.kt | 76 +++++++++++-------- app/src/main/res/values-night/colors.xml | 2 + app/src/main/res/values/colors.xml | 2 + 4 files changed, 74 insertions(+), 53 deletions(-) diff --git a/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt b/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt index e956cc2edd..68dd3b35d1 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt @@ -8,7 +8,6 @@ package com.nextcloud.client.assistant import android.app.Activity -import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer @@ -219,7 +218,6 @@ private fun ShowOverlayState(state: ScreenOverlayState?, activity: Activity, vie } } -@OptIn(ExperimentalFoundationApi::class) @Composable private fun AssistantContent( taskList: List, @@ -227,28 +225,29 @@ private fun AssistantContent( selectedTaskType: TaskTypeData?, viewModel: AssistantViewModel ) { - LazyColumn( - modifier = Modifier - .fillMaxSize() - .padding(16.dp) - ) { - stickyHeader { + + Column(modifier = Modifier.fillMaxSize()) { + taskTypes?.let { TaskTypesRow(selectedTaskType, data = taskTypes) { task -> viewModel.selectTaskType(task) } - - Spacer(modifier = Modifier.height(8.dp)) } - items(taskList) { task -> - TaskView( - task, - showTaskActions = { - val newState = ScreenOverlayState.TaskActions(task) - viewModel.updateScreenState(newState) - } - ) - Spacer(modifier = Modifier.height(8.dp)) + LazyColumn( + modifier = Modifier + .fillMaxSize() + .padding(12.dp) + ) { + items(taskList) { task -> + TaskView( + task, + showTaskActions = { + val newState = ScreenOverlayState.TaskActions(task) + viewModel.updateScreenState(newState) + } + ) + Spacer(modifier = Modifier.height(8.dp)) + } } } } @@ -269,11 +268,13 @@ private fun EmptyTaskList( .fillMaxSize() .padding(16.dp) ) { - TaskTypesRow(selectedTaskType, data = taskTypes) { task -> - viewModel.selectTaskType(task) - } + taskTypes?.let { + TaskTypesRow(selectedTaskType, data = taskTypes) { task -> + viewModel.selectTaskType(task) + } - Spacer(modifier = Modifier.height(8.dp)) + Spacer(modifier = Modifier.height(8.dp)) + } CenterText(text = text) } diff --git a/app/src/main/java/com/nextcloud/client/assistant/taskTypes/TaskTypesRow.kt b/app/src/main/java/com/nextcloud/client/assistant/taskTypes/TaskTypesRow.kt index 99a336de45..4fb5c4ddb2 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/taskTypes/TaskTypesRow.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/taskTypes/TaskTypesRow.kt @@ -7,45 +7,61 @@ */ package com.nextcloud.client.assistant.taskTypes -import androidx.compose.foundation.horizontalScroll -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.rememberScrollState -import androidx.compose.material3.ButtonDefaults -import androidx.compose.material3.FilledTonalButton +import android.annotation.SuppressLint +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.ScrollableTabRow +import androidx.compose.material3.Tab +import androidx.compose.material3.TabRowDefaults +import androidx.compose.material3.TabRowDefaults.tabIndicatorOffset import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.colorResource +import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import com.owncloud.android.R import com.owncloud.android.lib.resources.assistant.model.TaskTypeData +@SuppressLint("ResourceType") @Composable -fun TaskTypesRow(selectedTaskType: TaskTypeData?, data: List?, selectTaskType: (TaskTypeData) -> Unit) { - Row( - modifier = Modifier - .fillMaxWidth() - .horizontalScroll(rememberScrollState()) - ) { - data?.forEach { taskType -> - taskType.name?.let { taskTypeName -> - FilledTonalButton( - onClick = { selectTaskType(taskType) }, - colors = ButtonDefaults.buttonColors( - containerColor = if (selectedTaskType?.id == taskType.id) { - Color.Unspecified - } else { - Color.Gray - } - ) - ) { - Text(text = taskTypeName) - } +fun TaskTypesRow(selectedTaskType: TaskTypeData?, data: List, selectTaskType: (TaskTypeData) -> Unit) { + val selectedTabIndex = data.indexOfFirst { it.id == selectedTaskType?.id }.takeIf { it >= 0 } ?: 0 - Spacer(modifier = Modifier.padding(end = 8.dp)) + ScrollableTabRow( + selectedTabIndex = selectedTabIndex, + edgePadding = 0.dp, + containerColor = colorResource(R.color.actionbar_color), + indicator = { + TabRowDefaults.SecondaryIndicator( + Modifier.tabIndicatorOffset(it[selectedTabIndex]), + color = MaterialTheme.colorScheme.primary, + ) + } + ) { + data.forEach { taskType -> + taskType.name?.let { taskTypeName -> + Tab( + selected = selectedTaskType?.id == taskType.id, + onClick = { selectTaskType(taskType) }, + selectedContentColor = colorResource(R.color.text_color), + unselectedContentColor = colorResource(R.color.disabled_text), + text = { Text(text = taskTypeName) } + ) } } } } + +@Composable +@Preview +private fun TaskTypesRowPreview() { + val selectedTaskType = TaskTypeData("1", "Free text to text prompt", "", null, null) + val taskTypes = listOf( + TaskTypeData("1", "Free text to text prompt", "", null, null), + TaskTypeData("2", "Extract topics", "", null, null), + TaskTypeData("3", "Generate Headline", "", null, null), + TaskTypeData("4", "Summarize", "", null, null) + ) + + TaskTypesRow(selectedTaskType, taskTypes) { } +} \ No newline at end of file diff --git a/app/src/main/res/values-night/colors.xml b/app/src/main/res/values-night/colors.xml index 1ce3f0da4f..8972d2bb67 100644 --- a/app/src/main/res/values-night/colors.xml +++ b/app/src/main/res/values-night/colors.xml @@ -36,4 +36,6 @@ #1E1E1E @android:color/white + + #101418 diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index efefff8f3b..e0da603d4f 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -76,4 +76,6 @@ @android:color/white #666666 #A5A5A5 + + #F7F9FF From 0d53be7890e4be9b0b577fd27331e0536700dfa0 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 4 Dec 2024 14:44:56 +0100 Subject: [PATCH 28/34] fix colors Signed-off-by: alperozturk --- .../client/assistant/component/CenterText.kt | 5 +++-- .../nextcloud/client/assistant/task/TaskView.kt | 14 +++++++------- .../assistant/taskDetail/TaskDetailBottomSheet.kt | 7 +++---- .../client/assistant/taskTypes/TaskTypesRow.kt | 5 ++--- 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/com/nextcloud/client/assistant/component/CenterText.kt b/app/src/main/java/com/nextcloud/client/assistant/component/CenterText.kt index 3831b785e9..cf3cefb617 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/component/CenterText.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/component/CenterText.kt @@ -9,13 +9,14 @@ package com.nextcloud.client.assistant.component import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.res.colorResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.sp +import com.owncloud.android.R @Composable fun CenterText(text: String) { @@ -24,7 +25,7 @@ fun CenterText(text: String) { text = text, fontSize = 18.sp, textAlign = TextAlign.Center, - color = MaterialTheme.colorScheme.onPrimaryContainer + color = colorResource(R.color.text_color) ) } } diff --git a/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt b/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt index 1bd8809253..218b506630 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt @@ -23,7 +23,6 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.MoreVert import androidx.compose.material3.Icon import androidx.compose.material3.IconButton -import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -33,13 +32,14 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.colorResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.nextcloud.client.assistant.taskDetail.TaskDetailBottomSheet +import com.owncloud.android.R import com.owncloud.android.lib.resources.assistant.model.Task import com.owncloud.android.lib.resources.assistant.model.TaskInput import com.owncloud.android.lib.resources.assistant.model.TaskOutput @@ -54,7 +54,7 @@ fun TaskView(task: Task, showTaskActions: () -> Unit) { modifier = Modifier .fillMaxWidth() .clip(RoundedCornerShape(8.dp)) - .background(MaterialTheme.colorScheme.primary) + .background(colorResource(R.color.primary)) .clickable { showTaskDetailBottomSheet = true } @@ -65,7 +65,7 @@ fun TaskView(task: Task, showTaskActions: () -> Unit) { task.input?.input?.let { Text( text = it, - color = Color.White, + color = colorResource(R.color.text_color), fontSize = 18.sp, textAlign = TextAlign.Left, fontWeight = FontWeight.Bold, @@ -85,7 +85,7 @@ fun TaskView(task: Task, showTaskActions: () -> Unit) { Text( text = output, fontSize = 18.sp, - color = Color.White, + color = colorResource(R.color.text_color), textAlign = TextAlign.Left, modifier = Modifier .animateContentSize( @@ -97,7 +97,7 @@ fun TaskView(task: Task, showTaskActions: () -> Unit) { ) } - TaskStatusView(task, foregroundColor = Color.White) + TaskStatusView(task, foregroundColor = colorResource(R.color.text_color)) if (showTaskDetailBottomSheet) { TaskDetailBottomSheet(task, showTaskActions = { @@ -116,7 +116,7 @@ fun TaskView(task: Task, showTaskActions: () -> Unit) { Icon( imageVector = Icons.Filled.MoreVert, contentDescription = "More button", - tint = Color.White + tint = colorResource(R.color.text_color) ) } } diff --git a/app/src/main/java/com/nextcloud/client/assistant/taskDetail/TaskDetailBottomSheet.kt b/app/src/main/java/com/nextcloud/client/assistant/taskDetail/TaskDetailBottomSheet.kt index 7cce23d3e7..07e5bc2d1b 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/taskDetail/TaskDetailBottomSheet.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/taskDetail/TaskDetailBottomSheet.kt @@ -39,7 +39,6 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview @@ -61,7 +60,7 @@ fun TaskDetailBottomSheet(task: Task, showTaskActions: () -> Unit, dismiss: () - ModalBottomSheet( modifier = Modifier.padding(top = 32.dp), - containerColor = MaterialTheme.colorScheme.surface, + containerColor = colorResource(R.color.bg_default), onDismissRequest = { dismiss() }, sheetState = sheetState ) { @@ -80,7 +79,7 @@ fun TaskDetailBottomSheet(task: Task, showTaskActions: () -> Unit, dismiss: () - Icon( imageVector = Icons.Filled.MoreVert, contentDescription = "More button", - tint = Color.White + tint = colorResource(R.color.text_color) ) } } @@ -143,7 +142,7 @@ fun TaskDetailBottomSheet(task: Task, showTaskActions: () -> Unit, dismiss: () - ) } - TaskStatusView(task, foregroundColor = MaterialTheme.colorScheme.onPrimaryContainer) + TaskStatusView(task, foregroundColor = colorResource(R.color.text_color)) Spacer(modifier = Modifier.height(32.dp)) } diff --git a/app/src/main/java/com/nextcloud/client/assistant/taskTypes/TaskTypesRow.kt b/app/src/main/java/com/nextcloud/client/assistant/taskTypes/TaskTypesRow.kt index 4fb5c4ddb2..8dc8aab7f1 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/taskTypes/TaskTypesRow.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/taskTypes/TaskTypesRow.kt @@ -8,7 +8,6 @@ package com.nextcloud.client.assistant.taskTypes import android.annotation.SuppressLint -import androidx.compose.material3.MaterialTheme import androidx.compose.material3.ScrollableTabRow import androidx.compose.material3.Tab import androidx.compose.material3.TabRowDefaults @@ -34,7 +33,7 @@ fun TaskTypesRow(selectedTaskType: TaskTypeData?, data: List, sele indicator = { TabRowDefaults.SecondaryIndicator( Modifier.tabIndicatorOffset(it[selectedTabIndex]), - color = MaterialTheme.colorScheme.primary, + color = colorResource(R.color.primary), ) } ) { @@ -64,4 +63,4 @@ private fun TaskTypesRowPreview() { ) TaskTypesRow(selectedTaskType, taskTypes) { } -} \ No newline at end of file +} From 98529dc29188bcc41bddfbc5decd8d58f2fd89ef Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 4 Dec 2024 14:48:40 +0100 Subject: [PATCH 29/34] fix colors Signed-off-by: alperozturk --- .../java/com/nextcloud/client/assistant/task/TaskView.kt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt b/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt index 218b506630..c01c15a581 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/task/TaskView.kt @@ -32,6 +32,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.colorResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign @@ -65,7 +66,7 @@ fun TaskView(task: Task, showTaskActions: () -> Unit) { task.input?.input?.let { Text( text = it, - color = colorResource(R.color.text_color), + color = Color.White, fontSize = 18.sp, textAlign = TextAlign.Left, fontWeight = FontWeight.Bold, @@ -85,7 +86,7 @@ fun TaskView(task: Task, showTaskActions: () -> Unit) { Text( text = output, fontSize = 18.sp, - color = colorResource(R.color.text_color), + color = Color.White, textAlign = TextAlign.Left, modifier = Modifier .animateContentSize( @@ -97,7 +98,7 @@ fun TaskView(task: Task, showTaskActions: () -> Unit) { ) } - TaskStatusView(task, foregroundColor = colorResource(R.color.text_color)) + TaskStatusView(task, foregroundColor = Color.White) if (showTaskDetailBottomSheet) { TaskDetailBottomSheet(task, showTaskActions = { @@ -116,7 +117,7 @@ fun TaskView(task: Task, showTaskActions: () -> Unit) { Icon( imageVector = Icons.Filled.MoreVert, contentDescription = "More button", - tint = colorResource(R.color.text_color) + tint = Color.White ) } } From 54cc4f837791713b7cf7e10f39d72d7fcb33da12 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 4 Dec 2024 14:51:57 +0100 Subject: [PATCH 30/34] fix code analytics Signed-off-by: alperozturk --- .../java/com/nextcloud/client/assistant/AsssistantScreen.kt | 1 - .../com/nextcloud/client/assistant/taskTypes/TaskTypesRow.kt | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt b/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt index 68dd3b35d1..e28ffdd726 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt @@ -225,7 +225,6 @@ private fun AssistantContent( selectedTaskType: TaskTypeData?, viewModel: AssistantViewModel ) { - Column(modifier = Modifier.fillMaxSize()) { taskTypes?.let { TaskTypesRow(selectedTaskType, data = taskTypes) { task -> diff --git a/app/src/main/java/com/nextcloud/client/assistant/taskTypes/TaskTypesRow.kt b/app/src/main/java/com/nextcloud/client/assistant/taskTypes/TaskTypesRow.kt index 8dc8aab7f1..08f6883fb5 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/taskTypes/TaskTypesRow.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/taskTypes/TaskTypesRow.kt @@ -33,7 +33,7 @@ fun TaskTypesRow(selectedTaskType: TaskTypeData?, data: List, sele indicator = { TabRowDefaults.SecondaryIndicator( Modifier.tabIndicatorOffset(it[selectedTabIndex]), - color = colorResource(R.color.primary), + color = colorResource(R.color.primary) ) } ) { From 06b8db9e26e079caba4f91ce74777708fecc151c Mon Sep 17 00:00:00 2001 From: alperozturk Date: Mon, 9 Dec 2024 12:37:20 +0100 Subject: [PATCH 31/34] update library Signed-off-by: alperozturk --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index aabd00b24e..46dd9286a0 100644 --- a/build.gradle +++ b/build.gradle @@ -10,7 +10,7 @@ */ buildscript { ext { - androidLibraryVersion ="4a95888afc472369e85fccae3d3573ff9e36fb50" + androidLibraryVersion ="f174c1ee78" androidPluginVersion = '8.7.3' androidxMediaVersion = '1.4.1' androidxTestVersion = "1.6.1" From 2d53e53a471d44c3bfc20ef134b7994dd6d40dd7 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Mon, 9 Dec 2024 12:37:38 +0100 Subject: [PATCH 32/34] use input and output together for share and copy Signed-off-by: alperozturk --- .../client/assistant/extensions/TaskExtensions.kt | 9 +++++++-- .../client/assistant/model/ScreenOverlayState.kt | 8 ++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/nextcloud/client/assistant/extensions/TaskExtensions.kt b/app/src/main/java/com/nextcloud/client/assistant/extensions/TaskExtensions.kt index 1302b7a522..50544e2490 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/extensions/TaskExtensions.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/extensions/TaskExtensions.kt @@ -16,9 +16,14 @@ import com.owncloud.android.R import com.owncloud.android.lib.resources.assistant.model.Task import java.util.concurrent.TimeUnit -fun Task.getInput(): String? = input?.input +fun Task.getInputAndOutput(): String { + val inputText = input?.input ?: "" + val outputText = output?.output ?: "" -fun Task.getOutput(): String? = output?.output + return "$inputText\n\n$outputText" +} + +fun Task.getInput(): String? = input?.input @Suppress("MagicNumber") fun Task.getInputTitle(): String { diff --git a/app/src/main/java/com/nextcloud/client/assistant/model/ScreenOverlayState.kt b/app/src/main/java/com/nextcloud/client/assistant/model/ScreenOverlayState.kt index 6ee8ea6132..a051885e9b 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/model/ScreenOverlayState.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/model/ScreenOverlayState.kt @@ -9,7 +9,7 @@ package com.nextcloud.client.assistant.model import android.app.Activity import com.nextcloud.client.assistant.extensions.getInput -import com.nextcloud.client.assistant.extensions.getOutput +import com.nextcloud.client.assistant.extensions.getInputAndOutput import com.nextcloud.utils.extensions.showShareIntent import com.owncloud.android.R import com.owncloud.android.lib.resources.assistant.model.Task @@ -20,15 +20,15 @@ sealed class ScreenOverlayState { data class DeleteTask(val id: Long) : ScreenOverlayState() data class AddTask(val taskType: TaskTypeData, val input: String) : ScreenOverlayState() data class TaskActions(val task: Task) : ScreenOverlayState() { + private fun getInputAndOutput(): String = task.getInputAndOutput() private fun getInput(): String? = task.getInput() - private fun getOutput(): String? = task.getOutput() private fun getCopyToClipboardAction(activity: Activity): Triple Unit> { return Triple( R.drawable.ic_content_copy, R.string.common_copy ) { - ClipboardUtil.copyToClipboard(activity, getOutput()) + ClipboardUtil.copyToClipboard(activity, getInputAndOutput(), showToast = false) } } @@ -37,7 +37,7 @@ sealed class ScreenOverlayState { R.drawable.ic_share, R.string.common_share ) { - activity.showShareIntent(getOutput()) + activity.showShareIntent(getInputAndOutput()) } } From 980162478652bcf59e13efc32b7214ab8759a717 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Mon, 9 Dec 2024 12:37:49 +0100 Subject: [PATCH 33/34] change title of the add new task Signed-off-by: alperozturk --- app/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b8d0528dfa..f0b93bdd5f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -54,7 +54,7 @@ No task available for %s task type, you can create a new task from bottom right. Delete Task Are you sure you want to delete this task? - Add New Task + Add new task Delete Task From ddcd22357b08f19271af83f2aed2adc646de239c Mon Sep 17 00:00:00 2001 From: alperozturk Date: Tue, 10 Dec 2024 14:13:56 +0100 Subject: [PATCH 34/34] update ss Signed-off-by: alperozturk --- ...ialog.DialogFragmentIT_testBottomSheet.png | Bin 23366 -> 23379 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/app/screenshots/gplay/debug/com.owncloud.android.ui.dialog.DialogFragmentIT_testBottomSheet.png b/app/screenshots/gplay/debug/com.owncloud.android.ui.dialog.DialogFragmentIT_testBottomSheet.png index e0156daaab8ca13cf3ce619290374ba4a52cb355..69957a6c218b076073d29ea5b2265a7b9b8143ca 100644 GIT binary patch literal 23379 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