Move badge settings to decentralized data store, add preference for plugin badges
This commit is contained in:
parent
0f6d636ca0
commit
2479fdbc03
@ -89,6 +89,7 @@ fun IconsSettingsScreen() {
|
|||||||
val cloudFileBadges by viewModel.cloudFileBadges.collectAsStateWithLifecycle(null)
|
val cloudFileBadges by viewModel.cloudFileBadges.collectAsStateWithLifecycle(null)
|
||||||
val suspendedAppBadges by viewModel.suspendedAppBadges.collectAsStateWithLifecycle(null)
|
val suspendedAppBadges by viewModel.suspendedAppBadges.collectAsStateWithLifecycle(null)
|
||||||
val shortcutBadges by viewModel.shortcutBadges.collectAsStateWithLifecycle(null)
|
val shortcutBadges by viewModel.shortcutBadges.collectAsStateWithLifecycle(null)
|
||||||
|
val pluginBadges by viewModel.pluginBadges.collectAsStateWithLifecycle(null)
|
||||||
|
|
||||||
val previewIcons by remember(iconSize) {
|
val previewIcons by remember(iconSize) {
|
||||||
viewModel.getPreviewIcons(with(density) { iconSize.dp.toPx() }.toInt())
|
viewModel.getPreviewIcons(with(density) { iconSize.dp.toPx() }.toInt())
|
||||||
@ -325,6 +326,14 @@ fun IconsSettingsScreen() {
|
|||||||
viewModel.setShortcuts(it)
|
viewModel.setShortcuts(it)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
SwitchPreference(
|
||||||
|
title = stringResource(R.string.preference_plugin_badges),
|
||||||
|
summary = stringResource(R.string.preference_plugin_badges_summary),
|
||||||
|
value = pluginBadges == true,
|
||||||
|
onValueChanged = {
|
||||||
|
viewModel.setPluginBadges(it)
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import androidx.lifecycle.ViewModel
|
|||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import androidx.lifecycle.viewmodel.initializer
|
import androidx.lifecycle.viewmodel.initializer
|
||||||
import androidx.lifecycle.viewmodel.viewModelFactory
|
import androidx.lifecycle.viewmodel.viewModelFactory
|
||||||
|
import de.mm20.launcher2.badges.settings.BadgeSettings
|
||||||
import de.mm20.launcher2.icons.IconPack
|
import de.mm20.launcher2.icons.IconPack
|
||||||
import de.mm20.launcher2.icons.IconService
|
import de.mm20.launcher2.icons.IconService
|
||||||
import de.mm20.launcher2.icons.LauncherIcon
|
import de.mm20.launcher2.icons.LauncherIcon
|
||||||
@ -24,6 +25,7 @@ import org.koin.core.component.get
|
|||||||
|
|
||||||
class IconsSettingsScreenVM(
|
class IconsSettingsScreenVM(
|
||||||
private val dataStore: LauncherDataStore,
|
private val dataStore: LauncherDataStore,
|
||||||
|
private val badgeSettings: BadgeSettings,
|
||||||
private val iconService: IconService,
|
private val iconService: IconService,
|
||||||
private val favoritesService: FavoritesService,
|
private val favoritesService: FavoritesService,
|
||||||
private val permissionsManager: PermissionsManager,
|
private val permissionsManager: PermissionsManager,
|
||||||
@ -161,64 +163,33 @@ class IconsSettingsScreenVM(
|
|||||||
|
|
||||||
val hasNotificationsPermission = permissionsManager.hasPermission(PermissionGroup.Notifications)
|
val hasNotificationsPermission = permissionsManager.hasPermission(PermissionGroup.Notifications)
|
||||||
|
|
||||||
val notificationBadges = dataStore.data.map { it.badges.notifications }
|
val notificationBadges = badgeSettings.notifications
|
||||||
fun setNotifications(notifications: Boolean) {
|
fun setNotifications(notifications: Boolean) {
|
||||||
viewModelScope.launch {
|
badgeSettings.setNotifications(notifications)
|
||||||
dataStore.updateData {
|
|
||||||
it.toBuilder()
|
|
||||||
.setBadges(
|
|
||||||
it.badges.toBuilder()
|
|
||||||
.setNotifications(notifications)
|
|
||||||
)
|
|
||||||
.build()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun requestNotificationsPermission(context: AppCompatActivity) {
|
fun requestNotificationsPermission(context: AppCompatActivity) {
|
||||||
permissionsManager.requestPermission(context, PermissionGroup.Notifications)
|
permissionsManager.requestPermission(context, PermissionGroup.Notifications)
|
||||||
}
|
}
|
||||||
|
|
||||||
val cloudFileBadges = dataStore.data.map { it.badges.cloudFiles }
|
val cloudFileBadges = badgeSettings.cloudFiles
|
||||||
fun setCloudFiles(cloudFiles: Boolean) {
|
fun setCloudFiles(cloudFiles: Boolean) {
|
||||||
viewModelScope.launch {
|
badgeSettings.setCloudFiles(cloudFiles)
|
||||||
dataStore.updateData {
|
|
||||||
it.toBuilder()
|
|
||||||
.setBadges(
|
|
||||||
it.badges.toBuilder()
|
|
||||||
.setCloudFiles(cloudFiles)
|
|
||||||
)
|
|
||||||
.build()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val shortcutBadges = dataStore.data.map { it.badges.shortcuts }
|
val shortcutBadges = badgeSettings.shortcuts
|
||||||
fun setShortcuts(shortcuts: Boolean) {
|
fun setShortcuts(shortcuts: Boolean) {
|
||||||
viewModelScope.launch {
|
badgeSettings.setShortcuts(shortcuts)
|
||||||
dataStore.updateData {
|
|
||||||
it.toBuilder()
|
|
||||||
.setBadges(
|
|
||||||
it.badges.toBuilder()
|
|
||||||
.setShortcuts(shortcuts)
|
|
||||||
)
|
|
||||||
.build()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val suspendedAppBadges = dataStore.data.map { it.badges.suspendedApps }
|
val suspendedAppBadges = badgeSettings.suspendedApps
|
||||||
fun setSuspendedApps(suspendedApps: Boolean) {
|
fun setSuspendedApps(suspendedApps: Boolean) {
|
||||||
viewModelScope.launch {
|
badgeSettings.setSuspendedApps(suspendedApps)
|
||||||
dataStore.updateData {
|
|
||||||
it.toBuilder()
|
|
||||||
.setBadges(
|
|
||||||
it.badges.toBuilder()
|
|
||||||
.setSuspendedApps(suspendedApps)
|
|
||||||
)
|
|
||||||
.build()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val pluginBadges = badgeSettings.plugins
|
||||||
|
fun setPluginBadges(plugins: Boolean) {
|
||||||
|
badgeSettings.setPlugins(plugins)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getPreviewIcons(size: Int): Flow<List<LauncherIcon?>> {
|
fun getPreviewIcons(size: Int): Flow<List<LauncherIcon?>> {
|
||||||
@ -247,6 +218,7 @@ class IconsSettingsScreenVM(
|
|||||||
iconService = get(),
|
iconService = get(),
|
||||||
permissionsManager = get(),
|
permissionsManager = get(),
|
||||||
favoritesService = get(),
|
favoritesService = get(),
|
||||||
|
badgeSettings = get(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -42,6 +42,7 @@ dependencies {
|
|||||||
|
|
||||||
implementation(libs.androidx.core)
|
implementation(libs.androidx.core)
|
||||||
implementation(libs.androidx.appcompat)
|
implementation(libs.androidx.appcompat)
|
||||||
|
implementation(libs.androidx.datastore)
|
||||||
implementation(libs.materialcomponents.core)
|
implementation(libs.materialcomponents.core)
|
||||||
|
|
||||||
implementation(libs.koin.android)
|
implementation(libs.koin.android)
|
||||||
|
|||||||
@ -0,0 +1,66 @@
|
|||||||
|
package de.mm20.launcher2.settings
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.datastore.core.DataMigration
|
||||||
|
import androidx.datastore.core.Serializer
|
||||||
|
import androidx.datastore.dataStore
|
||||||
|
import de.mm20.launcher2.backup.Backupable
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.serialization.SerializationException
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
abstract class BaseSettings<T>(
|
||||||
|
internal val context: Context,
|
||||||
|
private val fileName: String,
|
||||||
|
private val serializer: Serializer<T>,
|
||||||
|
migrations: List<DataMigration<T>>
|
||||||
|
): Backupable {
|
||||||
|
|
||||||
|
protected val scope = CoroutineScope(Job() + Dispatchers.Default)
|
||||||
|
|
||||||
|
protected val Context.dataStore by dataStore(
|
||||||
|
fileName = fileName,
|
||||||
|
serializer = serializer,
|
||||||
|
produceMigrations = {
|
||||||
|
migrations
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
protected fun updateData(block: suspend (T) -> T) {
|
||||||
|
scope.launch {
|
||||||
|
context.dataStore.updateData(block)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun backup(toDir: File) {
|
||||||
|
val data = context.dataStore.data.first()
|
||||||
|
val file = File(toDir, fileName)
|
||||||
|
file.outputStream().use {
|
||||||
|
serializer.writeTo(data, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun restore(fromDir: File) {
|
||||||
|
val file = File(fromDir, fileName)
|
||||||
|
if (!file.exists()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
file.inputStream().use {
|
||||||
|
val data = serializer.readFrom(it)
|
||||||
|
context.dataStore.updateData {
|
||||||
|
data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: SerializationException) {
|
||||||
|
Log.e("MM20", "Cannot restore $fileName", e)
|
||||||
|
} catch (e: IllegalArgumentException) {
|
||||||
|
Log.e("MM20", "Cannot restore $fileName", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -552,6 +552,8 @@
|
|||||||
<string name="preference_cloud_badges_summary">Show a badge for files that are stored in a cloud</string>
|
<string name="preference_cloud_badges_summary">Show a badge for files that are stored in a cloud</string>
|
||||||
<string name="preference_shortcut_badges">Shortcut badges</string>
|
<string name="preference_shortcut_badges">Shortcut badges</string>
|
||||||
<string name="preference_shortcut_badges_summary">Show a badge which indicates to which app a shortcut belongs</string>
|
<string name="preference_shortcut_badges_summary">Show a badge which indicates to which app a shortcut belongs</string>
|
||||||
|
<string name="preference_plugin_badges">Plugin badges</string>
|
||||||
|
<string name="preference_plugin_badges_summary">Indicate by which plugin a search result was created</string>
|
||||||
<string name="preference_microsoft">Microsoft</string>
|
<string name="preference_microsoft">Microsoft</string>
|
||||||
<string name="preference_ms_signin">Sign in with Microsoft</string>
|
<string name="preference_ms_signin">Sign in with Microsoft</string>
|
||||||
<string name="preference_ms_signin_summary">Sign in to search OneDrive</string>
|
<string name="preference_ms_signin_summary">Sign in to search OneDrive</string>
|
||||||
|
|||||||
@ -221,7 +221,7 @@ message Settings {
|
|||||||
bool cloud_files = 3;
|
bool cloud_files = 3;
|
||||||
bool shortcuts = 4;
|
bool shortcuts = 4;
|
||||||
}
|
}
|
||||||
BadgeSettings badges = 18;
|
BadgeSettings badges = 18 [deprecated = true];
|
||||||
|
|
||||||
message GridSettings {
|
message GridSettings {
|
||||||
uint32 column_count = 1;
|
uint32 column_count = 1;
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import de.mm20.launcher2.backup.Backupable
|
|||||||
import de.mm20.launcher2.crashreporter.CrashReporter
|
import de.mm20.launcher2.crashreporter.CrashReporter
|
||||||
import de.mm20.launcher2.files.settings.migrations.Migration1
|
import de.mm20.launcher2.files.settings.migrations.Migration1
|
||||||
import de.mm20.launcher2.preferences.LauncherDataStore
|
import de.mm20.launcher2.preferences.LauncherDataStore
|
||||||
|
import de.mm20.launcher2.settings.BaseSettings
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
@ -19,26 +20,15 @@ import java.io.File
|
|||||||
|
|
||||||
class FileSearchSettings(
|
class FileSearchSettings(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val dataStore: LauncherDataStore,
|
dataStore: LauncherDataStore,
|
||||||
) : Backupable {
|
) : BaseSettings<FileSearchSettingsData>(
|
||||||
|
context = context,
|
||||||
private val scope = CoroutineScope(Job() + Dispatchers.Default)
|
|
||||||
|
|
||||||
private val Context.dataStore by dataStore(
|
|
||||||
fileName = "file_search.json",
|
fileName = "file_search.json",
|
||||||
serializer = FileSearchSettingsDataSerializer,
|
serializer = FileSearchSettingsDataSerializer,
|
||||||
produceMigrations = {
|
migrations = listOf(
|
||||||
listOf(
|
|
||||||
Migration1(dataStore),
|
Migration1(dataStore),
|
||||||
)
|
)
|
||||||
},
|
) {
|
||||||
)
|
|
||||||
|
|
||||||
private fun updateData(block: suspend (FileSearchSettingsData) -> FileSearchSettingsData) {
|
|
||||||
scope.launch {
|
|
||||||
context.dataStore.updateData(block)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal val data
|
internal val data
|
||||||
get() = context.dataStore.data
|
get() = context.dataStore.data
|
||||||
@ -98,29 +88,6 @@ class FileSearchSettings(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun backup(toDir: File) {
|
|
||||||
val data = context.dataStore.data.first()
|
|
||||||
val file = File(toDir, "file_search.json")
|
|
||||||
file.writeText(FileSearchSettingsDataSerializer.json.encodeToString(FileSearchSettingsData.serializer(), data))
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun restore(fromDir: File) {
|
|
||||||
val file = File(fromDir, "file_search.json")
|
|
||||||
if (!file.exists()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
val data = FileSearchSettingsDataSerializer.json.decodeFromString(FileSearchSettingsData.serializer(), file.readText())
|
|
||||||
context.dataStore.updateData {
|
|
||||||
data
|
|
||||||
}
|
|
||||||
} catch (e: SerializationException) {
|
|
||||||
CrashReporter.logException(e)
|
|
||||||
} catch (e: IllegalArgumentException) {
|
|
||||||
CrashReporter.logException(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setPluginEnabled(authority: String, enabled: Boolean) {
|
fun setPluginEnabled(authority: String, enabled: Boolean) {
|
||||||
updateData {
|
updateData {
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
|
|||||||
@ -12,7 +12,7 @@ import java.io.InputStream
|
|||||||
import java.io.OutputStream
|
import java.io.OutputStream
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
internal data class FileSearchSettingsData(
|
data class FileSearchSettingsData(
|
||||||
val localFiles: Boolean = true,
|
val localFiles: Boolean = true,
|
||||||
val gdriveFiles: Boolean = false,
|
val gdriveFiles: Boolean = false,
|
||||||
val nextcloudFiles: Boolean = false,
|
val nextcloudFiles: Boolean = false,
|
||||||
|
|||||||
@ -139,7 +139,7 @@ androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-co
|
|||||||
|
|
||||||
|
|
||||||
[bundles]
|
[bundles]
|
||||||
kotlin = ["kotlin-stdlib", "kotlinx-coroutines-core", "kotlinx-coroutines-android", "kotlinx-collections-immutable"]
|
kotlin = ["kotlin-stdlib", "kotlinx-coroutines-core", "kotlinx-coroutines-android", "kotlinx-collections-immutable", "kotlinx-serialization-json"]
|
||||||
androidx-lifecycle = ["androidx-lifecycle-viewmodel", "androidx-lifecycle-common", "androidx-lifecycle-runtime", "androidx-lifecycle-viewmodelcompose", "androidx-lifecycle-runtimecompose"]
|
androidx-lifecycle = ["androidx-lifecycle-viewmodel", "androidx-lifecycle-common", "androidx-lifecycle-runtime", "androidx-lifecycle-viewmodelcompose", "androidx-lifecycle-runtimecompose"]
|
||||||
retrofit = ["retrofit-core", "retrofit-gson"]
|
retrofit = ["retrofit-core", "retrofit-gson"]
|
||||||
tests = ["junit"]
|
tests = ["junit"]
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
plugins {
|
plugins {
|
||||||
alias(libs.plugins.android.library)
|
alias(libs.plugins.android.library)
|
||||||
alias(libs.plugins.kotlin.android)
|
alias(libs.plugins.kotlin.android)
|
||||||
|
alias(libs.plugins.kotlin.plugin.serialization)
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package de.mm20.launcher2.badges
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import de.mm20.launcher2.badges.providers.*
|
import de.mm20.launcher2.badges.providers.*
|
||||||
|
import de.mm20.launcher2.badges.settings.BadgeSettings
|
||||||
import de.mm20.launcher2.preferences.LauncherDataStore
|
import de.mm20.launcher2.preferences.LauncherDataStore
|
||||||
import de.mm20.launcher2.search.Searchable
|
import de.mm20.launcher2.search.Searchable
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
@ -13,16 +14,17 @@ interface BadgeService {
|
|||||||
fun getBadge(searchable: Searchable): Flow<Badge?>
|
fun getBadge(searchable: Searchable): Flow<Badge?>
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class BadgeServiceImpl(private val context: Context) : BadgeService, KoinComponent {
|
internal class BadgeServiceImpl(
|
||||||
|
private val context: Context,
|
||||||
|
private val settings: BadgeSettings,
|
||||||
|
) : BadgeService, KoinComponent {
|
||||||
|
|
||||||
private val dataStore: LauncherDataStore by inject()
|
|
||||||
private val scope = CoroutineScope(Job() + Dispatchers.Default)
|
private val scope = CoroutineScope(Job() + Dispatchers.Default)
|
||||||
|
|
||||||
private val badgeProviders = MutableStateFlow<List<BadgeProvider>>(emptyList())
|
private val badgeProviders = MutableStateFlow<List<BadgeProvider>>(emptyList())
|
||||||
|
|
||||||
init {
|
init {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
dataStore.data.map { it.badges }.distinctUntilChanged().collectLatest {
|
settings.data.distinctUntilChanged().collectLatest {
|
||||||
val providers = mutableListOf<BadgeProvider>()
|
val providers = mutableListOf<BadgeProvider>()
|
||||||
providers += WorkProfileBadgeProvider()
|
providers += WorkProfileBadgeProvider()
|
||||||
if (it.notifications) {
|
if (it.notifications) {
|
||||||
@ -37,7 +39,9 @@ internal class BadgeServiceImpl(private val context: Context) : BadgeService, Ko
|
|||||||
if (it.suspendedApps) {
|
if (it.suspendedApps) {
|
||||||
providers += SuspendedAppsBadgeProvider()
|
providers += SuspendedAppsBadgeProvider()
|
||||||
}
|
}
|
||||||
|
if (it.plugins) {
|
||||||
providers += PluginBadgeProvider(context)
|
providers += PluginBadgeProvider(context)
|
||||||
|
}
|
||||||
badgeProviders.value = providers
|
badgeProviders.value = providers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,13 @@
|
|||||||
package de.mm20.launcher2.badges
|
package de.mm20.launcher2.badges
|
||||||
|
|
||||||
|
import de.mm20.launcher2.backup.Backupable
|
||||||
|
import de.mm20.launcher2.badges.settings.BadgeSettings
|
||||||
import org.koin.android.ext.koin.androidContext
|
import org.koin.android.ext.koin.androidContext
|
||||||
|
import org.koin.core.qualifier.named
|
||||||
import org.koin.dsl.module
|
import org.koin.dsl.module
|
||||||
|
|
||||||
val badgesModule = module {
|
val badgesModule = module {
|
||||||
single<BadgeService> { BadgeServiceImpl(androidContext()) }
|
single<BadgeService> { BadgeServiceImpl(androidContext(), get()) }
|
||||||
|
single<BadgeSettings> { BadgeSettings(androidContext(), get()) }
|
||||||
|
factory<Backupable>(named<BadgeSettings>()) { get<BadgeSettings>() }
|
||||||
}
|
}
|
||||||
@ -0,0 +1,68 @@
|
|||||||
|
package de.mm20.launcher2.badges.settings
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import de.mm20.launcher2.badges.settings.migrations.Migration1
|
||||||
|
import de.mm20.launcher2.preferences.LauncherDataStore
|
||||||
|
import de.mm20.launcher2.settings.BaseSettings
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
|
|
||||||
|
class BadgeSettings(
|
||||||
|
private val context: Context,
|
||||||
|
dataStore: LauncherDataStore,
|
||||||
|
) : BaseSettings<BadgeSettingsData>(
|
||||||
|
context = context,
|
||||||
|
fileName = "badges.json",
|
||||||
|
serializer = BadgeSettingsDataSerializer,
|
||||||
|
migrations = listOf(
|
||||||
|
Migration1(dataStore),
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
|
||||||
|
internal val data
|
||||||
|
get() = context.dataStore.data
|
||||||
|
|
||||||
|
val notifications
|
||||||
|
get() = context.dataStore.data.map { it.notifications }
|
||||||
|
|
||||||
|
fun setNotifications(notifications: Boolean) {
|
||||||
|
updateData {
|
||||||
|
it.copy(notifications = notifications)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val suspendedApps
|
||||||
|
get() = context.dataStore.data.map { it.suspendedApps }
|
||||||
|
|
||||||
|
fun setSuspendedApps(suspendedApps: Boolean) {
|
||||||
|
updateData {
|
||||||
|
it.copy(suspendedApps = suspendedApps)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val cloudFiles
|
||||||
|
get() = context.dataStore.data.map { it.cloudFiles }
|
||||||
|
|
||||||
|
fun setCloudFiles(cloudFiles: Boolean) {
|
||||||
|
updateData {
|
||||||
|
it.copy(cloudFiles = cloudFiles)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val shortcuts
|
||||||
|
get() = context.dataStore.data.map { it.shortcuts }
|
||||||
|
|
||||||
|
fun setShortcuts(shortcuts: Boolean) {
|
||||||
|
updateData {
|
||||||
|
it.copy(shortcuts = shortcuts)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val plugins
|
||||||
|
get() = context.dataStore.data.map { it.plugins }
|
||||||
|
|
||||||
|
fun setPlugins(plugins: Boolean) {
|
||||||
|
updateData {
|
||||||
|
it.copy(plugins = plugins)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,50 @@
|
|||||||
|
package de.mm20.launcher2.badges.settings
|
||||||
|
|
||||||
|
import androidx.datastore.core.CorruptionException
|
||||||
|
import androidx.datastore.core.Serializer
|
||||||
|
import de.mm20.launcher2.files.settings.FileSearchSettingsData
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.SerializationException
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import kotlinx.serialization.json.decodeFromStream
|
||||||
|
import kotlinx.serialization.json.encodeToStream
|
||||||
|
import java.io.IOException
|
||||||
|
import java.io.InputStream
|
||||||
|
import java.io.OutputStream
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class BadgeSettingsData(
|
||||||
|
val notifications: Boolean = true,
|
||||||
|
val suspendedApps: Boolean = true,
|
||||||
|
val cloudFiles: Boolean = true,
|
||||||
|
val shortcuts: Boolean = true,
|
||||||
|
val plugins: Boolean = true,
|
||||||
|
val schemaVersion: Int = 1,
|
||||||
|
)
|
||||||
|
|
||||||
|
internal object BadgeSettingsDataSerializer : Serializer<BadgeSettingsData> {
|
||||||
|
|
||||||
|
private val json = Json {
|
||||||
|
ignoreUnknownKeys = true
|
||||||
|
encodeDefaults = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override val defaultValue: BadgeSettingsData
|
||||||
|
get() = BadgeSettingsData(schemaVersion = 0)
|
||||||
|
|
||||||
|
override suspend fun readFrom(input: InputStream): BadgeSettingsData {
|
||||||
|
try {
|
||||||
|
return json.decodeFromStream(input)
|
||||||
|
} catch (e: IllegalArgumentException) {
|
||||||
|
throw (CorruptionException("Cannot read json.", e))
|
||||||
|
} catch (e: SerializationException) {
|
||||||
|
throw (CorruptionException("Cannot read json.", e))
|
||||||
|
} catch (e: IOException) {
|
||||||
|
throw (CorruptionException("Cannot read json.", e))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun writeTo(t: BadgeSettingsData, output: OutputStream) {
|
||||||
|
json.encodeToStream(t, output)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
package de.mm20.launcher2.badges.settings.migrations
|
||||||
|
|
||||||
|
import androidx.datastore.core.DataMigration
|
||||||
|
import de.mm20.launcher2.badges.settings.BadgeSettingsData
|
||||||
|
import de.mm20.launcher2.preferences.LauncherDataStore
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
|
|
||||||
|
class Migration1(
|
||||||
|
private val dataStore: LauncherDataStore,
|
||||||
|
): DataMigration<BadgeSettingsData> {
|
||||||
|
override suspend fun cleanUp() {
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun shouldMigrate(currentData: BadgeSettingsData): Boolean {
|
||||||
|
return currentData.schemaVersion < 1
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun migrate(currentData: BadgeSettingsData): BadgeSettingsData {
|
||||||
|
val data = dataStore.data.first().badges
|
||||||
|
return currentData.copy(
|
||||||
|
notifications = data.notifications,
|
||||||
|
suspendedApps = data.suspendedApps,
|
||||||
|
cloudFiles = data.cloudFiles,
|
||||||
|
shortcuts = data.shortcuts,
|
||||||
|
schemaVersion = 1,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user