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 eeb649d8..9285a6ff 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 @@ -16,15 +16,12 @@ import androidx.compose.material.icons.rounded.Loop import androidx.compose.material.icons.rounded.Person import androidx.compose.material.icons.rounded.Place import androidx.compose.material.icons.rounded.Public -import androidx.compose.material.icons.rounded.Sort import androidx.compose.material.icons.rounded.Star import androidx.compose.material.icons.rounded.Tag import androidx.compose.material.icons.rounded.Today import androidx.compose.material.icons.rounded.VisibilityOff 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 @@ -34,11 +31,11 @@ import androidx.compose.ui.Modifier 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.LocalLifecycleOwner import androidx.lifecycle.compose.collectAsStateWithLifecycle -import androidx.lifecycle.repeatOnLifecycle import androidx.lifecycle.viewmodel.compose.viewModel +import de.mm20.launcher2.icons.Wikipedia +import de.mm20.launcher2.plugin.PluginType import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.component.BottomSheetDialog import de.mm20.launcher2.ui.component.MissingPermissionBanner @@ -49,8 +46,6 @@ 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.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 @@ -59,24 +54,40 @@ fun SearchSettingsScreen() { val viewModel: SearchSettingsScreenVM = viewModel() val context = LocalContext.current - val lifecycleOwner = LocalLifecycleOwner.current val navController = LocalNavController.current - var showFilterEditor by remember { - mutableStateOf(false) - } + var showFilterEditor by remember { 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 } } } + val hasAppShortcutsPermission by viewModel.hasAppShortcutPermission.collectAsStateWithLifecycle(null) + val hasContactsPermission by viewModel.hasContactsPermission.collectAsStateWithLifecycle(null) + val hasCalendarPermission by viewModel.hasCalendarPermission.collectAsStateWithLifecycle(null) + val hasLocationPermission by viewModel.hasLocationPermission.collectAsStateWithLifecycle(null) + + val favorites by viewModel.favorites.collectAsStateWithLifecycle(null) + val appShortcuts by viewModel.appShortcuts.collectAsStateWithLifecycle(null) + val calendar by viewModel.calendarSearch.collectAsStateWithLifecycle(null) + val places by viewModel.placesSearch.collectAsStateWithLifecycle(null) + val contacts by viewModel.contacts.collectAsStateWithLifecycle(null) + val calculator by viewModel.calculator.collectAsStateWithLifecycle(null) + val unitConverter by viewModel.unitConverter.collectAsStateWithLifecycle(null) + val wikipedia by viewModel.wikipedia.collectAsStateWithLifecycle(null) + val websites by viewModel.websites.collectAsStateWithLifecycle(null) + + + val autoFocus by viewModel.autoFocus.collectAsStateWithLifecycle(null) + val launchOnEnter by viewModel.launchOnEnter.collectAsStateWithLifecycle(null) + val reverseSearchResults by viewModel.reverseSearchResults.collectAsStateWithLifecycle(null) + val filterBar by viewModel.filterBar.collectAsStateWithLifecycle(null) + PreferenceScreen(title = stringResource(R.string.preference_screen_search)) { item { PreferenceCategory { - val favorites by viewModel.favorites.collectAsStateWithLifecycle(null) PreferenceWithSwitch( title = stringResource(R.string.preference_search_favorites), summary = stringResource(R.string.preference_search_favorites_summary), @@ -99,9 +110,6 @@ fun SearchSettingsScreen() { } ) - val hasContactsPermission by viewModel.hasContactsPermission.collectAsStateWithLifecycle( - null - ) AnimatedVisibility(hasContactsPermission == false) { MissingPermissionBanner( text = stringResource(R.string.missing_permission_contact_search_settings), @@ -111,7 +119,6 @@ fun SearchSettingsScreen() { modifier = Modifier.padding(16.dp) ) } - val contacts by viewModel.contacts.collectAsStateWithLifecycle(null) SwitchPreference( title = stringResource(R.string.preference_search_contacts), summary = stringResource(R.string.preference_search_contacts_summary), @@ -133,10 +140,6 @@ fun SearchSettingsScreen() { }, ) } 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), @@ -160,10 +163,6 @@ fun SearchSettingsScreen() { } ) } - - val hasAppShortcutsPermission by viewModel.hasAppShortcutPermission.collectAsStateWithLifecycle( - null - ) AnimatedVisibility(hasAppShortcutsPermission == false) { MissingPermissionBanner( text = stringResource( @@ -176,7 +175,6 @@ fun SearchSettingsScreen() { modifier = Modifier.padding(16.dp) ) } - val appShortcuts by viewModel.appShortcuts.collectAsStateWithLifecycle(null) SwitchPreference( title = stringResource(R.string.preference_search_appshortcuts), summary = stringResource(R.string.preference_search_appshortcuts_summary), @@ -188,7 +186,6 @@ fun SearchSettingsScreen() { enabled = hasAppShortcutsPermission == true ) - val calculator by viewModel.calculator.collectAsStateWithLifecycle(null) SwitchPreference( title = stringResource(R.string.preference_search_calculator), summary = stringResource(R.string.preference_search_calculator_summary), @@ -199,7 +196,6 @@ fun SearchSettingsScreen() { } ) - val unitConverter by viewModel.unitConverter.collectAsStateWithLifecycle(null) PreferenceWithSwitch( title = stringResource(R.string.preference_search_unitconverter), summary = stringResource(R.string.preference_search_unitconverter_summary), @@ -213,7 +209,6 @@ fun SearchSettingsScreen() { } ) - val wikipedia by viewModel.wikipedia.collectAsStateWithLifecycle(null) PreferenceWithSwitch( title = stringResource(R.string.preference_search_wikipedia), summary = stringResource(R.string.preference_search_wikipedia_summary), @@ -227,7 +222,6 @@ fun SearchSettingsScreen() { } ) - val websites by viewModel.websites.collectAsStateWithLifecycle(null) SwitchPreference( title = stringResource(R.string.preference_search_websites), summary = stringResource(R.string.preference_search_websites_summary), @@ -238,14 +232,43 @@ fun SearchSettingsScreen() { } ) - Preference( - title = stringResource(R.string.preference_search_locations), - summary = stringResource(R.string.preference_search_locations_summary), - icon = Icons.Rounded.Place, - onClick = { - navController?.navigate("settings/search/locations") - } - ) + AnimatedVisibility(hasLocationPermission == false) { + MissingPermissionBanner( + text = stringResource( + R.string.missing_permission_location_search, + ), + onClick = { + viewModel.requestLocationPermission(context as AppCompatActivity) + }, + modifier = Modifier.padding(16.dp) + ) + } + + if (hasLocationPlugins) { + Preference( + title = stringResource(R.string.preference_search_locations), + summary = stringResource(R.string.preference_search_locations_summary), + icon = Icons.Rounded.Place, + enabled = hasLocationPermission == true, + onClick = { + navController?.navigate("settings/search/locations") + } + ) + } else { + PreferenceWithSwitch( + title = stringResource(R.string.preference_search_locations), + summary = stringResource(R.string.preference_search_locations_summary), + icon = Icons.Rounded.Place, + onClick = { + navController?.navigate("settings/search/locations") + }, + switchValue = places == true, + onSwitchChanged = { + viewModel.setPlacesSearch(it) + }, + enabled = hasLocationPermission == true, + ) + } Preference( title = stringResource(R.string.preference_screen_search_actions), @@ -278,7 +301,6 @@ fun SearchSettingsScreen() { } } item { - val filterBar by viewModel.filterBar.collectAsStateWithLifecycle(null) PreferenceCategory { Preference( title = stringResource(R.string.preference_default_filter), @@ -300,7 +322,7 @@ fun SearchSettingsScreen() { Preference( title = stringResource(R.string.preference_customize_filter_bar), summary = stringResource(R.string.preference_customize_filter_bar_summary), - onClick = { + onClick = { navController?.navigate("settings/search/filterbar") } ) @@ -309,7 +331,6 @@ fun SearchSettingsScreen() { } item { PreferenceCategory { - val autoFocus by viewModel.autoFocus.collectAsStateWithLifecycle(null) SwitchPreference( title = stringResource(R.string.preference_search_bar_auto_focus), summary = stringResource(R.string.preference_search_bar_auto_focus_summary), @@ -319,7 +340,6 @@ fun SearchSettingsScreen() { viewModel.setAutoFocus(it) } ) - val launchOnEnter by viewModel.launchOnEnter.collectAsStateWithLifecycle(null) SwitchPreference( title = stringResource(R.string.preference_search_bar_launch_on_enter), summary = stringResource(R.string.preference_search_bar_launch_on_enter_summary), @@ -332,9 +352,6 @@ fun SearchSettingsScreen() { } item { PreferenceCategory { - val reverseSearchResults by viewModel.reverseSearchResults.collectAsStateWithLifecycle( - null - ) ListPreference( title = stringResource(R.string.preference_layout_search_results), items = listOf( 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 e4c3afcb..a3f4b265 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 @@ -31,11 +31,11 @@ class SearchSettingsScreenVM : ViewModel(), KoinComponent { private val websiteSearchSettings: WebsiteSearchSettings by inject() private val unitConverterSettings: UnitConverterSettings by inject() private val calculatorSearchSettings: CalculatorSearchSettings by inject() + private val locationSearchSettings: LocationSearchSettings 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() val favorites = searchUiSettings.favorites .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null) @@ -62,6 +62,18 @@ class SearchSettingsScreenVM : ViewModel(), KoinComponent { contactSearchSettings.setEnabled(contacts) } + val hasLocationPermission = permissionsManager.hasPermission(PermissionGroup.Location) + .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null) + val placesSearch = locationSearchSettings.osmLocations + .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null) + fun setPlacesSearch(enabled: Boolean) { + locationSearchSettings.setOsmLocations(enabled) + } + + fun requestLocationPermission(activity: AppCompatActivity) { + permissionsManager.requestPermission(activity, PermissionGroup.Location) + } + fun requestCalendarPermission(activity: AppCompatActivity) { permissionsManager.requestPermission(activity, PermissionGroup.Calendar) }