Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
696 changes: 334 additions & 362 deletions app/src/main/java/com/anytypeio/anytype/ui/home/HomeScreen.kt

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -221,10 +221,8 @@ class HomeScreenFragment : Fragment(),
onCreateNewObjectLongClicked = throttledClick(
onClick = { vm.onCreateNewObjectLongClicked() }
),
onBundledWidgetClicked = vm::onBundledWidgetClicked,
onMove = vm::onMove,
onObjectCheckboxClicked = vm::onObjectCheckboxClicked,
onCreateDataViewObject = {_, _ -> },
onNavBarShareButtonClicked = vm::onNavBarShareIconClicked,
navPanelState = vm.navPanelState.collectAsStateWithLifecycle().value,
onHomeButtonClicked = vm::onHomeButtonClicked,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,41 +28,55 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.DpOffset
import androidx.compose.ui.unit.dp
import com.anytypeio.anytype.R
import com.anytypeio.anytype.core_models.ObjectType
import com.anytypeio.anytype.core_models.ObjectWrapper
import com.anytypeio.anytype.core_models.Relations
import com.anytypeio.anytype.core_ui.common.DefaultPreviews
import com.anytypeio.anytype.core_ui.views.BodyRegular
import com.anytypeio.anytype.presentation.objects.ObjectIcon
import com.anytypeio.anytype.presentation.widgets.DropDownMenuAction
import com.anytypeio.anytype.presentation.widgets.SectionType
import com.anytypeio.anytype.presentation.widgets.Widget
import com.anytypeio.anytype.presentation.widgets.WidgetId
import com.anytypeio.anytype.presentation.widgets.WidgetView

/**
* Represents a menu item that can be displayed in the widget long-click menu.
*/
sealed class WidgetMenuItem {
data class CreateObjectOfType(val widgetId: WidgetId) : WidgetMenuItem()
data object ChangeWidgetType : WidgetMenuItem()
data object RemoveWidget : WidgetMenuItem()
}

@Composable
fun WidgetLongClickMenu(
widgetView: WidgetView,
menuItems: List<WidgetMenuItem>,
isCardMenuExpanded: MutableState<Boolean>,
onDropDownMenuAction: (DropDownMenuAction) -> Unit
) {
when (widgetView.sectionType) {
SectionType.PINNED -> {
DropdownMenu(
modifier = Modifier.width(254.dp),
expanded = isCardMenuExpanded.value,
onDismissRequest = { isCardMenuExpanded.value = false },
containerColor = colorResource(R.color.background_secondary),
shape = RoundedCornerShape(12.dp),
tonalElevation = 8.dp,
offset = DpOffset(
x = 16.dp,
y = 8.dp
)
) {
if (widgetView.canCreateObjectOfType) {
if (menuItems.isEmpty()) {
// No menu to show, ensure it's closed
if (isCardMenuExpanded.value) {
isCardMenuExpanded.value = false
}
return
}

DropdownMenu(
modifier = Modifier.width(254.dp),
expanded = isCardMenuExpanded.value,
onDismissRequest = { isCardMenuExpanded.value = false },
containerColor = colorResource(R.color.background_secondary),
shape = RoundedCornerShape(12.dp),
tonalElevation = 8.dp,
offset = DpOffset(
x = 16.dp,
y = 8.dp
)
) {
menuItems.forEachIndexed { index, menuItem ->
when (menuItem) {
is WidgetMenuItem.CreateObjectOfType -> {
DropdownMenuItem(
onClick = {
onDropDownMenuAction(DropDownMenuAction.CreateObjectOfType(widgetView.id)).also {
onDropDownMenuAction(DropDownMenuAction.CreateObjectOfType(menuItem.widgetId)).also {
isCardMenuExpanded.value = false
}
},
Expand All @@ -88,12 +102,15 @@ fun WidgetLongClickMenu(
}
}
)
Divider(
thickness = 8.dp,
color = colorResource(id = R.color.shape_primary)
)
// Add thick divider after "Create Object" if not the last item
if (index < menuItems.lastIndex) {
Divider(
thickness = 8.dp,
color = colorResource(id = R.color.shape_primary)
)
}
}
if(widgetView.canChangeWidgetType()) {
is WidgetMenuItem.ChangeWidgetType -> {
DropdownMenuItem(
onClick = {
onDropDownMenuAction(DropDownMenuAction.ChangeWidgetType).also {
Expand Down Expand Up @@ -122,59 +139,25 @@ fun WidgetLongClickMenu(
}
}
)
// Add thin divider after "Change Type" if not the last item
if (index < menuItems.lastIndex) {
Divider(
thickness = 0.5.dp,
color = colorResource(id = R.color.shape_primary)
)
}
}
Divider(
thickness = 0.5.dp,
color = colorResource(id = R.color.shape_primary)
)
DropdownMenuItem(
onClick = {
onDropDownMenuAction(DropDownMenuAction.RemoveWidget).also {
isCardMenuExpanded.value = false
}
},
text = {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxWidth()
) {
Text(
modifier = Modifier.weight(1f),
style = BodyRegular,
color = colorResource(id = R.color.text_primary),
text = stringResource(R.string.widget_unpin)
)
Image(
painter = painterResource(id = R.drawable.ic_unpin_24),
contentDescription = "Unpin widget icon",
modifier = Modifier.size(24.dp),
colorFilter = ColorFilter.tint(
colorResource(id = R.color.text_primary)
)
)
}
is WidgetMenuItem.RemoveWidget -> {
// Add thin divider before "Remove/Unpin" if not the first item
if (index > 0) {
Divider(
thickness = 0.5.dp,
color = colorResource(id = R.color.shape_primary)
)
}
)
}
}

SectionType.TYPES -> {
if (widgetView.canCreateObjectOfType) {
DropdownMenu(
modifier = Modifier.width(254.dp),
expanded = isCardMenuExpanded.value,
onDismissRequest = { isCardMenuExpanded.value = false },
containerColor = colorResource(R.color.background_secondary),
shape = RoundedCornerShape(12.dp),
tonalElevation = 8.dp,
offset = DpOffset(
x = 16.dp,
y = 8.dp
)
) {
DropdownMenuItem(
onClick = {
onDropDownMenuAction(DropDownMenuAction.CreateObjectOfType(widgetView.id)).also {
onDropDownMenuAction(DropDownMenuAction.RemoveWidget).also {
isCardMenuExpanded.value = false
}
},
Expand All @@ -183,15 +166,15 @@ fun WidgetLongClickMenu(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxWidth()
) {
androidx.compose.material.Text(
Text(
modifier = Modifier.weight(1f),
style = BodyRegular,
color = colorResource(id = R.color.text_primary),
text = stringResource(R.string.widgets_menu_new_object_type)
text = stringResource(R.string.widget_unpin)
)
Image(
painter = painterResource(id = R.drawable.ic_menu_item_create),
contentDescription = "New object icon",
painter = painterResource(id = R.drawable.ic_unpin_24),
contentDescription = "Unpin widget icon",
modifier = Modifier.size(24.dp),
colorFilter = ColorFilter.tint(
colorResource(id = R.color.text_primary)
Expand All @@ -201,14 +184,8 @@ fun WidgetLongClickMenu(
}
)
}
} else {
isCardMenuExpanded.value = false
}
}

null -> {
//do nothing
}
}
}

Expand Down Expand Up @@ -238,6 +215,41 @@ private fun WidgetView.canChangeWidgetType(): Boolean {
}
}

/**
* Determines which menu items should be shown for this widget.
* Returns a list of menu items, or an empty list if no menu should be displayed.
*/
fun WidgetView.getWidgetMenuItems(): List<WidgetMenuItem> {
return when (sectionType) {
SectionType.PINNED -> {
buildList {
// Add "Create Object of Type" if applicable
if (canCreateObjectOfType) {
add(WidgetMenuItem.CreateObjectOfType(id))
}
// Add "Change Widget Type" if applicable
if (canChangeWidgetType()) {
add(WidgetMenuItem.ChangeWidgetType)
}
// Always add "Unpin" for pinned widgets
add(WidgetMenuItem.RemoveWidget)
}
}
SectionType.TYPES -> {
// TYPES widgets only show menu if they can create objects
if (canCreateObjectOfType) {
listOf(WidgetMenuItem.CreateObjectOfType(id))
} else {
emptyList()
}
}
null -> {
// No section type means no menu
emptyList()
}
}
}

@Composable
fun BinWidgetMenu(
widgetView: WidgetView,
Expand Down Expand Up @@ -300,28 +312,9 @@ fun WidgetLongClickMenuPreview_PinnedSection_WithCreateOption() {
.background(Color.Gray.copy(alpha = 0.1f))
) {
WidgetLongClickMenu(
widgetView = WidgetView.SetOfObjects(
id = "widget-1",
icon = ObjectIcon.None,
source = Widget.Source.Default(
obj = ObjectWrapper.Basic(
mapOf(
Relations.ID to "obj-1",
Relations.UNIQUE_KEY to "Obj 1",
Relations.LAYOUT to ObjectType.Layout.OBJECT_TYPE.code.toDouble(),
Relations.RECOMMENDED_LAYOUT to ObjectType.Layout.BASIC.code.toDouble()
)
)
),
elements = emptyList(),
isExpanded = true,
isCompact = false,
sectionType = SectionType.PINNED,
tabs = emptyList(),
name = WidgetView.Name.Default("My Widget")
),
isCardMenuExpanded = isExpanded,
onDropDownMenuAction = { /* Preview action */ }
onDropDownMenuAction = { /* Preview action */ },
menuItems = emptyList()
)
}
}
Original file line number Diff line number Diff line change
@@ -1,83 +1,41 @@
package com.anytypeio.anytype.ui.widgets.types

import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.Box
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.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
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.alpha
import androidx.compose.ui.draw.clip
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import com.anytypeio.anytype.R
import com.anytypeio.anytype.core_ui.views.HeadlineSubheading
import com.anytypeio.anytype.presentation.home.InteractionMode
import com.anytypeio.anytype.presentation.widgets.DropDownMenuAction
import com.anytypeio.anytype.presentation.widgets.WidgetView
import com.anytypeio.anytype.ui.widgets.menu.WidgetLongClickMenu
import com.anytypeio.anytype.ui.widgets.menu.WidgetMenuItem

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun AllContentWidgetCard(
modifier: Modifier = Modifier,
index: Int,
widgetView: WidgetView,
mode: InteractionMode,
onWidgetClicked: () -> Unit = {},
onDropDownMenuAction: (DropDownMenuAction) -> Unit = {},
alpha: Float,
onDropDownMenuAction: (DropDownMenuAction) -> Unit,
menuItems: List<WidgetMenuItem> = emptyList(),
isCardMenuExpanded: MutableState<Boolean> = mutableStateOf(false),
modifier: Modifier = Modifier
) {
val haptic = LocalHapticFeedback.current
val isCardMenuExpanded = remember {
mutableStateOf(false)
}
Box(
modifier = modifier
.fillMaxWidth()
.padding(top = if (index == 0) 6.dp else 0.dp)
.alpha(alpha)
) {
Box(modifier = modifier) {
Box(
modifier = Modifier
.padding(start = 20.dp, end = 20.dp, top = 6.dp, bottom = 6.dp)
.fillMaxWidth()
.height(52.dp)
.background(
shape = RoundedCornerShape(16.dp),
color = colorResource(id = R.color.dashboard_card_background)
)
.clip(RoundedCornerShape(16.dp))
.then(
if (mode !is InteractionMode.Edit) {
Modifier.combinedClickable(
onClick = {
onWidgetClicked()
},
onLongClick = {
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
isCardMenuExpanded.value = true
}
)
} else {
Modifier
}
)
.alpha(alpha)
) {
Image(
painter = painterResource(id = R.drawable.ic_widget_all_content),
Expand All @@ -99,7 +57,7 @@ fun AllContentWidgetCard(
)
}
WidgetLongClickMenu(
widgetView = widgetView,
menuItems = menuItems,
isCardMenuExpanded = isCardMenuExpanded,
onDropDownMenuAction = onDropDownMenuAction
)
Expand Down
Loading