From b48ddf5d448f65c59f79eb9c7af9e9fcba431059 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 28 Feb 2024 16:34:22 +0100 Subject: [PATCH] Add loading and empty states Signed-off-by: alperozturk --- .../client/assistant/AssistantViewModel.kt | 10 ++- .../client/assistant/AsssistantScreen.kt | 72 +++++++++++++------ .../client/assistant/component/CenterText.kt | 44 ++++++++++++ .../client/assistant/component/TaskView.kt | 31 +++++++- .../android/ui/activity/DrawerActivity.java | 2 + app/src/main/res/values/strings.xml | 5 ++ 6 files changed, 139 insertions(+), 25 deletions(-) create mode 100644 app/src/main/java/com/nextcloud/client/assistant/component/CenterText.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 ac96ad264a..2c2909dc95 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/AssistantViewModel.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/AssistantViewModel.kt @@ -21,12 +21,13 @@ package com.nextcloud.client.assistant +import androidx.compose.ui.res.stringResource import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.nextcloud.client.assistant.repository.AssistantRepository import com.nextcloud.common.NextcloudClient +import com.owncloud.android.R 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 @@ -49,6 +50,9 @@ class AssistantViewModel(client: NextcloudClient) : ViewModel() { private val _taskList = MutableStateFlow?>(null) val taskList: StateFlow?> = _taskList + private val _loading = MutableStateFlow(true) + val loading: StateFlow = _loading + private val _isTaskCreated = MutableStateFlow(false) val isTaskCreated: StateFlow = _isTaskCreated @@ -97,6 +101,10 @@ class AssistantViewModel(client: NextcloudClient) : ViewModel() { _taskList.update { result } + + _loading.update { + false + } } } 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 7c29ca7f43..edb251bea6 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/AsssistantScreen.kt @@ -23,34 +23,43 @@ 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.Spacer import androidx.compose.foundation.layout.fillMaxSize 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.material3.Text 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.setValue +import androidx.compose.ui.Alignment 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.style.TextAlign import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp import com.google.android.material.floatingactionbutton.FloatingActionButton import com.nextcloud.client.assistant.component.AddTaskAlertDialog +import com.nextcloud.client.assistant.component.CenterText 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.Task import com.owncloud.android.lib.resources.assistant.model.TaskType import com.owncloud.android.utils.DisplayUtils -@OptIn(ExperimentalFoundationApi::class) @Composable fun AssistantScreen(viewModel: AssistantViewModel, floatingActionButton: FloatingActionButton) { - // TODO hide sort group, floating action and search bar + // TODO hide sort group, search bar + // TODO top bar, back button causes crash + val loading by viewModel.loading.collectAsState() val selectedTask by viewModel.selectedTask.collectAsState() val taskList by viewModel.taskList.collectAsState() val isTaskCreated by viewModel.isTaskCreated.collectAsState() @@ -63,27 +72,12 @@ fun AssistantScreen(viewModel: AssistantViewModel, floatingActionButton: Floatin showAddTaskAlertDialog = true } - LazyColumn( - modifier = Modifier - .fillMaxSize() - .padding(16.dp) - ) { - stickyHeader { - taskTypes?.let { taskTypes -> - taskTypes.resultData?.types.let { - TaskTypesRow(selectedTask, data = it) { task-> - viewModel.selectTask(task) - } - } - } - - Spacer(modifier = Modifier.height(8.dp)) - } - - items(taskList?.resultData?.tasks ?: listOf()) { - TaskView(task = it) - Spacer(modifier = Modifier.height(8.dp)) - } + if (loading) { + CenterText(text = stringResource(id = R.string.assistant_screen_loading)) + } else { + val tasks = taskList?.resultData?.tasks ?: return + val types = taskTypes?.resultData?.types ?: return + AssistantContent(tasks, types, selectedTask, viewModel) } if (isTaskCreated) { @@ -101,3 +95,35 @@ fun AssistantScreen(viewModel: AssistantViewModel, floatingActionButton: Floatin } } } + +@OptIn(ExperimentalFoundationApi::class) +@Composable +private fun AssistantContent( + taskList: List, + taskTypes: List, + selectedTask: TaskType?, + viewModel: AssistantViewModel +) { + LazyColumn( + modifier = Modifier + .fillMaxSize() + .padding(16.dp) + ) { + stickyHeader { + TaskTypesRow(selectedTask, data = taskTypes) { task -> + viewModel.selectTask(task) + } + + Spacer(modifier = Modifier.height(8.dp)) + } + + items(taskList) { + if (taskList.isEmpty()) { + CenterText(text = stringResource(id = R.string.assistant_screen_no_task_available_text)) + } else { + TaskView(task = it) + Spacer(modifier = Modifier.height(8.dp)) + } + } + } +} 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 new file mode 100644 index 0000000000..20c56d17e4 --- /dev/null +++ b/app/src/main/java/com/nextcloud/client/assistant/component/CenterText.kt @@ -0,0 +1,44 @@ +/* + * 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 . + */ + +package com.nextcloud.client.assistant.component + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +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.text.style.TextAlign +import androidx.compose.ui.unit.sp + +@Composable +fun CenterText(text: String) { + Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { + Text( + text = text, + fontSize = 18.sp, + color = Color.Black, + textAlign = TextAlign.Center + ) + } +} diff --git a/app/src/main/java/com/nextcloud/client/assistant/component/TaskView.kt b/app/src/main/java/com/nextcloud/client/assistant/component/TaskView.kt index dbc9b43450..dd300be986 100644 --- a/app/src/main/java/com/nextcloud/client/assistant/component/TaskView.kt +++ b/app/src/main/java/com/nextcloud/client/assistant/component/TaskView.kt @@ -22,10 +22,13 @@ package com.nextcloud.client.assistant.component import android.annotation.SuppressLint +import android.widget.Space import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column +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.shape.RoundedCornerShape import androidx.compose.material3.Text @@ -57,10 +60,35 @@ fun TaskView( .clip(RoundedCornerShape(16.dp)) .background(Color(R.color.primary)) ) { + Spacer(modifier = Modifier.height(8.dp)) + + Text( + text = stringResource(id = R.string.assistant_screen_task_view_input), + modifier = Modifier.padding(4.dp), + color = Color.White + ) + + Text( + text = task.input, + modifier = Modifier.padding(4.dp), + color = Color.White + ) + + Spacer(modifier = Modifier.height(16.dp)) + + Text( + text = stringResource(id = R.string.assistant_screen_task_view_output), + color = Color.White, + modifier = Modifier + .padding(4.dp) + .clickable { expanded = !expanded } + ) + Text( text = if (expanded) task.output else task.output.take(100) + "...", + color = Color.White, modifier = Modifier - .padding(16.dp) + .padding(4.dp) .clickable { expanded = !expanded } ) @@ -72,6 +100,7 @@ fun TaskView( stringResource(id = R.string.assistant_screen_task_view_show_less) }, textAlign = TextAlign.End, + color = Color.White, modifier = Modifier .fillMaxWidth() .padding(16.dp) diff --git a/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java b/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java index 307e7acc31..dee3775740 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java +++ b/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java @@ -546,6 +546,8 @@ public abstract class DrawerActivity extends ToolbarActivity startActivity(intent); } else if (itemId == R.id.nav_assistant) { // FIXME Back navigation is broken, create general function to switch to Jetpack Compose + + showSortListGroup(false); ComposeFragment composeFragment = new ComposeFragment(); Bundle bundle = new Bundle(); bundle.putSerializable(ComposeFragment.destinationKey, ComposeDestinations.AssistantScreen); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2f624a72d1..8121888306 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -18,9 +18,14 @@ Biggest first Smallest first + Task List are loading, please wait + No task available, you can create a new task from bottom right. + Task successfully created Type some text + Input: + Output: Show more Show less