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 1c58158b4..74217ea85 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 @@ -17,33 +17,47 @@ import de.mm20.launcher2.ui.launcher.widgets.clock.parts.MusicPartProvider import de.mm20.launcher2.ui.launcher.widgets.clock.parts.PartProvider import de.mm20.launcher2.ui.launcher.widgets.clock.parts.SmartspacerPartProvider import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.channelFlow import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.launch import org.koin.core.component.KoinComponent import org.koin.core.component.inject class ClockWidgetVM : ViewModel(), KoinComponent { private val settings: ClockWidgetSettings by inject() - private val partProviders = settings.parts.combine(settings.useSmartspacer) { p, s -> - p to s - }.map { (parts, smartspacer) -> - if (smartspacer && isAtLeastApiLevel(29)) { - return@map listOf(SmartspacerPartProvider()) - } + /** + * Kept for the lifetime of the ViewModel instead of being rebuilt whenever the clock widget + * is subscribed again - which happens on every return to the home screen, because the + * launcher stops while it is in the background. Providers cache the data behind their + * ranking, so a fresh instance starts at ranking 0 and makes its part disappear until its + * query returns; the agenda part would blink on every visit that way. + */ + private val partProviders = MutableStateFlow>(emptyList()) - val providers = mutableListOf() - if (parts.date) providers += DatePartProvider() - if (parts.calendar) providers += CalendarPartProvider() - if (parts.music) providers += MusicPartProvider() - providers += BatteryPartProvider(parts.battery) - if (parts.alarm) providers += AlarmPartProvider() - providers - }.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), emptyList()) + init { + viewModelScope.launch { + settings.parts.combine(settings.useSmartspacer) { p, s -> p to s } + .collect { (parts, smartspacer) -> + partProviders.value = if (smartspacer && isAtLeastApiLevel(29)) { + listOf(SmartspacerPartProvider()) + } else { + buildList { + if (parts.date) add(DatePartProvider()) + if (parts.calendar) add(CalendarPartProvider()) + if (parts.music) add(MusicPartProvider()) + add(BatteryPartProvider(parts.battery)) + if (parts.alarm) add(AlarmPartProvider()) + } + } + } + } + } fun getActiveParts(context: Context): Flow> = channelFlow { partProviders.collectLatest { providers ->