Add UI Components

Signed-off-by: alperozturk <alper_ozturk@proton.me>
This commit is contained in:
alperozturk 2024-02-27 16:44:17 +01:00 committed by Alper Öztürk
parent b7b5907f98
commit 6767ab8636
6 changed files with 249 additions and 29 deletions

View file

@ -36,7 +36,7 @@ import kotlinx.coroutines.launch
class AssistantViewModel(context: Context, user: User) : ViewModel() { class AssistantViewModel(context: Context, user: User) : ViewModel() {
private val repository = AssistantRepository(user, context) private var repository: AssistantRepository? = null
private val _taskTypes = MutableStateFlow<TaskTypes?>(null) private val _taskTypes = MutableStateFlow<TaskTypes?>(null)
val taskTypes: StateFlow<TaskTypes?> = _taskTypes val taskTypes: StateFlow<TaskTypes?> = _taskTypes
@ -46,22 +46,24 @@ class AssistantViewModel(context: Context, user: User) : ViewModel() {
init { init {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
repository = AssistantRepository(user, context)
_taskTypes.update { _taskTypes.update {
repository.getTaskTypes() repository?.getTaskTypes()
} }
} }
} }
fun deleteTask(id: String) { fun deleteTask(id: String) {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
repository.deleteTask(id) repository?.deleteTask(id)
} }
} }
fun getTask(id: String) { fun getTask(id: String) {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
_task.update { _task.update {
repository.getTask(id) repository?.getTask(id)
} }
} }
} }
@ -69,11 +71,9 @@ class AssistantViewModel(context: Context, user: User) : ViewModel() {
fun createTask( fun createTask(
input: String, input: String,
type: String, type: String,
appId: String,
identifier: String,
) { ) {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
repository.createTask(input, type, appId, identifier) repository?.createTask(input, type, identifier = " ")
} }
} }
} }

View file

@ -22,29 +22,136 @@
package com.nextcloud.client.assistant package com.nextcloud.client.assistant
import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.layout.Box 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.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.rememberScrollState
import androidx.compose.material3.Scaffold import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.ButtonColors
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.FilledTonalButton
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.material3.TextFieldDefaults
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue 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.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.nextcloud.android.common.ui.theme.utils.ColorRole
import com.nextcloud.operations.assistant.model.OcsType
import com.nextcloud.ui.composeComponents.SimpleAlertDialog
import com.owncloud.android.R
@OptIn(ExperimentalFoundationApi::class) @OptIn(ExperimentalFoundationApi::class)
@Composable @Composable
fun AssistantScreen(viewModel: AssistantViewModel) { fun AssistantScreen(viewModel: AssistantViewModel, floatingActionButton: FloatingActionButton) {
// TODO hide sort group, floating action and search bar
val taskTypes by viewModel.taskTypes.collectAsState() val taskTypes by viewModel.taskTypes.collectAsState()
var selectedTaskType: String? by remember {
mutableStateOf(null)
}
var showAddTaskAlertDialog by remember {
mutableStateOf(false)
}
floatingActionButton.setOnClickListener {
showAddTaskAlertDialog = true
}
LazyColumn(
modifier = Modifier
.fillMaxSize()
.padding(16.dp)
) {
stickyHeader {
taskTypes?.let { it ->
TaskTypesRow(selectedTaskType, data = it.ocs.data.types) { taskId ->
selectedTaskType = taskId
}
}
}
LazyColumn(modifier = Modifier.fillMaxSize().padding(16.dp)) {
items(taskTypes?.ocs?.data?.types ?: listOf()) { items(taskTypes?.ocs?.data?.types ?: listOf()) {
Text(text = it.toString()) Text(text = it.toString())
} }
} }
} if (showAddTaskAlertDialog) {
selectedTaskType?.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<OcsType>, 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,97 @@
/*
* 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.ui.composeComponents
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.owncloud.android.R
@Composable
fun SimpleAlertDialog(
backgroundColor: Color,
textColor: Color,
titleId: Int,
description: String?,
heightFraction: Float? = null,
content: @Composable (() -> Unit)? = null,
onComplete: () -> Unit,
dismiss: () -> Unit
) {
val modifier = if (heightFraction != null) {
Modifier
.fillMaxWidth()
.fillMaxHeight(heightFraction)
} else {
Modifier.fillMaxWidth()
}
AlertDialog(
containerColor = backgroundColor,
onDismissRequest = { dismiss() },
title = {
Text(text = stringResource(id = titleId), color = textColor)
},
text = {
Column(modifier = modifier) {
if (description != null) {
Text(text = description, color = textColor)
}
content?.let {
Spacer(modifier = Modifier.height(16.dp))
content()
}
}
},
confirmButton = {
TextButton(onClick = {
onComplete()
dismiss()
}) {
Text(
stringResource(id = R.string.common_ok),
color = textColor
)
}
},
dismissButton = {
TextButton(onClick = { dismiss() }) {
Text(
stringResource(id = R.string.common_cancel),
color = textColor
)
}
}
)
}

View file

@ -25,13 +25,18 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.ViewCompositionStrategy import androidx.compose.ui.platform.ViewCompositionStrategy
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.nextcloud.client.assistant.AssistantScreen import com.nextcloud.client.assistant.AssistantScreen
import com.nextcloud.client.assistant.AssistantViewModel import com.nextcloud.client.assistant.AssistantViewModel
import com.nextcloud.utils.extensions.getSerializableArgument import com.nextcloud.utils.extensions.getSerializableArgument
import com.owncloud.android.R
import com.owncloud.android.databinding.FragmentComposeViewBinding import com.owncloud.android.databinding.FragmentComposeViewBinding
import com.owncloud.android.ui.fragment.FileFragment import com.owncloud.android.ui.fragment.FileFragment
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
class ComposeFragment : FileFragment() { class ComposeFragment : FileFragment() {
@ -54,26 +59,34 @@ class ComposeFragment : FileFragment() {
binding.composeView.apply { binding.composeView.apply {
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
setContent {
when (destination) {
ComposeDestinations.AssistantScreen -> {
AssistantScreen(
viewModel = AssistantViewModel(
context = requireContext(),
user = containerActivity.storageManager.user
)
)
}
else -> { setContent {
} Content(destination)
}
} }
} }
return binding.root return binding.root
} }
@Composable
private fun Content(destination: ComposeDestinations?) {
val floatingActionButton: FloatingActionButton = requireActivity().findViewById(R.id.fab_main)
return when (destination) {
ComposeDestinations.AssistantScreen -> {
AssistantScreen(
viewModel = AssistantViewModel(
context = requireContext(),
user = containerActivity.storageManager.user
),
floatingActionButton
)
}
else -> {
}
}
}
override fun onDestroyView() { override fun onDestroyView() {
super.onDestroyView() super.onDestroyView()
_binding = null _binding = null

View file

@ -555,9 +555,6 @@ public abstract class DrawerActivity extends ToolbarActivity
.beginTransaction() .beginTransaction()
.replace(R.id.left_fragment_container, composeFragment) .replace(R.id.left_fragment_container, composeFragment)
.commit(); .commit();
Log_OC.w(TAG, "ADD JETPACK Compose PAGE");
} else { } else {
if (menuItem.getItemId() >= MENU_ITEM_EXTERNAL_LINK && if (menuItem.getItemId() >= MENU_ITEM_EXTERNAL_LINK &&
menuItem.getItemId() <= MENU_ITEM_EXTERNAL_LINK + 100) { menuItem.getItemId() <= MENU_ITEM_EXTERNAL_LINK + 100) {

View file

@ -14,3 +14,9 @@ include ':appscan'
// substitute module('com.github.nextcloud:android-library') using project(':library') // substitute module('com.github.nextcloud:android-library') using project(':library')
// } // }
//} //}
includeBuild('/Users/alperozturk/Desktop/nextcloud/nextcloud_android_library') {
dependencySubstitution {
substitute module('com.github.nextcloud:android-library') using project(':library')
}
}