Migrate file search settings to decentralized json data store
This commit is contained in:
parent
25cd9b707e
commit
966d43d4d1
@ -47,7 +47,6 @@ class SearchablePickerVM: ViewModel(), KoinComponent {
|
|||||||
shortcuts = settings.appShortcutSearch,
|
shortcuts = settings.appShortcutSearch,
|
||||||
contacts = settings.contactsSearch,
|
contacts = settings.contactsSearch,
|
||||||
calendars = settings.calendarSearch,
|
calendars = settings.calendarSearch,
|
||||||
files = settings.fileSearch,
|
|
||||||
).collectLatest {
|
).collectLatest {
|
||||||
if (searchQuery != query) return@collectLatest
|
if (searchQuery != query) return@collectLatest
|
||||||
items = withContext(Dispatchers.Default) {
|
items = withContext(Dispatchers.Default) {
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import androidx.appcompat.app.AppCompatActivity
|
|||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import de.mm20.launcher2.files.settings.FileSearchSettings
|
||||||
import de.mm20.launcher2.searchable.SavableSearchableRepository
|
import de.mm20.launcher2.searchable.SavableSearchableRepository
|
||||||
import de.mm20.launcher2.permissions.PermissionGroup
|
import de.mm20.launcher2.permissions.PermissionGroup
|
||||||
import de.mm20.launcher2.permissions.PermissionsManager
|
import de.mm20.launcher2.permissions.PermissionsManager
|
||||||
@ -47,6 +48,7 @@ class SearchVM : ViewModel(), KoinComponent {
|
|||||||
private val searchableRepository: SavableSearchableRepository by inject()
|
private val searchableRepository: SavableSearchableRepository by inject()
|
||||||
private val permissionsManager: PermissionsManager by inject()
|
private val permissionsManager: PermissionsManager by inject()
|
||||||
private val dataStore: LauncherDataStore by inject()
|
private val dataStore: LauncherDataStore by inject()
|
||||||
|
private val fileSearchSettings: FileSearchSettings by inject()
|
||||||
|
|
||||||
val launchOnEnter = dataStore.data.map { it.searchBar.launchOnEnter }
|
val launchOnEnter = dataStore.data.map { it.searchBar.launchOnEnter }
|
||||||
.stateIn(viewModelScope, SharingStarted.Eagerly, false)
|
.stateIn(viewModelScope, SharingStarted.Eagerly, false)
|
||||||
@ -122,7 +124,6 @@ class SearchVM : ViewModel(), KoinComponent {
|
|||||||
unitConverter = settings.unitConverterSearch,
|
unitConverter = settings.unitConverterSearch,
|
||||||
calendars = settings.calendarSearch,
|
calendars = settings.calendarSearch,
|
||||||
contacts = settings.contactsSearch,
|
contacts = settings.contactsSearch,
|
||||||
files = settings.fileSearch,
|
|
||||||
shortcuts = settings.appShortcutSearch,
|
shortcuts = settings.appShortcutSearch,
|
||||||
websites = settings.websiteSearch,
|
websites = settings.websiteSearch,
|
||||||
wikipedia = settings.wikipediaSearch,
|
wikipedia = settings.wikipediaSearch,
|
||||||
@ -293,7 +294,7 @@ class SearchVM : ViewModel(), KoinComponent {
|
|||||||
|
|
||||||
val missingFilesPermission = combine(
|
val missingFilesPermission = combine(
|
||||||
permissionsManager.hasPermission(PermissionGroup.ExternalStorage),
|
permissionsManager.hasPermission(PermissionGroup.ExternalStorage),
|
||||||
dataStore.data.map { it.fileSearch.localFiles }.distinctUntilChanged()
|
fileSearchSettings.localFiles.distinctUntilChanged()
|
||||||
) { perm, enabled -> !perm && enabled }
|
) { perm, enabled -> !perm && enabled }
|
||||||
|
|
||||||
fun requestFilesPermission(context: AppCompatActivity) {
|
fun requestFilesPermission(context: AppCompatActivity) {
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import androidx.lifecycle.viewModelScope
|
|||||||
import de.mm20.launcher2.accounts.Account
|
import de.mm20.launcher2.accounts.Account
|
||||||
import de.mm20.launcher2.accounts.AccountType
|
import de.mm20.launcher2.accounts.AccountType
|
||||||
import de.mm20.launcher2.accounts.AccountsRepository
|
import de.mm20.launcher2.accounts.AccountsRepository
|
||||||
|
import de.mm20.launcher2.files.settings.FileSearchSettings
|
||||||
import de.mm20.launcher2.permissions.PermissionGroup
|
import de.mm20.launcher2.permissions.PermissionGroup
|
||||||
import de.mm20.launcher2.permissions.PermissionsManager
|
import de.mm20.launcher2.permissions.PermissionsManager
|
||||||
import de.mm20.launcher2.preferences.LauncherDataStore
|
import de.mm20.launcher2.preferences.LauncherDataStore
|
||||||
@ -18,7 +19,7 @@ import org.koin.core.component.KoinComponent
|
|||||||
import org.koin.core.component.inject
|
import org.koin.core.component.inject
|
||||||
|
|
||||||
class FileSearchSettingsScreenVM : ViewModel(), KoinComponent {
|
class FileSearchSettingsScreenVM : ViewModel(), KoinComponent {
|
||||||
private val dataStore: LauncherDataStore by inject()
|
private val fileSearchSettings: FileSearchSettings by inject()
|
||||||
private val accountsRepository: AccountsRepository by inject()
|
private val accountsRepository: AccountsRepository by inject()
|
||||||
private val permissionsManager: PermissionsManager by inject()
|
private val permissionsManager: PermissionsManager by inject()
|
||||||
|
|
||||||
@ -43,84 +44,28 @@ class FileSearchSettingsScreenVM : ViewModel(), KoinComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val localFiles = dataStore.data.map { it.fileSearch.localFiles }
|
val localFiles = fileSearchSettings.localFiles
|
||||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null)
|
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null)
|
||||||
fun setLocalFiles(localFiles: Boolean) {
|
fun setLocalFiles(localFiles: Boolean) {
|
||||||
viewModelScope.launch {
|
fileSearchSettings.setLocalFiles(localFiles)
|
||||||
dataStore.updateData {
|
|
||||||
it.toBuilder()
|
|
||||||
.setFileSearch(
|
|
||||||
it.fileSearch
|
|
||||||
.toBuilder()
|
|
||||||
.setLocalFiles(localFiles)
|
|
||||||
)
|
|
||||||
.build()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val nextcloud = dataStore.data.map { it.fileSearch.nextcloud }
|
val nextcloud = fileSearchSettings.nextcloudFiles
|
||||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null)
|
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null)
|
||||||
fun setNextcloud(nextcloud: Boolean) {
|
fun setNextcloud(nextcloud: Boolean) {
|
||||||
viewModelScope.launch {
|
fileSearchSettings.setNextcloudFiles(nextcloud)
|
||||||
dataStore.updateData {
|
|
||||||
it.toBuilder()
|
|
||||||
.setFileSearch(
|
|
||||||
it.fileSearch
|
|
||||||
.toBuilder()
|
|
||||||
.setNextcloud(nextcloud)
|
|
||||||
)
|
|
||||||
.build()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val gdrive = dataStore.data.map { it.fileSearch.gdrive }
|
val gdrive = fileSearchSettings.gdriveFiles
|
||||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null)
|
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null)
|
||||||
fun setGdrive(gdrive: Boolean) {
|
fun setGdrive(gdrive: Boolean) {
|
||||||
viewModelScope.launch {
|
fileSearchSettings.setGdriveFiles(gdrive)
|
||||||
dataStore.updateData {
|
|
||||||
it.toBuilder()
|
|
||||||
.setFileSearch(
|
|
||||||
it.fileSearch
|
|
||||||
.toBuilder()
|
|
||||||
.setGdrive(gdrive)
|
|
||||||
)
|
|
||||||
.build()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val onedrive = dataStore.data.map { it.fileSearch.onedrive }
|
val owncloud = fileSearchSettings.owncloudFiles
|
||||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null)
|
|
||||||
fun setOneDrive(onedrive: Boolean) {
|
|
||||||
viewModelScope.launch {
|
|
||||||
dataStore.updateData {
|
|
||||||
it.toBuilder()
|
|
||||||
.setFileSearch(
|
|
||||||
it.fileSearch
|
|
||||||
.toBuilder()
|
|
||||||
.setOnedrive(onedrive)
|
|
||||||
)
|
|
||||||
.build()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val owncloud = dataStore.data.map { it.fileSearch.owncloud }
|
|
||||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null)
|
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null)
|
||||||
fun setOwncloud(owncloud: Boolean) {
|
fun setOwncloud(owncloud: Boolean) {
|
||||||
viewModelScope.launch {
|
fileSearchSettings.setOwncloudFiles(owncloud)
|
||||||
dataStore.updateData {
|
|
||||||
it.toBuilder()
|
|
||||||
.setFileSearch(
|
|
||||||
it.fileSearch
|
|
||||||
.toBuilder()
|
|
||||||
.setOwncloud(owncloud)
|
|
||||||
)
|
|
||||||
.build()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun requestFilePermission(context: AppCompatActivity) {
|
fun requestFilePermission(context: AppCompatActivity) {
|
||||||
|
|||||||
@ -169,7 +169,7 @@ message Settings {
|
|||||||
bool nextcloud = 4;
|
bool nextcloud = 4;
|
||||||
bool owncloud = 5;
|
bool owncloud = 5;
|
||||||
}
|
}
|
||||||
FilesSearchSettings file_search = 9;
|
FilesSearchSettings file_search = 9 [deprecated = true];
|
||||||
|
|
||||||
message ContactsSearchSettings {
|
message ContactsSearchSettings {
|
||||||
bool enabled = 1;
|
bool enabled = 1;
|
||||||
|
|||||||
@ -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 {
|
||||||
@ -35,9 +36,11 @@ android {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(libs.bundles.kotlin)
|
implementation(libs.bundles.kotlin)
|
||||||
|
implementation(libs.kotlinx.serialization.json)
|
||||||
implementation(libs.androidx.core)
|
implementation(libs.androidx.core)
|
||||||
implementation(libs.androidx.appcompat)
|
implementation(libs.androidx.appcompat)
|
||||||
implementation(libs.androidx.exifinterface)
|
implementation(libs.androidx.exifinterface)
|
||||||
|
implementation(libs.androidx.datastore)
|
||||||
|
|
||||||
implementation(libs.bundles.androidx.lifecycle)
|
implementation(libs.bundles.androidx.lifecycle)
|
||||||
|
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import de.mm20.launcher2.files.providers.LocalFileProvider
|
|||||||
import de.mm20.launcher2.files.providers.NextcloudFileProvider
|
import de.mm20.launcher2.files.providers.NextcloudFileProvider
|
||||||
import de.mm20.launcher2.files.providers.OwncloudFileProvider
|
import de.mm20.launcher2.files.providers.OwncloudFileProvider
|
||||||
import de.mm20.launcher2.files.providers.PluginFileProvider
|
import de.mm20.launcher2.files.providers.PluginFileProvider
|
||||||
|
import de.mm20.launcher2.files.settings.FileSearchSettings
|
||||||
import de.mm20.launcher2.nextcloud.NextcloudApiHelper
|
import de.mm20.launcher2.nextcloud.NextcloudApiHelper
|
||||||
import de.mm20.launcher2.owncloud.OwncloudClient
|
import de.mm20.launcher2.owncloud.OwncloudClient
|
||||||
import de.mm20.launcher2.permissions.PermissionsManager
|
import de.mm20.launcher2.permissions.PermissionsManager
|
||||||
@ -28,7 +29,7 @@ import kotlinx.coroutines.flow.map
|
|||||||
internal class FileRepository(
|
internal class FileRepository(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val permissionsManager: PermissionsManager,
|
private val permissionsManager: PermissionsManager,
|
||||||
private val dataStore: LauncherDataStore,
|
private val settings: FileSearchSettings,
|
||||||
private val pluginRepository: PluginRepository,
|
private val pluginRepository: PluginRepository,
|
||||||
) : SearchableRepository<File> {
|
) : SearchableRepository<File> {
|
||||||
|
|
||||||
@ -52,8 +53,7 @@ internal class FileRepository(
|
|||||||
enabled = true,
|
enabled = true,
|
||||||
)
|
)
|
||||||
|
|
||||||
dataStore.data.map { it.fileSearch }
|
settings.data.combine(filePlugins) { settings, plugins ->
|
||||||
.combine(filePlugins) { settings, plugins ->
|
|
||||||
settings to plugins
|
settings to plugins
|
||||||
}.collectLatest { (settings, plugins) ->
|
}.collectLatest { (settings, plugins) ->
|
||||||
val providers = mutableListOf<FileProvider>()
|
val providers = mutableListOf<FileProvider>()
|
||||||
@ -64,9 +64,9 @@ internal class FileRepository(
|
|||||||
permissionsManager
|
permissionsManager
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
if (settings.gdrive) providers.add(GDriveFileProvider(context))
|
if (settings.gdriveFiles) providers.add(GDriveFileProvider(context))
|
||||||
if (settings.nextcloud) providers.add(NextcloudFileProvider(nextcloudClient))
|
if (settings.nextcloudFiles) providers.add(NextcloudFileProvider(nextcloudClient))
|
||||||
if (settings.owncloud) providers.add(OwncloudFileProvider(owncloudClient))
|
if (settings.owncloudFiles) providers.add(OwncloudFileProvider(owncloudClient))
|
||||||
|
|
||||||
for (plugin in plugins) {
|
for (plugin in plugins) {
|
||||||
providers.add(PluginFileProvider(context, plugin))
|
providers.add(PluginFileProvider(context, plugin))
|
||||||
|
|||||||
@ -1,11 +1,13 @@
|
|||||||
package de.mm20.launcher2.files
|
package de.mm20.launcher2.files
|
||||||
|
|
||||||
|
import de.mm20.launcher2.backup.Backupable
|
||||||
import de.mm20.launcher2.files.providers.GDriveFile
|
import de.mm20.launcher2.files.providers.GDriveFile
|
||||||
import de.mm20.launcher2.files.providers.LocalFile
|
import de.mm20.launcher2.files.providers.LocalFile
|
||||||
import de.mm20.launcher2.files.providers.NextcloudFile
|
import de.mm20.launcher2.files.providers.NextcloudFile
|
||||||
import de.mm20.launcher2.files.providers.OneDriveFile
|
import de.mm20.launcher2.files.providers.OneDriveFile
|
||||||
import de.mm20.launcher2.files.providers.OwncloudFile
|
import de.mm20.launcher2.files.providers.OwncloudFile
|
||||||
import de.mm20.launcher2.files.providers.PluginFile
|
import de.mm20.launcher2.files.providers.PluginFile
|
||||||
|
import de.mm20.launcher2.files.settings.FileSearchSettings
|
||||||
import de.mm20.launcher2.search.File
|
import de.mm20.launcher2.search.File
|
||||||
import de.mm20.launcher2.search.SearchableDeserializer
|
import de.mm20.launcher2.search.SearchableDeserializer
|
||||||
import de.mm20.launcher2.search.SearchableRepository
|
import de.mm20.launcher2.search.SearchableRepository
|
||||||
@ -14,11 +16,25 @@ import org.koin.core.qualifier.named
|
|||||||
import org.koin.dsl.module
|
import org.koin.dsl.module
|
||||||
|
|
||||||
val filesModule = module {
|
val filesModule = module {
|
||||||
factory<SearchableRepository<File>>(named<File>()) { FileRepository(androidContext(), get(), get(), get()) }
|
factory<SearchableRepository<File>>(named<File>()) {
|
||||||
|
FileRepository(
|
||||||
|
androidContext(),
|
||||||
|
get(),
|
||||||
|
get(),
|
||||||
|
get()
|
||||||
|
)
|
||||||
|
}
|
||||||
factory<SearchableDeserializer>(named(LocalFile.Domain)) { LocalFileDeserializer(androidContext()) }
|
factory<SearchableDeserializer>(named(LocalFile.Domain)) { LocalFileDeserializer(androidContext()) }
|
||||||
factory<SearchableDeserializer>(named(OwncloudFile.Domain)) { OwncloudFileDeserializer() }
|
factory<SearchableDeserializer>(named(OwncloudFile.Domain)) { OwncloudFileDeserializer() }
|
||||||
factory<SearchableDeserializer>(named(NextcloudFile.Domain)) { NextcloudFileDeserializer() }
|
factory<SearchableDeserializer>(named(NextcloudFile.Domain)) { NextcloudFileDeserializer() }
|
||||||
factory<SearchableDeserializer>(named(OneDriveFile.Domain)) { OneDriveFileDeserializer() }
|
factory<SearchableDeserializer>(named(OneDriveFile.Domain)) { OneDriveFileDeserializer() }
|
||||||
factory<SearchableDeserializer>(named(GDriveFile.Domain)) { GDriveFileDeserializer() }
|
factory<SearchableDeserializer>(named(GDriveFile.Domain)) { GDriveFileDeserializer() }
|
||||||
factory<SearchableDeserializer>(named(PluginFile.Domain)) { PluginFileDeserializer(androidContext(), get()) }
|
factory<SearchableDeserializer>(named(PluginFile.Domain)) {
|
||||||
|
PluginFileDeserializer(
|
||||||
|
androidContext(),
|
||||||
|
get()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
single<FileSearchSettings> { FileSearchSettings(androidContext(), get()) }
|
||||||
|
factory<Backupable>(named<FileSearchSettings>()) { get<FileSearchSettings>() }
|
||||||
}
|
}
|
||||||
@ -0,0 +1,112 @@
|
|||||||
|
package de.mm20.launcher2.files.settings
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.datastore.dataStore
|
||||||
|
import de.mm20.launcher2.backup.Backupable
|
||||||
|
import de.mm20.launcher2.crashreporter.CrashReporter
|
||||||
|
import de.mm20.launcher2.files.settings.migrations.Migration1
|
||||||
|
import de.mm20.launcher2.preferences.LauncherDataStore
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.serialization.SerializationException
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class FileSearchSettings(
|
||||||
|
private val context: Context,
|
||||||
|
private val dataStore: LauncherDataStore,
|
||||||
|
) : Backupable {
|
||||||
|
|
||||||
|
private val scope = CoroutineScope(Job() + Dispatchers.Default)
|
||||||
|
|
||||||
|
private val Context.dataStore by dataStore(
|
||||||
|
fileName = "file_search.json",
|
||||||
|
serializer = FileSearchSettingsDataSerializer,
|
||||||
|
produceMigrations = {
|
||||||
|
listOf(
|
||||||
|
Migration1(dataStore),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun updateData(block: suspend (FileSearchSettingsData) -> FileSearchSettingsData) {
|
||||||
|
scope.launch {
|
||||||
|
context.dataStore.updateData(block)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val data
|
||||||
|
get() = context.dataStore.data
|
||||||
|
|
||||||
|
val localFiles
|
||||||
|
get(): Flow<Boolean> {
|
||||||
|
return context.dataStore.data.map { it.localFiles }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setLocalFiles(localFiles: Boolean) {
|
||||||
|
updateData {
|
||||||
|
it.copy(localFiles = localFiles)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val gdriveFiles
|
||||||
|
get(): Flow<Boolean> {
|
||||||
|
return context.dataStore.data.map { it.gdriveFiles }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setGdriveFiles(gdriveFiles: Boolean) {
|
||||||
|
updateData {
|
||||||
|
it.copy(gdriveFiles = gdriveFiles)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val nextcloudFiles
|
||||||
|
get(): Flow<Boolean> {
|
||||||
|
return context.dataStore.data.map { it.nextcloudFiles }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setNextcloudFiles(nextcloudFiles: Boolean) {
|
||||||
|
updateData {
|
||||||
|
it.copy(nextcloudFiles = nextcloudFiles)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val owncloudFiles
|
||||||
|
get(): Flow<Boolean> {
|
||||||
|
return context.dataStore.data.map { it.owncloudFiles }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setOwncloudFiles(owncloudFiles: Boolean) {
|
||||||
|
updateData {
|
||||||
|
it.copy(owncloudFiles = owncloudFiles)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,49 @@
|
|||||||
|
package de.mm20.launcher2.files.settings
|
||||||
|
|
||||||
|
import androidx.datastore.core.CorruptionException
|
||||||
|
import androidx.datastore.core.Serializer
|
||||||
|
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
|
||||||
|
internal data class FileSearchSettingsData(
|
||||||
|
val localFiles: Boolean = true,
|
||||||
|
val gdriveFiles: Boolean = false,
|
||||||
|
val nextcloudFiles: Boolean = false,
|
||||||
|
val owncloudFiles: Boolean = false,
|
||||||
|
val plugins: Set<String> = emptySet(),
|
||||||
|
val schemaVersion: Int = 1,
|
||||||
|
)
|
||||||
|
|
||||||
|
internal object FileSearchSettingsDataSerializer : Serializer<FileSearchSettingsData> {
|
||||||
|
|
||||||
|
internal val json = Json {
|
||||||
|
ignoreUnknownKeys = true
|
||||||
|
encodeDefaults = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override val defaultValue: FileSearchSettingsData
|
||||||
|
get() = FileSearchSettingsData(schemaVersion = 0)
|
||||||
|
|
||||||
|
override suspend fun readFrom(input: InputStream): FileSearchSettingsData {
|
||||||
|
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: FileSearchSettingsData, output: OutputStream) {
|
||||||
|
json.encodeToStream(t, output)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
package de.mm20.launcher2.files.settings.migrations
|
||||||
|
|
||||||
|
import androidx.datastore.core.DataMigration
|
||||||
|
import de.mm20.launcher2.files.settings.FileSearchSettingsData
|
||||||
|
import de.mm20.launcher2.preferences.LauncherDataStore
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This migration is used to migrate the data from the old proto data store.
|
||||||
|
* TODO: remove after a few releases
|
||||||
|
*/
|
||||||
|
internal class Migration1(
|
||||||
|
private val dataStore: LauncherDataStore,
|
||||||
|
): DataMigration<FileSearchSettingsData> {
|
||||||
|
override suspend fun cleanUp() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun shouldMigrate(currentData: FileSearchSettingsData): Boolean {
|
||||||
|
return currentData.schemaVersion < 1
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun migrate(currentData: FileSearchSettingsData): FileSearchSettingsData {
|
||||||
|
val data = dataStore.data.first().fileSearch
|
||||||
|
return currentData.copy(
|
||||||
|
localFiles = data.localFiles,
|
||||||
|
gdriveFiles = data.gdrive,
|
||||||
|
nextcloudFiles = data.nextcloud,
|
||||||
|
owncloudFiles = data.owncloud,
|
||||||
|
schemaVersion = 1,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -41,13 +41,6 @@ interface SearchService {
|
|||||||
calendars: CalendarSearchSettings = Settings.CalendarSearchSettings.newBuilder()
|
calendars: CalendarSearchSettings = Settings.CalendarSearchSettings.newBuilder()
|
||||||
.setEnabled(false)
|
.setEnabled(false)
|
||||||
.build(),
|
.build(),
|
||||||
files: FilesSearchSettings = Settings.FilesSearchSettings.newBuilder()
|
|
||||||
.setLocalFiles(false)
|
|
||||||
.setGdrive(false)
|
|
||||||
.setOnedrive(false)
|
|
||||||
.setOwncloud(false)
|
|
||||||
.setNextcloud(false)
|
|
||||||
.build(),
|
|
||||||
calculator: CalculatorSearchSettings = Settings.CalculatorSearchSettings.newBuilder()
|
calculator: CalculatorSearchSettings = Settings.CalculatorSearchSettings.newBuilder()
|
||||||
.setEnabled(false)
|
.setEnabled(false)
|
||||||
.build(),
|
.build(),
|
||||||
@ -82,7 +75,6 @@ internal class SearchServiceImpl(
|
|||||||
shortcuts: AppShortcutSearchSettings,
|
shortcuts: AppShortcutSearchSettings,
|
||||||
contacts: ContactsSearchSettings,
|
contacts: ContactsSearchSettings,
|
||||||
calendars: CalendarSearchSettings,
|
calendars: CalendarSearchSettings,
|
||||||
files: FilesSearchSettings,
|
|
||||||
calculator: CalculatorSearchSettings,
|
calculator: CalculatorSearchSettings,
|
||||||
unitConverter: UnitConverterSearchSettings,
|
unitConverter: UnitConverterSearchSettings,
|
||||||
websites: WebsiteSearchSettings,
|
websites: WebsiteSearchSettings,
|
||||||
@ -184,7 +176,6 @@ internal class SearchServiceImpl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (files.localFiles || files.owncloud || files.onedrive || files.gdrive || files.nextcloud) {
|
|
||||||
launch {
|
launch {
|
||||||
fileRepository.search(
|
fileRepository.search(
|
||||||
query,
|
query,
|
||||||
@ -196,7 +187,6 @@ internal class SearchServiceImpl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
launch {
|
launch {
|
||||||
customAttributesRepository.search(query)
|
customAttributesRepository.search(query)
|
||||||
.withCustomLabels(customAttributesRepository)
|
.withCustomLabels(customAttributesRepository)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user