From 790d22fda2cf693e99cd81c2dd2720ade0476350 Mon Sep 17 00:00:00 2001 From: Evgenii Kozlov Date: Wed, 8 Feb 2023 14:08:10 +0100 Subject: [PATCH] DROID-952 Widgets | Enhancement | Basic dropdown menu for widgets (#2905) --- .../anytypeio/anytype/ui/home/HomeScreen.kt | 281 +++++++++++------- .../anytype/ui/home/HomeScreenFragment.kt | 8 +- app/src/main/res/values/strings.xml | 3 + 3 files changed, 187 insertions(+), 105 deletions(-) diff --git a/app/src/main/java/com/anytypeio/anytype/ui/home/HomeScreen.kt b/app/src/main/java/com/anytypeio/anytype/ui/home/HomeScreen.kt index 67dc744afc..ee7404e3db 100644 --- a/app/src/main/java/com/anytypeio/anytype/ui/home/HomeScreen.kt +++ b/app/src/main/java/com/anytypeio/anytype/ui/home/HomeScreen.kt @@ -1,7 +1,8 @@ package com.anytypeio.anytype.ui.home -import androidx.compose.foundation.Canvas +import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.clickable +import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -10,7 +11,6 @@ import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height 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 @@ -18,13 +18,17 @@ import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.Button import androidx.compose.material.ButtonDefaults import androidx.compose.material.Card +import androidx.compose.material.Divider +import androidx.compose.material.DropdownMenu +import androidx.compose.material.DropdownMenuItem import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.rotate -import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp @@ -32,8 +36,8 @@ import com.anytypeio.anytype.R import com.anytypeio.anytype.core_models.Id import com.anytypeio.anytype.presentation.widgets.TreePath import com.anytypeio.anytype.presentation.widgets.WidgetView -import timber.log.Timber +@OptIn(ExperimentalFoundationApi::class) @Composable fun HomeScreen( widgets: List, @@ -41,7 +45,9 @@ fun HomeScreen( onCreateWidget: () -> Unit, onEditWidgets: () -> Unit, onRefresh: () -> Unit, - onDeleteWidget: (Id) -> Unit + onDeleteWidget: (Id) -> Unit, + onChangeWidgetSource: (Id) -> Unit, + onChangeWidgetType: (Id) -> Unit ) { LazyColumn( modifier = Modifier @@ -49,90 +55,22 @@ fun HomeScreen( .fillMaxWidth() .padding(top = 12.dp) ) { - Timber.d("Widgets:\n$widgets") items( items = widgets, itemContent = { item -> when (item) { is WidgetView.Tree -> { - Card( - modifier = Modifier - .fillMaxWidth() - .padding(start = 20.dp, end = 20.dp, top = 6.dp, bottom = 6.dp), - shape = RoundedCornerShape(16.dp) - ) { - Circle { - onDeleteWidget(item.id) - } - Column(Modifier.padding(16.dp)) { - TreeWidgetHeader(item) - item.elements.forEach { element -> - Row( - modifier = Modifier - .padding(vertical = 8.dp) - .clickable { - onExpand(element.path) - } - ) { - if (element.indent > 0) { - Spacer(Modifier.width(20.dp.times(element.indent))) - } - Box( - Modifier - .width(20.dp) - .height(20.dp) - ) { - when (val icon = element.icon) { - is WidgetView.Tree.Icon.Branch -> { - Text( - text = ">", - modifier = Modifier - .align(Alignment.Center) - .rotate(if (icon.isExpanded) 90f else 0f) - ) - } - is WidgetView.Tree.Icon.Leaf -> { - Text( - text = "•", - modifier = Modifier.align(Alignment.Center) - ) - } - is WidgetView.Tree.Icon.Set -> { - Text( - text = "#", - modifier = Modifier.align(Alignment.Center) - ) - } - } - } - Text( - text = element.obj.name?.trim() ?: "Untitled" - ) - } - } - } - } + TreeWidgetCard( + item = item, + onExpand = onExpand, + onChangeWidgetSource = onChangeWidgetSource, + onChangeWidgetType = onChangeWidgetType, + onDeleteWidget = onDeleteWidget + ) } is WidgetView.Link -> { - Card( - modifier = Modifier - .fillMaxWidth() - .height(52.dp) - .padding(start = 20.dp, end = 20.dp, top = 6.dp, bottom = 6.dp), - shape = RoundedCornerShape(16.dp) - ) { - Box(Modifier.fillMaxHeight()) { - Text( - text = item.obj.name.orEmpty().trim(), - style = MaterialTheme.typography.h6, - modifier = Modifier - .align(Alignment.CenterStart) - .padding(start = 16.dp) - ) - } - } - Circle { - onDeleteWidget(item.id) - } + LinkWidgetCard( + item = item + ) } is WidgetView.Action.CreateWidget -> { Box(Modifier.fillMaxWidth()) { @@ -167,6 +105,162 @@ fun HomeScreen( } } +@Composable +private fun LinkWidgetCard(item: WidgetView.Link) { + Card( + modifier = Modifier + .fillMaxWidth() + .height(52.dp) + .padding(start = 20.dp, end = 20.dp, top = 6.dp, bottom = 6.dp), + shape = RoundedCornerShape(16.dp) + ) { + Box(Modifier.fillMaxHeight()) { + Text( + text = item.obj.name.orEmpty().trim(), + style = MaterialTheme.typography.h6, + modifier = Modifier + .align(Alignment.CenterStart) + .padding(start = 16.dp) + ) + } + } +} + +@Composable +@OptIn(ExperimentalFoundationApi::class) +private fun TreeWidgetCard( + item: WidgetView.Tree, + onExpand: (TreePath) -> Unit, + onChangeWidgetSource: (Id) -> Unit, + onChangeWidgetType: (Id) -> Unit, + onDeleteWidget: (Id) -> Unit +) { + val isDropDownMenuExpanded = remember { + mutableStateOf(false) + } + Card( + modifier = Modifier + .fillMaxWidth() + .padding(start = 20.dp, end = 20.dp, top = 6.dp, bottom = 6.dp), + shape = RoundedCornerShape(16.dp) + ) { + Column( + Modifier + .padding(16.dp) + .combinedClickable( + onClick = {}, + onLongClick = { + isDropDownMenuExpanded.value = + !isDropDownMenuExpanded.value + } + ) + ) { + TreeWidgetHeader(item) + item.elements.forEach { element -> + Row( + modifier = Modifier + .padding(vertical = 8.dp) + .clickable { + onExpand(element.path) + } + ) { + if (element.indent > 0) { + Spacer(Modifier.width(20.dp.times(element.indent))) + } + Box( + Modifier + .width(20.dp) + .height(20.dp) + ) { + when (val icon = element.icon) { + is WidgetView.Tree.Icon.Branch -> { + Text( + // TODO replace with drawable + text = ">", + modifier = Modifier + .align(Alignment.Center) + .rotate(if (icon.isExpanded) 90f else 0f) + ) + } + is WidgetView.Tree.Icon.Leaf -> { + Text( + // TODO replace with drawable + text = "•", + modifier = Modifier.align(Alignment.Center) + ) + } + is WidgetView.Tree.Icon.Set -> { + Text( + // TODO replace with drawable + text = "#", + modifier = Modifier.align(Alignment.Center) + ) + } + } + } + Text( + text = element.obj.name?.trim() ?: "Untitled" + ) + } + Divider( + thickness = 0.5.dp, + modifier = Modifier.padding(horizontal = 8.dp) + ) + } + } + WidgetMenu( + expanded = isDropDownMenuExpanded.value, + onDismiss = { + isDropDownMenuExpanded.value = false + }, + onChangeSourceClicked = { + isDropDownMenuExpanded.value = false + onChangeWidgetSource(item.id) + }, + onChangeTypeClicked = { + isDropDownMenuExpanded.value = false + onChangeWidgetType(item.id) + }, + onRemoveWidgetClicked = { + isDropDownMenuExpanded.value = false + onDeleteWidget(item.id) + } + ) + } +} + +@Composable +private fun WidgetMenu( + expanded: Boolean, + onDismiss: () -> Unit, + onChangeTypeClicked: () -> Unit, + onRemoveWidgetClicked: () -> Unit, + onChangeSourceClicked: () -> Unit +) { + DropdownMenu( + expanded = expanded, + onDismissRequest = onDismiss + ) { + DropdownMenuItem( + onClick = onChangeSourceClicked + ) { + Text(stringResource(R.string.widget_change_source)) + } + Divider(thickness = 0.5.dp) + DropdownMenuItem( + onClick = onChangeTypeClicked + ) { + Text(stringResource(R.string.widget_change_type)) + } + Divider(thickness = 0.5.dp) + DropdownMenuItem( + onClick = onRemoveWidgetClicked + ) { + Text(stringResource(id = R.string.remove_widget)) + } + } +} + @Composable private fun TreeWidgetHeader(item: WidgetView.Tree) { Row() { @@ -204,24 +298,3 @@ fun WidgetActionButton( Text(text = label) } } - -@Composable -fun Circle( - onClick: () -> Unit -) { - Box( - Modifier - .height(24.dp) - .width(24.dp)) { - Canvas( - modifier = Modifier - .size(24.dp) - .align(Alignment.CenterEnd) - .padding(4.dp) - .clickable { onClick() }, - onDraw = { - drawCircle(color = Color.Red) - } - ) - } -} diff --git a/app/src/main/java/com/anytypeio/anytype/ui/home/HomeScreenFragment.kt b/app/src/main/java/com/anytypeio/anytype/ui/home/HomeScreenFragment.kt index 0b9ea7cc74..e769f19cce 100644 --- a/app/src/main/java/com/anytypeio/anytype/ui/home/HomeScreenFragment.kt +++ b/app/src/main/java/com/anytypeio/anytype/ui/home/HomeScreenFragment.kt @@ -38,7 +38,13 @@ class HomeScreenFragment : BaseComposeFragment() { }, onDeleteWidget = vm::onDeleteWidgetClicked, onEditWidgets = { context.toast("Coming soon") }, - onRefresh = vm::onRefresh + onRefresh = vm::onRefresh, + onChangeWidgetSource = { + toast("TODO") + }, + onChangeWidgetType = { + toast("TODO") + } ) } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b8bfa28d62..fb257b6560 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -323,5 +323,8 @@ Do the computation of an expensive paragraph of text on a background thread: Compact version of the object Widget with list view of set object List + Change source + Change widget type + Remove widget