Long press tag to edit

This commit is contained in:
MM20 2024-10-20 21:42:02 +02:00
parent 4f5e80dede
commit 52bba7f5f2
No known key found for this signature in database
GPG Key ID: 0B61A8F2DEAFA389
4 changed files with 244 additions and 136 deletions

View File

@ -2,9 +2,9 @@ package de.mm20.launcher2.ui.common
import androidx.compose.animation.AnimatedContent import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.EnterExitState import androidx.compose.animation.EnterExitState
import androidx.compose.animation.SharedTransitionLayout
import androidx.compose.animation.core.animateFloat import androidx.compose.animation.core.animateFloat
import androidx.compose.foundation.ScrollState import androidx.compose.foundation.ScrollState
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.horizontalScroll import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
@ -54,7 +54,6 @@ fun FavoritesTagSelector(
) { ) {
val sheetManager = LocalBottomSheetManager.current val sheetManager = LocalBottomSheetManager.current
AnimatedContent( AnimatedContent(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
@ -104,6 +103,9 @@ fun FavoritesTagSelector(
onSelectTag(tag.tag) onSelectTag(tag.tag)
} }
}, },
onLongClick = {
sheetManager.showEditTagSheet(tag.tag)
}
) )
} }
if (canScroll) { if (canScroll) {
@ -168,6 +170,9 @@ fun FavoritesTagSelector(
onSelectTag(tag.tag) onSelectTag(tag.tag)
} }
}, },
onLongClick = {
sheetManager.showEditTagSheet(tag.tag)
}
) )
} }
} }
@ -202,5 +207,5 @@ fun FavoritesTagSelector(
} }
} }
} }
} }

View File

@ -1,21 +1,36 @@
package de.mm20.launcher2.ui.common package de.mm20.launcher2.ui.common
import androidx.compose.animation.animateColor
import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.core.animateDp
import androidx.compose.animation.core.updateTransition
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Close import androidx.compose.material.icons.rounded.Close
import androidx.compose.material.icons.rounded.Tag import androidx.compose.material.icons.rounded.Tag
import androidx.compose.material3.FilterChip
import androidx.compose.material3.FilterChipDefaults import androidx.compose.material3.FilterChipDefaults
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SelectableChipColors import androidx.compose.material3.SelectableChipColors
import androidx.compose.material3.SelectableChipElevation import androidx.compose.material3.SelectableChipElevation
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.minimumInteractiveComponentSize
import androidx.compose.runtime.*
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import de.mm20.launcher2.search.data.Tag import de.mm20.launcher2.search.data.Tag
import de.mm20.launcher2.ui.ktx.splitLeadingEmoji import de.mm20.launcher2.ui.ktx.splitLeadingEmoji
@ -25,6 +40,7 @@ fun TagChip(
tag: Tag, tag: Tag,
selected: Boolean = false, selected: Boolean = false,
onClick: () -> Unit = {}, onClick: () -> Unit = {},
onLongClick: (() -> Unit)? = null,
clearable: Boolean = false, clearable: Boolean = false,
onClear: (() -> Unit)? = null, onClear: (() -> Unit)? = null,
colors: SelectableChipColors = FilterChipDefaults.filterChipColors(), colors: SelectableChipColors = FilterChipDefaults.filterChipColors(),
@ -34,7 +50,76 @@ fun TagChip(
tag.tag.splitLeadingEmoji() tag.tag.splitLeadingEmoji()
} }
FilterChip( val shape = MaterialTheme.shapes.small
val transition = updateTransition(selected)
val backgroundColor by transition.animateColor {
if (it) MaterialTheme.colorScheme.secondaryContainer else MaterialTheme.colorScheme.surfaceContainerLow
}
val borderColor by transition.animateColor {
if (it) MaterialTheme.colorScheme.secondaryContainer else MaterialTheme.colorScheme.outlineVariant
}
val borderWidth by transition.animateDp {
if (it) 0.dp else 1.dp
}
val textColor by transition.animateColor {
if (it) MaterialTheme.colorScheme.onSecondaryContainer else MaterialTheme.colorScheme.onSurfaceVariant
}
val iconColor by transition.animateColor {
if (it) MaterialTheme.colorScheme.onSecondaryContainer else MaterialTheme.colorScheme.primary
}
Row(
modifier = modifier
.minimumInteractiveComponentSize()
.height(32.dp)
.background(backgroundColor, shape)
.border(borderWidth, borderColor, shape)
.clip(shape)
.combinedClickable(
onClick = onClick,
onLongClick = onLongClick
)
.padding(horizontal = 8.dp),
verticalAlignment = Alignment.CenterVertically,
) {
if (emoji != null && tagName != null) {
Text(
emoji,
modifier = Modifier.width(FilterChipDefaults.IconSize),
textAlign = TextAlign.Center,
)
} else {
Icon(
modifier = Modifier
.size(FilterChipDefaults.IconSize),
imageVector = Icons.Rounded.Tag,
contentDescription = null,
tint = iconColor
)
}
Text(
tagName ?: emoji ?: "",
style = MaterialTheme.typography.labelLarge,
color = textColor,
modifier = Modifier.padding(horizontal = 8.dp)
)
if (clearable) {
Icon(
modifier = Modifier
.clickable {
onClear?.invoke()
}
.size(FilterChipDefaults.IconSize),
imageVector = Icons.Rounded.Close,
contentDescription = null,
)
}
}
/*FilterChip(
modifier = modifier, modifier = modifier,
selected = selected, selected = selected,
onClick = onClick, onClick = onClick,
@ -63,13 +148,15 @@ fun TagChip(
trailingIcon = if (clearable) { trailingIcon = if (clearable) {
{ {
Icon( Icon(
modifier = Modifier.clickable { modifier = Modifier
.clickable {
onClear?.invoke() onClear?.invoke()
}.size(FilterChipDefaults.IconSize), }
.size(FilterChipDefaults.IconSize),
imageVector = Icons.Rounded.Close, imageVector = Icons.Rounded.Close,
contentDescription = null, contentDescription = null,
) )
} }
} else null } else null
) )*/
} }

View File

@ -15,6 +15,7 @@ class LauncherBottomSheetManager(registryOwner: SavedStateRegistryOwner) :
val customizeSearchableSheetShown = mutableStateOf<SavableSearchable?>(null) val customizeSearchableSheetShown = mutableStateOf<SavableSearchable?>(null)
val editFavoritesSheetShown = mutableStateOf(false) val editFavoritesSheetShown = mutableStateOf(false)
val hiddenItemsSheetShown = mutableStateOf(false) val hiddenItemsSheetShown = mutableStateOf(false)
val editTagSheetShown = mutableStateOf<String?>(null)
init { init {
registryOwner.lifecycle.addObserver(LifecycleEventObserver { _, event -> registryOwner.lifecycle.addObserver(LifecycleEventObserver { _, event ->
@ -25,8 +26,9 @@ class LauncherBottomSheetManager(registryOwner: SavedStateRegistryOwner) :
val state = registry.consumeRestoredStateForKey(PROVIDER) val state = registry.consumeRestoredStateForKey(PROVIDER)
editFavoritesSheetShown.value = state?.getBoolean(FAVORITES) ?: false editFavoritesSheetShown.value = state?.getBoolean(FAVORITES) == true
hiddenItemsSheetShown.value = state?.getBoolean(HIDDEN) ?: false hiddenItemsSheetShown.value = state?.getBoolean(HIDDEN) == true
editTagSheetShown.value = state?.getString(TAG)
} }
}) })
} }
@ -35,6 +37,7 @@ class LauncherBottomSheetManager(registryOwner: SavedStateRegistryOwner) :
return bundleOf( return bundleOf(
FAVORITES to editFavoritesSheetShown.value, FAVORITES to editFavoritesSheetShown.value,
HIDDEN to hiddenItemsSheetShown.value, HIDDEN to hiddenItemsSheetShown.value,
TAG to editTagSheetShown.value,
) )
} }
@ -62,10 +65,19 @@ class LauncherBottomSheetManager(registryOwner: SavedStateRegistryOwner) :
hiddenItemsSheetShown.value = false hiddenItemsSheetShown.value = false
} }
fun showEditTagSheet(tagName: String) {
editTagSheetShown.value = tagName
}
fun dismissEditTagSheet() {
editTagSheetShown.value = null
}
companion object { companion object {
private const val PROVIDER = "bottom_sheet_manager" private const val PROVIDER = "bottom_sheet_manager"
private const val FAVORITES = "favorites" private const val FAVORITES = "favorites"
private const val HIDDEN = "hidden" private const val HIDDEN = "hidden"
private const val TAG = "tag"
private const val WIDGETS = "widgets" private const val WIDGETS = "widgets"
} }

View File

@ -1,6 +1,7 @@
package de.mm20.launcher2.ui.launcher.sheets package de.mm20.launcher2.ui.launcher.sheets
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import de.mm20.launcher2.ui.settings.tags.EditTagSheet
@Composable @Composable
fun LauncherBottomSheets() { fun LauncherBottomSheets() {
@ -13,4 +14,7 @@ fun LauncherBottomSheets() {
if (bottomSheetManager.editFavoritesSheetShown.value) { if (bottomSheetManager.editFavoritesSheetShown.value) {
EditFavoritesSheet(onDismiss = { bottomSheetManager.dismissEditFavoritesSheet() }) EditFavoritesSheet(onDismiss = { bottomSheetManager.dismissEditFavoritesSheet() })
} }
bottomSheetManager.editTagSheetShown.value?.let {
EditTagSheet(tag = it, onDismiss = { bottomSheetManager.dismissEditTagSheet() })
}
} }