Bring back clock widget fill height option

Close #1493
This commit is contained in:
MM20 2025-07-13 20:55:29 +02:00
parent 83b96e4fcd
commit 8ae2fc93fc
No known key found for this signature in database
GPG Key ID: 0B61A8F2DEAFA389
5 changed files with 117 additions and 74 deletions

View File

@ -1,18 +1,17 @@
package de.mm20.launcher2.ui.launcher.scaffold package de.mm20.launcher2.ui.launcher.scaffold
import android.annotation.SuppressLint
import androidx.activity.compose.BackHandler import androidx.activity.compose.BackHandler
import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.animateDpAsState import androidx.compose.animation.core.animateDpAsState
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.expandVertically import androidx.compose.animation.expandVertically
import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut import androidx.compose.animation.fadeOut
import androidx.compose.animation.shrinkVertically import androidx.compose.animation.shrinkVertically
import androidx.compose.foundation.ScrollState import androidx.compose.foundation.ScrollState
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
@ -26,6 +25,7 @@ import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.State import androidx.compose.runtime.State
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableIntStateOf
@ -35,17 +35,18 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.zIndex import androidx.compose.ui.zIndex
import de.mm20.launcher2.preferences.ui.ClockWidgetSettings
import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.ktx.toDp
import de.mm20.launcher2.ui.launcher.widgets.WidgetColumn import de.mm20.launcher2.ui.launcher.widgets.WidgetColumn
import de.mm20.launcher2.ui.launcher.widgets.clock.ClockWidget import de.mm20.launcher2.ui.launcher.widgets.clock.ClockWidget
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.koin.compose.koinInject
internal object ClockAndWidgetsHomeComponent: ScaffoldComponent() { internal object ClockAndWidgetsHomeComponent : ScaffoldComponent() {
private var editMode by mutableStateOf(false) private var editMode by mutableStateOf(false)
private val scrollState = ScrollState(0) private val scrollState = ScrollState(0)
@ -54,7 +55,7 @@ internal object ClockAndWidgetsHomeComponent: ScaffoldComponent() {
} }
override val isAtBottom: State<Boolean?> = derivedStateOf { override val isAtBottom: State<Boolean?> = derivedStateOf {
!scrollState.canScrollForward !scrollState.canScrollForward || scrollState.value == 0
} }
override val drawBackground: Boolean = false override val drawBackground: Boolean = false
@ -72,11 +73,19 @@ internal object ClockAndWidgetsHomeComponent: ScaffoldComponent() {
) { ) {
val scope = rememberCoroutineScope() val scope = rememberCoroutineScope()
val topPadding by animateDpAsState(if (editMode) 80.dp else 0.dp) val clockWidgetSettings: ClockWidgetSettings = koinInject()
val fillHeight by clockWidgetSettings.fillHeight.collectAsState(null)
if (fillHeight == null) return
val topPadding by animateDpAsState(if (editMode) 80.dp else 0.dp)
val previousScroll = remember { mutableIntStateOf(scrollState.value) } val previousScroll = remember { mutableIntStateOf(scrollState.value) }
LaunchedEffect(scrollState.value, scrollState.canScrollForward, scrollState.canScrollBackward) { LaunchedEffect(
scrollState.value,
scrollState.canScrollForward,
scrollState.canScrollBackward
) {
val delta = scrollState.value - previousScroll.intValue val delta = scrollState.value - previousScroll.intValue
previousScroll.intValue = scrollState.value previousScroll.intValue = scrollState.value
if (!editMode) { if (!editMode) {
@ -92,8 +101,15 @@ internal object ClockAndWidgetsHomeComponent: ScaffoldComponent() {
.padding(insets), .padding(insets),
) { ) {
ClockWidget( ClockWidget(
modifier = Modifier
.fillMaxWidth()
then if (fillHeight == true) Modifier.height(
state.size.height.toDp() - insets.calculateTopPadding()
).padding(
bottom = insets.calculateBottomPadding()
) else Modifier,
editMode = editMode, editMode = editMode,
fillScreenHeight = false, fillScreenHeight = fillHeight == true,
) )
WidgetColumn( WidgetColumn(
modifier = Modifier modifier = Modifier
@ -126,7 +142,10 @@ internal object ClockAndWidgetsHomeComponent: ScaffoldComponent() {
scope.launch { state.unlock() } scope.launch { state.unlock() }
} }
) { ) {
Icon(Icons.AutoMirrored.Rounded.ArrowBack, stringResource(R.string.action_done)) Icon(
Icons.AutoMirrored.Rounded.ArrowBack,
stringResource(R.string.action_done)
)
} }
}, },
colors = TopAppBarDefaults.topAppBarColors( colors = TopAppBarDefaults.topAppBarColors(

View File

@ -24,10 +24,10 @@ import androidx.compose.material.icons.rounded.AlignVerticalBottom
import androidx.compose.material.icons.rounded.AlignVerticalCenter import androidx.compose.material.icons.rounded.AlignVerticalCenter
import androidx.compose.material.icons.rounded.AlignVerticalTop import androidx.compose.material.icons.rounded.AlignVerticalTop
import androidx.compose.material.icons.rounded.AutoAwesome import androidx.compose.material.icons.rounded.AutoAwesome
import androidx.compose.material.icons.rounded.AvTimer
import androidx.compose.material.icons.rounded.BatteryFull import androidx.compose.material.icons.rounded.BatteryFull
import androidx.compose.material.icons.rounded.ColorLens import androidx.compose.material.icons.rounded.ColorLens
import androidx.compose.material.icons.rounded.DarkMode import androidx.compose.material.icons.rounded.DarkMode
import androidx.compose.material.icons.rounded.Height
import androidx.compose.material.icons.rounded.HorizontalSplit import androidx.compose.material.icons.rounded.HorizontalSplit
import androidx.compose.material.icons.rounded.LightMode import androidx.compose.material.icons.rounded.LightMode
import androidx.compose.material.icons.rounded.MusicNote import androidx.compose.material.icons.rounded.MusicNote
@ -363,6 +363,7 @@ fun ConfigureClockWidgetSheet(
val color by viewModel.color.collectAsState() val color by viewModel.color.collectAsState()
val style by viewModel.clockStyle.collectAsState() val style by viewModel.clockStyle.collectAsState()
val fillHeight by viewModel.fillHeight.collectAsState() val fillHeight by viewModel.fillHeight.collectAsState()
val widgetsOnHome by viewModel.widgetsOnHome.collectAsState()
val alignment by viewModel.alignment.collectAsState() val alignment by viewModel.alignment.collectAsState()
val showSeconds by viewModel.showSeconds.collectAsState() val showSeconds by viewModel.showSeconds.collectAsState()
val timeFormat by viewModel.timeFormat.collectAsState() val timeFormat by viewModel.timeFormat.collectAsState()
@ -564,71 +565,79 @@ fun ConfigureClockWidgetSheet(
} }
} }
} }
if (fillHeight == true) { OutlinedCard(
OutlinedCard( modifier = Modifier.padding(top = 16.dp),
modifier = Modifier.padding(top = 16.dp), ) {
Column(
modifier = Modifier.fillMaxWidth()
) { ) {
Column( SwitchPreference(
modifier = Modifier.fillMaxWidth() title = stringResource(R.string.preference_clock_widget_fill_height),
) { icon = Icons.Rounded.Height,
var showDropdown by remember { mutableStateOf(false) } value = fillHeight == true || widgetsOnHome == false,
Preference( onValueChanged = {
title = stringResource(R.string.preference_clock_widget_alignment), viewModel.setFillHeight(it)
summary = when (alignment) { },
ClockWidgetAlignment.Top -> stringResource(R.string.preference_clock_widget_alignment_top) enabled = widgetsOnHome == true,
ClockWidgetAlignment.Center -> stringResource(R.string.preference_clock_widget_alignment_center) )
else -> stringResource(R.string.preference_clock_widget_alignment_bottom) var showDropdown by remember { mutableStateOf(false) }
}, Preference(
icon = when (alignment) { title = stringResource(R.string.preference_clock_widget_alignment),
ClockWidgetAlignment.Top -> Icons.Rounded.AlignVerticalTop summary = when (alignment) {
ClockWidgetAlignment.Center -> Icons.Rounded.AlignVerticalCenter ClockWidgetAlignment.Top -> stringResource(R.string.preference_clock_widget_alignment_top)
else -> Icons.Rounded.AlignVerticalBottom ClockWidgetAlignment.Center -> stringResource(R.string.preference_clock_widget_alignment_center)
else -> stringResource(R.string.preference_clock_widget_alignment_bottom)
},
icon = when (alignment) {
ClockWidgetAlignment.Top -> Icons.Rounded.AlignVerticalTop
ClockWidgetAlignment.Center -> Icons.Rounded.AlignVerticalCenter
else -> Icons.Rounded.AlignVerticalBottom
},
onClick = {
showDropdown = true
},
enabled = fillHeight == true,
)
DropdownMenu(
expanded = showDropdown,
onDismissRequest = { showDropdown = false }) {
DropdownMenuItem(
leadingIcon = {
Icon(
Icons.Rounded.AlignVerticalTop,
null
)
}, },
text = { Text(stringResource(R.string.preference_clock_widget_alignment_top)) },
onClick = { onClick = {
showDropdown = true viewModel.setAlignment(ClockWidgetAlignment.Top)
showDropdown = false
} }
) )
DropdownMenu( DropdownMenuItem(
expanded = showDropdown, leadingIcon = {
onDismissRequest = { showDropdown = false }) { Icon(
DropdownMenuItem( Icons.Rounded.AlignVerticalCenter,
leadingIcon = { null
Icon( )
Icons.Rounded.AlignVerticalTop, },
null text = { Text(stringResource(R.string.preference_clock_widget_alignment_center)) },
) onClick = {
}, viewModel.setAlignment(ClockWidgetAlignment.Center)
text = { Text(stringResource(R.string.preference_clock_widget_alignment_top)) }, showDropdown = false
onClick = { })
viewModel.setAlignment(ClockWidgetAlignment.Top) DropdownMenuItem(
showDropdown = false leadingIcon = {
} Icon(
) Icons.Rounded.AlignVerticalBottom,
DropdownMenuItem( null
leadingIcon = { )
Icon( },
Icons.Rounded.AlignVerticalCenter, text = { Text(stringResource(R.string.preference_clock_widget_alignment_bottom)) },
null onClick = {
) viewModel.setAlignment(ClockWidgetAlignment.Bottom)
}, showDropdown = false
text = { Text(stringResource(R.string.preference_clock_widget_alignment_center)) }, })
onClick = {
viewModel.setAlignment(ClockWidgetAlignment.Center)
showDropdown = false
})
DropdownMenuItem(
leadingIcon = {
Icon(
Icons.Rounded.AlignVerticalBottom,
null
)
},
text = { Text(stringResource(R.string.preference_clock_widget_alignment_bottom)) },
onClick = {
viewModel.setAlignment(ClockWidgetAlignment.Bottom)
showDropdown = false
})
}
} }
} }
} }

View File

@ -7,6 +7,7 @@ import de.mm20.launcher2.preferences.ClockWidgetColors
import de.mm20.launcher2.preferences.ClockWidgetStyle import de.mm20.launcher2.preferences.ClockWidgetStyle
import de.mm20.launcher2.preferences.TimeFormat import de.mm20.launcher2.preferences.TimeFormat
import de.mm20.launcher2.preferences.ui.ClockWidgetSettings import de.mm20.launcher2.preferences.ui.ClockWidgetSettings
import de.mm20.launcher2.preferences.ui.UiSettings
import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.stateIn
@ -15,6 +16,8 @@ import org.koin.core.component.inject
class ClockWidgetSettingsScreenVM : ViewModel(), KoinComponent { class ClockWidgetSettingsScreenVM : ViewModel(), KoinComponent {
private val settings: ClockWidgetSettings by inject() private val settings: ClockWidgetSettings by inject()
private val uiSettings: UiSettings by inject()
val compact = settings.compact val compact = settings.compact
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null) .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null)
fun setCompact(compact: Boolean) { fun setCompact(compact: Boolean) {
@ -68,9 +71,16 @@ class ClockWidgetSettingsScreenVM : ViewModel(), KoinComponent {
settings.setUseThemeColor(boolean) settings.setUseThemeColor(boolean)
} }
val widgetsOnHome = uiSettings.homeScreenWidgets
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null)
val fillHeight = settings.fillHeight val fillHeight = settings.fillHeight
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null) .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null)
fun setFillHeight(fillHeight: Boolean) {
settings.setFillHeight(fillHeight)
}
val parts = settings.parts val parts = settings.parts
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null) .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null)

View File

@ -51,7 +51,6 @@ data class LauncherSettingsData internal constructor(
val clockWidgetBatteryPart: Boolean = true, val clockWidgetBatteryPart: Boolean = true,
val clockWidgetMusicPart: Boolean = true, val clockWidgetMusicPart: Boolean = true,
val clockWidgetDatePart: Boolean = true, val clockWidgetDatePart: Boolean = true,
@Deprecated("Use homeScreenWidgets")
val clockWidgetFillHeight: Boolean = true, val clockWidgetFillHeight: Boolean = true,
val clockWidgetAlignment: ClockWidgetAlignment = ClockWidgetAlignment.Bottom, val clockWidgetAlignment: ClockWidgetAlignment = ClockWidgetAlignment.Bottom,

View File

@ -64,7 +64,13 @@ class ClockWidgetSettings internal constructor(
} }
val fillHeight val fillHeight
get() = launcherDataStore.data.map { !it.homeScreenWidgets } get() = launcherDataStore.data.map { it.clockWidgetFillHeight || !it.homeScreenWidgets }
fun setFillHeight(fillHeight: Boolean) {
launcherDataStore.update {
it.copy(clockWidgetFillHeight = fillHeight)
}
}
val dock val dock
get() = launcherDataStore.data.map { it.homeScreenDock } get() = launcherDataStore.data.map { it.homeScreenDock }