瀏覽代碼

UI Fixes

Signed-off-by: alperozturk <alper_ozturk@proton.me>
alperozturk 1 年之前
父節點
當前提交
f55017f077

+ 29 - 2
.idea/inspectionProfiles/ktlint.xml

@@ -2,9 +2,36 @@
   <profile version="1.0">
     <option name="myName" value="ktlint" />
     <inspection_tool class="AutoCloseableResource" enabled="true" level="WARNING" enabled_by_default="true">
-      <option name="METHOD_MATCHER_CONFIG" value="java.util.Formatter,format,java.io.Writer,append,com.google.common.base.Preconditions,checkNotNull,org.hibernate.Session,close,java.io.PrintWriter,printf,java.io.PrintStream,printf,java.nio.channels.FileChannel,position" />
+      <option name="METHOD_MATCHER_CONFIG" value="java.util.Formatter,format,java.io.Writer,append,com.google.common.base.Preconditions,checkNotNull,org.hibernate.Session,close,java.io.PrintWriter,printf,java.io.PrintStream,printf,java.nio.channels.FileChannel,position,okhttp3.Call,execute" />
     </inspection_tool>
     <inspection_tool class="KotlinUnusedImport" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="PreviewAnnotationInFunctionWithParameters" enabled="true" level="ERROR" enabled_by_default="true">
+      <option name="composableFile" value="true" />
+    </inspection_tool>
+    <inspection_tool class="PreviewApiLevelMustBeValid" enabled="true" level="ERROR" enabled_by_default="true">
+      <option name="composableFile" value="true" />
+    </inspection_tool>
+    <inspection_tool class="PreviewDimensionRespectsLimit" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="composableFile" value="true" />
+    </inspection_tool>
+    <inspection_tool class="PreviewFontScaleMustBeGreaterThanZero" enabled="true" level="ERROR" enabled_by_default="true">
+      <option name="composableFile" value="true" />
+    </inspection_tool>
+    <inspection_tool class="PreviewMultipleParameterProviders" enabled="true" level="ERROR" enabled_by_default="true">
+      <option name="composableFile" value="true" />
+    </inspection_tool>
+    <inspection_tool class="PreviewMustBeTopLevelFunction" enabled="true" level="ERROR" enabled_by_default="true">
+      <option name="composableFile" value="true" />
+    </inspection_tool>
+    <inspection_tool class="PreviewNeedsComposableAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
+      <option name="composableFile" value="true" />
+    </inspection_tool>
+    <inspection_tool class="PreviewNotSupportedInUnitTestFiles" enabled="true" level="ERROR" enabled_by_default="true">
+      <option name="composableFile" value="true" />
+    </inspection_tool>
+    <inspection_tool class="PreviewPickerAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
+      <option name="composableFile" value="true" />
+    </inspection_tool>
     <inspection_tool class="RedundantSemicolon" enabled="true" level="ERROR" enabled_by_default="true" />
   </profile>
-</component>
+</component>

+ 16 - 0
app/src/main/java/com/nextcloud/client/assistant/AssistantViewModel.kt

@@ -26,7 +26,9 @@ import androidx.lifecycle.viewModelScope
 import com.nextcloud.client.assistant.repository.AssistantRepository
 import com.nextcloud.common.NextcloudClient
 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.TaskList
+import com.owncloud.android.lib.resources.assistant.model.TaskType
 import com.owncloud.android.lib.resources.assistant.model.TaskTypes
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.flow.MutableStateFlow
@@ -38,6 +40,9 @@ class AssistantViewModel(client: NextcloudClient) : ViewModel() {
 
     private val repository: AssistantRepository = AssistantRepository(client)
 
+    private val _selectedTask = MutableStateFlow<TaskType?>(null)
+    val selectedTask: StateFlow<TaskType?> = _selectedTask
+
     private val _taskTypes = MutableStateFlow<RemoteOperationResult<TaskTypes>?>(null)
     val taskTypes: StateFlow<RemoteOperationResult<TaskTypes>?> = _taskTypes
 
@@ -65,12 +70,23 @@ class AssistantViewModel(client: NextcloudClient) : ViewModel() {
         }
     }
 
+    fun selectTask(task: TaskType) {
+        _selectedTask.update {
+            task
+        }
+    }
+
     private fun getTaskTypes() {
         viewModelScope.launch(Dispatchers.IO) {
             val result = repository.getTaskTypes()
+
             _taskTypes.update {
                 result
             }
+
+            _selectedTask.update {
+                result.resultData.types.first()
+            }
         }
     }
 

+ 12 - 78
app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt

@@ -23,20 +23,12 @@ package com.nextcloud.client.assistant
 
 import android.app.Activity
 import androidx.compose.foundation.ExperimentalFoundationApi
-import androidx.compose.foundation.horizontalScroll
-import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.lazy.LazyColumn
 import androidx.compose.foundation.lazy.items
-import androidx.compose.foundation.rememberScrollState
-import androidx.compose.foundation.text.KeyboardOptions
-import androidx.compose.material3.ButtonDefaults
-import androidx.compose.material3.FilledTonalButton
-import androidx.compose.material3.Text
-import androidx.compose.material3.TextField
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.collectAsState
 import androidx.compose.runtime.getValue
@@ -44,13 +36,13 @@ 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.platform.LocalContext
 import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.text.input.KeyboardType
 import androidx.compose.ui.unit.dp
 import com.google.android.material.floatingactionbutton.FloatingActionButton
-import com.nextcloud.ui.composeComponents.SimpleAlertDialog
+import com.nextcloud.client.assistant.component.AddTaskAlertDialog
+import com.nextcloud.client.assistant.component.TaskTypesRow
+import com.nextcloud.client.assistant.component.TaskView
 import com.owncloud.android.R
 import com.owncloud.android.lib.resources.assistant.model.TaskType
 import com.owncloud.android.utils.DisplayUtils
@@ -59,12 +51,10 @@ import com.owncloud.android.utils.DisplayUtils
 @Composable
 fun AssistantScreen(viewModel: AssistantViewModel, floatingActionButton: FloatingActionButton) {
     // TODO hide sort group, floating action and search bar
+    val selectedTask by viewModel.selectedTask.collectAsState()
     val taskList by viewModel.taskList.collectAsState()
     val isTaskCreated by viewModel.isTaskCreated.collectAsState()
     val taskTypes by viewModel.taskTypes.collectAsState()
-    var selectedTaskType: String? by remember {
-        mutableStateOf(null)
-    }
     var showAddTaskAlertDialog by remember {
         mutableStateOf(false)
     }
@@ -81,15 +71,18 @@ fun AssistantScreen(viewModel: AssistantViewModel, floatingActionButton: Floatin
         stickyHeader {
             taskTypes?.let { taskTypes ->
                 taskTypes.resultData?.types.let {
-                    TaskTypesRow(selectedTaskType, data = it) { taskId ->
-                        selectedTaskType = taskId
+                    TaskTypesRow(selectedTask, data = it) { task->
+                        viewModel.selectTask(task)
                     }
                 }
             }
+
+            Spacer(modifier = Modifier.height(8.dp))
         }
 
         items(taskList?.resultData?.tasks ?: listOf()) {
-            Text(text = it.toString())
+            TaskView(task = it)
+            Spacer(modifier = Modifier.height(8.dp))
         }
     }
 
@@ -101,69 +94,10 @@ fun AssistantScreen(viewModel: AssistantViewModel, floatingActionButton: Floatin
     }
 
     if (showAddTaskAlertDialog) {
-        selectedTaskType?.let {
+        selectedTask?.let {
             AddTaskAlertDialog(viewModel, it) {
                 showAddTaskAlertDialog = false
             }
         }
     }
 }
-
-@Composable
-private fun AddTaskAlertDialog(viewModel: AssistantViewModel, type: String, dismiss: () -> Unit) {
-
-    var input by remember {
-        mutableStateOf("")
-    }
-
-    // TODO add to UI LIB
-    SimpleAlertDialog(
-        backgroundColor = Color.White,
-        textColor = Color.Black,
-        titleId = R.string.about_title,
-        description = stringResource(id = R.string.about_title),
-        dismiss = { dismiss() },
-        onComplete = { viewModel.createTask(input = input, type = type) },
-        content = {
-            TextField(
-                placeholder = {
-                    Text(
-                        text = stringResource(id = R.string.samples),
-                    )
-                },
-                keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text),
-                value = input,
-                onValueChange = {
-                    input = it
-                },
-                singleLine = true
-            )
-        }
-    )
-}
-
-@Composable
-private fun TaskTypesRow(selectedTaskType: String?, data: List<TaskType>?, selectTaskType: (String) -> Unit) {
-    Row(
-        modifier = Modifier
-            .fillMaxWidth()
-            .horizontalScroll(rememberScrollState())
-    ) {
-        data?.forEach {
-            FilledTonalButton(
-                onClick = { selectTaskType(it.id) },
-                colors = ButtonDefaults.buttonColors(
-                    containerColor = if (selectedTaskType == it.id) {
-                        Color.Unspecified
-                    } else {
-                        Color.Gray
-                    }
-                )
-            ) {
-                Text(text = it.name)
-            }
-
-            Spacer(modifier = Modifier.padding(end = 8.dp))
-        }
-    }
-}

+ 69 - 0
app/src/main/java/com/nextcloud/client/assistant/component/AddTaskAlertDialog.kt

@@ -0,0 +1,69 @@
+/*
+ * Nextcloud Android client application
+ *
+ * @author Alper Ozturk
+ * Copyright (C) 2024 Alper Ozturk
+ * Copyright (C) 2024 Nextcloud GmbH
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package com.nextcloud.client.assistant.component
+
+import androidx.compose.foundation.text.KeyboardOptions
+import androidx.compose.material3.Text
+import androidx.compose.material3.TextField
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.input.KeyboardType
+import com.nextcloud.client.assistant.AssistantViewModel
+import com.nextcloud.ui.composeComponents.SimpleAlertDialog
+import com.owncloud.android.R
+import com.owncloud.android.lib.resources.assistant.model.TaskType
+
+@Composable
+fun AddTaskAlertDialog(viewModel: AssistantViewModel, taskType: TaskType, dismiss: () -> Unit) {
+    var input by remember {
+        mutableStateOf("")
+    }
+
+    SimpleAlertDialog(
+        backgroundColor = Color.White,
+        textColor = Color.Black,
+        title = taskType.name,
+        description = taskType.description,
+        dismiss = { dismiss() },
+        onComplete = { viewModel.createTask(input = input, type = taskType.id) },
+        content = {
+            TextField(
+                placeholder = {
+                    Text(
+                        text = stringResource(id = R.string.assistant_screen_create_task_alert_dialog_input_field_placeholder),
+                    )
+                },
+                keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text),
+                value = input,
+                onValueChange = {
+                    input = it
+                },
+                singleLine = true
+            )
+        }
+    )
+}

+ 63 - 0
app/src/main/java/com/nextcloud/client/assistant/component/TaskTypesRow.kt

@@ -0,0 +1,63 @@
+/*
+ * Nextcloud Android client application
+ *
+ * @author Alper Ozturk
+ * Copyright (C) 2024 Alper Ozturk
+ * Copyright (C) 2024 Nextcloud GmbH
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package com.nextcloud.client.assistant.component
+
+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 androidx.compose.material3.Text
+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
+
+@Composable
+fun TaskTypesRow(selectedTaskType: TaskType?, data: List<TaskType>?, selectTaskType: (TaskType) -> Unit) {
+    Row(
+        modifier = Modifier
+            .fillMaxWidth()
+            .horizontalScroll(rememberScrollState())
+    ) {
+        data?.forEach {
+            FilledTonalButton(
+                onClick = { selectTaskType(it) },
+                colors = ButtonDefaults.buttonColors(
+                    containerColor = if (selectedTaskType?.id == it.id) {
+                        Color.Unspecified
+                    } else {
+                        Color.Gray
+                    }
+                )
+            ) {
+                Text(text = it.name)
+            }
+
+            Spacer(modifier = Modifier.padding(end = 8.dp))
+        }
+    }
+}

+ 82 - 0
app/src/main/java/com/nextcloud/client/assistant/component/TaskView.kt

@@ -0,0 +1,82 @@
+/*
+ * Nextcloud Android client application
+ *
+ * @author Alper Ozturk
+ * Copyright (C) 2024 Alper Ozturk
+ * Copyright (C) 2024 Nextcloud GmbH
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package com.nextcloud.client.assistant.component
+
+import android.annotation.SuppressLint
+import androidx.compose.foundation.background
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+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.res.stringResource
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.unit.dp
+import com.owncloud.android.R
+import com.owncloud.android.lib.resources.assistant.model.Task
+
+@SuppressLint("ResourceAsColor")
+@Composable
+fun TaskView(
+    task: Task,
+) {
+    var expanded by remember { mutableStateOf(false) }
+
+    // TODO Check color
+    Column(
+        modifier = Modifier
+            .fillMaxWidth()
+            .clip(RoundedCornerShape(16.dp))
+            .background(Color(R.color.primary))
+    ) {
+        Text(
+            text = if (expanded) task.output else task.output.take(100) + "...",
+            modifier = Modifier
+                .padding(16.dp)
+                .clickable { expanded = !expanded }
+        )
+
+        if (task.output.length >= 100) {
+            Text(
+                text = if (!expanded) {
+                    stringResource(id = R.string.assistant_screen_task_view_show_more)
+                } else {
+                    stringResource(id = R.string.assistant_screen_task_view_show_less)
+                },
+                textAlign = TextAlign.End,
+                modifier = Modifier
+                    .fillMaxWidth()
+                    .padding(16.dp)
+                    .clickable { expanded = true }
+            )
+        }
+    }
+}

+ 2 - 2
app/src/main/java/com/nextcloud/ui/composeComponents/SimpleAlertDialog.kt

@@ -40,7 +40,7 @@ import com.owncloud.android.R
 fun SimpleAlertDialog(
     backgroundColor: Color,
     textColor: Color,
-    titleId: Int,
+    title: String,
     description: String?,
     heightFraction: Float? = null,
     content: @Composable (() -> Unit)? = null,
@@ -59,7 +59,7 @@ fun SimpleAlertDialog(
         containerColor = backgroundColor,
         onDismissRequest = { dismiss() },
         title = {
-            Text(text = stringResource(id = titleId), color = textColor)
+            Text(text = title, color = textColor)
         },
         text = {
             Column(modifier = modifier) {

+ 5 - 0
app/src/main/res/values/strings.xml

@@ -18,6 +18,11 @@
     <string name="menu_item_sort_by_size_biggest_first">Biggest first</string>
     <string name="menu_item_sort_by_size_smallest_first">Smallest first</string>
 
+    <string name="assistant_screen_task_create_success_message">Task successfully created</string>
+    <string name="assistant_screen_create_task_alert_dialog_input_field_placeholder">Type some text</string>
+
+    <string name="assistant_screen_task_view_show_more">Show more</string>
+    <string name="assistant_screen_task_view_show_less">Show less</string>
 
     <string name="drawer_item_assistant">Assistant</string>
     <string name="drawer_item_all_files">All files</string>