Refactor preferences module

This commit is contained in:
MM20
2024-01-19 22:29:37 +01:00
parent 94aee6baba
commit 92ddc75060
171 changed files with 3202 additions and 2962 deletions
@@ -8,7 +8,7 @@ import de.mm20.launcher2.badges.providers.NotificationBadgeProvider
import de.mm20.launcher2.badges.providers.PluginBadgeProvider
import de.mm20.launcher2.badges.providers.SuspendedAppsBadgeProvider
import de.mm20.launcher2.badges.providers.WorkProfileBadgeProvider
import de.mm20.launcher2.badges.settings.BadgeSettings
import de.mm20.launcher2.preferences.ui.BadgeSettings
import de.mm20.launcher2.search.Searchable
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@@ -39,7 +39,7 @@ internal class BadgeServiceImpl(
init {
scope.launch {
settings.data.distinctUntilChanged().collectLatest {
settings.distinctUntilChanged().collectLatest {
val providers = mutableListOf<BadgeProvider>()
providers += WorkProfileBadgeProvider()
if (it.notifications) {
@@ -1,13 +1,8 @@
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(), get()) }
single<BadgeSettings> { BadgeSettings(androidContext(), get()) }
factory<Backupable>(named<BadgeSettings>()) { get<BadgeSettings>() }
}
@@ -1,68 +0,0 @@
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)
}
}
}
@@ -1,50 +0,0 @@
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)
}
}
@@ -1,28 +0,0 @@
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,
)
}
}
@@ -31,7 +31,7 @@ import de.mm20.launcher2.icons.transformations.LauncherIconTransformation
import de.mm20.launcher2.icons.transformations.LegacyToAdaptiveTransformation
import de.mm20.launcher2.icons.transformations.transform
import de.mm20.launcher2.ktx.isAtLeastApiLevel
import de.mm20.launcher2.preferences.LauncherDataStore
import de.mm20.launcher2.preferences.ui.IconSettings
import de.mm20.launcher2.search.Application
import de.mm20.launcher2.search.SavableSearchable
import kotlinx.coroutines.CoroutineScope
@@ -50,7 +50,7 @@ import kotlinx.coroutines.launch
class IconService(
val context: Context,
private val iconPackManager: IconPackManager,
private val dataStore: LauncherDataStore,
private val settings: IconSettings,
private val customAttributesRepository: CustomAttributesRepository,
) {
@@ -90,7 +90,7 @@ class IconService(
iconPacksUpdated.tryEmit(Unit)
scope.launch {
dataStore.data.map { it.icons }.distinctUntilChanged().collectLatest { settings ->
settings.distinctUntilChanged().collectLatest { settings ->
iconPacksUpdated.collectLatest {
val fallbackProvider = if (settings.themedIcons) {
ThemedPlaceholderIconProvider(context)
@@ -99,8 +99,8 @@ class IconService(
}
val providers = mutableListOf<IconProvider>()
if (settings.iconPack.isNotBlank()) {
val pack = iconPackManager.getIconPack(settings.iconPack)
if (!settings.iconPack.isNullOrBlank()) {
val pack = iconPackManager.getIconPack(settings.iconPack!!)
if (pack != null) {
providers.add(
IconPackIconProvider(
@@ -4,5 +4,5 @@ import org.koin.android.ext.koin.androidContext
import org.koin.dsl.module
val musicModule = module {
single<MusicService> { MusicServiceImpl(androidContext(), get()) }
single<MusicService> { MusicServiceImpl(androidContext(), get(), get()) }
}
@@ -4,21 +4,17 @@ import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.media.AudioManager
import android.media.MediaMetadata
import android.media.session.MediaController
import android.media.session.MediaSession
import android.media.session.PlaybackState.CustomAction
import android.net.Uri
import android.os.Handler
import android.os.Looper
import android.os.SystemClock
import android.service.notification.StatusBarNotification
import android.view.KeyEvent
import androidx.core.app.NotificationCompat
import androidx.core.content.edit
import androidx.core.graphics.drawable.toBitmap
import coil.imageLoader
@@ -27,7 +23,7 @@ import coil.size.Scale
import de.mm20.launcher2.crashreporter.CrashReporter
import de.mm20.launcher2.notifications.Notification
import de.mm20.launcher2.notifications.NotificationRepository
import de.mm20.launcher2.preferences.LauncherDataStore
import de.mm20.launcher2.preferences.media.MediaSettings
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
@@ -47,7 +43,6 @@ import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
import java.io.IOException
interface MusicService {
@@ -81,11 +76,11 @@ interface MusicService {
internal class MusicServiceImpl(
private val context: Context,
notificationRepository: NotificationRepository
notificationRepository: NotificationRepository,
private val settings: MediaSettings,
) : MusicService, KoinComponent {
private val scope = CoroutineScope(Job() + Dispatchers.Default)
private val dataStore: LauncherDataStore by inject()
private val preferences: SharedPreferences by lazy {
context.getSharedPreferences(PREFS, Context.MODE_PRIVATE)
@@ -108,12 +103,12 @@ internal class MusicServiceImpl(
private val currentMediaController: SharedFlow<MediaController?> =
combine(
notificationRepository.notifications,
dataStore.data.map { it.musicWidget }
settings,
) { notifications, settings ->
withContext(Dispatchers.Default) {
val musicApps = getEnabledPlayerPackages(
settings.allowListList.toSet(),
settings.denyListList.toSet()
settings.allowList,
settings.denyList,
)
val sbn: Notification? = notifications.filter {
it.mediaSessionToken != null && musicApps.contains(it.packageName)
@@ -3,15 +3,6 @@ package de.mm20.launcher2.search
import de.mm20.launcher2.calculator.CalculatorRepository
import de.mm20.launcher2.data.customattrs.CustomAttributesRepository
import de.mm20.launcher2.data.customattrs.utils.withCustomLabels
import de.mm20.launcher2.preferences.Settings
import de.mm20.launcher2.preferences.Settings.AppShortcutSearchSettings
import de.mm20.launcher2.preferences.Settings.CalculatorSearchSettings
import de.mm20.launcher2.preferences.Settings.CalendarSearchSettings
import de.mm20.launcher2.preferences.Settings.ContactsSearchSettings
import de.mm20.launcher2.preferences.Settings.FilesSearchSettings
import de.mm20.launcher2.preferences.Settings.UnitConverterSearchSettings
import de.mm20.launcher2.preferences.Settings.WebsiteSearchSettings
import de.mm20.launcher2.preferences.Settings.WikipediaSearchSettings
import de.mm20.launcher2.search.data.Calculator
import de.mm20.launcher2.search.data.UnitConverter
import de.mm20.launcher2.searchactions.SearchActionService
@@ -32,27 +23,6 @@ import kotlinx.coroutines.supervisorScope
interface SearchService {
fun search(
query: String,
shortcuts: AppShortcutSearchSettings = Settings.AppShortcutSearchSettings.newBuilder()
.setEnabled(false)
.build(),
contacts: ContactsSearchSettings = Settings.ContactsSearchSettings.newBuilder()
.setEnabled(false)
.build(),
calendars: CalendarSearchSettings = Settings.CalendarSearchSettings.newBuilder()
.setEnabled(false)
.build(),
calculator: CalculatorSearchSettings = Settings.CalculatorSearchSettings.newBuilder()
.setEnabled(false)
.build(),
unitConverter: UnitConverterSearchSettings = Settings.UnitConverterSearchSettings.newBuilder()
.setEnabled(false)
.build(),
websites: WebsiteSearchSettings = Settings.WebsiteSearchSettings.newBuilder()
.setEnabled(false)
.build(),
wikipedia: WikipediaSearchSettings = Settings.WikipediaSearchSettings.newBuilder()
.setEnabled(false)
.build(),
): Flow<SearchResults>
}
@@ -72,13 +42,6 @@ internal class SearchServiceImpl(
override fun search(
query: String,
shortcuts: AppShortcutSearchSettings,
contacts: ContactsSearchSettings,
calendars: CalendarSearchSettings,
calculator: CalculatorSearchSettings,
unitConverter: UnitConverterSearchSettings,
websites: WebsiteSearchSettings,
wikipedia: WikipediaSearchSettings,
): Flow<SearchResults> = channelFlow {
val results = MutableStateFlow(SearchResults())
supervisorScope {
@@ -99,82 +62,68 @@ internal class SearchServiceImpl(
}
}
}
if (shortcuts.enabled) {
launch {
appShortcutRepository.search(query)
.withCustomLabels(customAttributesRepository)
.collectLatest { r ->
results.update {
it.copy(shortcuts = r.toImmutableList())
}
}
}
}
if (contacts.enabled) {
launch {
contactRepository.search(query)
.withCustomLabels(customAttributesRepository)
.collectLatest { r ->
results.update {
it.copy(contacts = r.toImmutableList())
}
}
}
}
if (calendars.enabled) {
launch {
calendarRepository.search(query)
.withCustomLabels(customAttributesRepository)
.collectLatest { r ->
results.update {
it.copy(calendars = r.toImmutableList())
}
}
}
}
if (calculator.enabled) {
launch {
calculatorRepository.search(query).collectLatest { r ->
launch {
appShortcutRepository.search(query)
.withCustomLabels(customAttributesRepository)
.collectLatest { r ->
results.update {
it.copy(calculators = r?.let { persistentListOf(it) }
?: persistentListOf())
it.copy(shortcuts = r.toImmutableList())
}
}
}
launch {
contactRepository.search(query)
.withCustomLabels(customAttributesRepository)
.collectLatest { r ->
results.update {
it.copy(contacts = r.toImmutableList())
}
}
}
launch {
calendarRepository.search(query)
.withCustomLabels(customAttributesRepository)
.collectLatest { r ->
results.update {
it.copy(calendars = r.toImmutableList())
}
}
}
launch {
calculatorRepository.search(query).collectLatest { r ->
results.update {
it.copy(calculators = r?.let { persistentListOf(it) }
?: persistentListOf())
}
}
}
if (unitConverter.enabled) {
launch {
unitConverterRepository.search(query, unitConverter.currencies)
.collectLatest { r ->
results.update {
it.copy(unitConverters = r?.let { persistentListOf(it) }
?: persistentListOf())
}
launch {
unitConverterRepository.search(query)
.collectLatest { r ->
results.update {
it.copy(unitConverters = r?.let { persistentListOf(it) }
?: persistentListOf())
}
}
}
}
if (websites.enabled) {
launch {
websiteRepository.search(query)
.withCustomLabels(customAttributesRepository)
.collectLatest { r ->
results.update {
it.copy(websites = r.toImmutableList())
}
launch {
websiteRepository.search(query)
.withCustomLabels(customAttributesRepository)
.collectLatest { r ->
results.update {
it.copy(websites = r.toImmutableList())
}
}
}
}
if (wikipedia.enabled) {
launch {
delay(750)
articleRepository.search(query)
.withCustomLabels(customAttributesRepository)
.collectLatest { r ->
results.update {
it.copy(wikipedia = r.toImmutableList())
}
launch {
delay(750)
articleRepository.search(query)
.withCustomLabels(customAttributesRepository)
.collectLatest { r ->
results.update {
it.copy(wikipedia = r.toImmutableList())
}
}
}
}
launch {
fileRepository.search(