diff --git a/database/src/main/java/de/mm20/launcher2/database/SearchDao.kt b/database/src/main/java/de/mm20/launcher2/database/SearchDao.kt index 19fff42d..baad5026 100644 --- a/database/src/main/java/de/mm20/launcher2/database/SearchDao.kt +++ b/database/src/main/java/de/mm20/launcher2/database/SearchDao.kt @@ -18,8 +18,8 @@ interface SearchDao { @Insert(onConflict = OnConflictStrategy.IGNORE) fun insertSkipExisting(items: FavoritesItemEntity) - @Query("SELECT * FROM Searchable WHERE pinned > 0 AND (NOT :excludeCalendarEvents OR NOT `key` LIKE 'calendar://%') ORDER BY pinned DESC, launchCount DESC") - fun getFavorites(excludeCalendarEvents: Boolean = false): Flow> + @Query("SELECT * FROM Searchable WHERE pinned > 0 AND (NOT :excludeCalendarEvents OR NOT `key` LIKE 'calendar://%') ORDER BY pinned DESC, launchCount DESC LIMIT :limit") + fun getFavorites(excludeCalendarEvents: Boolean = false, limit: Int): Flow> @Query("SELECT * FROM Searchable WHERE pinned > 0 AND `key` LIKE 'calendar://%' ORDER BY pinned DESC, launchCount DESC") fun getPinnedCalendarEvents(): Flow> diff --git a/favorites/src/main/java/de/mm20/launcher2/favorites/FavoritesItem.kt b/favorites/src/main/java/de/mm20/launcher2/favorites/FavoritesItem.kt index b9fbdd04..43d685a8 100644 --- a/favorites/src/main/java/de/mm20/launcher2/favorites/FavoritesItem.kt +++ b/favorites/src/main/java/de/mm20/launcher2/favorites/FavoritesItem.kt @@ -17,8 +17,8 @@ data class FavoritesItem( var launchCount: Int, var pinPosition: Int, var hidden: Boolean -) : KoinComponent { - private val serializer: SearchableSerializer by inject { parametersOf(searchable) } +) { + private val serializer: SearchableSerializer = getSerializer(searchable) fun toDatabaseEntity(): FavoritesItemEntity? { val serializer = serializer diff --git a/favorites/src/main/java/de/mm20/launcher2/favorites/FavoritesRepository.kt b/favorites/src/main/java/de/mm20/launcher2/favorites/FavoritesRepository.kt index 6ca66edb..735525d3 100644 --- a/favorites/src/main/java/de/mm20/launcher2/favorites/FavoritesRepository.kt +++ b/favorites/src/main/java/de/mm20/launcher2/favorites/FavoritesRepository.kt @@ -1,21 +1,41 @@ package de.mm20.launcher2.favorites import android.content.Context +import de.mm20.launcher2.appshortcuts.AppShortcutDeserializer +import de.mm20.launcher2.appshortcuts.AppShortcutSerializer +import de.mm20.launcher2.calendar.CalendarEventDeserializer +import de.mm20.launcher2.calendar.CalendarEventSerializer +import de.mm20.launcher2.contacts.ContactDeserializer +import de.mm20.launcher2.contacts.ContactSerializer import de.mm20.launcher2.database.AppDatabase import de.mm20.launcher2.database.entities.FavoritesItemEntity +import de.mm20.launcher2.files.* import de.mm20.launcher2.ktx.ceilToInt -import de.mm20.launcher2.preferences.LauncherDataStore +import de.mm20.launcher2.search.NullDeserializer +import de.mm20.launcher2.search.NullSerializer import de.mm20.launcher2.search.SearchableDeserializer -import de.mm20.launcher2.search.data.CalendarEvent -import de.mm20.launcher2.search.data.Searchable +import de.mm20.launcher2.search.SearchableSerializer +import de.mm20.launcher2.search.data.* +import de.mm20.launcher2.websites.WebsiteDeserializer +import de.mm20.launcher2.websites.WebsiteSerializer +import de.mm20.launcher2.wikipedia.WikipediaDeserializer +import de.mm20.launcher2.wikipedia.WikipediaSerializer import kotlinx.coroutines.* -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.channelFlow +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.flow.map import org.koin.core.component.KoinComponent import org.koin.core.component.get import org.koin.core.parameter.parametersOf interface FavoritesRepository { - fun getFavorites(excludeCalendarEvents: Boolean = false): Flow> + fun getFavorites( + columns: Int, + maxRows: Int? = null, + excludeCalendarEvents: Boolean = false + ): Flow> + fun getPinnedCalendarEvents(): Flow> fun isPinned(searchable: Searchable): Flow fun pinItem(searchable: Searchable) @@ -32,42 +52,42 @@ interface FavoritesRepository { internal class FavoritesRepositoryImpl( private val context: Context, private val database: AppDatabase, - private val dataStore: LauncherDataStore ) : FavoritesRepository, KoinComponent { private val scope = CoroutineScope(Job() + Dispatchers.Default) - override fun getFavorites(excludeCalendarEvents: Boolean): Flow> = + override fun getFavorites( + columns: Int, + maxRows: Int?, + excludeCalendarEvents: Boolean + ): Flow> = channelFlow { - withContext(Dispatchers.IO) { - - val gridColumns = dataStore.data.map { it.grid.columnCount }.distinctUntilChanged() val dao = database.searchDao() - - val pinnedFavorites = dao.getFavorites(excludeCalendarEvents).map { - it.mapNotNull { - val item = fromDatabaseEntity(it).searchable - if (item == null) { - dao.deleteByKey(it.key) - } - return@mapNotNull item - } - } - - pinnedFavorites.collectLatest { pinned -> - gridColumns.collectLatest { columns -> - var favCount = (pinned.size.toDouble() / columns).ceilToInt() * columns - if (pinned.size < columns) favCount += columns - val autoFavs = dao.getAutoFavorites(favCount - pinned.size).mapNotNull { + val pinnedFavorites = + dao.getFavorites(excludeCalendarEvents, columns * (maxRows ?: 20)).map { + it.mapNotNull { val item = fromDatabaseEntity(it).searchable if (item == null) { dao.deleteByKey(it.key) } return@mapNotNull item } - send(pinned + autoFavs) } + + pinnedFavorites.collectLatest { pinned -> + var favCount = (pinned.size.toDouble() / columns).ceilToInt() * columns + if (pinned.size < columns) favCount += columns + val autoFavs = dao.getAutoFavorites( + favCount.coerceAtMost((maxRows ?: 20) * columns) - pinned.size + ).mapNotNull { + val item = fromDatabaseEntity(it).searchable + if (item == null) { + dao.deleteByKey(it.key) + } + return@mapNotNull item + } + send(pinned + autoFavs) } } } @@ -173,7 +193,7 @@ internal class FavoritesRepositoryImpl( private fun fromDatabaseEntity(entity: FavoritesItemEntity): FavoritesItem { - val deserializer: SearchableDeserializer = get { parametersOf(entity.serializedSearchable) } + val deserializer: SearchableDeserializer = getDeserializer(context, entity.serializedSearchable) return FavoritesItem( key = entity.key, searchable = deserializer.deserialize(entity.serializedSearchable.substringAfter("#")), diff --git a/favorites/src/main/java/de/mm20/launcher2/favorites/Module.kt b/favorites/src/main/java/de/mm20/launcher2/favorites/Module.kt index 4d66cc4f..9a0bbc92 100644 --- a/favorites/src/main/java/de/mm20/launcher2/favorites/Module.kt +++ b/favorites/src/main/java/de/mm20/launcher2/favorites/Module.kt @@ -18,80 +18,5 @@ import org.koin.android.ext.koin.androidContext import org.koin.dsl.module val favoritesModule = module { - factory { (searchable: Searchable) -> - if (searchable is LauncherApp) { - return@factory LauncherAppSerializer() - } - if (searchable is AppShortcut) { - return@factory AppShortcutSerializer() - } - if (searchable is CalendarEvent) { - return@factory CalendarEventSerializer() - } - if (searchable is Contact) { - return@factory ContactSerializer() - } - if (searchable is Wikipedia) { - return@factory WikipediaSerializer() - } - if (searchable is GDriveFile) { - return@factory GDriveFileSerializer() - } - if (searchable is OneDriveFile) { - return@factory OneDriveFileSerializer() - } - if (searchable is OwncloudFile) { - return@factory OwncloudFileSerializer() - } - if (searchable is NextcloudFile) { - return@factory NextcloudFileSerializer() - } - if (searchable is LocalFile) { - return@factory LocalFileSerializer() - } - if (searchable is Website) { - return@factory WebsiteSerializer() - } - return@factory NullSerializer() - } - - factory { (serialized: String) -> - val type = serialized.substringBefore("#") - if (type == "app") { - return@factory LauncherAppDeserializer(androidContext()) - } - if (type == "shortcut") { - return@factory AppShortcutDeserializer(androidContext()) - } - if (type == "calendar") { - return@factory CalendarEventDeserializer(androidContext()) - } - if (type == "contact") { - return@factory ContactDeserializer(androidContext()) - } - if (type == "wikipedia") { - return@factory WikipediaDeserializer(androidContext()) - } - if (type == "gdrive") { - return@factory GDriveFileDeserializer() - } - if (type == "onedrive") { - return@factory OneDriveFileDeserializer() - } - if (type == "nextcloud") { - return@factory NextcloudFileDeserializer() - } - if (type == "owncloud") { - return@factory OwncloudFileDeserializer() - } - if (type == "file") { - return@factory LocalFileDeserializer(androidContext()) - } - if (type == "website") { - return@factory WebsiteDeserializer() - } - return@factory NullDeserializer() - } - - single { FavoritesRepositoryImpl(androidContext(), get(), get()) } + single { FavoritesRepositoryImpl(androidContext(), get()) } } \ No newline at end of file diff --git a/favorites/src/main/java/de/mm20/launcher2/favorites/Serialization.kt b/favorites/src/main/java/de/mm20/launcher2/favorites/Serialization.kt new file mode 100644 index 00000000..09cd476f --- /dev/null +++ b/favorites/src/main/java/de/mm20/launcher2/favorites/Serialization.kt @@ -0,0 +1,95 @@ +package de.mm20.launcher2.favorites + +import android.content.Context +import de.mm20.launcher2.appshortcuts.AppShortcutDeserializer +import de.mm20.launcher2.appshortcuts.AppShortcutSerializer +import de.mm20.launcher2.calendar.CalendarEventDeserializer +import de.mm20.launcher2.calendar.CalendarEventSerializer +import de.mm20.launcher2.contacts.ContactDeserializer +import de.mm20.launcher2.contacts.ContactSerializer +import de.mm20.launcher2.files.* +import de.mm20.launcher2.search.NullDeserializer +import de.mm20.launcher2.search.NullSerializer +import de.mm20.launcher2.search.SearchableDeserializer +import de.mm20.launcher2.search.SearchableSerializer +import de.mm20.launcher2.search.data.* +import de.mm20.launcher2.websites.WebsiteDeserializer +import de.mm20.launcher2.websites.WebsiteSerializer +import de.mm20.launcher2.wikipedia.WikipediaDeserializer +import de.mm20.launcher2.wikipedia.WikipediaSerializer + + +internal fun getSerializer(searchable: Searchable?): SearchableSerializer { + if (searchable is LauncherApp) { + return LauncherAppSerializer() + } + if (searchable is AppShortcut) { + return AppShortcutSerializer() + } + if (searchable is CalendarEvent) { + return CalendarEventSerializer() + } + if (searchable is Contact) { + return ContactSerializer() + } + if (searchable is Wikipedia) { + return WikipediaSerializer() + } + if (searchable is GDriveFile) { + return GDriveFileSerializer() + } + if (searchable is OneDriveFile) { + return OneDriveFileSerializer() + } + if (searchable is OwncloudFile) { + return OwncloudFileSerializer() + } + if (searchable is NextcloudFile) { + return NextcloudFileSerializer() + } + if (searchable is LocalFile) { + return LocalFileSerializer() + } + if (searchable is Website) { + return WebsiteSerializer() + } + return NullSerializer() +} + +internal fun getDeserializer(context: Context, serialized: String): SearchableDeserializer { + val type = serialized.substringBefore("#") + if (type == "app") { + return LauncherAppDeserializer(context) + } + if (type == "shortcut") { + return AppShortcutDeserializer(context) + } + if (type == "calendar") { + return CalendarEventDeserializer(context) + } + if (type == "contact") { + return ContactDeserializer(context) + } + if (type == "wikipedia") { + return WikipediaDeserializer(context) + } + if (type == "gdrive") { + return GDriveFileDeserializer() + } + if (type == "onedrive") { + return OneDriveFileDeserializer() + } + if (type == "nextcloud") { + return NextcloudFileDeserializer() + } + if (type == "owncloud") { + return OwncloudFileDeserializer() + } + if (type == "file") { + return LocalFileDeserializer(context) + } + if (type == "website") { + return WebsiteDeserializer() + } + return NullDeserializer() +} \ No newline at end of file diff --git a/i18n/src/main/res/values/strings.xml b/i18n/src/main/res/values/strings.xml index f916a7bc..bf9dc86b 100644 --- a/i18n/src/main/res/values/strings.xml +++ b/i18n/src/main/res/values/strings.xml @@ -485,6 +485,8 @@ Select a clock Date Show the current date + Favorites + Show the first row of pinned items Media Show media controls when there is an active media session Battery diff --git a/preferences/src/main/java/de/mm20/launcher2/preferences/Defaults.kt b/preferences/src/main/java/de/mm20/launcher2/preferences/Defaults.kt index 5e9d5bb1..e36cca44 100644 --- a/preferences/src/main/java/de/mm20/launcher2/preferences/Defaults.kt +++ b/preferences/src/main/java/de/mm20/launcher2/preferences/Defaults.kt @@ -39,6 +39,7 @@ fun createFactorySettings(context: Context): Settings { .setBatteryPart(true) .setDatePart(true) .setMusicPart(true) + .setFavoritesPart(false) .build() ) .setFavorites( diff --git a/preferences/src/main/proto/settings.proto b/preferences/src/main/proto/settings.proto index ac608ee8..d8ad4f38 100644 --- a/preferences/src/main/proto/settings.proto +++ b/preferences/src/main/proto/settings.proto @@ -56,6 +56,7 @@ message Settings { bool music_part = 4; bool battery_part = 5; bool alarm_part = 6; + bool favorites_part = 7; } ClockWidgetSettings clock_widget = 7; diff --git a/ui/src/main/java/de/mm20/launcher2/ui/base/ProvideSettings.kt b/ui/src/main/java/de/mm20/launcher2/ui/base/ProvideSettings.kt index 04713652..702dd79e 100644 --- a/ui/src/main/java/de/mm20/launcher2/ui/base/ProvideSettings.kt +++ b/ui/src/main/java/de/mm20/launcher2/ui/base/ProvideSettings.kt @@ -35,8 +35,9 @@ fun ProvideSettings( val favoritesEnabled by remember { combine( widgetRepository.isFavoritesWidgetEnabled(), - dataStore.data.map { it.favorites.enabled } - ) { a, b -> a || b }.distinctUntilChanged() + dataStore.data.map { it.favorites.enabled }, + dataStore.data.map { it.clockWidget.favoritesPart }, + ) { a, b, c -> a || b || c }.distinctUntilChanged() }.collectAsState(true) val gridColumns by remember { diff --git a/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/SearchVM.kt b/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/SearchVM.kt index 880dc713..598e5ecd 100644 --- a/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/SearchVM.kt +++ b/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/SearchVM.kt @@ -3,7 +3,6 @@ package de.mm20.launcher2.ui.launcher.search import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel -import androidx.lifecycle.asLiveData import androidx.lifecycle.viewModelScope import de.mm20.launcher2.applications.AppRepository import de.mm20.launcher2.appshortcuts.AppShortcutRepository @@ -75,8 +74,13 @@ class SearchVM : ViewModel(), KoinComponent { return@collectLatest } widgetRepository.isCalendarWidgetEnabled().collectLatest { excludeCalendar -> - favoritesRepository.getFavorites(excludeCalendarEvents = excludeCalendar).collectLatest { - favorites.value = it + dataStore.data.map { it.grid.columnCount }.collectLatest { columns -> + favoritesRepository.getFavorites( + columns = columns, + excludeCalendarEvents = excludeCalendar + ).collectLatest { + favorites.value = it + } } } } diff --git a/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/grid/GridItem.kt b/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/grid/GridItem.kt index 6e75f550..de4b8bed 100644 --- a/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/grid/GridItem.kt +++ b/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/grid/GridItem.kt @@ -1,7 +1,6 @@ package de.mm20.launcher2.ui.launcher.search.common import androidx.activity.compose.BackHandler -import androidx.appcompat.app.AppCompatActivity import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.animation.core.animateFloatAsState import androidx.compose.animation.core.tween @@ -42,7 +41,7 @@ import kotlinx.coroutines.delay @OptIn(ExperimentalFoundationApi::class) @Composable -fun GridItem(modifier: Modifier = Modifier, item: Searchable) { +fun GridItem(modifier: Modifier = Modifier, item: Searchable, showLabels: Boolean = true) { val viewModel = remember(item.key) { GridItemVM(item) } val context = LocalContext.current @@ -74,16 +73,18 @@ fun GridItem(modifier: Modifier = Modifier, item: Searchable) { showPopup = true } ) - Text( - modifier = Modifier - .fillMaxWidth() - .padding(top = 8.dp), - text = item.label, - textAlign = TextAlign.Center, - style = MaterialTheme.typography.bodySmall, - maxLines = 1, - overflow = TextOverflow.Ellipsis - ) + if (showLabels) { + Text( + modifier = Modifier + .fillMaxWidth() + .padding(top = 8.dp), + text = item.label, + textAlign = TextAlign.Center, + style = MaterialTheme.typography.bodySmall, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } if (showPopup) { ItemPopup(origin = bounds, searchable = item, onDismissRequest = { showPopup = false }) } diff --git a/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/grid/SearchResultGrid.kt b/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/grid/SearchResultGrid.kt index bd190ff5..68db6076 100644 --- a/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/grid/SearchResultGrid.kt +++ b/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/grid/SearchResultGrid.kt @@ -14,9 +14,9 @@ import kotlin.math.ceil fun SearchResultGrid( items: List, modifier: Modifier = Modifier, + showLabels: Boolean = true, + columns: Int = LocalGridColumns.current, ) { - - val columns = LocalGridColumns.current Column( modifier = modifier .animateContentSize() @@ -31,7 +31,9 @@ fun SearchResultGrid( GridItem( modifier = Modifier .weight(1f) - .padding(4.dp, 8.dp), item = item + .padding(4.dp, 8.dp), + item = item, + showLabels = showLabels ) } else { Spacer(modifier = Modifier.weight(1f)) diff --git a/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/clock/ClockWidget.kt b/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/clock/ClockWidget.kt index b2b3bdf9..7fee5767 100644 --- a/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/clock/ClockWidget.kt +++ b/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/clock/ClockWidget.kt @@ -56,7 +56,6 @@ fun ClockWidget( if (layout == ClockWidgetLayout.Vertical) { Column( horizontalAlignment = Alignment.CenterHorizontally, - modifier = Modifier.height(IntrinsicSize.Min), ) { Box( modifier = Modifier.clickable( diff --git a/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/clock/ClockWidgetVM.kt b/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/clock/ClockWidgetVM.kt index da4cc1be..2bc6d29e 100644 --- a/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/clock/ClockWidgetVM.kt +++ b/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/clock/ClockWidgetVM.kt @@ -32,6 +32,7 @@ class ClockWidgetVM : ViewModel(), KoinComponent { if (it.musicPart) providers += MusicPartProvider() if (it.batteryPart) providers += BatteryPartProvider() if (it.alarmPart) providers += AlarmPartProvider() + if (it.favoritesPart) providers += FavoritesPartProvider() partProviders.value = providers } } @@ -48,9 +49,11 @@ class ClockWidgetVM : ViewModel(), KoinComponent { val rankings = providers.map { it.getRanking(context) } combine(rankings) { r -> var prov = providers[0] + var ranking = r[0] for (i in 1 until providers.size) { - if (r[i - 1] < r[i]) { + if (ranking < r[i]) { prov = providers[i] + ranking = r[i] } } return@combine prov diff --git a/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/clock/parts/FavoritesPartProvider.kt b/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/clock/parts/FavoritesPartProvider.kt new file mode 100644 index 00000000..d3e22558 --- /dev/null +++ b/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/clock/parts/FavoritesPartProvider.kt @@ -0,0 +1,69 @@ +package de.mm20.launcher2.ui.launcher.widgets.clock.parts + +import android.content.Context +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentHeight +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import de.mm20.launcher2.favorites.FavoritesRepository +import de.mm20.launcher2.preferences.LauncherDataStore +import de.mm20.launcher2.preferences.Settings.ClockWidgetSettings.ClockWidgetLayout +import de.mm20.launcher2.ui.launcher.search.common.grid.SearchResultGrid +import de.mm20.launcher2.widgets.WidgetRepository +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.flow.map +import org.koin.core.component.KoinComponent +import org.koin.core.component.inject + +class FavoritesPartProvider : PartProvider, KoinComponent { + + private val favoritesRepository: FavoritesRepository by inject() + private val widgetRepository: WidgetRepository by inject() + private val dataStore: LauncherDataStore by inject() + + override fun getRanking(context: Context): Flow = flow { + emit(2) + } + + @Composable + override fun Component(layout: ClockWidgetLayout) { + val columns by remember(layout) { + dataStore.data.map { + val c = it.grid.columnCount + if (layout == ClockWidgetLayout.Horizontal) c - 2 else c + } + }.collectAsState(0) + val excludeCalendar by remember { widgetRepository.isCalendarWidgetEnabled() }.collectAsState( + true + ) + + val favorites by remember(columns, excludeCalendar, layout) { + favoritesRepository.getFavorites( + columns = columns, + maxRows = 1, + excludeCalendarEvents = excludeCalendar + ) + }.collectAsState(emptyList()) + + + Column( + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 8.dp) + .wrapContentHeight() + ) { + SearchResultGrid( + items = favorites, showLabels = false, columns = columns, + ) + + } + } +} \ No newline at end of file diff --git a/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/favorites/FavoritesWidgetVM.kt b/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/favorites/FavoritesWidgetVM.kt index e040c8e6..a7871d66 100644 --- a/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/favorites/FavoritesWidgetVM.kt +++ b/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/favorites/FavoritesWidgetVM.kt @@ -16,13 +16,19 @@ import org.koin.core.component.inject class FavoritesWidgetVM: ViewModel(), KoinComponent { private val favoritesRepository: FavoritesRepository by inject() private val widgetRepository: WidgetRepository by inject() + private val dataStore: LauncherDataStore by inject() val favorites = MutableLiveData>(emptyList()) init { viewModelScope.launch { widgetRepository.isCalendarWidgetEnabled().collectLatest { excludeCalendar -> - favoritesRepository.getFavorites(excludeCalendarEvents = excludeCalendar).collectLatest { - favorites.value = it + dataStore.data.map { it.grid.columnCount }.collectLatest { columns -> + favoritesRepository.getFavorites( + columns = columns, + excludeCalendarEvents = excludeCalendar + ).collectLatest { + favorites.value = it + } } } } diff --git a/ui/src/main/java/de/mm20/launcher2/ui/settings/clockwidget/ClockWidgetSettingsScreen.kt b/ui/src/main/java/de/mm20/launcher2/ui/settings/clockwidget/ClockWidgetSettingsScreen.kt index 4df06da3..ee92a28b 100644 --- a/ui/src/main/java/de/mm20/launcher2/ui/settings/clockwidget/ClockWidgetSettingsScreen.kt +++ b/ui/src/main/java/de/mm20/launcher2/ui/settings/clockwidget/ClockWidgetSettingsScreen.kt @@ -66,6 +66,20 @@ fun ClockWidgetSettingsScreen() { viewModel.setDatePart(it) } ) + val favoritesPart by viewModel.favoritesPart.observeAsState() + SwitchPreference( + title = stringResource(R.string.preference_clockwidget_favorites_part), + summary = stringResource(R.string.preference_clockwidget_favorites_part_summary), + icon = Icons.Rounded.Star, + value = favoritesPart == true, + onValueChanged = { + viewModel.setFavoritesPart(it) + } + ) + } + } + item { + PreferenceCategory { val musicPart by viewModel.musicPart.observeAsState() SwitchPreference( title = stringResource(R.string.preference_clockwidget_music_part), diff --git a/ui/src/main/java/de/mm20/launcher2/ui/settings/clockwidget/ClockWidgetSettingsScreenVM.kt b/ui/src/main/java/de/mm20/launcher2/ui/settings/clockwidget/ClockWidgetSettingsScreenVM.kt index 771c052b..5470e183 100644 --- a/ui/src/main/java/de/mm20/launcher2/ui/settings/clockwidget/ClockWidgetSettingsScreenVM.kt +++ b/ui/src/main/java/de/mm20/launcher2/ui/settings/clockwidget/ClockWidgetSettingsScreenVM.kt @@ -46,6 +46,29 @@ class ClockWidgetSettingsScreenVM : ViewModel(), KoinComponent { .setClockWidget( it.clockWidget.toBuilder() .setDatePart(datePart) + .also { + if (datePart) { + it.setFavoritesPart(false) + } + } + ).build() + } + } + } + + val favoritesPart = dataStore.data.map { it.clockWidget.favoritesPart }.asLiveData() + fun setFavoritesPart(favoritesPart: Boolean) { + viewModelScope.launch { + dataStore.updateData { + it.toBuilder() + .setClockWidget( + it.clockWidget.toBuilder() + .setFavoritesPart(favoritesPart) + .also { + if (favoritesPart) { + it.setDatePart(false) + } + } ).build() } }