Refactor widgets
This commit is contained in:
@@ -156,6 +156,7 @@ dependencies {
|
||||
implementation(project(":core:database"))
|
||||
implementation(project(":data:search-actions"))
|
||||
implementation(project(":services:global-actions"))
|
||||
implementation(project(":services:widgets"))
|
||||
|
||||
// Uncomment this if you want annoying notifications in your debug builds yelling at you how terrible your code is
|
||||
//debugImplementation(libs.leakcanary)
|
||||
|
||||
@@ -30,6 +30,7 @@ import de.mm20.launcher2.permissions.permissionsModule
|
||||
import de.mm20.launcher2.preferences.preferencesModule
|
||||
import de.mm20.launcher2.searchactions.searchActionsModule
|
||||
import de.mm20.launcher2.services.tags.servicesTagsModule
|
||||
import de.mm20.launcher2.services.widgets.widgetsServiceModule
|
||||
import de.mm20.launcher2.weather.weatherModule
|
||||
import kotlinx.coroutines.*
|
||||
import org.koin.android.ext.koin.androidContext
|
||||
@@ -81,6 +82,7 @@ class LauncherApplication : Application(), CoroutineScope, ImageLoaderFactory {
|
||||
widgetsModule,
|
||||
wikipediaModule,
|
||||
servicesTagsModule,
|
||||
widgetsServiceModule,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -150,4 +150,5 @@ dependencies {
|
||||
implementation(project(":services:backup"))
|
||||
implementation(project(":data:search-actions"))
|
||||
implementation(project(":services:global-actions"))
|
||||
implementation(project(":services:widgets"))
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import de.mm20.launcher2.ui.component.ProvideIconShape
|
||||
import de.mm20.launcher2.ui.locals.LocalCardStyle
|
||||
import de.mm20.launcher2.ui.locals.LocalFavoritesEnabled
|
||||
import de.mm20.launcher2.ui.locals.LocalGridSettings
|
||||
import de.mm20.launcher2.widgets.FavoritesWidget
|
||||
import de.mm20.launcher2.widgets.WidgetRepository
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
@@ -35,7 +36,7 @@ fun ProvideSettings(
|
||||
|
||||
val favoritesEnabled by remember {
|
||||
combine(
|
||||
widgetRepository.isFavoritesWidgetEnabled(),
|
||||
widgetRepository.exists(FavoritesWidget.Type),
|
||||
dataStore.data.map { it.favorites.enabled },
|
||||
dataStore.data.map { it.clockWidget.favoritesPart },
|
||||
) { a, b, c -> a || b || c }.distinctUntilChanged()
|
||||
|
||||
@@ -8,6 +8,7 @@ import de.mm20.launcher2.favorites.FavoritesRepository
|
||||
import de.mm20.launcher2.preferences.LauncherDataStore
|
||||
import de.mm20.launcher2.search.SavableSearchable
|
||||
import de.mm20.launcher2.search.data.Tag
|
||||
import de.mm20.launcher2.widgets.CalendarWidget
|
||||
import de.mm20.launcher2.widgets.WidgetRepository
|
||||
import kotlinx.coroutines.flow.*
|
||||
import org.koin.core.component.KoinComponent
|
||||
@@ -36,7 +37,7 @@ abstract class FavoritesVM : ViewModel(), KoinComponent {
|
||||
open val favorites: Flow<List<SavableSearchable>> = selectedTag.flatMapLatest { tag ->
|
||||
if (tag == null) {
|
||||
val columns = dataStore.data.map { it.grid.columnCount }
|
||||
val excludeCalendar = widgetRepository.isCalendarWidgetEnabled()
|
||||
val excludeCalendar = widgetRepository.exists(CalendarWidget.Type)
|
||||
val includeFrequentlyUsed = dataStore.data.map { it.favorites.frequentlyUsed }
|
||||
val frequentlyUsedRows = dataStore.data.map { it.favorites.frequentlyUsedRows }
|
||||
|
||||
|
||||
@@ -61,11 +61,13 @@ import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.ui.component.BottomSheetDialog
|
||||
import de.mm20.launcher2.ui.launcher.widgets.picker.PickAppWidgetActivity
|
||||
import de.mm20.launcher2.widgets.CalendarWidget
|
||||
import de.mm20.launcher2.widgets.ExternalWidget
|
||||
import de.mm20.launcher2.widgets.AppWidget
|
||||
import de.mm20.launcher2.widgets.AppWidgetConfig
|
||||
import de.mm20.launcher2.widgets.FavoritesWidget
|
||||
import de.mm20.launcher2.widgets.MusicWidget
|
||||
import de.mm20.launcher2.widgets.WeatherWidget
|
||||
import de.mm20.launcher2.widgets.Widget
|
||||
import java.util.UUID
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class BindAndConfigureAppWidgetActivity : Activity() {
|
||||
@@ -191,9 +193,12 @@ private class BindAndConfigureAppWidgetContract(
|
||||
)
|
||||
|
||||
if (widgetId != null && widgetProviderInfo != null) {
|
||||
return ExternalWidget(
|
||||
height = widgetProviderInfo.minHeight,
|
||||
widgetId = widgetId,
|
||||
return AppWidget(
|
||||
id = UUID.randomUUID(),
|
||||
config = AppWidgetConfig(
|
||||
height = widgetProviderInfo.minHeight,
|
||||
widgetId = widgetId,
|
||||
),
|
||||
widgetProviderInfo = widgetProviderInfo,
|
||||
)
|
||||
}
|
||||
@@ -277,7 +282,15 @@ fun WidgetPickerSheet(
|
||||
.fillMaxWidth()
|
||||
.padding(bottom = 16.dp, start = 16.dp, end = 16.dp),
|
||||
onClick = {
|
||||
viewModel.pickWidget(it)
|
||||
val id = UUID.randomUUID()
|
||||
val widget = when(it.type) {
|
||||
WeatherWidget.Type -> WeatherWidget(id)
|
||||
CalendarWidget.Type -> CalendarWidget(id)
|
||||
MusicWidget.Type -> MusicWidget(id)
|
||||
FavoritesWidget.Type -> FavoritesWidget(id)
|
||||
else -> return@OutlinedCard
|
||||
}
|
||||
viewModel.pickWidget(widget)
|
||||
onDismiss()
|
||||
}) {
|
||||
Row(
|
||||
@@ -285,18 +298,18 @@ fun WidgetPickerSheet(
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Icon(
|
||||
imageVector = when (it) {
|
||||
is WeatherWidget -> Icons.Rounded.LightMode
|
||||
is CalendarWidget -> Icons.Rounded.Today
|
||||
is MusicWidget -> Icons.Rounded.MusicNote
|
||||
is FavoritesWidget -> Icons.Rounded.Star
|
||||
imageVector = when (it.type) {
|
||||
WeatherWidget.Type -> Icons.Rounded.LightMode
|
||||
CalendarWidget.Type -> Icons.Rounded.Today
|
||||
MusicWidget.Type -> Icons.Rounded.MusicNote
|
||||
FavoritesWidget.Type -> Icons.Rounded.Star
|
||||
else -> Icons.Rounded.Widgets
|
||||
},
|
||||
contentDescription = null,
|
||||
modifier = Modifier.padding(end = 16.dp)
|
||||
)
|
||||
Text(
|
||||
text = it.loadLabel(context),
|
||||
text = it.label,
|
||||
style = MaterialTheme.typography.titleSmall
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,14 +1,21 @@
|
||||
package de.mm20.launcher2.ui.launcher.sheets
|
||||
|
||||
import WidgetsService
|
||||
import android.appwidget.AppWidgetProviderInfo
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.rounded.Star
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.lifecycle.viewmodel.initializer
|
||||
import androidx.lifecycle.viewmodel.viewModelFactory
|
||||
import de.mm20.launcher2.ktx.normalize
|
||||
import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.widgets.FavoritesWidget
|
||||
import de.mm20.launcher2.widgets.Widget
|
||||
import de.mm20.launcher2.widgets.WidgetRepository
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -24,7 +31,7 @@ import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.get
|
||||
|
||||
class WidgetPickerSheetVM(
|
||||
private val widgetRepository: WidgetRepository,
|
||||
private val widgetsService: WidgetsService,
|
||||
private val context: Context,
|
||||
) : ViewModel() {
|
||||
|
||||
@@ -32,11 +39,11 @@ class WidgetPickerSheetVM(
|
||||
|
||||
val searchQuery = MutableStateFlow("")
|
||||
|
||||
private val enabledWidgets = widgetRepository.getWidgets()
|
||||
private val enabledWidgets = widgetsService.getWidgets()
|
||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(100), emptyList())
|
||||
|
||||
private val allBuiltInWidgets = enabledWidgets.map { w ->
|
||||
widgetRepository.getInternalWidgets().filter { !w.contains(it) }
|
||||
widgetsService.getBuiltInWidgets().filter { b -> !w.any { it::class == b::class } }
|
||||
}.shareIn(viewModelScope, SharingStarted.WhileSubscribed(100))
|
||||
|
||||
val builtInWidgets = allBuiltInWidgets
|
||||
@@ -45,13 +52,13 @@ class WidgetPickerSheetVM(
|
||||
withContext(Dispatchers.IO) {
|
||||
val normalizedQuery = query.normalize()
|
||||
widgets.filter {
|
||||
it.loadLabel(context).normalize().contains(normalizedQuery)
|
||||
it.label.normalize().contains(normalizedQuery)
|
||||
}
|
||||
}
|
||||
}.shareIn(viewModelScope, SharingStarted.WhileSubscribed(100))
|
||||
|
||||
private val allAppWidgets = flow {
|
||||
val widgets = widgetRepository.getAppWidgets()
|
||||
val widgets = widgetsService.getAppWidgetProviders()
|
||||
emit(widgets)
|
||||
}.shareIn(viewModelScope, SharingStarted.WhileSubscribed(100))
|
||||
|
||||
@@ -105,7 +112,7 @@ class WidgetPickerSheetVM(
|
||||
|
||||
fun pickWidget(widget: Widget) {
|
||||
val position = enabledWidgets.value.size
|
||||
widgetRepository.addWidget(widget, position)
|
||||
widgetsService.addWidget(widget, position)
|
||||
}
|
||||
|
||||
fun toggleGroup(group: String) {
|
||||
@@ -123,10 +130,17 @@ class WidgetPickerSheetVM(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
data class AppWidgetGroup(
|
||||
val appName: String,
|
||||
val packageName: String,
|
||||
val widgets: List<AppWidgetProviderInfo>
|
||||
)
|
||||
|
||||
data class BuiltInWidgetInfo(
|
||||
val type: String,
|
||||
@StringRes val label: Int,
|
||||
val icon: ImageVector
|
||||
)
|
||||
@@ -3,32 +3,19 @@ package de.mm20.launcher2.ui.launcher.widgets
|
||||
import android.app.Activity
|
||||
import android.appwidget.AppWidgetHost
|
||||
import android.appwidget.AppWidgetManager
|
||||
import android.content.Intent
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.graphics.res.animatedVectorResource
|
||||
import androidx.compose.animation.graphics.res.rememberAnimatedVectorPainter
|
||||
import androidx.compose.animation.graphics.vector.AnimatedImageVector
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.gestures.rememberDraggableState
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.offset
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.rounded.Add
|
||||
import androidx.compose.material3.ExtendedFloatingActionButton
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
@@ -37,7 +24,6 @@ import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.layout.onPlaced
|
||||
@@ -45,19 +31,15 @@ import androidx.compose.ui.layout.positionInParent
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalLifecycleOwner
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.IntOffset
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.Dialog
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.repeatOnLifecycle
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.ui.ktx.animateTo
|
||||
import de.mm20.launcher2.ui.launcher.sheets.LocalBottomSheetManager
|
||||
import de.mm20.launcher2.ui.launcher.widgets.clock.ClockWidget
|
||||
import de.mm20.launcher2.ui.launcher.widgets.picker.PickAppWidgetActivity
|
||||
import de.mm20.launcher2.widgets.ExternalWidget
|
||||
import de.mm20.launcher2.widgets.AppWidget
|
||||
import kotlinx.coroutines.awaitCancellation
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@@ -85,19 +67,6 @@ fun WidgetColumn(
|
||||
}
|
||||
}
|
||||
|
||||
val pickWidgetLauncher =
|
||||
rememberLauncherForActivityResult(contract = ActivityResultContracts.StartActivityForResult()) {
|
||||
val data = it.data ?: return@rememberLauncherForActivityResult
|
||||
val widgetId = data.getIntExtra(
|
||||
AppWidgetManager.EXTRA_APPWIDGET_ID,
|
||||
AppWidgetManager.INVALID_APPWIDGET_ID
|
||||
)
|
||||
if (widgetId == AppWidgetManager.INVALID_APPWIDGET_ID) return@rememberLauncherForActivityResult
|
||||
if (it.resultCode == Activity.RESULT_OK) {
|
||||
viewModel.addAppWidget(context, widgetId)
|
||||
}
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = modifier
|
||||
) {
|
||||
@@ -109,7 +78,7 @@ fun WidgetColumn(
|
||||
}
|
||||
val widgetsWithIndex = remember(widgets) { widgets.withIndex() }
|
||||
for ((i, widget) in widgetsWithIndex) {
|
||||
key(if (widget is ExternalWidget) widget.widgetId else widget) {
|
||||
key(widget.id) {
|
||||
var dragOffsetAfterSwap = remember<Float?> { null }
|
||||
val offsetY = remember(widgets) { mutableStateOf(dragOffsetAfterSwap ?: 0f) }
|
||||
|
||||
@@ -122,13 +91,13 @@ fun WidgetColumn(
|
||||
appWidgetHost = widgetHost,
|
||||
editMode = editMode,
|
||||
onWidgetRemove = {
|
||||
if (widget is ExternalWidget) {
|
||||
widgetHost.deleteAppWidgetId(widget.widgetId)
|
||||
if (widget is AppWidget) {
|
||||
widgetHost.deleteAppWidgetId(widget.config.widgetId)
|
||||
}
|
||||
viewModel.removeWidget(widget)
|
||||
},
|
||||
onWidgetResize = {
|
||||
viewModel.setWidgetHeight(widget, it)
|
||||
onWidgetUpdate = {
|
||||
viewModel.updateWidget(it)
|
||||
},
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
|
||||
@@ -2,6 +2,7 @@ package de.mm20.launcher2.ui.launcher.widgets
|
||||
|
||||
import android.app.Activity
|
||||
import android.appwidget.AppWidgetHost
|
||||
import android.util.Log
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.core.animateDpAsState
|
||||
import androidx.compose.foundation.gestures.*
|
||||
@@ -29,7 +30,6 @@ 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.weather.WeatherWidget
|
||||
import de.mm20.launcher2.widgets.*
|
||||
import java.lang.Integer.max
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
@Composable
|
||||
@@ -38,7 +38,7 @@ fun WidgetItem(
|
||||
appWidgetHost: AppWidgetHost,
|
||||
modifier: Modifier = Modifier,
|
||||
editMode: Boolean = false,
|
||||
onWidgetResize: (newHeight: Int) -> Unit = {},
|
||||
onWidgetUpdate: (widget: Widget) -> Unit = {},
|
||||
onWidgetRemove: () -> Unit = {},
|
||||
draggableState: DraggableState = rememberDraggableState {},
|
||||
onDragStopped: () -> Unit = {}
|
||||
@@ -84,7 +84,7 @@ fun WidgetItem(
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
maxLines = 1
|
||||
)
|
||||
if (widget is ExternalWidget) {
|
||||
if (widget is AppWidget) {
|
||||
IconButton(onClick = { resizeMode = !resizeMode }) {
|
||||
Icon(
|
||||
imageVector = Icons.Rounded.Edit,
|
||||
@@ -124,19 +124,19 @@ fun WidgetItem(
|
||||
is FavoritesWidget -> {
|
||||
FavoritesWidget()
|
||||
}
|
||||
is ExternalWidget -> {
|
||||
var height by remember(widget) { mutableStateOf(widget.height) }
|
||||
is AppWidget -> {
|
||||
var dragDelta by remember { mutableStateOf(0) }
|
||||
Column {
|
||||
ExternalWidget(
|
||||
appWidgetHost = appWidgetHost,
|
||||
widgetId = widget.widgetId,
|
||||
widgetId = widget.config.widgetId,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
height = height,
|
||||
height = widget.config.height + dragDelta,
|
||||
)
|
||||
if (resizeMode) {
|
||||
val density = LocalDensity.current
|
||||
val drgStt = rememberDraggableState {
|
||||
height += (it / density.density).roundToInt()
|
||||
dragDelta += (it / density.density).roundToInt()
|
||||
}
|
||||
Icon(
|
||||
imageVector = Icons.Rounded.DragHandle,
|
||||
@@ -150,7 +150,12 @@ fun WidgetItem(
|
||||
orientation = Orientation.Vertical,
|
||||
startDragImmediately = true,
|
||||
onDragStopped = {
|
||||
onWidgetResize(height)
|
||||
onWidgetUpdate(widget.copy(
|
||||
config = widget.config.copy(
|
||||
height = widget.config.height + dragDelta
|
||||
)
|
||||
))
|
||||
dragDelta = 0
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
package de.mm20.launcher2.ui.launcher.widgets
|
||||
|
||||
import android.appwidget.AppWidgetManager
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.asLiveData
|
||||
import de.mm20.launcher2.preferences.LauncherDataStore
|
||||
import de.mm20.launcher2.widgets.ExternalWidget
|
||||
import de.mm20.launcher2.widgets.Widget
|
||||
import de.mm20.launcher2.widgets.WidgetRepository
|
||||
import kotlinx.coroutines.flow.map
|
||||
@@ -19,49 +17,28 @@ class WidgetsVM : ViewModel(), KoinComponent {
|
||||
|
||||
val editButton = dataStore.data.map { it.widgets.editButton }.asLiveData()
|
||||
|
||||
val widgets = widgetRepository.getWidgets().asLiveData()
|
||||
val widgets = widgetRepository.get().asLiveData()
|
||||
|
||||
fun addWidget(widget: Widget) {
|
||||
widgetRepository.addWidget(widget, widgets.value?.size ?: 0)
|
||||
}
|
||||
|
||||
fun addAppWidget(context: Context, widgetId: Int) {
|
||||
if (widgetId == AppWidgetManager.INVALID_APPWIDGET_ID) return
|
||||
val appWidget = AppWidgetManager.getInstance(context)
|
||||
.getAppWidgetInfo(widgetId) ?: return
|
||||
val widget = ExternalWidget(
|
||||
widgetProviderInfo = appWidget,
|
||||
height = appWidget.minHeight,
|
||||
widgetId = widgetId,
|
||||
)
|
||||
addWidget(widget)
|
||||
}
|
||||
|
||||
fun removeWidget(widget: Widget) {
|
||||
widgetRepository.removeWidget(widget)
|
||||
widgetRepository.delete(widget)
|
||||
}
|
||||
|
||||
fun setWidgetHeight(widget: Widget, newHeight: Int) {
|
||||
widgetRepository.setWidgetHeight(widget, newHeight)
|
||||
}
|
||||
|
||||
fun getAvailableBuiltInWidgets(): List<Widget> {
|
||||
return widgetRepository.getInternalWidgets().filter {
|
||||
widgets.value?.contains(it)?.not() ?: false
|
||||
}
|
||||
fun updateWidget(widget: Widget) {
|
||||
widgetRepository.update(widget)
|
||||
}
|
||||
|
||||
fun moveUp(index: Int) {
|
||||
val widgets = widgets.value?.toMutableList() ?: return
|
||||
val widget = widgets.removeAt(index)
|
||||
widgets.add(index - 1, widget)
|
||||
widgetRepository.saveWidgets(widgets)
|
||||
widgetRepository.set(widgets)
|
||||
}
|
||||
|
||||
fun moveDown(index: Int) {
|
||||
val widgets = widgets.value?.toMutableList() ?: return
|
||||
val widget = widgets.removeAt(index)
|
||||
widgets.add(index + 1, widget)
|
||||
widgetRepository.saveWidgets(widgets)
|
||||
widgetRepository.set(widgets)
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -16,6 +16,7 @@ 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.CalendarWidget
|
||||
import de.mm20.launcher2.widgets.WidgetRepository
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flow
|
||||
@@ -41,7 +42,7 @@ class FavoritesPartProvider : PartProvider, KoinComponent {
|
||||
if (layout == ClockWidgetLayout.Horizontal) c - 2 else c
|
||||
}
|
||||
}.collectAsState(0)
|
||||
val excludeCalendar by remember { widgetRepository.isCalendarWidgetEnabled() }.collectAsState(
|
||||
val excludeCalendar by remember { widgetRepository.exists(CalendarWidget.Type) }.collectAsState(
|
||||
true
|
||||
)
|
||||
|
||||
|
||||
+5
-1
@@ -1,5 +1,6 @@
|
||||
package de.mm20.launcher2.ui.launcher.widgets.favorites
|
||||
|
||||
import WidgetsService
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import de.mm20.launcher2.preferences.Settings.ClockWidgetSettings.ClockWidgetLayout
|
||||
import de.mm20.launcher2.ui.common.FavoritesVM
|
||||
@@ -9,13 +10,16 @@ import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.shareIn
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.core.component.inject
|
||||
|
||||
class FavoritesWidgetVM : FavoritesVM() {
|
||||
|
||||
private val widgetsService: WidgetsService by inject()
|
||||
|
||||
override val tagsExpanded: Flow<Boolean> = dataStore.data.map { it.ui.widgetTagsMultiline }
|
||||
.shareIn(viewModelScope, SharingStarted.Lazily)
|
||||
|
||||
private val isTopWidget = widgetRepository.isFavoritesWidgetFirst()
|
||||
private val isTopWidget = widgetsService.isFavoritesWidgetFirst()
|
||||
private val clockWidgetFavSlots = dataStore.data.combine(isTopWidget) { data, isTop ->
|
||||
if (!isTop || !data.clockWidget.favoritesPart) 0
|
||||
else {
|
||||
|
||||
+8
-4
@@ -4,6 +4,10 @@ import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.asLiveData
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import de.mm20.launcher2.preferences.LauncherDataStore
|
||||
import de.mm20.launcher2.widgets.CalendarWidget
|
||||
import de.mm20.launcher2.widgets.FavoritesWidget
|
||||
import de.mm20.launcher2.widgets.MusicWidget
|
||||
import de.mm20.launcher2.widgets.WeatherWidget
|
||||
import de.mm20.launcher2.widgets.WidgetRepository
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -16,10 +20,10 @@ class WidgetSettingsScreenVM : ViewModel(), KoinComponent {
|
||||
private val widgetRepository: WidgetRepository by inject()
|
||||
private val dataStore: LauncherDataStore by inject()
|
||||
|
||||
val calendarWidget = widgetRepository.isCalendarWidgetEnabled().asLiveData()
|
||||
val musicWidget = widgetRepository.isMusicWidgetEnabled().asLiveData()
|
||||
val weatherWidget = widgetRepository.isWeatherWidgetEnabled().asLiveData()
|
||||
val favoritesWidget = widgetRepository.isFavoritesWidgetEnabled().asLiveData()
|
||||
val calendarWidget = widgetRepository.exists(CalendarWidget.Type).asLiveData()
|
||||
val musicWidget = widgetRepository.exists(MusicWidget.Type).asLiveData()
|
||||
val weatherWidget = widgetRepository.exists(WeatherWidget.Type).asLiveData()
|
||||
val favoritesWidget = widgetRepository.exists(FavoritesWidget.Type).asLiveData()
|
||||
val editButton = dataStore.data.map { it.widgets.editButton }.asLiveData()
|
||||
fun setEditButton(editButton: Boolean) {
|
||||
viewModelScope.launch {
|
||||
|
||||
Reference in New Issue
Block a user