From 291f716b97a7e6f1ef2e9ffaaafca31133cd694a Mon Sep 17 00:00:00 2001 From: MrSluffy Date: Sat, 27 Jul 2024 20:13:52 +0800 Subject: [PATCH] Initial implementation Drag pref group --- .../overview/LawnchairOverviewActionsView.kt | 20 +-- .../preferences/PreferenceManager.kt | 2 + .../layout/DraggablePreferenceGroup.kt | 116 ++++++++++++++++++ .../ExperimentalFeaturesPreferences.kt | 5 - .../destinations/QuickstepPreferences.kt | 76 ++++++++---- 5 files changed, 185 insertions(+), 34 deletions(-) create mode 100644 lawnchair/src/app/lawnchair/ui/preferences/components/layout/DraggablePreferenceGroup.kt diff --git a/lawnchair/src/app/lawnchair/overview/LawnchairOverviewActionsView.kt b/lawnchair/src/app/lawnchair/overview/LawnchairOverviewActionsView.kt index bb9281fdef..1b9757ec47 100644 --- a/lawnchair/src/app/lawnchair/overview/LawnchairOverviewActionsView.kt +++ b/lawnchair/src/app/lawnchair/overview/LawnchairOverviewActionsView.kt @@ -80,30 +80,36 @@ class LawnchairOverviewActionsView @JvmOverloads constructor( prefs.recentsActionScreenshot.subscribeChanges(this, ::updateVisibilities) prefs.recentsActionShare.subscribeChanges(this, ::updateVisibilities) prefs.recentsActionLocked.subscribeChanges(this, ::updateVisibilities) + prefs.recentActionOrder.subscribeChanges(this, ::updateVisibilities) updateVisibilities() } private fun updateVisibilities() { - val buttons = mutableListOf() + val order = prefs.recentActionOrder.get().split(",").map { it.toInt() } + + val buttonMap = mutableMapOf() if (prefs.recentsActionScreenshot.get() && !isOnePlusStock) { - buttons.add(screenshotAction) + buttonMap[0] = screenshotAction } if (prefs.recentsActionShare.get()) { - buttons.add(shareAction) + buttonMap[1] = shareAction } if (prefs.recentsActionLens.get() && isLensAvailable()) { - buttons.add(lensAction) + buttonMap[2] = lensAction } if (prefs.recentsActionLocked.get()) { - buttons.add(lockedAction) + buttonMap[3] = lockedAction } if (prefs.recentsActionClearAll.get()) { - buttons.add(clearAllAction) + buttonMap[4] = clearAllAction } + + val buttonsInOrder = order.mapNotNull { buttonMap[it] } + container.removeAllViews() container.addView(createSpace()) - buttons.forEach { view -> + buttonsInOrder.forEach { view -> view.isVisible = true container.addView(view) container.addView(createSpace()) diff --git a/lawnchair/src/app/lawnchair/preferences/PreferenceManager.kt b/lawnchair/src/app/lawnchair/preferences/PreferenceManager.kt index 24331b7e06..5be9788b3b 100644 --- a/lawnchair/src/app/lawnchair/preferences/PreferenceManager.kt +++ b/lawnchair/src/app/lawnchair/preferences/PreferenceManager.kt @@ -66,6 +66,8 @@ class PreferenceManager private constructor(private val context: Context) : Base override fun unflattenValue(value: String) = value } + val recentActionOrder = StringPref("pref_recentActionOrder", "0,1,2,3,4", recreate) + private val fontCache = FontCache.INSTANCE.get(context) val fontWorkspace = FontPref("pref_workspaceFont", fontCache.uiText, recreate) val fontHeading = FontPref("pref_fontHeading", fontCache.uiRegular, recreate) diff --git a/lawnchair/src/app/lawnchair/ui/preferences/components/layout/DraggablePreferenceGroup.kt b/lawnchair/src/app/lawnchair/ui/preferences/components/layout/DraggablePreferenceGroup.kt new file mode 100644 index 0000000000..fc45b8383f --- /dev/null +++ b/lawnchair/src/app/lawnchair/ui/preferences/components/layout/DraggablePreferenceGroup.kt @@ -0,0 +1,116 @@ +package app.lawnchair.ui.preferences.components.layout + +import androidx.compose.foundation.gestures.Orientation +import androidx.compose.foundation.gestures.draggable +import androidx.compose.foundation.gestures.rememberDraggableState +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.offset +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Divider +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableFloatStateOf +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.IntOffset +import androidx.compose.ui.unit.dp +import app.lawnchair.preferences.BasePreferenceManager +import kotlin.math.roundToInt +import kotlinx.coroutines.runBlocking + +@Composable +fun DraggablePreferenceGroup( + pref: BasePreferenceManager.StringPref, + items: List<@Composable () -> Unit>, + modifier: Modifier = Modifier, + heading: String? = null, + description: String? = null, + showDescription: Boolean = true, + showDividers: Boolean = true, + dividerStartIndent: Dp = 16.dp, + dividerEndIndent: Dp = 16.dp, +) { + var order by remember { + mutableStateOf( + pref.get().split(",").map { it.toInt() } + ?: items.indices.toList(), + ) + } + var draggingItemIndex by remember { mutableStateOf(null) } + var draggingOffset by remember { mutableFloatStateOf(0f) } + + fun saveOrder(order: List) { + runBlocking { + pref.set(order.joinToString(",")) + } + } + + Column( + modifier = modifier, + ) { + PreferenceGroupHeading(heading) + Surface( + modifier = Modifier.padding(horizontal = 16.dp), + shape = MaterialTheme.shapes.large, + tonalElevation = 1.dp, + ) { + if (showDividers) { + Column { + order.forEachIndexed { index, itemIndex -> + val isDragging = draggingItemIndex == index + Box( + modifier = Modifier + .offset { IntOffset(0, if (isDragging) draggingOffset.roundToInt() else 0) } + .draggable( + state = rememberDraggableState { delta -> + if (isDragging) { + draggingOffset += delta + } + }, + orientation = Orientation.Vertical, + onDragStarted = { + draggingItemIndex = index + draggingOffset = 0f + }, + onDragStopped = { + draggingItemIndex?.let { + val newIndex = (index + (draggingOffset / 100).roundToInt()).coerceIn(0, order.lastIndex) + order = order.toMutableList().apply { + add(newIndex, removeAt(it)) + } + saveOrder(order) + } + draggingItemIndex = null + draggingOffset = 0f + }, + ), + ) { + items[itemIndex]() + } + if (index != order.lastIndex) { + Divider( + Modifier + .padding(start = dividerStartIndent, end = dividerEndIndent), + ) + } + } + } + } else { + Column { + items.forEach { item -> + Box { + item() + } + } + } + } + } + PreferenceGroupDescription(description = description, showDescription = showDescription) + } +} diff --git a/lawnchair/src/app/lawnchair/ui/preferences/destinations/ExperimentalFeaturesPreferences.kt b/lawnchair/src/app/lawnchair/ui/preferences/destinations/ExperimentalFeaturesPreferences.kt index 4e0f668871..39a2920a23 100644 --- a/lawnchair/src/app/lawnchair/ui/preferences/destinations/ExperimentalFeaturesPreferences.kt +++ b/lawnchair/src/app/lawnchair/ui/preferences/destinations/ExperimentalFeaturesPreferences.kt @@ -44,11 +44,6 @@ fun ExperimentalFeaturesPreferences( label = stringResource(id = R.string.always_reload_icons_label), description = stringResource(id = R.string.always_reload_icons_description), ) - SwitchPreference( - adapter = prefs.recentsActionLocked.getAdapter(), - label = stringResource(id = R.string.recents_lock_unlock), - description = stringResource(id = R.string.recents_lock_unlock_description), - ) } } } diff --git a/lawnchair/src/app/lawnchair/ui/preferences/destinations/QuickstepPreferences.kt b/lawnchair/src/app/lawnchair/ui/preferences/destinations/QuickstepPreferences.kt index b9cc0b3989..e4b262d9be 100644 --- a/lawnchair/src/app/lawnchair/ui/preferences/destinations/QuickstepPreferences.kt +++ b/lawnchair/src/app/lawnchair/ui/preferences/destinations/QuickstepPreferences.kt @@ -18,6 +18,7 @@ import app.lawnchair.preferences2.preferenceManager2 import app.lawnchair.ui.preferences.components.controls.SliderPreference import app.lawnchair.ui.preferences.components.controls.SwitchPreference import app.lawnchair.ui.preferences.components.controls.WarningPreference +import app.lawnchair.ui.preferences.components.layout.DraggablePreferenceGroup import app.lawnchair.ui.preferences.components.layout.ExpandAndShrink import app.lawnchair.ui.preferences.components.layout.PreferenceGroup import app.lawnchair.ui.preferences.components.layout.PreferenceLayout @@ -37,6 +38,52 @@ fun QuickstepPreferences( context.packageManager.getLaunchIntentForPackage("com.google.ar.lens") != null } + val screenshotPreference: @Composable () -> Unit = { + if (!isOnePlusStock) { + SwitchPreference( + adapter = prefs.recentsActionScreenshot.getAdapter(), + label = stringResource(id = R.string.action_screenshot), + ) + } + } + + val lockUnlockPreference: @Composable () -> Unit = { + SwitchPreference( + adapter = prefs.recentsActionLocked.getAdapter(), + label = stringResource(id = R.string.recents_lock_unlock), + description = stringResource(id = R.string.recents_lock_unlock_description), + ) + } + + val sharePreference: @Composable () -> Unit = { + SwitchPreference( + adapter = prefs.recentsActionShare.getAdapter(), + label = stringResource(id = R.string.action_share), + ) + } + val lensPreference: @Composable () -> Unit = { + if (lensAvailable) { + SwitchPreference( + adapter = prefs.recentsActionLens.getAdapter(), + label = stringResource(id = R.string.action_lens), + ) + } + } + val clearAllPreference: @Composable () -> Unit = { + SwitchPreference( + adapter = prefs.recentsActionClearAll.getAdapter(), + label = stringResource(id = R.string.recents_clear_all), + ) + } + + val items = listOf( + screenshotPreference, + lockUnlockPreference, + sharePreference, + lensPreference, + clearAllPreference, + ) + PreferenceLayout( label = stringResource(id = R.string.quickstep_label), modifier = modifier, @@ -58,28 +105,13 @@ fun QuickstepPreferences( ) } } - PreferenceGroup(heading = stringResource(id = R.string.recents_actions_label)) { - if (!isOnePlusStock) { - SwitchPreference( - adapter = prefs.recentsActionScreenshot.getAdapter(), - label = stringResource(id = R.string.action_screenshot), - ) - } - SwitchPreference( - adapter = prefs.recentsActionShare.getAdapter(), - label = stringResource(id = R.string.action_share), - ) - if (lensAvailable) { - SwitchPreference( - adapter = prefs.recentsActionLens.getAdapter(), - label = stringResource(id = R.string.action_lens), - ) - } - SwitchPreference( - adapter = prefs.recentsActionClearAll.getAdapter(), - label = stringResource(id = R.string.recents_clear_all), - ) - } + + DraggablePreferenceGroup( + heading = stringResource(id = R.string.recents_actions_label), + items = items, + pref = prefs.recentActionOrder, + ) + val overrideWindowCornerRadius by prefs.overrideWindowCornerRadius.observeAsState() PreferenceGroup( heading = stringResource(id = R.string.window_corner_radius_label),