diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/clock/ClockWidget.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/clock/ClockWidget.kt index 455aa2f3..22ae4054 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/clock/ClockWidget.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/clock/ClockWidget.kt @@ -16,13 +16,13 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp +import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.viewmodel.compose.viewModel import de.mm20.launcher2.preferences.Settings.ClockWidgetSettings.ClockStyle import de.mm20.launcher2.preferences.Settings.ClockWidgetSettings.ClockWidgetColors import de.mm20.launcher2.preferences.Settings.ClockWidgetSettings.ClockWidgetLayout import de.mm20.launcher2.ui.base.LocalTime import de.mm20.launcher2.ui.launcher.widgets.clock.clocks.* -import de.mm20.launcher2.ui.launcher.widgets.clock.parts.FavoritesPartProvider import de.mm20.launcher2.ui.launcher.widgets.clock.parts.PartProvider import de.mm20.launcher2.ui.locals.LocalPreferDarkContentOverWallpaper @@ -41,8 +41,7 @@ fun ClockWidget( viewModel.updateTime(time) } - val partProvider by remember { viewModel.getActivePart(context) }.collectAsState(null) - val withFavoriteBar by viewModel.withFavorites.observeAsState() + val partProviders by remember { viewModel.getActiveParts(context) }.collectAsStateWithLifecycle(emptyList()) Box( modifier = Modifier @@ -76,21 +75,11 @@ fun ClockWidget( Clock(clockStyle, ClockWidgetLayout.Vertical) } - DynamicZone( - modifier = if (true == withFavoriteBar) { - Modifier.padding(bottom = 8.dp, top = 8.dp) - } else { - Modifier.padding(bottom = 16.dp) - }, - layout = ClockWidgetLayout.Vertical, - provider = partProvider, - ) - - if (true == withFavoriteBar) { + for (part in partProviders) { DynamicZone( - modifier = Modifier.padding(bottom = 16.dp), + modifier = Modifier.padding(bottom = 8.dp), layout = ClockWidgetLayout.Vertical, - provider = viewModel.favoritesPartProvider, + provider = part, ) } } @@ -110,7 +99,7 @@ fun ClockWidget( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween ) { - if (true == withFavoriteBar) { + if (partProviders.size > 1) { HorizontalPager( pageCount = 2, beyondBoundsPageCount = 1, @@ -119,17 +108,14 @@ fun ClockWidget( DynamicZone( modifier = Modifier.fillMaxWidth(), layout = ClockWidgetLayout.Horizontal, - provider = when (it) { - 0 -> viewModel.favoritesPartProvider - else -> partProvider - } + provider = partProviders[it], ) } - } else { + } else if (partProviders.isNotEmpty()) { DynamicZone( modifier = Modifier.weight(1f), layout = ClockWidgetLayout.Horizontal, - provider = partProvider + provider = partProviders[0], ) } Box( diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/clock/ClockWidgetVM.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/clock/ClockWidgetVM.kt index a96b610d..5b334b5d 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/clock/ClockWidgetVM.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/clock/ClockWidgetVM.kt @@ -1,9 +1,7 @@ package de.mm20.launcher2.ui.launcher.widgets.clock -import android.content.BroadcastReceiver import android.content.Context import android.content.Intent -import android.content.IntentFilter import android.provider.AlarmClock import android.util.Log import androidx.lifecycle.ViewModel @@ -11,55 +9,47 @@ import androidx.lifecycle.asLiveData import androidx.lifecycle.viewModelScope import de.mm20.launcher2.ktx.tryStartActivity import de.mm20.launcher2.preferences.LauncherDataStore -import de.mm20.launcher2.ui.launcher.widgets.clock.parts.* -import kotlinx.coroutines.channels.awaitClose -import kotlinx.coroutines.channels.trySendBlocking -import kotlinx.coroutines.flow.* -import kotlinx.coroutines.launch +import de.mm20.launcher2.ui.launcher.widgets.clock.parts.AlarmPartProvider +import de.mm20.launcher2.ui.launcher.widgets.clock.parts.BatteryPartProvider +import de.mm20.launcher2.ui.launcher.widgets.clock.parts.DatePartProvider +import de.mm20.launcher2.ui.launcher.widgets.clock.parts.FavoritesPartProvider +import de.mm20.launcher2.ui.launcher.widgets.clock.parts.MusicPartProvider +import de.mm20.launcher2.ui.launcher.widgets.clock.parts.PartProvider +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.channelFlow +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.stateIn import org.koin.core.component.KoinComponent import org.koin.core.component.inject class ClockWidgetVM : ViewModel(), KoinComponent { private val dataStore: LauncherDataStore by inject() - private val partProviders = MutableStateFlow>(emptyList()) + private val partProviders = dataStore.data.map { it.clockWidget }.distinctUntilChanged().map { + val providers = mutableListOf() + if (it.datePart) providers += DatePartProvider() + if (it.favoritesPart) providers += FavoritesPartProvider() + if (it.musicPart) providers += MusicPartProvider() + if (it.batteryPart) providers += BatteryPartProvider() + if (it.alarmPart) providers += AlarmPartProvider() + providers + }.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), emptyList()) - init { - viewModelScope.launch { - dataStore.data.map { it.clockWidget }.distinctUntilChanged().collectLatest { - val providers = mutableListOf( - DatePartProvider() - ) - if (it.musicPart) providers += MusicPartProvider() - if (it.batteryPart) providers += BatteryPartProvider() - if (it.alarmPart) providers += AlarmPartProvider() - partProviders.value = providers - } - } - } - - val withFavorites = dataStore.data.map { it.clockWidget.favoritesPart }.asLiveData() - val favoritesPartProvider = FavoritesPartProvider() - - val time = MutableStateFlow(System.currentTimeMillis()) - - fun getActivePart(context: Context): Flow = channelFlow { + fun getActiveParts(context: Context): Flow> = channelFlow { partProviders.collectLatest { providers -> if (providers.isEmpty()) { - send(null) + send(emptyList()) return@collectLatest } - val rankings = providers.map { it.getRanking(context) } + val rankings = providers.map { it.getRanking(context).map { r -> r to it } } combine(rankings) { r -> - var prov = providers[0] - var ranking = r[0] - for (i in 1 until providers.size) { - if (ranking < r[i]) { - prov = providers[i] - ranking = r[i] - } - } - return@combine prov + val sorted = r.sortedBy { it.first } + sorted.takeLast(if (sorted.last().second is FavoritesPartProvider) 2 else 1) + .map { it.second } }.collectLatest { send(it) } diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/clock/parts/FavoritesPartProvider.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/clock/parts/FavoritesPartProvider.kt index 8832c072..8d4fbff6 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/clock/parts/FavoritesPartProvider.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/clock/parts/FavoritesPartProvider.kt @@ -30,7 +30,7 @@ class FavoritesPartProvider : PartProvider, KoinComponent { private val dataStore: LauncherDataStore by inject() override fun getRanking(context: Context): Flow = flow { - emit(2) + emit(Int.MAX_VALUE) } @Composable diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/clockwidget/ClockWidgetSettingsScreen.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/clockwidget/ClockWidgetSettingsScreen.kt index aa786d58..257af212 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/clockwidget/ClockWidgetSettingsScreen.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/clockwidget/ClockWidgetSettingsScreen.kt @@ -75,6 +75,20 @@ fun ClockWidgetSettingsScreen() { value = fillHeight == true, onValueChanged = { viewModel.setFillHeight(it) } ) + } + } + item { + PreferenceCategory { + val datePart by viewModel.datePart.observeAsState() + SwitchPreference( + title = stringResource(R.string.preference_clockwidget_date_part), + summary = stringResource(R.string.preference_clockwidget_date_part_summary), + icon = Icons.Rounded.Today, + value = datePart == true, + onValueChanged = { + viewModel.setDatePart(it) + }, + ) val favoritesPart by viewModel.favoritesPart.observeAsState() SwitchPreference( title = stringResource(R.string.preference_clockwidget_favorites_part), diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/clockwidget/ClockWidgetSettingsScreenVM.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/clockwidget/ClockWidgetSettingsScreenVM.kt index f9f0717c..b83a77c8 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/clockwidget/ClockWidgetSettingsScreenVM.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/clockwidget/ClockWidgetSettingsScreenVM.kt @@ -66,6 +66,19 @@ class ClockWidgetSettingsScreenVM : ViewModel(), KoinComponent { } } + val datePart = dataStore.data.map { it.clockWidget.datePart }.asLiveData() + fun setDatePart(datePart: Boolean) { + viewModelScope.launch { + dataStore.updateData { + it.toBuilder() + .setClockWidget( + it.clockWidget.toBuilder() + .setDatePart(datePart) + ).build() + } + } + } + val favoritesPart = dataStore.data.map { it.clockWidget.favoritesPart }.asLiveData() fun setFavoritesPart(favoritesPart: Boolean) { viewModelScope.launch { diff --git a/core/preferences/src/main/java/de/mm20/launcher2/preferences/DataStore.kt b/core/preferences/src/main/java/de/mm20/launcher2/preferences/DataStore.kt index 8d80b9f3..a805aae5 100644 --- a/core/preferences/src/main/java/de/mm20/launcher2/preferences/DataStore.kt +++ b/core/preferences/src/main/java/de/mm20/launcher2/preferences/DataStore.kt @@ -22,7 +22,7 @@ internal val Context.dataStore: LauncherDataStore by dataStore( } ) -internal const val SchemaVersion = 12 +internal const val SchemaVersion = 13 internal fun getMigrations(context: Context): List> { return listOf( @@ -38,5 +38,6 @@ internal fun getMigrations(context: Context): List> { Migration_9_10(), Migration_10_11(), Migration_11_12(), + Migration_12_13(), ) } \ No newline at end of file diff --git a/core/preferences/src/main/java/de/mm20/launcher2/preferences/Defaults.kt b/core/preferences/src/main/java/de/mm20/launcher2/preferences/Defaults.kt index 019ccf66..e0616da7 100644 --- a/core/preferences/src/main/java/de/mm20/launcher2/preferences/Defaults.kt +++ b/core/preferences/src/main/java/de/mm20/launcher2/preferences/Defaults.kt @@ -51,6 +51,7 @@ fun createFactorySettings(context: Context): Settings { .setAlarmPart(true) .setBatteryPart(true) .setMusicPart(true) + .setDatePart(true) .setFavoritesPart(false) .setFillHeight(true) .build() diff --git a/core/preferences/src/main/java/de/mm20/launcher2/preferences/migrations/Migration_12_13.kt b/core/preferences/src/main/java/de/mm20/launcher2/preferences/migrations/Migration_12_13.kt new file mode 100644 index 00000000..74cd7127 --- /dev/null +++ b/core/preferences/src/main/java/de/mm20/launcher2/preferences/migrations/Migration_12_13.kt @@ -0,0 +1,14 @@ +package de.mm20.launcher2.preferences.migrations + +import de.mm20.launcher2.preferences.Settings + +class Migration_12_13: VersionedMigration(12, 13) { + override suspend fun applyMigrations(builder: Settings.Builder): Settings.Builder { + return builder + .setClockWidget( + builder.clockWidget.toBuilder() + .setDatePart(true) + .build() + ) + } +} \ No newline at end of file diff --git a/core/preferences/src/main/proto/settings.proto b/core/preferences/src/main/proto/settings.proto index 948dddf9..59cce7a4 100644 --- a/core/preferences/src/main/proto/settings.proto +++ b/core/preferences/src/main/proto/settings.proto @@ -116,7 +116,7 @@ message Settings { EmptyClock = 4; } ClockStyle clock_style = 2; - reserved 3; + bool date_part = 3; bool music_part = 4; bool battery_part = 5; bool alarm_part = 6;