Move badge settings to decentralized data store, add preference for plugin badges

This commit is contained in:
MM20
2023-12-07 22:44:41 +01:00
parent 0f6d636ca0
commit 2479fdbc03
15 changed files with 268 additions and 95 deletions
@@ -2,6 +2,7 @@ package de.mm20.launcher2.badges
import android.content.Context
import de.mm20.launcher2.badges.providers.*
import de.mm20.launcher2.badges.settings.BadgeSettings
import de.mm20.launcher2.preferences.LauncherDataStore
import de.mm20.launcher2.search.Searchable
import kotlinx.coroutines.*
@@ -13,16 +14,17 @@ interface BadgeService {
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 badgeProviders = MutableStateFlow<List<BadgeProvider>>(emptyList())
init {
scope.launch {
dataStore.data.map { it.badges }.distinctUntilChanged().collectLatest {
settings.data.distinctUntilChanged().collectLatest {
val providers = mutableListOf<BadgeProvider>()
providers += WorkProfileBadgeProvider()
if (it.notifications) {
@@ -37,7 +39,9 @@ internal class BadgeServiceImpl(private val context: Context) : BadgeService, Ko
if (it.suspendedApps) {
providers += SuspendedAppsBadgeProvider()
}
providers += PluginBadgeProvider(context)
if (it.plugins) {
providers += PluginBadgeProvider(context)
}
badgeProviders.value = providers
}
}
@@ -1,8 +1,13 @@
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.core.qualifier.named
import org.koin.dsl.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,
)
}
}