Simplify calendar search settings when no plugins are installed
This commit is contained in:
parent
dfb598b24b
commit
b4056df5c2
@ -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.appearance.AppearanceSettingsScreen
|
||||||
import de.mm20.launcher2.ui.settings.backup.BackupSettingsScreen
|
import de.mm20.launcher2.ui.settings.backup.BackupSettingsScreen
|
||||||
import de.mm20.launcher2.ui.settings.buildinfo.BuildInfoSettingsScreen
|
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.calendarsearch.CalendarSearchSettingsScreen
|
||||||
import de.mm20.launcher2.ui.settings.cards.CardsSettingsScreen
|
import de.mm20.launcher2.ui.settings.cards.CardsSettingsScreen
|
||||||
import de.mm20.launcher2.ui.settings.colorscheme.ThemeSettingsScreen
|
import de.mm20.launcher2.ui.settings.colorscheme.ThemeSettingsScreen
|
||||||
@ -198,6 +199,11 @@ class SettingsActivity : BaseActivity() {
|
|||||||
composable("settings/search/calendar") {
|
composable("settings/search/calendar") {
|
||||||
CalendarSearchSettingsScreen()
|
CalendarSearchSettingsScreen()
|
||||||
}
|
}
|
||||||
|
composable("settings/search/calendar/{providerId}") {
|
||||||
|
CalendarProviderSettingsScreen(
|
||||||
|
it.arguments?.getString("providerId") ?: return@composable
|
||||||
|
)
|
||||||
|
}
|
||||||
composable("settings/search/searchactions") {
|
composable("settings/search/searchactions") {
|
||||||
SearchActionsSettingsScreen()
|
SearchActionsSettingsScreen()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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<CalendarProviderSettingsScreenVM>()
|
||||||
|
LaunchedEffect(providerId) {
|
||||||
|
viewModel.init(providerId)
|
||||||
|
}
|
||||||
|
|
||||||
|
val enabled by viewModel.isProviderEnabled.collectAsStateWithLifecycle(false)
|
||||||
|
val calendarLists by viewModel.calendarLists.collectAsStateWithLifecycle(sortedMapOf<String, List<CalendarList>>())
|
||||||
|
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,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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<String>("")
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,32 +1,21 @@
|
|||||||
package de.mm20.launcher2.ui.settings.calendarsearch
|
package de.mm20.launcher2.ui.settings.calendarsearch
|
||||||
|
|
||||||
import android.app.PendingIntent
|
import android.app.PendingIntent
|
||||||
import android.util.Log
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
import androidx.compose.foundation.layout.padding
|
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.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.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.Text
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.derivedStateOf
|
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.pluralStringResource
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
@ -35,36 +24,27 @@ import androidx.lifecycle.viewmodel.compose.viewModel
|
|||||||
import de.mm20.launcher2.crashreporter.CrashReporter
|
import de.mm20.launcher2.crashreporter.CrashReporter
|
||||||
import de.mm20.launcher2.ktx.sendWithBackgroundPermission
|
import de.mm20.launcher2.ktx.sendWithBackgroundPermission
|
||||||
import de.mm20.launcher2.plugin.PluginState
|
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.R
|
||||||
import de.mm20.launcher2.ui.component.Banner
|
import de.mm20.launcher2.ui.component.Banner
|
||||||
import de.mm20.launcher2.ui.component.MissingPermissionBanner
|
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.PreferenceCategory
|
||||||
import de.mm20.launcher2.ui.component.preferences.PreferenceScreen
|
import de.mm20.launcher2.ui.component.preferences.PreferenceScreen
|
||||||
import de.mm20.launcher2.ui.component.preferences.PreferenceWithSwitch
|
import de.mm20.launcher2.ui.component.preferences.PreferenceWithSwitch
|
||||||
import de.mm20.launcher2.ui.locals.LocalDarkTheme
|
import de.mm20.launcher2.ui.locals.LocalNavController
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun CalendarSearchSettingsScreen() {
|
fun CalendarSearchSettingsScreen() {
|
||||||
val viewModel: CalendarSearchSettingsScreenVM = viewModel()
|
val viewModel: CalendarSearchSettingsScreenVM = viewModel()
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
val navController = LocalNavController.current
|
||||||
|
|
||||||
val hasCalendarPermission by viewModel.hasCalendarPermission.collectAsState(null)
|
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 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<String?>(null) }
|
|
||||||
|
|
||||||
PreferenceScreen(title = stringResource(R.string.preference_search_calendar)) {
|
PreferenceScreen(title = stringResource(R.string.preference_search_calendar)) {
|
||||||
item {
|
item {
|
||||||
|
PreferenceCategory {
|
||||||
AnimatedVisibility(hasCalendarPermission == false) {
|
AnimatedVisibility(hasCalendarPermission == false) {
|
||||||
MissingPermissionBanner(
|
MissingPermissionBanner(
|
||||||
text = stringResource(R.string.missing_permission_calendar_search_settings),
|
text = stringResource(R.string.missing_permission_calendar_search_settings),
|
||||||
@ -74,23 +54,16 @@ fun CalendarSearchSettingsScreen() {
|
|||||||
modifier = Modifier.padding(16.dp)
|
modifier = Modifier.padding(16.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val selectedCalendars = remember(excludedCalendars, calendarLists) {
|
|
||||||
calendarLists?.count { it.providerId == "local" }
|
|
||||||
?.minus(excludedCalendars.count {
|
|
||||||
it.startsWith("local:")
|
|
||||||
})
|
|
||||||
}
|
|
||||||
PreferenceWithSwitch(
|
PreferenceWithSwitch(
|
||||||
title = stringResource(R.string.preference_search_calendar),
|
title = stringResource(R.string.preference_search_calendar),
|
||||||
summary = if (selectedCalendars != null && calendarLists != null) "$selectedCalendars lists selected"
|
summary = stringResource(R.string.preference_search_local_calendar_summary),
|
||||||
else stringResource(R.string.preference_search_calendar_summary),
|
|
||||||
switchValue = enabledProviders.contains("local") && hasCalendarPermission == true,
|
switchValue = enabledProviders.contains("local") && hasCalendarPermission == true,
|
||||||
onSwitchChanged = {
|
onSwitchChanged = {
|
||||||
viewModel.setProviderEnabled("local", it)
|
viewModel.setProviderEnabled("local", it)
|
||||||
},
|
},
|
||||||
enabled = hasCalendarPermission == true,
|
enabled = hasCalendarPermission == true,
|
||||||
onClick = {
|
onClick = {
|
||||||
showDialogForProvider = "local"
|
navController?.navigate("settings/search/calendar/local")
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
for (plugin in plugins) {
|
for (plugin in plugins) {
|
||||||
@ -114,86 +87,22 @@ fun CalendarSearchSettingsScreen() {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val selectedCalendars = remember(excludedCalendars, calendarLists) {
|
|
||||||
calendarLists?.count { it.providerId == plugin.plugin.authority }
|
|
||||||
?.minus(excludedCalendars.count {
|
|
||||||
it.startsWith(
|
|
||||||
"${plugin.plugin.authority}:"
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
PreferenceWithSwitch(
|
PreferenceWithSwitch(
|
||||||
title = plugin.plugin.label,
|
title = plugin.plugin.label,
|
||||||
enabled = state is PluginState.Ready,
|
enabled = state is PluginState.Ready,
|
||||||
summary = (state as? PluginState.SetupRequired)?.message
|
summary = (state as? PluginState.SetupRequired)?.message
|
||||||
?: if (selectedCalendars != null && calendarLists != null) {
|
?: (state as? PluginState.Ready)?.text
|
||||||
pluralStringResource(
|
?: plugin.plugin.description,
|
||||||
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,
|
switchValue = enabledProviders.contains(plugin.plugin.authority) && state is PluginState.Ready,
|
||||||
onSwitchChanged = {
|
onSwitchChanged = {
|
||||||
viewModel.setProviderEnabled(plugin.plugin.authority, it)
|
viewModel.setProviderEnabled(plugin.plugin.authority, it)
|
||||||
},
|
},
|
||||||
onClick = {
|
onClick = {
|
||||||
showDialogForProvider = plugin.plugin.authority
|
navController?.navigate("settings/search/calendar/${plugin.plugin.authority}")
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,6 +25,7 @@ import androidx.compose.material.icons.rounded.Warning
|
|||||||
import androidx.compose.material.icons.rounded.Work
|
import androidx.compose.material.icons.rounded.Work
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.derivedStateOf
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
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.PreferenceWithSwitch
|
||||||
import de.mm20.launcher2.ui.component.preferences.SwitchPreference
|
import de.mm20.launcher2.ui.component.preferences.SwitchPreference
|
||||||
import de.mm20.launcher2.icons.Wikipedia
|
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.launcher.search.filters.SearchFilters
|
||||||
import de.mm20.launcher2.ui.locals.LocalNavController
|
import de.mm20.launcher2.ui.locals.LocalNavController
|
||||||
|
|
||||||
@ -65,6 +67,11 @@ fun SearchSettingsScreen() {
|
|||||||
mutableStateOf(false)
|
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)) {
|
PreferenceScreen(title = stringResource(R.string.preference_screen_search)) {
|
||||||
item {
|
item {
|
||||||
@ -116,6 +123,7 @@ fun SearchSettingsScreen() {
|
|||||||
enabled = hasContactsPermission == true
|
enabled = hasContactsPermission == true
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (hasCalendarPlugins) {
|
||||||
Preference(
|
Preference(
|
||||||
title = stringResource(R.string.preference_search_calendar),
|
title = stringResource(R.string.preference_search_calendar),
|
||||||
summary = stringResource(R.string.preference_search_calendar_summary),
|
summary = stringResource(R.string.preference_search_calendar_summary),
|
||||||
@ -124,6 +132,34 @@ fun SearchSettingsScreen() {
|
|||||||
navController?.navigate("settings/search/calendar")
|
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(
|
val hasAppShortcutsPermission by viewModel.hasAppShortcutPermission.collectAsStateWithLifecycle(
|
||||||
null
|
null
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import androidx.lifecycle.ViewModel
|
|||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
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.plugins.PluginService
|
||||||
import de.mm20.launcher2.preferences.search.CalculatorSearchSettings
|
import de.mm20.launcher2.preferences.search.CalculatorSearchSettings
|
||||||
import de.mm20.launcher2.preferences.search.CalendarSearchSettings
|
import de.mm20.launcher2.preferences.search.CalendarSearchSettings
|
||||||
import de.mm20.launcher2.preferences.search.ContactSearchSettings
|
import de.mm20.launcher2.preferences.search.ContactSearchSettings
|
||||||
@ -32,6 +33,7 @@ class SearchSettingsScreenVM : ViewModel(), KoinComponent {
|
|||||||
private val calculatorSearchSettings: CalculatorSearchSettings by inject()
|
private val calculatorSearchSettings: CalculatorSearchSettings by inject()
|
||||||
private val searchFilterSettings: SearchFilterSettings by inject()
|
private val searchFilterSettings: SearchFilterSettings by inject()
|
||||||
|
|
||||||
|
private val pluginService: PluginService by inject()
|
||||||
private val permissionsManager: PermissionsManager by inject()
|
private val permissionsManager: PermissionsManager by inject()
|
||||||
private val locationSearchSettings: LocationSearchSettings by inject()
|
private val locationSearchSettings: LocationSearchSettings by inject()
|
||||||
|
|
||||||
@ -42,6 +44,14 @@ class SearchSettingsScreenVM : ViewModel(), KoinComponent {
|
|||||||
searchUiSettings.setFavorites(favorites)
|
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)
|
val hasContactsPermission = permissionsManager.hasPermission(PermissionGroup.Contacts)
|
||||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null)
|
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null)
|
||||||
@ -52,6 +62,10 @@ class SearchSettingsScreenVM : ViewModel(), KoinComponent {
|
|||||||
contactSearchSettings.setEnabled(contacts)
|
contactSearchSettings.setEnabled(contacts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun requestCalendarPermission(activity: AppCompatActivity) {
|
||||||
|
permissionsManager.requestPermission(activity, PermissionGroup.Calendar)
|
||||||
|
}
|
||||||
|
|
||||||
fun requestContactsPermission(activity: AppCompatActivity) {
|
fun requestContactsPermission(activity: AppCompatActivity) {
|
||||||
permissionsManager.requestPermission(activity, PermissionGroup.Contacts)
|
permissionsManager.requestPermission(activity, PermissionGroup.Contacts)
|
||||||
}
|
}
|
||||||
@ -130,4 +144,7 @@ class SearchSettingsScreenVM : ViewModel(), KoinComponent {
|
|||||||
fun setSearchFilters(searchFilters: SearchFilters) {
|
fun setSearchFilters(searchFilters: SearchFilters) {
|
||||||
searchFilterSettings.setDefaultFilter(searchFilters)
|
searchFilterSettings.setDefaultFilter(searchFilters)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val plugins = pluginService.getPluginsWithState(enabled = true)
|
||||||
|
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), emptyList())
|
||||||
}
|
}
|
||||||
@ -608,6 +608,7 @@
|
|||||||
<string name="preference_search_contacts_summary">Search contacts on this device</string>
|
<string name="preference_search_contacts_summary">Search contacts on this device</string>
|
||||||
<string name="preference_search_calendar">Calendar</string>
|
<string name="preference_search_calendar">Calendar</string>
|
||||||
<string name="preference_search_calendar_summary">Search upcoming appointments and events</string>
|
<string name="preference_search_calendar_summary">Search upcoming appointments and events</string>
|
||||||
|
<string name="preference_search_local_calendar_summary">Search calendars on this device</string>
|
||||||
<string name="preference_search_appshortcuts">App shortcuts</string>
|
<string name="preference_search_appshortcuts">App shortcuts</string>
|
||||||
<string name="preference_search_appshortcuts_summary">Search app shortcuts</string>
|
<string name="preference_search_appshortcuts_summary">Search app shortcuts</string>
|
||||||
<string name="preference_search_calculator">Calculator</string>
|
<string name="preference_search_calculator">Calculator</string>
|
||||||
|
|||||||
@ -12,6 +12,8 @@ class CalendarSearchSettings internal constructor(
|
|||||||
val enabledProviders
|
val enabledProviders
|
||||||
get() = dataStore.data.map { it.calendarSearchProviders }
|
get() = dataStore.data.map { it.calendarSearchProviders }
|
||||||
|
|
||||||
|
fun isProviderEnabled(provider: String) = dataStore.data.map { it.calendarSearchProviders.contains(provider) }
|
||||||
|
|
||||||
fun setProviderEnabled(provider: String, enabled: Boolean) {
|
fun setProviderEnabled(provider: String, enabled: Boolean) {
|
||||||
dataStore.update {
|
dataStore.update {
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
|
|||||||
@ -47,6 +47,9 @@ interface PluginService {
|
|||||||
enabled: Boolean? = null,
|
enabled: Boolean? = null,
|
||||||
): Flow<List<PluginWithState>>
|
): Flow<List<PluginWithState>>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a plugin with its current state or null if the plugin is not found.
|
||||||
|
*/
|
||||||
fun getPluginWithState(
|
fun getPluginWithState(
|
||||||
authority: String,
|
authority: String,
|
||||||
): Flow<PluginWithState?>
|
): Flow<PluginWithState?>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user