diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/component/preferences/CheckboxPreference.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/component/preferences/CheckboxPreference.kt index 9e7fe3e0..a46909f3 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/component/preferences/CheckboxPreference.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/component/preferences/CheckboxPreference.kt @@ -1,6 +1,8 @@ package de.mm20.launcher2.ui.component.preferences import androidx.compose.material3.Checkbox +import androidx.compose.material3.CheckboxColors +import androidx.compose.material3.CheckboxDefaults import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.vector.ImageVector @@ -12,7 +14,8 @@ fun CheckboxPreference( summary: String? = null, value: Boolean, onValueChanged: (Boolean) -> Unit, - enabled: Boolean = true + enabled: Boolean = true, + checkboxColors: CheckboxColors = CheckboxDefaults.colors(), ) { Preference( title = title, @@ -25,7 +28,7 @@ fun CheckboxPreference( }, controls = { Checkbox( - enabled = enabled, checked = value, onCheckedChange = onValueChanged, + enabled = enabled, checked = value, onCheckedChange = onValueChanged, colors = checkboxColors ) } ) diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/component/preferences/PreferenceWithSwitch.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/component/preferences/PreferenceWithSwitch.kt index d24637f4..534cc9e1 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/component/preferences/PreferenceWithSwitch.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/component/preferences/PreferenceWithSwitch.kt @@ -19,7 +19,8 @@ fun PreferenceWithSwitch( enabled: Boolean = true, onClick: () -> Unit = {}, switchValue: Boolean, - onSwitchChanged: (Boolean) -> Unit + onSwitchChanged: (Boolean) -> Unit, + iconPadding: Boolean = true ) { Row( verticalAlignment = (Alignment.CenterVertically) @@ -32,7 +33,8 @@ fun PreferenceWithSwitch( summary = summary, icon = icon, enabled = enabled, - onClick = onClick + onClick = onClick, + iconPadding = iconPadding ) } Box( 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 246f92c8..48d5b87f 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 @@ -4,26 +4,46 @@ import android.app.PendingIntent import androidx.appcompat.app.AppCompatActivity import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentHeight +import androidx.compose.foundation.layout.wrapContentWidth +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items import androidx.compose.material.icons.Icons import androidx.compose.material.icons.rounded.ErrorOutline +import androidx.compose.material3.AlertDialogDefaults +import androidx.compose.material3.BasicAlertDialog +import androidx.compose.material3.CheckboxDefaults +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface 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.stringResource import androidx.compose.ui.unit.dp +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.compose.collectAsStateWithLifecycle 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.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.PreferenceScreen +import de.mm20.launcher2.ui.component.preferences.PreferenceWithSwitch import de.mm20.launcher2.ui.component.preferences.SwitchPreference +import de.mm20.launcher2.ui.locals.LocalDarkTheme @Composable fun CalendarSearchSettingsScreen() { @@ -34,6 +54,14 @@ fun CalendarSearchSettingsScreen() { val plugins by viewModel.availablePlugins.collectAsState(emptyList()) 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) { @@ -45,21 +73,32 @@ fun CalendarSearchSettingsScreen() { modifier = Modifier.padding(16.dp) ) } - SwitchPreference( + 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 = stringResource(R.string.preference_search_calendar_summary), - value = enabledProviders.contains("local") && hasCalendarPermission == true, - onValueChanged = { + 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 + 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), + text = state.message + ?: stringResource(id = R.string.plugin_state_setup_required), icon = Icons.Rounded.ErrorOutline, primaryAction = { TextButton(onClick = { @@ -74,18 +113,76 @@ fun CalendarSearchSettingsScreen() { } ) } - SwitchPreference( + 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.Ready)?.text - ?: (state as? PluginState.SetupRequired)?.message - ?: plugin.plugin.description, - value = enabledProviders.contains(plugin.plugin.authority) && state is PluginState.Ready, - onValueChanged = { + summary = (state as? PluginState.SetupRequired)?.message + ?: if (selectedCalendars != null && calendarLists != null) "$selectedCalendars lists selected" + else (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 = { + showDialogForProvider = plugin.plugin.authority + } ) } } } -} \ No newline at end of file + + val dialogCalendarLists by remember { + derivedStateOf { + if (showDialogForProvider == null) null + else calendarLists?.filter { it.providerId == showDialogForProvider } + } + } + + if (showDialogForProvider != null && dialogCalendarLists != null) { + BasicAlertDialog( + onDismissRequest = { + showDialogForProvider = null + }, + ) { + Surface( + modifier = Modifier + .wrapContentWidth() + .wrapContentHeight(), + shape = MaterialTheme.shapes.large, + tonalElevation = AlertDialogDefaults.TonalElevation + ) { + LazyColumn { + items(dialogCalendarLists ?: emptyList()) { + CheckboxPreference( + title = it.name, + summary = it.owner, + iconPadding = false, + value = it.id !in excludedCalendars, + onValueChanged = { value -> + viewModel.setCalendarExcluded(it.id, !value) + }, + checkboxColors = CheckboxDefaults.colors( + checkedColor = if (it.color == 0) MaterialTheme.colorScheme.primary + else Color( + it.color.atTone(if (LocalDarkTheme.current) 80 else 40) + ), + checkmarkColor = if (it.color == 0) MaterialTheme.colorScheme.onPrimary + else Color( + it.color.atTone(if (LocalDarkTheme.current) 20 else 100) + ) + ) + ) + } + } + } + } + } +} diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/calendarsearch/CalendarSearchSettingsScreenVM.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/calendarsearch/CalendarSearchSettingsScreenVM.kt index 74e4c091..3c5141cd 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/calendarsearch/CalendarSearchSettingsScreenVM.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/calendarsearch/CalendarSearchSettingsScreenVM.kt @@ -2,16 +2,21 @@ package de.mm20.launcher2.ui.settings.calendarsearch import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.ViewModel +import de.mm20.launcher2.calendar.CalendarRepository +import de.mm20.launcher2.calendar.providers.CalendarList import de.mm20.launcher2.permissions.PermissionGroup import de.mm20.launcher2.permissions.PermissionsManager +import de.mm20.launcher2.plugin.Plugin import de.mm20.launcher2.plugin.PluginType import de.mm20.launcher2.plugins.PluginService import de.mm20.launcher2.preferences.search.CalendarSearchSettings +import kotlinx.coroutines.flow.Flow import org.koin.core.component.KoinComponent import org.koin.core.component.inject class CalendarSearchSettingsScreenVM : ViewModel(), KoinComponent { private val settings: CalendarSearchSettings by inject() + private val calendarRepository: CalendarRepository by inject() private val pluginService: PluginService by inject() private val permissionsManager: PermissionsManager by inject() @@ -31,4 +36,11 @@ class CalendarSearchSettingsScreenVM : ViewModel(), KoinComponent { fun requestCalendarPermission(activity: AppCompatActivity) { permissionsManager.requestPermission(activity, PermissionGroup.Calendar) } + + val calendarLists = calendarRepository.getCalendars() + + val excludedCalendars = settings.excludedCalendars + fun setCalendarExcluded(calendarId: String, excluded: Boolean) { + settings.setCalendarExcluded(calendarId, excluded) + } } \ No newline at end of file diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/plugins/PluginSettingsScreen.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/plugins/PluginSettingsScreen.kt index 8867c174..4c0370a8 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/plugins/PluginSettingsScreen.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/plugins/PluginSettingsScreen.kt @@ -16,6 +16,10 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.wrapContentHeight +import androidx.compose.foundation.layout.wrapContentWidth +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items import androidx.compose.foundation.rememberScrollState import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.rounded.ArrowBack @@ -29,6 +33,9 @@ import androidx.compose.material.icons.rounded.Place import androidx.compose.material.icons.rounded.Settings import androidx.compose.material.icons.rounded.Today import androidx.compose.material.icons.rounded.Verified +import androidx.compose.material3.AlertDialogDefaults +import androidx.compose.material3.BasicAlertDialog +import androidx.compose.material3.CheckboxDefaults import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme @@ -39,9 +46,14 @@ import androidx.compose.material3.TextButton import androidx.compose.material3.TopAppBar import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment 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 @@ -53,11 +65,15 @@ import de.mm20.launcher2.crashreporter.CrashReporter import de.mm20.launcher2.ktx.sendWithBackgroundPermission import de.mm20.launcher2.plugin.PluginState import de.mm20.launcher2.plugin.PluginType +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.Preference import de.mm20.launcher2.ui.component.preferences.PreferenceCategory +import de.mm20.launcher2.ui.component.preferences.PreferenceWithSwitch import de.mm20.launcher2.ui.component.preferences.SwitchPreference +import de.mm20.launcher2.ui.locals.LocalDarkTheme import de.mm20.launcher2.ui.locals.LocalNavController @Composable @@ -88,6 +104,11 @@ fun PluginSettingsScreen(pluginId: String) { minActiveState = Lifecycle.State.RESUMED ) + val calendarPlugins by viewModel.calendarPlugins.collectAsStateWithLifecycle( + emptyList(), + minActiveState = Lifecycle.State.RESUMED + ) + val weatherPlugins by viewModel.weatherPlugins.collectAsStateWithLifecycle( emptyList(), minActiveState = Lifecycle.State.RESUMED @@ -108,6 +129,10 @@ fun PluginSettingsScreen(pluginId: String) { null ) + val enabledCalendarSearchPlugins by viewModel.enabledCalendarSearchPlugins.collectAsStateWithLifecycle( + null + ) + val weatherProviderId by viewModel.weatherProvider.collectAsStateWithLifecycle( null ) @@ -316,7 +341,9 @@ fun PluginSettingsScreen(pluginId: String) { primaryAction = { TextButton(onClick = { try { - state.setupActivity.sendWithBackgroundPermission(context) + state.setupActivity.sendWithBackgroundPermission( + context + ) } catch (e: PendingIntent.CanceledException) { CrashReporter.logException(e) } @@ -367,7 +394,9 @@ fun PluginSettingsScreen(pluginId: String) { primaryAction = { TextButton(onClick = { try { - state.setupActivity.sendWithBackgroundPermission(context) + state.setupActivity.sendWithBackgroundPermission( + context + ) } catch (e: PendingIntent.CanceledException) { CrashReporter.logException(e) } @@ -402,6 +431,111 @@ fun PluginSettingsScreen(pluginId: String) { } } } + if (calendarPlugins.isNotEmpty()) { + PreferenceCategory( + stringResource(R.string.plugin_type_calendar), + iconPadding = false, + ) { + val excludedCalendars by viewModel.excludedCalendars.collectAsState( + emptySet() + ) + for (plugin in calendarPlugins) { + val state = plugin.state + if (state is PluginState.SetupRequired) { + Banner( + modifier = Modifier.padding(16.dp), + text = state.message + ?: stringResource(R.string.plugin_state_setup_required), + icon = Icons.Rounded.Info, + primaryAction = { + TextButton(onClick = { + try { + state.setupActivity.sendWithBackgroundPermission( + context + ) + } catch (e: PendingIntent.CanceledException) { + CrashReporter.logException(e) + } + }) { + Text(stringResource(R.string.plugin_action_setup)) + } + } + ) + } else if (state is PluginState.Error) { + Banner( + modifier = Modifier.padding(16.dp), + text = stringResource(R.string.plugin_state_error), + icon = Icons.Rounded.Error, + color = MaterialTheme.colorScheme.errorContainer, + ) + } + val calendarLists by remember(plugin.state, plugin.plugin) { + viewModel.getCalendarLists(plugin.plugin) + }.collectAsStateWithLifecycle(null, minActiveState = Lifecycle.State.RESUMED) + var showDialog by remember { mutableStateOf(false) } + val selectedCalendars = remember(excludedCalendars, calendarLists) { + calendarLists?.size?.minus(excludedCalendars.count { it.startsWith(plugin.plugin.authority) }) + } + PreferenceWithSwitch( + title = plugin.plugin.label, + enabled = enabledCalendarSearchPlugins != null && state is PluginState.Ready, + summary = (state as? PluginState.SetupRequired)?.message + ?: if (selectedCalendars != null && calendarLists != null) "$selectedCalendars lists selected" + else (state as? PluginState.Ready)?.text ?: plugin.plugin.description, + switchValue = enabledCalendarSearchPlugins?.contains(plugin.plugin.authority) == true && state is PluginState.Ready, + onSwitchChanged = { + viewModel.setCalendarSearchPluginEnabled( + plugin.plugin.authority, + it + ) + }, + iconPadding = false, + onClick = { + showDialog = true + } + ) + if (showDialog && calendarLists?.isNotEmpty() == true) { + BasicAlertDialog( + onDismissRequest = { + showDialog = false + }, + ) { + Surface( + modifier = Modifier.wrapContentWidth() + .wrapContentHeight(), + shape = MaterialTheme.shapes.large, + tonalElevation = AlertDialogDefaults.TonalElevation + ) { + LazyColumn { + items(calendarLists!!) { + CheckboxPreference( + title = it.name, + summary = it.owner, + iconPadding = false, + value = it.id !in excludedCalendars, + onValueChanged = { value -> + viewModel.setCalendarExcluded(it.id, !value) + }, + + checkboxColors = CheckboxDefaults.colors( + checkedColor = if (it.color == 0) MaterialTheme.colorScheme.primary + else Color( + it.color.atTone(if (LocalDarkTheme.current) 80 else 40) + ), + checkmarkColor = if (it.color == 0) MaterialTheme.colorScheme.onPrimary + else Color( + it.color.atTone(if (LocalDarkTheme.current) 20 else 100) + ) + ) + ) + } + } + } + } + } + } + } + } if (weatherPlugins.isNotEmpty()) { PreferenceCategory( stringResource(R.string.plugin_type_weather), @@ -418,7 +552,9 @@ fun PluginSettingsScreen(pluginId: String) { primaryAction = { TextButton(onClick = { try { - state.setupActivity.sendWithBackgroundPermission(context) + state.setupActivity.sendWithBackgroundPermission( + context + ) } catch (e: PendingIntent.CanceledException) { CrashReporter.logException(e) } diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/plugins/PluginSettingsScreenVM.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/plugins/PluginSettingsScreenVM.kt index bc7a2409..339a6bdb 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/plugins/PluginSettingsScreenVM.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/plugins/PluginSettingsScreenVM.kt @@ -7,12 +7,16 @@ import android.net.Uri import android.provider.Settings import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import de.mm20.launcher2.calendar.CalendarRepository +import de.mm20.launcher2.calendar.providers.CalendarList import de.mm20.launcher2.ktx.tryStartActivity +import de.mm20.launcher2.plugin.Plugin import de.mm20.launcher2.plugin.PluginPackage import de.mm20.launcher2.plugin.PluginState import de.mm20.launcher2.plugin.PluginType import de.mm20.launcher2.plugins.PluginService import de.mm20.launcher2.plugins.PluginWithState +import de.mm20.launcher2.preferences.search.CalendarSearchSettings import de.mm20.launcher2.preferences.search.FileSearchSettings import de.mm20.launcher2.preferences.search.LocationSearchSettings import de.mm20.launcher2.preferences.weather.WeatherSettings @@ -31,8 +35,10 @@ import org.koin.core.component.inject class PluginSettingsScreenVM : ViewModel(), KoinComponent { private val pluginService by inject() + private val calendarRepository by inject() private val fileSearchSettings: FileSearchSettings by inject() private val locationSearchSettings: LocationSearchSettings by inject() + private val calendarSearchSettings: CalendarSearchSettings by inject() private val weatherSettings: WeatherSettings by inject() private var pluginPackageName = MutableStateFlow(null) @@ -79,6 +85,11 @@ class PluginSettingsScreenVM : ViewModel(), KoinComponent { it.filter { it.plugin.type == PluginType.LocationSearch } } + val calendarPlugins = states + .map { + it.filter { it.plugin.type == PluginType.Calendar } + } + val weatherPlugins = states .map { it.filter { it.plugin.type == PluginType.Weather } @@ -121,8 +132,22 @@ class PluginSettingsScreenVM : ViewModel(), KoinComponent { locationSearchSettings.setPluginEnabled(authority, enabled) } + val enabledCalendarSearchPlugins = calendarSearchSettings.providers + fun setCalendarSearchPluginEnabled(authority: String, enabled: Boolean) { + calendarSearchSettings.setProviderEnabled(authority, enabled) + } + val weatherProvider = weatherSettings.providerId fun setWeatherProvider(providerId: String) { weatherSettings.setProvider(providerId) } + + fun getCalendarLists(plugin: Plugin): Flow> { + return calendarRepository.getCalendars(plugin.authority) + } + + val excludedCalendars = calendarSearchSettings.excludedCalendars + fun setCalendarExcluded(calendarId: String, excluded: Boolean) { + calendarSearchSettings.setCalendarExcluded(calendarId, excluded) + } } \ No newline at end of file diff --git a/core/preferences/src/main/java/de/mm20/launcher2/preferences/LauncherSettingsData.kt b/core/preferences/src/main/java/de/mm20/launcher2/preferences/LauncherSettingsData.kt index cc223a0c..b5dbcb36 100644 --- a/core/preferences/src/main/java/de/mm20/launcher2/preferences/LauncherSettingsData.kt +++ b/core/preferences/src/main/java/de/mm20/launcher2/preferences/LauncherSettingsData.kt @@ -56,6 +56,7 @@ data class LauncherSettingsData internal constructor( @Deprecated("Use calendarSearchProviders `local` instead") val calendarSearchEnabled: Boolean = true, val calendarSearchProviders: Set = setOf("local"), + val calendarSearchExcludedCalendars: Set = setOf(), val shortcutSearchEnabled: Boolean = true, 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 cc1895bf..8a66e7bc 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 @@ -21,4 +21,16 @@ class CalendarSearchSettings internal constructor( } } } + + val excludedCalendars + get() = dataStore.data.map { it.calendarSearchExcludedCalendars } + fun setCalendarExcluded(calendarId: String, excluded: Boolean) { + dataStore.update { + if (excluded) { + it.copy(calendarSearchExcludedCalendars = it.calendarSearchExcludedCalendars + calendarId) + } else { + it.copy(calendarSearchExcludedCalendars = it.calendarSearchExcludedCalendars - calendarId) + } + } + } } \ No newline at end of file diff --git a/data/calendar/src/main/java/de/mm20/launcher2/calendar/CalendarRepository.kt b/data/calendar/src/main/java/de/mm20/launcher2/calendar/CalendarRepository.kt index 17644ecf..fed0555c 100644 --- a/data/calendar/src/main/java/de/mm20/launcher2/calendar/CalendarRepository.kt +++ b/data/calendar/src/main/java/de/mm20/launcher2/calendar/CalendarRepository.kt @@ -1,6 +1,7 @@ package de.mm20.launcher2.calendar import android.content.Context +import android.util.Log import de.mm20.launcher2.calendar.providers.AndroidCalendarProvider import de.mm20.launcher2.calendar.providers.CalendarList import de.mm20.launcher2.calendar.providers.CalendarProvider @@ -58,8 +59,9 @@ internal class CalendarRepositoryImpl( val hasPermission = permissionsManager.hasPermission(PermissionGroup.Calendar) val providerIds = settings.providers + val excludedCalendars = settings.excludedCalendars - return combineTransform(hasPermission, providerIds) { perm, providerIds -> + return combineTransform(hasPermission, providerIds, excludedCalendars) { perm, providerIds, excludedCalendars -> val providers = providerIds.mapNotNull { when (it) { "local" -> if (perm) AndroidCalendarProvider(context) else null @@ -72,6 +74,7 @@ internal class CalendarRepositoryImpl( queryCalendarEvents( query = query, excludeAllDayEvents = false, + excludeCalendars = excludedCalendars.toList(), providers = providers, intervalStart = now, intervalEnd = now + 730.days.inWholeMilliseconds, diff --git a/data/calendar/src/main/java/de/mm20/launcher2/calendar/providers/PluginCalendarProvider.kt b/data/calendar/src/main/java/de/mm20/launcher2/calendar/providers/PluginCalendarProvider.kt index 14253d4b..57387542 100644 --- a/data/calendar/src/main/java/de/mm20/launcher2/calendar/providers/PluginCalendarProvider.kt +++ b/data/calendar/src/main/java/de/mm20/launcher2/calendar/providers/PluginCalendarProvider.kt @@ -47,10 +47,12 @@ class PluginCalendarProvider( } override fun Uri.Builder.appendQueryParameters(query: CalendarQuery): Uri.Builder { - appendQueryParameter( - CalendarPluginContract.Params.Query, - query.query - ) + if (query.query != null) { + appendQueryParameter( + CalendarPluginContract.Params.Query, + query.query + ) + } val start = query.start if (start != null) { appendQueryParameter(