Add favorites part to clock widget
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 })
|
||||
}
|
||||
|
||||
+5
-3
@@ -14,9 +14,9 @@ import kotlin.math.ceil
|
||||
fun SearchResultGrid(
|
||||
items: List<Searchable>,
|
||||
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))
|
||||
|
||||
@@ -56,7 +56,6 @@ fun ClockWidget(
|
||||
if (layout == ClockWidgetLayout.Vertical) {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = Modifier.height(IntrinsicSize.Min),
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier.clickable(
|
||||
|
||||
@@ -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
|
||||
|
||||
+69
@@ -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<Int> = 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,
|
||||
)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
-2
@@ -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<List<Searchable>>(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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+14
@@ -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),
|
||||
|
||||
+23
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user