diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/SettingsActivity.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/SettingsActivity.kt index 5c54368b..08ff431e 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/SettingsActivity.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/SettingsActivity.kt @@ -38,6 +38,7 @@ import de.mm20.launcher2.ui.settings.about.AboutSettingsScreen import de.mm20.launcher2.ui.settings.appearance.AppearanceSettingsScreen import de.mm20.launcher2.ui.settings.backup.BackupSettingsScreen import de.mm20.launcher2.ui.settings.buildinfo.BuildInfoSettingsScreen +import de.mm20.launcher2.ui.settings.calendarsearch.CalendarProviderSettingsScreen import de.mm20.launcher2.ui.settings.calendarsearch.CalendarSearchSettingsScreen import de.mm20.launcher2.ui.settings.cards.CardsSettingsScreen import de.mm20.launcher2.ui.settings.colorscheme.ThemeSettingsScreen @@ -198,6 +199,11 @@ class SettingsActivity : BaseActivity() { composable("settings/search/calendar") { CalendarSearchSettingsScreen() } + composable("settings/search/calendar/{providerId}") { + CalendarProviderSettingsScreen( + it.arguments?.getString("providerId") ?: return@composable + ) + } composable("settings/search/searchactions") { SearchActionsSettingsScreen() } diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/calendarsearch/CalendarProviderSettingsScreen.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/calendarsearch/CalendarProviderSettingsScreen.kt new file mode 100644 index 00000000..4b645fae --- /dev/null +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/calendarsearch/CalendarProviderSettingsScreen.kt @@ -0,0 +1,97 @@ +package de.mm20.launcher2.ui.settings.calendarsearch + +import android.app.PendingIntent +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.items +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.rounded.ErrorOutline +import androidx.compose.material3.CheckboxDefaults +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import androidx.lifecycle.viewmodel.compose.viewModel +import de.mm20.launcher2.calendar.providers.CalendarList +import de.mm20.launcher2.crashreporter.CrashReporter +import de.mm20.launcher2.ktx.sendWithBackgroundPermission +import de.mm20.launcher2.plugin.PluginState +import de.mm20.launcher2.themes.atTone +import de.mm20.launcher2.ui.R +import de.mm20.launcher2.ui.component.Banner +import de.mm20.launcher2.ui.component.preferences.CheckboxPreference +import de.mm20.launcher2.ui.component.preferences.PreferenceCategory +import de.mm20.launcher2.ui.component.preferences.PreferenceScreen +import de.mm20.launcher2.ui.component.preferences.SwitchPreference +import de.mm20.launcher2.ui.locals.LocalDarkTheme + +@Composable +fun CalendarProviderSettingsScreen(providerId: String) { + val viewModel = viewModel() + LaunchedEffect(providerId) { + viewModel.init(providerId) + } + + val enabled by viewModel.isProviderEnabled.collectAsStateWithLifecycle(false) + val calendarLists by viewModel.calendarLists.collectAsStateWithLifecycle(sortedMapOf>()) + val excludedCalendars by viewModel.excludedCalendars.collectAsStateWithLifecycle(emptySet()) + + val pluginState by viewModel.pluginState.collectAsStateWithLifecycle(null) + + val providerAvailable = providerId == "local" || pluginState != null + + PreferenceScreen( + title = pluginState?.plugin?.label ?: stringResource(R.string.preference_search_calendar) + ) { + if (!providerAvailable) { + return@PreferenceScreen + } + item { + PreferenceCategory { + SwitchPreference( + title = + if (providerId == "local") stringResource(R.string.preference_search_calendar) + else pluginState?.plugin?.label ?: "", + summary = + if (providerId == "local") stringResource(R.string.preference_search_local_calendar_summary) + else (pluginState?.state as? PluginState.Ready)?.text + ?: pluginState?.plugin?.description, + value = enabled && (pluginState == null || pluginState?.state is PluginState.Ready), + onValueChanged = { viewModel.setProviderEnabled(providerId, it) } + ) + } + } + items(calendarLists.toList()) { (k, v) -> + PreferenceCategory( + title = k, + ) { + for (list in v) { + CheckboxPreference( + title = list.name, + value = !excludedCalendars.contains(list.id), + onValueChanged = { viewModel.setCalendarExcluded(list.id, !it) }, + checkboxColors = CheckboxDefaults.colors( + checkedColor = if (list.color == 0) MaterialTheme.colorScheme.primary + else Color( + list.color.atTone(if (LocalDarkTheme.current) 80 else 40) + ), + checkmarkColor = if (list.color == 0) MaterialTheme.colorScheme.onPrimary + else Color( + list.color.atTone(if (LocalDarkTheme.current) 20 else 100) + ) + ), + enabled = enabled, + ) + } + } + } + } +} \ No newline at end of file diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/calendarsearch/CalendarProviderSettingsScreenVM.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/calendarsearch/CalendarProviderSettingsScreenVM.kt new file mode 100644 index 00000000..d23de9ce --- /dev/null +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/calendarsearch/CalendarProviderSettingsScreenVM.kt @@ -0,0 +1,42 @@ +package de.mm20.launcher2.ui.settings.calendarsearch + +import androidx.lifecycle.ViewModel +import de.mm20.launcher2.calendar.CalendarRepository +import de.mm20.launcher2.permissions.PermissionGroup +import de.mm20.launcher2.permissions.PermissionsManager +import de.mm20.launcher2.plugins.PluginService +import de.mm20.launcher2.preferences.search.CalendarSearchSettings +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.map +import org.koin.core.component.KoinComponent +import org.koin.core.component.inject + +class CalendarProviderSettingsScreenVM: ViewModel(), KoinComponent { + private val providerId = MutableStateFlow("") + + fun init(providerId: String) { + this.providerId.value = providerId + } + + private val calendarSearchSettings: CalendarSearchSettings by inject() + private val calendarRepository: CalendarRepository by inject() + private val pluginService: PluginService by inject() + + val pluginState = providerId.flatMapLatest { pluginService.getPluginWithState(it) } + + val isProviderEnabled = providerId.flatMapLatest { calendarSearchSettings.isProviderEnabled(it) } + fun setProviderEnabled(providerId: String, enabled: Boolean) { + calendarSearchSettings.setProviderEnabled(providerId, enabled) + } + + val calendarLists = providerId + .flatMapLatest { calendarRepository.getCalendars(it) } + .map { it.groupBy { it.owner }.toSortedMap(compareBy { it }) } + + val excludedCalendars = calendarSearchSettings.excludedCalendars + + fun setCalendarExcluded(calendarId: String, excluded: Boolean) { + calendarSearchSettings.setCalendarExcluded(calendarId, excluded) + } +} \ No newline at end of file diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/calendarsearch/CalendarSearchSettingsScreen.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/calendarsearch/CalendarSearchSettingsScreen.kt index e3be947b..dbf9567e 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/calendarsearch/CalendarSearchSettingsScreen.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/calendarsearch/CalendarSearchSettingsScreen.kt @@ -1,32 +1,21 @@ package de.mm20.launcher2.ui.settings.calendarsearch import android.app.PendingIntent -import android.util.Log import androidx.appcompat.app.AppCompatActivity import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.rounded.CalendarToday -import androidx.compose.material.icons.rounded.Checklist import androidx.compose.material.icons.rounded.ErrorOutline -import androidx.compose.material3.CheckboxDefaults -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.ModalBottomSheet import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.lifecycle.Lifecycle @@ -35,163 +24,83 @@ import androidx.lifecycle.viewmodel.compose.viewModel import de.mm20.launcher2.crashreporter.CrashReporter import de.mm20.launcher2.ktx.sendWithBackgroundPermission import de.mm20.launcher2.plugin.PluginState -import de.mm20.launcher2.search.calendar.CalendarListType -import de.mm20.launcher2.themes.atTone import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.component.Banner import de.mm20.launcher2.ui.component.MissingPermissionBanner -import de.mm20.launcher2.ui.component.preferences.CheckboxPreference import de.mm20.launcher2.ui.component.preferences.PreferenceCategory import de.mm20.launcher2.ui.component.preferences.PreferenceScreen import de.mm20.launcher2.ui.component.preferences.PreferenceWithSwitch -import de.mm20.launcher2.ui.locals.LocalDarkTheme +import de.mm20.launcher2.ui.locals.LocalNavController @Composable fun CalendarSearchSettingsScreen() { val viewModel: CalendarSearchSettingsScreenVM = viewModel() val context = LocalContext.current + val navController = LocalNavController.current val hasCalendarPermission by viewModel.hasCalendarPermission.collectAsState(null) - val plugins by viewModel.availablePlugins.collectAsState(emptyList()) + val plugins by viewModel.availablePlugins.collectAsStateWithLifecycle(emptyList(), minActiveState = Lifecycle.State.RESUMED) val enabledProviders by viewModel.enabledProviders.collectAsState(emptySet()) - val calendarLists by viewModel.calendarLists.collectAsStateWithLifecycle( - null, - minActiveState = Lifecycle.State.RESUMED - ) - val excludedCalendars by viewModel.excludedCalendars.collectAsState(emptyList()) - - var showDialogForProvider by remember { mutableStateOf(null) } - PreferenceScreen(title = stringResource(R.string.preference_search_calendar)) { item { - AnimatedVisibility(hasCalendarPermission == false) { - MissingPermissionBanner( - text = stringResource(R.string.missing_permission_calendar_search_settings), - onClick = { - viewModel.requestCalendarPermission(context as AppCompatActivity) - }, - modifier = Modifier.padding(16.dp) - ) - } - val selectedCalendars = remember(excludedCalendars, calendarLists) { - calendarLists?.count { it.providerId == "local" } - ?.minus(excludedCalendars.count { - it.startsWith("local:") - }) - } - PreferenceWithSwitch( - title = stringResource(R.string.preference_search_calendar), - summary = if (selectedCalendars != null && calendarLists != null) "$selectedCalendars lists selected" - else stringResource(R.string.preference_search_calendar_summary), - switchValue = enabledProviders.contains("local") && hasCalendarPermission == true, - onSwitchChanged = { - viewModel.setProviderEnabled("local", it) - }, - enabled = hasCalendarPermission == true, - onClick = { - showDialogForProvider = "local" - } - ) - for (plugin in plugins) { - val state = plugin.state - if (state is PluginState.SetupRequired) { - Banner( - modifier = Modifier.padding(16.dp), - text = state.message - ?: stringResource(id = R.string.plugin_state_setup_required), - icon = Icons.Rounded.ErrorOutline, - primaryAction = { - TextButton(onClick = { - try { - state.setupActivity.sendWithBackgroundPermission(context) - } catch (e: PendingIntent.CanceledException) { - CrashReporter.logException(e) - } - }) { - Text(stringResource(id = R.string.plugin_action_setup)) - } - } + PreferenceCategory { + AnimatedVisibility(hasCalendarPermission == false) { + MissingPermissionBanner( + text = stringResource(R.string.missing_permission_calendar_search_settings), + onClick = { + viewModel.requestCalendarPermission(context as AppCompatActivity) + }, + modifier = Modifier.padding(16.dp) ) } - val selectedCalendars = remember(excludedCalendars, calendarLists) { - calendarLists?.count { it.providerId == plugin.plugin.authority } - ?.minus(excludedCalendars.count { - it.startsWith( - "${plugin.plugin.authority}:" - ) - }) - } PreferenceWithSwitch( - title = plugin.plugin.label, - enabled = state is PluginState.Ready, - summary = (state as? PluginState.SetupRequired)?.message - ?: if (selectedCalendars != null && calendarLists != null) { - pluralStringResource( - R.plurals.calendar_search_enabled_lists, - selectedCalendars, - selectedCalendars - ) - } - else (state as? PluginState.Ready)?.text ?: plugin.plugin.description, - switchValue = enabledProviders.contains(plugin.plugin.authority) && state is PluginState.Ready, + title = stringResource(R.string.preference_search_calendar), + summary = stringResource(R.string.preference_search_local_calendar_summary), + switchValue = enabledProviders.contains("local") && hasCalendarPermission == true, onSwitchChanged = { - viewModel.setProviderEnabled(plugin.plugin.authority, it) + viewModel.setProviderEnabled("local", it) }, + enabled = hasCalendarPermission == true, onClick = { - showDialogForProvider = plugin.plugin.authority + navController?.navigate("settings/search/calendar/local") } ) - } - } - } - - Log.d("MM20", "${calendarLists.toString()}") - - val dialogCalendarLists by remember { - derivedStateOf { - if (showDialogForProvider == null) null - else calendarLists?.filter { it.providerId == showDialogForProvider } - } - } - - if (showDialogForProvider != null && dialogCalendarLists != null) { - ModalBottomSheet( - onDismissRequest = { - showDialogForProvider = null - }, - ) { - val groups = remember(dialogCalendarLists) { - dialogCalendarLists!!.groupBy { it.owner }.entries.sortedBy { it.key } - } - - LazyColumn { - items(groups) { - PreferenceCategory( - title = it.key, - iconPadding = false, - ) { - for (list in it.value) { - CheckboxPreference( - title = list.name, - iconPadding = false, - value = list.id !in excludedCalendars, - onValueChanged = { value -> - viewModel.setCalendarExcluded(list.id, !value) - }, - checkboxColors = CheckboxDefaults.colors( - checkedColor = if (list.color == 0) MaterialTheme.colorScheme.primary - else Color( - list.color.atTone(if (LocalDarkTheme.current) 80 else 40) - ), - checkmarkColor = if (list.color == 0) MaterialTheme.colorScheme.onPrimary - else Color( - list.color.atTone(if (LocalDarkTheme.current) 20 else 100) - ) - ) - ) - } + for (plugin in plugins) { + val state = plugin.state + if (state is PluginState.SetupRequired) { + Banner( + modifier = Modifier.padding(16.dp), + text = state.message + ?: stringResource(id = R.string.plugin_state_setup_required), + icon = Icons.Rounded.ErrorOutline, + primaryAction = { + TextButton(onClick = { + try { + state.setupActivity.sendWithBackgroundPermission(context) + } catch (e: PendingIntent.CanceledException) { + CrashReporter.logException(e) + } + }) { + Text(stringResource(id = R.string.plugin_action_setup)) + } + } + ) } + PreferenceWithSwitch( + title = plugin.plugin.label, + enabled = state is PluginState.Ready, + summary = (state as? PluginState.SetupRequired)?.message + ?: (state as? PluginState.Ready)?.text + ?: plugin.plugin.description, + switchValue = enabledProviders.contains(plugin.plugin.authority) && state is PluginState.Ready, + onSwitchChanged = { + viewModel.setProviderEnabled(plugin.plugin.authority, it) + }, + onClick = { + navController?.navigate("settings/search/calendar/${plugin.plugin.authority}") + } + ) } } } diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/search/SearchSettingsScreen.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/search/SearchSettingsScreen.kt index 1b699562..eeb649d8 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/search/SearchSettingsScreen.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/search/SearchSettingsScreen.kt @@ -25,6 +25,7 @@ import androidx.compose.material.icons.rounded.Warning import androidx.compose.material.icons.rounded.Work import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -49,6 +50,7 @@ import de.mm20.launcher2.ui.component.preferences.PreferenceScreen import de.mm20.launcher2.ui.component.preferences.PreferenceWithSwitch import de.mm20.launcher2.ui.component.preferences.SwitchPreference import de.mm20.launcher2.icons.Wikipedia +import de.mm20.launcher2.plugin.PluginType import de.mm20.launcher2.ui.launcher.search.filters.SearchFilters import de.mm20.launcher2.ui.locals.LocalNavController @@ -65,6 +67,11 @@ fun SearchSettingsScreen() { mutableStateOf(false) } + val plugins by viewModel.plugins.collectAsStateWithLifecycle(emptyList()) + + val hasCalendarPlugins by remember { derivedStateOf { plugins.any { it.plugin.type == PluginType.Calendar } } } + val hasLocationPlugins by remember { derivedStateOf { plugins.any { it.plugin.type == PluginType.LocationSearch } } } + PreferenceScreen(title = stringResource(R.string.preference_screen_search)) { item { @@ -116,14 +123,43 @@ fun SearchSettingsScreen() { enabled = hasContactsPermission == true ) - Preference( - title = stringResource(R.string.preference_search_calendar), - summary = stringResource(R.string.preference_search_calendar_summary), - icon = Icons.Rounded.Today, - onClick = { - navController?.navigate("settings/search/calendar") - }, - ) + if (hasCalendarPlugins) { + Preference( + title = stringResource(R.string.preference_search_calendar), + summary = stringResource(R.string.preference_search_calendar_summary), + icon = Icons.Rounded.Today, + onClick = { + navController?.navigate("settings/search/calendar") + }, + ) + } else { + val hasCalendarPermission by viewModel.hasCalendarPermission.collectAsStateWithLifecycle( + null + ) + val calendar by viewModel.calendarSearch.collectAsStateWithLifecycle(null) + AnimatedVisibility(hasCalendarPermission == false) { + MissingPermissionBanner( + text = stringResource(R.string.missing_permission_calendar_search_settings), + onClick = { + viewModel.requestCalendarPermission(context as AppCompatActivity) + }, + modifier = Modifier.padding(16.dp) + ) + } + PreferenceWithSwitch( + title = stringResource(R.string.preference_search_calendar), + summary = stringResource(R.string.preference_search_calendar_summary), + switchValue = calendar == true, + onSwitchChanged = { + viewModel.setCalendarSearch(it) + }, + icon = Icons.Rounded.Today, + enabled = hasCalendarPermission == true, + onClick = { + navController?.navigate("settings/search/calendar/local") + } + ) + } val hasAppShortcutsPermission by viewModel.hasAppShortcutPermission.collectAsStateWithLifecycle( null diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/search/SearchSettingsScreenVM.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/search/SearchSettingsScreenVM.kt index bf4d1106..e4c3afcb 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/search/SearchSettingsScreenVM.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/search/SearchSettingsScreenVM.kt @@ -5,6 +5,7 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import de.mm20.launcher2.permissions.PermissionGroup import de.mm20.launcher2.permissions.PermissionsManager +import de.mm20.launcher2.plugins.PluginService import de.mm20.launcher2.preferences.search.CalculatorSearchSettings import de.mm20.launcher2.preferences.search.CalendarSearchSettings import de.mm20.launcher2.preferences.search.ContactSearchSettings @@ -32,6 +33,7 @@ class SearchSettingsScreenVM : ViewModel(), KoinComponent { private val calculatorSearchSettings: CalculatorSearchSettings by inject() private val searchFilterSettings: SearchFilterSettings by inject() + private val pluginService: PluginService by inject() private val permissionsManager: PermissionsManager by inject() private val locationSearchSettings: LocationSearchSettings by inject() @@ -42,6 +44,14 @@ class SearchSettingsScreenVM : ViewModel(), KoinComponent { searchUiSettings.setFavorites(favorites) } + val hasCalendarPermission = permissionsManager.hasPermission(PermissionGroup.Calendar) + .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null) + + val calendarSearch = calendarSearchSettings.isProviderEnabled("local") + .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null) + fun setCalendarSearch(enabled: Boolean) { + calendarSearchSettings.setProviderEnabled("local", enabled) + } val hasContactsPermission = permissionsManager.hasPermission(PermissionGroup.Contacts) .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null) @@ -52,6 +62,10 @@ class SearchSettingsScreenVM : ViewModel(), KoinComponent { contactSearchSettings.setEnabled(contacts) } + fun requestCalendarPermission(activity: AppCompatActivity) { + permissionsManager.requestPermission(activity, PermissionGroup.Calendar) + } + fun requestContactsPermission(activity: AppCompatActivity) { permissionsManager.requestPermission(activity, PermissionGroup.Contacts) } @@ -130,4 +144,7 @@ class SearchSettingsScreenVM : ViewModel(), KoinComponent { fun setSearchFilters(searchFilters: SearchFilters) { searchFilterSettings.setDefaultFilter(searchFilters) } + + val plugins = pluginService.getPluginsWithState(enabled = true) + .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), emptyList()) } \ No newline at end of file diff --git a/core/i18n/src/main/res/values/strings.xml b/core/i18n/src/main/res/values/strings.xml index dadf6e26..5ac31517 100644 --- a/core/i18n/src/main/res/values/strings.xml +++ b/core/i18n/src/main/res/values/strings.xml @@ -608,6 +608,7 @@ Search contacts on this device Calendar Search upcoming appointments and events + Search calendars on this device App shortcuts Search app shortcuts Calculator diff --git a/core/preferences/src/main/java/de/mm20/launcher2/preferences/search/CalendarSearchSettings.kt b/core/preferences/src/main/java/de/mm20/launcher2/preferences/search/CalendarSearchSettings.kt index 8a66e7bc..14f30306 100644 --- a/core/preferences/src/main/java/de/mm20/launcher2/preferences/search/CalendarSearchSettings.kt +++ b/core/preferences/src/main/java/de/mm20/launcher2/preferences/search/CalendarSearchSettings.kt @@ -12,6 +12,8 @@ class CalendarSearchSettings internal constructor( val enabledProviders get() = dataStore.data.map { it.calendarSearchProviders } + fun isProviderEnabled(provider: String) = dataStore.data.map { it.calendarSearchProviders.contains(provider) } + fun setProviderEnabled(provider: String, enabled: Boolean) { dataStore.update { if (enabled) { diff --git a/services/plugins/src/main/java/de/mm20/launcher2/plugins/PluginService.kt b/services/plugins/src/main/java/de/mm20/launcher2/plugins/PluginService.kt index 46e0fc76..2074791b 100644 --- a/services/plugins/src/main/java/de/mm20/launcher2/plugins/PluginService.kt +++ b/services/plugins/src/main/java/de/mm20/launcher2/plugins/PluginService.kt @@ -47,6 +47,9 @@ interface PluginService { enabled: Boolean? = null, ): Flow> + /** + * Get a plugin with its current state or null if the plugin is not found. + */ fun getPluginWithState( authority: String, ): Flow