Add favorites widget

This commit is contained in:
MM20 2022-03-30 22:29:20 +02:00
parent a86d453f4e
commit 0b7704cdf2
No known key found for this signature in database
GPG Key ID: 0B61A8F2DEAFA389
7 changed files with 82 additions and 2 deletions

View File

@ -204,6 +204,7 @@
<string name="widget_name_weather">Weather</string> <string name="widget_name_weather">Weather</string>
<string name="widget_name_calendar">Calendar</string> <string name="widget_name_calendar">Calendar</string>
<string name="widget_name_music">Music</string> <string name="widget_name_music">Music</string>
<string name="widget_name_favorites">Favorites</string>
<string name="widget_add_widget">Add widget</string> <string name="widget_add_widget">Add widget</string>
<!-- Add a third party widget (=a standard Android app widget) --> <!-- Add a third party widget (=a standard Android app widget) -->
<string name="widget_add_external">More</string> <string name="widget_add_external">More</string>

View File

@ -7,6 +7,8 @@ import de.mm20.launcher2.ui.component.ProvideIconShape
import de.mm20.launcher2.ui.locals.LocalCardStyle import de.mm20.launcher2.ui.locals.LocalCardStyle
import de.mm20.launcher2.ui.locals.LocalFavoritesEnabled import de.mm20.launcher2.ui.locals.LocalFavoritesEnabled
import de.mm20.launcher2.ui.locals.LocalGridColumns import de.mm20.launcher2.ui.locals.LocalGridColumns
import de.mm20.launcher2.widgets.WidgetRepository
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import org.koin.androidx.compose.inject import org.koin.androidx.compose.inject
@ -16,6 +18,7 @@ fun ProvideSettings(
content: @Composable () -> Unit content: @Composable () -> Unit
) { ) {
val dataStore: LauncherDataStore by inject() val dataStore: LauncherDataStore by inject()
val widgetRepository: WidgetRepository by inject()
val cardStyle by remember { val cardStyle by remember {
dataStore.data.map { it.cards }.distinctUntilChanged() dataStore.data.map { it.cards }.distinctUntilChanged()
@ -30,7 +33,10 @@ fun ProvideSettings(
}.collectAsState(Settings.IconSettings.IconShape.Circle) }.collectAsState(Settings.IconSettings.IconShape.Circle)
val favoritesEnabled by remember { val favoritesEnabled by remember {
dataStore.data.map { it.favorites.enabled }.distinctUntilChanged() combine(
widgetRepository.isFavoritesWidgetEnabled(),
dataStore.data.map { it.favorites.enabled }
) { a, b -> a || b }.distinctUntilChanged()
}.collectAsState(true) }.collectAsState(true)
val gridColumns by remember { val gridColumns by remember {

View File

@ -25,6 +25,7 @@ import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.component.LauncherCard import de.mm20.launcher2.ui.component.LauncherCard
import de.mm20.launcher2.ui.launcher.widgets.calendar.CalendarWidget import de.mm20.launcher2.ui.launcher.widgets.calendar.CalendarWidget
import de.mm20.launcher2.ui.launcher.widgets.external.ExternalWidget import de.mm20.launcher2.ui.launcher.widgets.external.ExternalWidget
import de.mm20.launcher2.ui.launcher.widgets.favorites.FavoritesWidget
import de.mm20.launcher2.ui.launcher.widgets.music.MusicWidget import de.mm20.launcher2.ui.launcher.widgets.music.MusicWidget
import de.mm20.launcher2.ui.launcher.widgets.weather.WeatherWidget import de.mm20.launcher2.ui.launcher.widgets.weather.WeatherWidget
import de.mm20.launcher2.widgets.* import de.mm20.launcher2.widgets.*
@ -120,6 +121,9 @@ fun WidgetItem(
is CalendarWidget -> { is CalendarWidget -> {
CalendarWidget() CalendarWidget()
} }
is FavoritesWidget -> {
FavoritesWidget()
}
is ExternalWidget -> { is ExternalWidget -> {
var height by remember(widget) { mutableStateOf(widget.height) } var height by remember(widget) { mutableStateOf(widget.height) }
Column { Column {

View File

@ -0,0 +1,15 @@
package de.mm20.launcher2.ui.launcher.widgets.favorites
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.lifecycle.viewmodel.compose.viewModel
import de.mm20.launcher2.ui.launcher.search.common.grid.SearchResultGrid
@Composable
fun FavoritesWidget() {
val viewModel: FavoritesWidgetVM = viewModel()
val favorites by viewModel.favorites.observeAsState(emptyList())
SearchResultGrid(favorites)
}

View File

@ -0,0 +1,30 @@
package de.mm20.launcher2.ui.launcher.widgets.favorites
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import de.mm20.launcher2.favorites.FavoritesRepository
import de.mm20.launcher2.preferences.LauncherDataStore
import de.mm20.launcher2.search.data.Searchable
import de.mm20.launcher2.widgets.WidgetRepository
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
class FavoritesWidgetVM: ViewModel(), KoinComponent {
private val favoritesRepository: FavoritesRepository by inject()
private val widgetRepository: WidgetRepository by inject()
val favorites = MutableLiveData<List<Searchable>>(emptyList())
init {
viewModelScope.launch {
widgetRepository.isCalendarWidgetEnabled().collectLatest { excludeCalendar ->
favoritesRepository.getFavorites(excludeCalendarEvents = excludeCalendar).collectLatest {
favorites.value = it
}
}
}
}
}

View File

@ -24,6 +24,7 @@ sealed class Widget {
"weather" -> WeatherWidget "weather" -> WeatherWidget
"music" -> MusicWidget "music" -> MusicWidget
"calendar" -> CalendarWidget "calendar" -> CalendarWidget
"favorites" -> FavoritesWidget
else -> null else -> null
} }
} else { } else {
@ -132,6 +133,24 @@ object CalendarWidget : Widget() {
} }
} }
object FavoritesWidget : Widget() {
override fun loadLabel(context: Context): String {
return context.getString(R.string.widget_name_favorites)
}
override fun toDatabaseEntity(position: Int): WidgetEntity {
return WidgetEntity(
type = WidgetType.INTERNAL.value,
data = "favorites",
height = -1,
position = position
)
}
override val isConfigurable: Boolean = false
}
class ExternalWidget( class ExternalWidget(
var height: Int, var height: Int,
val widgetId: Int, val widgetId: Int,

View File

@ -14,6 +14,7 @@ interface WidgetRepository {
fun removeWidget(widget: Widget) fun removeWidget(widget: Widget)
fun setWidgetHeight(widget: Widget, newHeight: Int) fun setWidgetHeight(widget: Widget, newHeight: Int)
fun isCalendarWidgetEnabled(): Flow<Boolean> fun isCalendarWidgetEnabled(): Flow<Boolean>
fun isFavoritesWidgetEnabled(): Flow<Boolean>
} }
internal class WidgetRepositoryImpl( internal class WidgetRepositoryImpl(
@ -30,7 +31,7 @@ internal class WidgetRepositoryImpl(
} }
override fun getInternalWidgets(): List<Widget> { override fun getInternalWidgets(): List<Widget> {
return listOf(WeatherWidget, MusicWidget, CalendarWidget) return listOf(WeatherWidget, MusicWidget, CalendarWidget, FavoritesWidget)
} }
@ -81,4 +82,8 @@ internal class WidgetRepositoryImpl(
return database.widgetDao().exists("internal", "calendar") return database.widgetDao().exists("internal", "calendar")
} }
override fun isFavoritesWidgetEnabled(): Flow<Boolean> {
return database.widgetDao().exists("internal", "favorites")
}
} }