diff --git a/i18n/src/main/res/values/strings.xml b/i18n/src/main/res/values/strings.xml
index bf9dc86b..97b16574 100644
--- a/i18n/src/main/res/values/strings.xml
+++ b/i18n/src/main/res/values/strings.xml
@@ -470,6 +470,7 @@
This app is free software.
Licensed under the GNU General Public License 3.0
Grid
+ Icon size
Number of columns
Debug
Troubleshooting tools
diff --git a/preferences/src/main/java/de/mm20/launcher2/preferences/DataStore.kt b/preferences/src/main/java/de/mm20/launcher2/preferences/DataStore.kt
index 01ca27ec..2a5d7bee 100644
--- a/preferences/src/main/java/de/mm20/launcher2/preferences/DataStore.kt
+++ b/preferences/src/main/java/de/mm20/launcher2/preferences/DataStore.kt
@@ -6,10 +6,7 @@ import androidx.datastore.core.DataStore
import androidx.datastore.core.handlers.ReplaceFileCorruptionHandler
import androidx.datastore.dataStore
import de.mm20.launcher2.crashreporter.CrashReporter
-import de.mm20.launcher2.preferences.migrations.FactorySettingsMigration
-import de.mm20.launcher2.preferences.migrations.Migration_1_2
-import de.mm20.launcher2.preferences.migrations.Migration_2_3
-import de.mm20.launcher2.preferences.migrations.Migration_3_4
+import de.mm20.launcher2.preferences.migrations.*
typealias LauncherDataStore = DataStore
@@ -22,6 +19,7 @@ internal val Context.dataStore: LauncherDataStore by dataStore(
Migration_1_2(),
Migration_2_3(),
Migration_3_4(),
+ Migration_4_5(),
)
},
corruptionHandler = ReplaceFileCorruptionHandler {
@@ -31,4 +29,4 @@ internal val Context.dataStore: LauncherDataStore by dataStore(
}
)
-internal const val SchemaVersion = 4
\ No newline at end of file
+internal const val SchemaVersion = 5
\ No newline at end of file
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 e36cca44..fc1f6eb8 100644
--- a/preferences/src/main/java/de/mm20/launcher2/preferences/Defaults.kt
+++ b/preferences/src/main/java/de/mm20/launcher2/preferences/Defaults.kt
@@ -109,6 +109,7 @@ fun createFactorySettings(context: Context): Settings {
.setGrid(
Settings.GridSettings.newBuilder()
.setColumnCount(context.resources.getInteger(R.integer.config_columnCount))
+ .setIconSize(48)
.build()
)
.setSearchBar(
diff --git a/preferences/src/main/java/de/mm20/launcher2/preferences/migrations/Migration_4_5.kt b/preferences/src/main/java/de/mm20/launcher2/preferences/migrations/Migration_4_5.kt
new file mode 100644
index 00000000..23fa9f64
--- /dev/null
+++ b/preferences/src/main/java/de/mm20/launcher2/preferences/migrations/Migration_4_5.kt
@@ -0,0 +1,13 @@
+package de.mm20.launcher2.preferences.migrations
+
+import de.mm20.launcher2.preferences.Settings
+
+class Migration_4_5: VersionedMigration(4, 5) {
+ override suspend fun applyMigrations(builder: Settings.Builder): Settings.Builder {
+ return builder.setGrid(
+ builder.grid.toBuilder()
+ .setIconSize(48)
+ .build()
+ )
+ }
+}
\ No newline at end of file
diff --git a/preferences/src/main/proto/settings.proto b/preferences/src/main/proto/settings.proto
index d8ad4f38..6d7e52d0 100644
--- a/preferences/src/main/proto/settings.proto
+++ b/preferences/src/main/proto/settings.proto
@@ -127,6 +127,7 @@ message Settings {
message GridSettings {
uint32 column_count = 1;
+ uint32 icon_size = 2;
}
GridSettings grid = 19;
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 702dd79e..622aad82 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
@@ -1,12 +1,14 @@
package de.mm20.launcher2.ui.base
import androidx.compose.runtime.*
+import androidx.compose.ui.unit.dp
import de.mm20.launcher2.preferences.LauncherDataStore
import de.mm20.launcher2.preferences.Settings
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.LocalGridColumns
+import de.mm20.launcher2.ui.locals.LocalGridIconSize
import de.mm20.launcher2.widgets.WidgetRepository
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
@@ -44,10 +46,15 @@ fun ProvideSettings(
dataStore.data.map { it.grid.columnCount }.distinctUntilChanged()
}.collectAsState(5)
+ val gridIconSize by remember {
+ dataStore.data.map { it.grid.iconSize.dp }.distinctUntilChanged()
+ }.collectAsState(48.dp)
+
CompositionLocalProvider(
LocalCardStyle provides cardStyle,
LocalFavoritesEnabled provides favoritesEnabled,
LocalGridColumns provides gridColumns,
+ LocalGridIconSize provides gridIconSize,
) {
ProvideIconShape(iconShape) {
content()
diff --git a/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/apps/AppItem.kt b/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/apps/AppItem.kt
index f250ebf6..5e63595e 100644
--- a/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/apps/AppItem.kt
+++ b/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/apps/AppItem.kt
@@ -26,6 +26,7 @@ import de.mm20.launcher2.ui.component.*
import de.mm20.launcher2.ui.ktx.toDp
import de.mm20.launcher2.ui.ktx.toPixels
import de.mm20.launcher2.ui.locals.LocalFavoritesEnabled
+import de.mm20.launcher2.ui.locals.LocalGridIconSize
import de.mm20.launcher2.ui.modifier.scale
import kotlinx.coroutines.launch
import kotlin.math.min
@@ -321,7 +322,7 @@ fun AppItemGridPopup(
modifier = Modifier
.fillMaxWidth()
.scale(
- 1 - (1 - 48.dp / 84.dp) * (1 - animationProgress),
+ 1 - (1 - LocalGridIconSize.current / 84.dp) * (1 - animationProgress),
transformOrigin = TransformOrigin(1f, 0f)
)
.offset(
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 de4b8bed..0581a383 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
@@ -35,8 +35,10 @@ import de.mm20.launcher2.ui.launcher.search.files.FileItemGridPopup
import de.mm20.launcher2.ui.launcher.search.shortcut.ShortcutItemGridPopup
import de.mm20.launcher2.ui.launcher.search.website.WebsiteItemGridPopup
import de.mm20.launcher2.ui.launcher.search.wikipedia.WikipediaItemGridPopup
+import de.mm20.launcher2.ui.locals.LocalGridIconSize
import de.mm20.launcher2.ui.locals.LocalWindowPosition
import kotlinx.coroutines.delay
+import kotlin.math.pow
@OptIn(ExperimentalFoundationApi::class)
@@ -49,7 +51,7 @@ fun GridItem(modifier: Modifier = Modifier, item: Searchable, showLabels: Boolea
var bounds by remember { mutableStateOf(Rect.Zero) }
Column(modifier = modifier, horizontalAlignment = Alignment.CenterHorizontally) {
val badge by viewModel.badge.collectAsState(null)
- val iconSize = 48.dp.toPixels()
+ val iconSize = LocalGridIconSize.current.toPixels()
val icon by remember(item.key) { viewModel.getIcon(iconSize.toInt()) }.collectAsState(null)
// If item is one of these types, try to launch them on click; show details otherwise
@@ -61,7 +63,7 @@ fun GridItem(modifier: Modifier = Modifier, item: Searchable, showLabels: Boolea
.onGloballyPositioned {
bounds = it.boundsInWindow()
},
- size = 48.dp,
+ size = LocalGridIconSize.current,
badge = badge,
icon = icon,
onClick = {
diff --git a/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/contacts/ContactItem.kt b/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/contacts/ContactItem.kt
index 275f1783..1d9a39f8 100644
--- a/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/contacts/ContactItem.kt
+++ b/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/contacts/ContactItem.kt
@@ -20,6 +20,7 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Rect
+import androidx.compose.ui.graphics.TransformOrigin
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
@@ -34,6 +35,8 @@ import de.mm20.launcher2.ui.icons.WhatsApp
import de.mm20.launcher2.ui.ktx.toDp
import de.mm20.launcher2.ui.ktx.toPixels
import de.mm20.launcher2.ui.locals.LocalFavoritesEnabled
+import de.mm20.launcher2.ui.locals.LocalGridIconSize
+import de.mm20.launcher2.ui.modifier.scale
@OptIn(ExperimentalUnitApi::class)
@Composable
@@ -306,6 +309,10 @@ fun ContactItemGridPopup(
ContactItem(
modifier = Modifier
.fillMaxWidth()
+ .scale(
+ 1 - (1 - LocalGridIconSize.current / 48.dp) * (1 - animationProgress),
+ transformOrigin = TransformOrigin(0f, 0f)
+ )
.offset(
x = -16.dp * (1 - animationProgress),
y = -16.dp * (1 - animationProgress)
diff --git a/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/files/FileItem.kt b/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/files/FileItem.kt
index 3320da68..bca07a90 100644
--- a/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/files/FileItem.kt
+++ b/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/files/FileItem.kt
@@ -16,6 +16,7 @@ import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Rect
+import androidx.compose.ui.graphics.TransformOrigin
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
@@ -31,6 +32,8 @@ import de.mm20.launcher2.ui.component.ToolbarAction
import de.mm20.launcher2.ui.ktx.toDp
import de.mm20.launcher2.ui.ktx.toPixels
import de.mm20.launcher2.ui.locals.LocalFavoritesEnabled
+import de.mm20.launcher2.ui.locals.LocalGridIconSize
+import de.mm20.launcher2.ui.modifier.scale
import java.text.DecimalFormat
import kotlin.math.roundToInt
@@ -279,6 +282,10 @@ fun FileItemGridPopup(
FileItem(
modifier = Modifier
.fillMaxWidth()
+ .scale(
+ 1 - (1 - LocalGridIconSize.current / 48.dp) * (1 - animationProgress),
+ transformOrigin = TransformOrigin(1f, 0f)
+ )
.offset(
x = 16.dp * (1 - animationProgress),
y = -16.dp * (1 - animationProgress)
diff --git a/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/shortcut/ShortcutItem.kt b/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/shortcut/ShortcutItem.kt
index db5a8a01..5200f8fb 100644
--- a/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/shortcut/ShortcutItem.kt
+++ b/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/shortcut/ShortcutItem.kt
@@ -30,6 +30,7 @@ import de.mm20.launcher2.ui.component.ToolbarAction
import de.mm20.launcher2.ui.ktx.toDp
import de.mm20.launcher2.ui.ktx.toPixels
import de.mm20.launcher2.ui.locals.LocalFavoritesEnabled
+import de.mm20.launcher2.ui.locals.LocalGridIconSize
import de.mm20.launcher2.ui.modifier.scale
import kotlin.math.pow
import kotlin.math.roundToInt
@@ -189,7 +190,7 @@ fun ShortcutItemGridPopup(
modifier = Modifier
.fillMaxWidth()
.scale(
- 1 - (1 - 48.dp / 84.dp) * (1 - animationProgress),
+ 1 - (1 - LocalGridIconSize.current / 84.dp) * (1 - animationProgress),
transformOrigin = TransformOrigin(1f, 0f)
)
.offset(
diff --git a/ui/src/main/java/de/mm20/launcher2/ui/locals/CompositionLocals.kt b/ui/src/main/java/de/mm20/launcher2/ui/locals/CompositionLocals.kt
index a2d9da68..1641b915 100644
--- a/ui/src/main/java/de/mm20/launcher2/ui/locals/CompositionLocals.kt
+++ b/ui/src/main/java/de/mm20/launcher2/ui/locals/CompositionLocals.kt
@@ -4,6 +4,7 @@ import android.appwidget.AppWidgetHost
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import de.mm20.launcher2.preferences.Settings
@@ -19,6 +20,8 @@ val LocalFavoritesEnabled = compositionLocalOf { true }
val LocalGridColumns = compositionLocalOf { 5 }
+val LocalGridIconSize = compositionLocalOf { 48.dp }
+
/**
* Workaround a bug in Jetpack Compose which incorrectly places popups
* that are nested inside other popups.
diff --git a/ui/src/main/java/de/mm20/launcher2/ui/settings/appearance/AppearanceSettingsScreen.kt b/ui/src/main/java/de/mm20/launcher2/ui/settings/appearance/AppearanceSettingsScreen.kt
index 1cd4de43..764eda39 100644
--- a/ui/src/main/java/de/mm20/launcher2/ui/settings/appearance/AppearanceSettingsScreen.kt
+++ b/ui/src/main/java/de/mm20/launcher2/ui/settings/appearance/AppearanceSettingsScreen.kt
@@ -85,6 +85,17 @@ fun AppearanceSettingsScreen() {
)
}
PreferenceCategory(title = stringResource(R.string.preference_category_grid)) {
+ val iconSize by viewModel.iconSize.observeAsState(48)
+ SliderPreference(
+ title = stringResource(R.string.preference_grid_icon_size),
+ value = iconSize,
+ step = 8,
+ min = 32,
+ max = 64,
+ onValueChanged = {
+ viewModel.setIconSize(it)
+ }
+ )
val columnCount by viewModel.columnCount.observeAsState(5)
SliderPreference(
title = stringResource(R.string.preference_grid_column_count),
diff --git a/ui/src/main/java/de/mm20/launcher2/ui/settings/appearance/AppearanceSettingsScreenVM.kt b/ui/src/main/java/de/mm20/launcher2/ui/settings/appearance/AppearanceSettingsScreenVM.kt
index f27e214d..e350235f 100644
--- a/ui/src/main/java/de/mm20/launcher2/ui/settings/appearance/AppearanceSettingsScreenVM.kt
+++ b/ui/src/main/java/de/mm20/launcher2/ui/settings/appearance/AppearanceSettingsScreenVM.kt
@@ -54,6 +54,17 @@ class AppearanceSettingsScreenVM : ViewModel(), KoinComponent {
}
}
+ val iconSize = dataStore.data.map { it.grid.iconSize }.asLiveData()
+ fun setIconSize(iconSize: Int) {
+ viewModelScope.launch {
+ dataStore.updateData {
+ it.toBuilder()
+ .setGrid(it.grid.toBuilder().setIconSize(iconSize))
+ .build()
+ }
+ }
+ }
+
val dimWallpaper = dataStore.data.map { it.appearance.dimWallpaper }.asLiveData()
fun setDimWallpaper(dimWallpaper: Boolean) {
viewModelScope.launch {