From fc6d1d382cdd7853dbd56d74125fe99f74d38a6e Mon Sep 17 00:00:00 2001
From: MM20 <15646950+MM2-0@users.noreply.github.com>
Date: Tue, 27 Sep 2022 21:06:07 +0200
Subject: [PATCH] Add preference to hide widget edit button
---
i18n/src/main/res/values/strings.xml | 1 +
.../de/mm20/launcher2/preferences/Defaults.kt | 4 +
.../preferences/migrations/Migration_9_10.kt | 19 +--
preferences/src/main/proto/settings.proto | 5 +
.../ui/launcher/widgets/WidgetColumn.kt | 119 ++++++++++--------
.../ui/launcher/widgets/WidgetsVM.kt | 6 +
.../widgets/WidgetSettingsScreenVM.kt | 21 +++-
.../settings/widgets/WidgetsSettingsScreen.kt | 109 +++++++++-------
8 files changed, 181 insertions(+), 103 deletions(-)
diff --git a/i18n/src/main/res/values/strings.xml b/i18n/src/main/res/values/strings.xml
index 81990716..43793d98 100644
--- a/i18n/src/main/res/values/strings.xml
+++ b/i18n/src/main/res/values/strings.xml
@@ -622,6 +622,7 @@
Show frequently used items in favorites
Edit button
Show a button to rearrange the favorites
+ Show a button to add, remove and rearrange widgets
You haven\'t connected a Nextcloud account yet
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 11e1d7a6..e3951933 100644
--- a/preferences/src/main/java/de/mm20/launcher2/preferences/Defaults.kt
+++ b/preferences/src/main/java/de/mm20/launcher2/preferences/Defaults.kt
@@ -155,6 +155,10 @@ fun createFactorySettings(context: Context): Settings {
.setRadius(8)
.setOpacity(1f)
)
+ .setWidgets(
+ Settings.WidgetSettings.newBuilder()
+ .setEditButton(true)
+ )
.build()
}
diff --git a/preferences/src/main/java/de/mm20/launcher2/preferences/migrations/Migration_9_10.kt b/preferences/src/main/java/de/mm20/launcher2/preferences/migrations/Migration_9_10.kt
index 192fe122..8bafb65c 100644
--- a/preferences/src/main/java/de/mm20/launcher2/preferences/migrations/Migration_9_10.kt
+++ b/preferences/src/main/java/de/mm20/launcher2/preferences/migrations/Migration_9_10.kt
@@ -2,13 +2,18 @@ package de.mm20.launcher2.preferences.migrations
import de.mm20.launcher2.preferences.Settings
-class Migration_9_10: VersionedMigration(9, 10) {
+class Migration_9_10 : VersionedMigration(9, 10) {
override suspend fun applyMigrations(builder: Settings.Builder): Settings.Builder {
- return builder.setFavorites(
- builder.favorites.toBuilder()
- .setFrequentlyUsed(true)
- .setFrequentlyUsedRows(1)
- .setEditButton(true)
- )
+ return builder
+ .setFavorites(
+ builder.favorites.toBuilder()
+ .setFrequentlyUsed(true)
+ .setFrequentlyUsedRows(1)
+ .setEditButton(true)
+ )
+ .setWidgets(
+ Settings.WidgetSettings.newBuilder()
+ .setEditButton(true)
+ )
}
}
\ No newline at end of file
diff --git a/preferences/src/main/proto/settings.proto b/preferences/src/main/proto/settings.proto
index 441656b0..7b6a2b0d 100644
--- a/preferences/src/main/proto/settings.proto
+++ b/preferences/src/main/proto/settings.proto
@@ -259,4 +259,9 @@ message Settings {
bool enabled = 1;
}
AppShortcutSearchSettings app_shortcut_search = 25;
+
+ message WidgetSettings {
+ bool edit_button = 1;
+ }
+ WidgetSettings widgets = 26;
}
\ No newline at end of file
diff --git a/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/WidgetColumn.kt b/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/WidgetColumn.kt
index 1cf68aa0..77bff548 100644
--- a/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/WidgetColumn.kt
+++ b/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/WidgetColumn.kt
@@ -7,20 +7,37 @@ 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.ExperimentalAnimationGraphicsApi
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.*
+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.*
-import androidx.compose.runtime.*
+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
+import androidx.compose.runtime.key
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
@@ -35,10 +52,9 @@ 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.launcher.widgets.clock.ClockWidget
import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.ktx.animateTo
-import de.mm20.launcher2.ui.ktx.conditional
+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 kotlinx.coroutines.awaitCancellation
@@ -69,17 +85,18 @@ 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)
+ 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
@@ -168,43 +185,47 @@ fun WidgetColumn(
}
}
- val icon =
- AnimatedImageVector.animatedVectorResource(R.drawable.anim_ic_edit_add)
- ExtendedFloatingActionButton(
- modifier = Modifier
- .padding(16.dp)
- .align(Alignment.CenterHorizontally),
- icon = {
- Icon(
- painter = rememberAnimatedVectorPainter(
- animatedImageVector = icon,
- atEnd = !editMode
- ), contentDescription = null
- )
- },
- text = {
- Text(
- stringResource(
- if (editMode) R.string.widget_add_widget
- else R.string.menu_edit_widgets
+ val editButton by viewModel.editButton.observeAsState()
+ if (editButton == true) {
+ val icon =
+ AnimatedImageVector.animatedVectorResource(R.drawable.anim_ic_edit_add)
+ ExtendedFloatingActionButton(
+ modifier = Modifier
+ .padding(16.dp)
+ .align(Alignment.CenterHorizontally),
+ icon = {
+ Icon(
+ painter = rememberAnimatedVectorPainter(
+ animatedImageVector = icon,
+ atEnd = !editMode
+ ), contentDescription = null
)
- )
- }, onClick = {
- if (!editMode) {
- onEditModeChange(true)
- } else {
- if (viewModel.getAvailableBuiltInWidgets().isEmpty()) {
- pickWidgetLauncher.launch(
- Intent(
- context,
- PickAppWidgetActivity::class.java
- )
+ },
+ text = {
+ Text(
+ stringResource(
+ if (editMode) R.string.widget_add_widget
+ else R.string.menu_edit_widgets
)
+ )
+ }, onClick = {
+ if (!editMode) {
+ onEditModeChange(true)
} else {
- showAddDialog = true
+ if (viewModel.getAvailableBuiltInWidgets().isEmpty()) {
+ pickWidgetLauncher.launch(
+ Intent(
+ context,
+ PickAppWidgetActivity::class.java
+ )
+ )
+ } else {
+ showAddDialog = true
+ }
}
- }
- })
+ })
+
+ }
if (showAddDialog) {
val availableBuiltInWidgets =
diff --git a/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/WidgetsVM.kt b/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/WidgetsVM.kt
index bbfb3105..f9ae71b0 100644
--- a/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/WidgetsVM.kt
+++ b/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/WidgetsVM.kt
@@ -6,18 +6,24 @@ import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.asLiveData
import androidx.lifecycle.liveData
+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 de.mm20.launcher2.widgets.WidgetType
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 WidgetsVM : ViewModel(), KoinComponent {
private val widgetRepository: WidgetRepository by inject()
+ private val dataStore: LauncherDataStore by inject()
+
+ val editButton = dataStore.data.map { it.widgets.editButton }.asLiveData()
+
val widgets = widgetRepository.getWidgets().asLiveData()
fun addWidget(widget: Widget) {
diff --git a/ui/src/main/java/de/mm20/launcher2/ui/settings/widgets/WidgetSettingsScreenVM.kt b/ui/src/main/java/de/mm20/launcher2/ui/settings/widgets/WidgetSettingsScreenVM.kt
index eceeb3be..1c37a1a9 100644
--- a/ui/src/main/java/de/mm20/launcher2/ui/settings/widgets/WidgetSettingsScreenVM.kt
+++ b/ui/src/main/java/de/mm20/launcher2/ui/settings/widgets/WidgetSettingsScreenVM.kt
@@ -2,16 +2,35 @@ package de.mm20.launcher2.ui.settings.widgets
import androidx.lifecycle.ViewModel
import androidx.lifecycle.asLiveData
+import androidx.lifecycle.viewModelScope
+import de.mm20.launcher2.preferences.LauncherDataStore
import de.mm20.launcher2.widgets.WidgetRepository
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.launch
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
-class WidgetSettingsScreenVM: ViewModel(), KoinComponent {
+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 editButton = dataStore.data.map { it.widgets.editButton }.asLiveData()
+ fun setEditButton(editButton: Boolean) {
+ viewModelScope.launch {
+ dataStore.updateData {
+ it.toBuilder()
+ .setWidgets(
+ it.widgets.toBuilder()
+ .setEditButton(editButton)
+ )
+ .build()
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/ui/src/main/java/de/mm20/launcher2/ui/settings/widgets/WidgetsSettingsScreen.kt b/ui/src/main/java/de/mm20/launcher2/ui/settings/widgets/WidgetsSettingsScreen.kt
index 42e95f38..f22594d9 100644
--- a/ui/src/main/java/de/mm20/launcher2/ui/settings/widgets/WidgetsSettingsScreen.kt
+++ b/ui/src/main/java/de/mm20/launcher2/ui/settings/widgets/WidgetsSettingsScreen.kt
@@ -13,7 +13,9 @@ import androidx.compose.ui.res.stringResource
import androidx.lifecycle.viewmodel.compose.viewModel
import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.component.preferences.Preference
+import de.mm20.launcher2.ui.component.preferences.PreferenceCategory
import de.mm20.launcher2.ui.component.preferences.PreferenceScreen
+import de.mm20.launcher2.ui.component.preferences.SwitchPreference
import de.mm20.launcher2.ui.locals.LocalNavController
@Composable
@@ -22,56 +24,71 @@ fun WidgetsSettingsScreen() {
val viewModel: WidgetSettingsScreenVM = viewModel()
PreferenceScreen(title = stringResource(R.string.preference_screen_widgets)) {
item {
- Preference(
- title = stringResource(R.string.preference_screen_clockwidget),
- icon = Icons.Rounded.Schedule,
- onClick = {
- navController?.navigate("settings/widgets/clock")
+ PreferenceCategory {
+ Preference(
+ title = stringResource(R.string.preference_screen_clockwidget),
+ icon = Icons.Rounded.Schedule,
+ onClick = {
+ navController?.navigate("settings/widgets/clock")
+ }
+ )
+
+ val weatherWidget by viewModel.weatherWidget.observeAsState()
+ if (weatherWidget == true) {
+ Preference(
+ title = stringResource(R.string.preference_screen_weatherwidget),
+ icon = Icons.Rounded.LightMode,
+ onClick = {
+ navController?.navigate("settings/widgets/weather")
+ }
+ )
}
- )
- val weatherWidget by viewModel.weatherWidget.observeAsState()
- if (weatherWidget == true) {
- Preference(
- title = stringResource(R.string.preference_screen_weatherwidget),
- icon = Icons.Rounded.LightMode,
- onClick = {
- navController?.navigate("settings/widgets/weather")
- }
- )
+ val musicWidget by viewModel.musicWidget.observeAsState()
+ if (musicWidget == true) {
+ Preference(
+ title = stringResource(R.string.preference_screen_musicwidget),
+ icon = Icons.Rounded.Audiotrack,
+ onClick = {
+ navController?.navigate("settings/widgets/music")
+ }
+ )
+ }
+
+ val calendarWidget by viewModel.calendarWidget.observeAsState()
+ if (calendarWidget == true) {
+ Preference(
+ title = stringResource(R.string.preference_screen_calendarwidget),
+ icon = Icons.Rounded.Today,
+ onClick = {
+ navController?.navigate("settings/widgets/calendar")
+ }
+ )
+ }
+
+ val favoritesWidget by viewModel.favoritesWidget.observeAsState()
+ if (favoritesWidget == true) {
+ Preference(
+ title = stringResource(R.string.favorites),
+ icon = Icons.Rounded.Star,
+ onClick = {
+ navController?.navigate("settings/favorites")
+ }
+ )
+ }
}
+ }
- val musicWidget by viewModel.musicWidget.observeAsState()
- if (musicWidget == true) {
- Preference(
- title = stringResource(R.string.preference_screen_musicwidget),
- icon = Icons.Rounded.Audiotrack,
- onClick = {
- navController?.navigate("settings/widgets/music")
- }
- )
- }
-
- val calendarWidget by viewModel.calendarWidget.observeAsState()
- if (calendarWidget == true) {
- Preference(
- title = stringResource(R.string.preference_screen_calendarwidget),
- icon = Icons.Rounded.Today,
- onClick = {
- navController?.navigate("settings/widgets/calendar")
- }
- )
- }
-
- val favoritesWidget by viewModel.favoritesWidget.observeAsState()
- if (favoritesWidget == true) {
- Preference(
- title = stringResource(R.string.favorites),
- icon = Icons.Rounded.Star,
- onClick = {
- navController?.navigate("settings/favorites")
- }
- )
+ item {
+ PreferenceCategory {
+ val editButton by viewModel.editButton.observeAsState()
+ SwitchPreference(
+ title = stringResource(id = R.string.preference_edit_button),
+ summary = stringResource(id = R.string.preference_widgets_edit_button_summary),
+ value = editButton == true,
+ onValueChanged = {
+ viewModel.setEditButton(it)
+ })
}
}
}