Signed-off-by: alperozturk <alper_ozturk@proton.me>
This commit is contained in:
alperozturk 2024-02-28 16:05:45 +01:00 committed by Alper Öztürk
parent ca52db7437
commit f55017f077
8 changed files with 278 additions and 82 deletions

View File

@ -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>

View File

@ -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()
}
}
}

View File

@ -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))
}
}
}

View File

@ -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
)
}
)
}

View File

@ -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))
}
}
}

View File

@ -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 }
)
}
}
}

View File

@ -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) {

View File

@ -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>