Refactor preferences module
This commit is contained in:
@@ -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)
|
||||
}
|
||||
}
|
||||
-28
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user