Add style to BinaryClock for 24-hour time (#1190)
* Add style to BinaryClock for 24-hour time * Use global time format preference for all clock widget styles * Add support for time format preference to remaining clock styles --------- Co-authored-by: MM20 <15646950+MM2-0@users.noreply.github.com>
This commit is contained in:
parent
4330b2a712
commit
5240431348
@ -31,6 +31,7 @@ import androidx.compose.material.icons.rounded.Height
|
||||
import androidx.compose.material.icons.rounded.HorizontalSplit
|
||||
import androidx.compose.material.icons.rounded.LightMode
|
||||
import androidx.compose.material.icons.rounded.MusicNote
|
||||
import androidx.compose.material.icons.rounded.Timer
|
||||
import androidx.compose.material.icons.rounded.Today
|
||||
import androidx.compose.material.icons.rounded.Tune
|
||||
import androidx.compose.material.icons.rounded.VerticalSplit
|
||||
@ -67,6 +68,7 @@ import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import de.mm20.launcher2.preferences.ClockWidgetAlignment
|
||||
import de.mm20.launcher2.preferences.ClockWidgetColors
|
||||
import de.mm20.launcher2.preferences.ClockWidgetStyle
|
||||
import de.mm20.launcher2.preferences.TimeFormat
|
||||
import de.mm20.launcher2.preferences.ui.ClockWidgetSettings
|
||||
import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.ui.base.LocalTime
|
||||
@ -83,6 +85,7 @@ import de.mm20.launcher2.ui.launcher.widgets.clock.clocks.SegmentClock
|
||||
import de.mm20.launcher2.ui.launcher.widgets.clock.parts.PartProvider
|
||||
import de.mm20.launcher2.ui.locals.LocalPreferDarkContentOverWallpaper
|
||||
import de.mm20.launcher2.ui.settings.clockwidget.ClockWidgetSettingsScreenVM
|
||||
import de.mm20.launcher2.ui.utils.isTwentyFourHours
|
||||
import org.koin.androidx.compose.inject
|
||||
|
||||
@Composable
|
||||
@ -164,7 +167,8 @@ fun ClockWidget(
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.then(if (fillScreenHeight) Modifier.weight(1f) else Modifier)
|
||||
.fillMaxWidth().padding(horizontal = if (compact == true) 0.dp else 24.dp),
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = if (compact == true) 0.dp else 24.dp),
|
||||
contentAlignment = when (alignment) {
|
||||
ClockWidgetAlignment.Center -> Alignment.Center
|
||||
ClockWidgetAlignment.Top -> Alignment.TopCenter
|
||||
@ -265,34 +269,42 @@ fun Clock(
|
||||
darkColors: Boolean = false
|
||||
) {
|
||||
val time = LocalTime.current
|
||||
val context = LocalContext.current
|
||||
val clockSettings: ClockWidgetSettings by inject()
|
||||
val showSeconds by clockSettings.showSeconds.collectAsState(initial = false)
|
||||
val useThemeColor by clockSettings.useThemeColor.collectAsState(initial = false)
|
||||
val timeFormat by clockSettings.timeFormat.collectAsState(null)
|
||||
|
||||
if (timeFormat == null) return
|
||||
|
||||
val isTwentyFourHours = timeFormat!!.isTwentyFourHours(context)
|
||||
|
||||
when (style) {
|
||||
is ClockWidgetStyle.Digital1 -> DigitalClock1(
|
||||
time,
|
||||
style,
|
||||
compact,
|
||||
showSeconds,
|
||||
useThemeColor,
|
||||
darkColors
|
||||
time = time,
|
||||
compact = compact,
|
||||
showSeconds = showSeconds,
|
||||
twentyFourHours = isTwentyFourHours,
|
||||
useThemeColor = useThemeColor,
|
||||
darkColors = darkColors,
|
||||
)
|
||||
|
||||
is ClockWidgetStyle.Digital2 -> DigitalClock2(
|
||||
time,
|
||||
compact,
|
||||
showSeconds,
|
||||
useThemeColor,
|
||||
darkColors
|
||||
time = time,
|
||||
compact = compact,
|
||||
showSeconds = showSeconds,
|
||||
twentyFourHours = isTwentyFourHours,
|
||||
useThemeColor = useThemeColor,
|
||||
darkColors = darkColors,
|
||||
)
|
||||
|
||||
is ClockWidgetStyle.Binary -> BinaryClock(
|
||||
time,
|
||||
compact,
|
||||
showSeconds,
|
||||
useThemeColor,
|
||||
darkColors
|
||||
time = time,
|
||||
compact = compact,
|
||||
showSeconds = showSeconds,
|
||||
twentyFourHours = isTwentyFourHours,
|
||||
useThemeColor = useThemeColor,
|
||||
darkColors = darkColors,
|
||||
)
|
||||
|
||||
is ClockWidgetStyle.Analog -> AnalogClock(
|
||||
@ -304,19 +316,21 @@ fun Clock(
|
||||
)
|
||||
|
||||
is ClockWidgetStyle.Orbit -> OrbitClock(
|
||||
time,
|
||||
compact,
|
||||
showSeconds,
|
||||
useThemeColor,
|
||||
darkColors
|
||||
time = time,
|
||||
compact = compact,
|
||||
showSeconds = showSeconds,
|
||||
twentyFourHours = isTwentyFourHours,
|
||||
useThemeColor = useThemeColor,
|
||||
darkColors = darkColors,
|
||||
)
|
||||
|
||||
is ClockWidgetStyle.Segment -> SegmentClock(
|
||||
time,
|
||||
compact,
|
||||
showSeconds,
|
||||
useThemeColor,
|
||||
darkColors
|
||||
time = time,
|
||||
compact = compact,
|
||||
showSeconds = showSeconds,
|
||||
twentyFourHours = isTwentyFourHours,
|
||||
useThemeColor = useThemeColor,
|
||||
darkColors = darkColors,
|
||||
)
|
||||
|
||||
is ClockWidgetStyle.Custom -> CustomClock(style, compact, useThemeColor, darkColors)
|
||||
@ -349,6 +363,7 @@ fun ConfigureClockWidgetSheet(
|
||||
val fillHeight by viewModel.fillHeight.collectAsState()
|
||||
val alignment by viewModel.alignment.collectAsState()
|
||||
val showSeconds by viewModel.showSeconds.collectAsState()
|
||||
val timeFormat by viewModel.timeFormat.collectAsState()
|
||||
val useAccentColor by viewModel.useThemeColor.collectAsState()
|
||||
val parts by viewModel.parts.collectAsState()
|
||||
|
||||
@ -488,13 +503,63 @@ fun ConfigureClockWidgetSheet(
|
||||
AnimatedVisibility(compact == false && style !is ClockWidgetStyle.Custom) {
|
||||
SwitchPreference(
|
||||
title = stringResource(R.string.preference_clock_widget_show_seconds),
|
||||
icon = Icons.Rounded.AccessTime,
|
||||
icon = Icons.Rounded.Timer,
|
||||
value = showSeconds,
|
||||
onValueChanged = {
|
||||
viewModel.setShowSeconds(it)
|
||||
}
|
||||
)
|
||||
}
|
||||
AnimatedVisibility(
|
||||
style !is ClockWidgetStyle.Analog &&
|
||||
style !is ClockWidgetStyle.Custom &&
|
||||
style !is ClockWidgetStyle.Empty
|
||||
) {
|
||||
var showDropdown by remember { mutableStateOf(false) }
|
||||
Preference(
|
||||
title = stringResource(R.string.preference_clock_widget_time_format),
|
||||
summary = when (timeFormat) {
|
||||
TimeFormat.TwelveHour -> stringResource(R.string.preference_clock_widget_time_format_12h)
|
||||
TimeFormat.TwentyFourHour -> stringResource(R.string.preference_clock_widget_time_format_24h)
|
||||
TimeFormat.System -> stringResource(R.string.preference_clock_widget_time_format_system)
|
||||
},
|
||||
icon = Icons.Rounded.AccessTime,
|
||||
onClick = {
|
||||
showDropdown = true
|
||||
}
|
||||
)
|
||||
DropdownMenu(
|
||||
expanded = showDropdown,
|
||||
onDismissRequest = { showDropdown = false }) {
|
||||
DropdownMenuItem(
|
||||
text = {
|
||||
Text(stringResource(R.string.preference_clock_widget_time_format_system))
|
||||
},
|
||||
onClick = {
|
||||
viewModel.setTimeFormat(TimeFormat.System)
|
||||
showDropdown = false
|
||||
}
|
||||
)
|
||||
DropdownMenuItem(
|
||||
text = {
|
||||
Text(stringResource(R.string.preference_clock_widget_time_format_24h))
|
||||
},
|
||||
onClick = {
|
||||
viewModel.setTimeFormat(TimeFormat.TwentyFourHour)
|
||||
showDropdown = false
|
||||
}
|
||||
)
|
||||
DropdownMenuItem(
|
||||
text = {
|
||||
Text(stringResource(R.string.preference_clock_widget_time_format_12h))
|
||||
},
|
||||
onClick = {
|
||||
viewModel.setTimeFormat(TimeFormat.TwelveHour)
|
||||
showDropdown = false
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
OutlinedCard(
|
||||
|
||||
@ -13,14 +13,19 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.unit.dp
|
||||
import de.mm20.launcher2.preferences.ClockWidgetStyle
|
||||
import de.mm20.launcher2.preferences.TimeFormat
|
||||
import de.mm20.launcher2.ui.locals.LocalDarkTheme
|
||||
import de.mm20.launcher2.ui.utils.isTwentyFourHours
|
||||
import java.util.Calendar
|
||||
|
||||
@Composable
|
||||
fun BinaryClock(
|
||||
time: Long,
|
||||
compact: Boolean,
|
||||
twentyFourHours: Boolean,
|
||||
showSeconds: Boolean,
|
||||
useThemeColor: Boolean,
|
||||
darkColors: Boolean,
|
||||
@ -30,8 +35,8 @@ fun BinaryClock(
|
||||
date.timeInMillis = time
|
||||
val second = date[Calendar.SECOND]
|
||||
val minute = date[Calendar.MINUTE]
|
||||
var hour = date[Calendar.HOUR]
|
||||
if (hour == 0) hour = 12
|
||||
var hour = date[if(!twentyFourHours) Calendar.HOUR else Calendar.HOUR_OF_DAY]
|
||||
if (!twentyFourHours && hour == 0) hour = 12
|
||||
|
||||
val color = if (useThemeColor) {
|
||||
if (!darkColors) {
|
||||
@ -56,11 +61,11 @@ fun BinaryClock(
|
||||
Row(
|
||||
modifier = Modifier.padding(start = 0.dp, top = 24.dp, end = 0.dp, bottom = 6.dp)
|
||||
) {
|
||||
for (i in 0 until 10) {
|
||||
val active = if (i < 4) {
|
||||
hour and (1 shl (3 - i)) != 0
|
||||
for (i in 0 until if (twentyFourHours) 11 else 10) {
|
||||
val active = if (i < if (twentyFourHours) 5 else 4) {
|
||||
hour and (1 shl ((if (twentyFourHours) 4 else 3) - i)) != 0
|
||||
} else {
|
||||
minute and (1 shl (9 - i)) != 0
|
||||
minute and (1 shl ((if (twentyFourHours) 10 else 9) - i)) != 0
|
||||
}
|
||||
Box(
|
||||
modifier = Modifier
|
||||
@ -70,7 +75,7 @@ fun BinaryClock(
|
||||
if (active) color else disabledColor
|
||||
)
|
||||
)
|
||||
if (i == 3) {
|
||||
if (i == if (twentyFourHours) 4 else 3) {
|
||||
Box(Modifier.size(8.dp))
|
||||
}
|
||||
}
|
||||
@ -98,8 +103,8 @@ fun BinaryClock(
|
||||
horizontalAlignment = Alignment.End
|
||||
) {
|
||||
Row {
|
||||
for (i in 0 until 4) {
|
||||
val active = hour and (1 shl (3 - i)) != 0
|
||||
for (i in 0 until if (twentyFourHours) 5 else 4) {
|
||||
val active = hour and (1 shl ((if (twentyFourHours) 4 else 3) - i)) != 0
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding( 4.dp)
|
||||
|
||||
@ -33,6 +33,7 @@ fun DigitalClock1(
|
||||
time: Long,
|
||||
style: ClockWidgetStyle.Digital1 = ClockWidgetStyle.Digital1(),
|
||||
compact: Boolean,
|
||||
twentyFourHours: Boolean,
|
||||
showSeconds: Boolean,
|
||||
useThemeColor: Boolean,
|
||||
darkColors: Boolean,
|
||||
@ -40,10 +41,10 @@ fun DigitalClock1(
|
||||
val verticalLayout = !compact
|
||||
val format = SimpleDateFormat(
|
||||
when {
|
||||
DateFormat.is24HourFormat(LocalContext.current) && verticalLayout -> {
|
||||
twentyFourHours && verticalLayout -> {
|
||||
"HH\nmm"
|
||||
}
|
||||
DateFormat.is24HourFormat(LocalContext.current) -> {
|
||||
twentyFourHours -> {
|
||||
"HH mm"
|
||||
}
|
||||
verticalLayout -> {
|
||||
|
||||
@ -21,6 +21,7 @@ fun DigitalClock2(
|
||||
time: Long,
|
||||
compact: Boolean,
|
||||
showSeconds: Boolean,
|
||||
twentyFourHours: Boolean,
|
||||
useThemeColor: Boolean,
|
||||
darkColors: Boolean,
|
||||
) {
|
||||
@ -40,14 +41,14 @@ fun DigitalClock2(
|
||||
}
|
||||
|
||||
val formatString = if (verticalLayout && showSeconds) {
|
||||
if (DateFormat.is24HourFormat(LocalContext.current)) {
|
||||
if (twentyFourHours) {
|
||||
"HH:mm:ss"
|
||||
}
|
||||
else {
|
||||
"hh:mm:ss"
|
||||
}
|
||||
} else {
|
||||
if (DateFormat.is24HourFormat(LocalContext.current)) {
|
||||
if (twentyFourHours) {
|
||||
"HH:mm"
|
||||
}
|
||||
else {
|
||||
|
||||
@ -48,6 +48,7 @@ fun OrbitClock(
|
||||
time: Long,
|
||||
compact: Boolean,
|
||||
showSeconds: Boolean,
|
||||
twentyFourHours: Boolean,
|
||||
useThemeColor: Boolean,
|
||||
darkColors: Boolean,
|
||||
) {
|
||||
@ -59,7 +60,7 @@ fun OrbitClock(
|
||||
val minute = parsed.minute
|
||||
val hour = parsed.hour
|
||||
val formattedHour = (
|
||||
if (DateFormat.is24HourFormat(LocalContext.current))
|
||||
if (twentyFourHours)
|
||||
hour
|
||||
else {
|
||||
((hour + 11) % 12) + 1
|
||||
|
||||
@ -52,11 +52,12 @@ fun SegmentClock(
|
||||
time: Long,
|
||||
compact: Boolean,
|
||||
showSeconds: Boolean,
|
||||
twentyFourHours: Boolean,
|
||||
useThemeColor: Boolean,
|
||||
darkColors: Boolean,
|
||||
) {
|
||||
val parsed = Instant.ofEpochMilli(time).atZone(ZoneId.systemDefault())
|
||||
val hour = if (DateFormat.is24HourFormat(LocalContext.current)) parsed.hour else (((parsed.hour + 11) % 12) + 1)
|
||||
val hour = if (twentyFourHours) parsed.hour else (((parsed.hour + 11) % 12) + 1)
|
||||
val minute = parsed.minute
|
||||
val second = parsed.second
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@ import androidx.lifecycle.viewModelScope
|
||||
import de.mm20.launcher2.preferences.ClockWidgetAlignment
|
||||
import de.mm20.launcher2.preferences.ClockWidgetColors
|
||||
import de.mm20.launcher2.preferences.ClockWidgetStyle
|
||||
import de.mm20.launcher2.preferences.TimeFormat
|
||||
import de.mm20.launcher2.preferences.ui.ClockWidgetSettings
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.combine
|
||||
@ -21,7 +22,7 @@ class ClockWidgetSettingsScreenVM : ViewModel(), KoinComponent {
|
||||
settings.setCompact(compact)
|
||||
}
|
||||
|
||||
val availableClockStyles = combine(settings.digital1, settings.custom) {digital1, custom ->
|
||||
val availableClockStyles = combine(settings.digital1, settings.custom) { digital1, custom ->
|
||||
listOf(
|
||||
digital1,
|
||||
ClockWidgetStyle.Digital2,
|
||||
@ -54,6 +55,13 @@ class ClockWidgetSettingsScreenVM : ViewModel(), KoinComponent {
|
||||
settings.setShowSeconds(showSeconds)
|
||||
}
|
||||
|
||||
val timeFormat = settings.timeFormat
|
||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), TimeFormat.System)
|
||||
|
||||
fun setTimeFormat(timeFormat: TimeFormat) {
|
||||
settings.setTimeFormat(timeFormat)
|
||||
}
|
||||
|
||||
val useThemeColor = settings.useThemeColor
|
||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), false)
|
||||
|
||||
|
||||
@ -0,0 +1,10 @@
|
||||
package de.mm20.launcher2.ui.utils
|
||||
|
||||
import android.content.Context
|
||||
import android.text.format.DateFormat
|
||||
import de.mm20.launcher2.preferences.TimeFormat
|
||||
import de.mm20.launcher2.preferences.TimeFormat.TwentyFourHour
|
||||
|
||||
fun TimeFormat.isTwentyFourHours(context: Context): Boolean {
|
||||
return this == TimeFormat.TwentyFourHour || this == TimeFormat.System && DateFormat.is24HourFormat(context)
|
||||
}
|
||||
@ -567,6 +567,10 @@
|
||||
<string name="preference_clockwidget_layout_vertical">Default</string>
|
||||
<string name="preference_clockwidget_layout_horizontal">Compact</string>
|
||||
<string name="preference_clock_widget_show_seconds">Show seconds</string>
|
||||
<string name="preference_clock_widget_time_format">Time format</string>
|
||||
<string name="preference_clock_widget_time_format_24h">24-hour</string>
|
||||
<string name="preference_clock_widget_time_format_12h">12-hour</string>
|
||||
<string name="preference_clock_widget_time_format_system">System default</string>
|
||||
<string name="widget_use_theme_colors">Use theme color</string>
|
||||
<string name="preference_clock_widget_fill_height">Fill screen height</string>
|
||||
<string name="preference_clock_widget_alignment">Alignment</string>
|
||||
|
||||
@ -34,6 +34,7 @@ data class LauncherSettingsData internal constructor(
|
||||
val clockWidgetCustom: ClockWidgetStyle.Custom = ClockWidgetStyle.Custom(),
|
||||
val clockWidgetColors: ClockWidgetColors = ClockWidgetColors.Auto,
|
||||
val clockWidgetShowSeconds: Boolean = false,
|
||||
val clockWidgetTimeFormat: TimeFormat = TimeFormat.System,
|
||||
val clockWidgetUseThemeColor: Boolean = false,
|
||||
val clockWidgetAlarmPart: Boolean = true,
|
||||
val clockWidgetBatteryPart: Boolean = true,
|
||||
@ -408,4 +409,11 @@ enum class KeyboardFilterBarItem {
|
||||
@SerialName("events") Events,
|
||||
@SerialName("tools") Tools,
|
||||
@SerialName("hidden") HiddenResults,
|
||||
}
|
||||
|
||||
@Serializable
|
||||
enum class TimeFormat {
|
||||
@SerialName("system") System,
|
||||
@SerialName("12h") TwelveHour,
|
||||
@SerialName("24h") TwentyFourHour
|
||||
}
|
||||
@ -5,6 +5,7 @@ import de.mm20.launcher2.preferences.ClockWidgetColors
|
||||
import de.mm20.launcher2.preferences.ClockWidgetStyle
|
||||
import de.mm20.launcher2.preferences.ClockWidgetStyleEnum
|
||||
import de.mm20.launcher2.preferences.LauncherDataStore
|
||||
import de.mm20.launcher2.preferences.TimeFormat
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.map
|
||||
@ -137,6 +138,15 @@ class ClockWidgetSettings internal constructor(
|
||||
}
|
||||
}
|
||||
|
||||
val timeFormat
|
||||
get() = launcherDataStore.data.map { it.clockWidgetTimeFormat }
|
||||
|
||||
fun setTimeFormat(timeFormat: TimeFormat) {
|
||||
launcherDataStore.update {
|
||||
it.copy(clockWidgetTimeFormat = timeFormat)
|
||||
}
|
||||
}
|
||||
|
||||
val useThemeColor
|
||||
get() = launcherDataStore.data.map { it.clockWidgetUseThemeColor }
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user