From e96a382b00976f55c4a9008e025ba73f4a2d3434 Mon Sep 17 00:00:00 2001 From: MM20 <15646950+MM2-0@users.noreply.github.com> Date: Sun, 30 Jun 2024 14:38:33 +0200 Subject: [PATCH] Move osm settings to its own settings page --- .../search/common/SearchableItemVM.kt | 1 + .../launcher2/ui/settings/SettingsActivity.kt | 6 +- .../locations/LocationsSettingsScreen.kt | 37 ++++------- .../locations/LocationsSettingsScreenVM.kt | 24 +------- ...gsScreen.kt => NextcloudSettingsScreen.kt} | 2 - .../ui/settings/osm/OsmSettingsScreen.kt | 61 +++++++++++++++++++ .../ui/settings/osm/OsmSettingsScreenVM.kt | 36 +++++++++++ .../preferences/LauncherSettingsData.kt | 4 +- .../search/LocationSearchSettings.kt | 33 ++++++++-- .../openstreetmaps/OsmLocationProvider.kt | 3 +- 10 files changed, 145 insertions(+), 62 deletions(-) rename app/ui/src/main/java/de/mm20/launcher2/ui/settings/nextcloud/{owncloudSettingsScreen.kt => NextcloudSettingsScreen.kt} (98%) create mode 100644 app/ui/src/main/java/de/mm20/launcher2/ui/settings/osm/OsmSettingsScreen.kt create mode 100644 app/ui/src/main/java/de/mm20/launcher2/ui/settings/osm/OsmSettingsScreenVM.kt diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/SearchableItemVM.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/SearchableItemVM.kt index 8ed28b83..cc1579c2 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/SearchableItemVM.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/SearchableItemVM.kt @@ -243,5 +243,6 @@ class SearchableItemVM : ListItemViewModel(), KoinComponent { .stateIn(viewModelScope, SharingStarted.Lazily, false) val mapTileServerUrl = locationSearchSettings.tileServer + .map { it ?: LocationSearchSettings.DefaultTileServerUrl } .stateIn(viewModelScope, SharingStarted.Lazily, "") } \ No newline at end of file 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 7ef99e96..33d3acf6 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 @@ -55,6 +55,7 @@ import de.mm20.launcher2.ui.settings.log.LogScreen import de.mm20.launcher2.ui.settings.main.MainSettingsScreen import de.mm20.launcher2.ui.settings.media.MediaIntegrationSettingsScreen import de.mm20.launcher2.ui.settings.nextcloud.NextcloudSettingsScreen +import de.mm20.launcher2.ui.settings.osm.OsmSettingsScreen import de.mm20.launcher2.ui.settings.owncloud.OwncloudSettingsScreen import de.mm20.launcher2.ui.settings.plugins.PluginSettingsScreen import de.mm20.launcher2.ui.settings.plugins.PluginsSettingsScreen @@ -106,7 +107,7 @@ class SettingsActivity : BaseActivity() { navController = navController, startDestination = "settings", exitTransition = { - slideOutHorizontally { it / 4 } + slideOutHorizontally {-it / 4 } }, enterTransition = { slideInHorizontally { it / 2 } + scaleIn(initialScale = 0.9f) + fadeIn() @@ -162,6 +163,9 @@ class SettingsActivity : BaseActivity() { composable("settings/search/locations") { LocationsSettingsScreen() } + composable("settings/search/locations/osm") { + OsmSettingsScreen() + } composable("settings/search/files") { FileSearchSettingsScreen() } diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/locations/LocationsSettingsScreen.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/locations/LocationsSettingsScreen.kt index eb88294d..9c5fbf9c 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/locations/LocationsSettingsScreen.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/locations/LocationsSettingsScreen.kt @@ -29,20 +29,22 @@ import de.mm20.launcher2.ui.component.Banner import de.mm20.launcher2.ui.component.preferences.ListPreference 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.SliderPreference import de.mm20.launcher2.ui.component.preferences.SwitchPreference import de.mm20.launcher2.ui.component.preferences.TextPreference import de.mm20.launcher2.ui.ktx.metersToLocalizedString +import de.mm20.launcher2.ui.locals.LocalNavController @Composable fun LocationsSettingsScreen() { val viewModel: LocationsSettingsScreenVM = viewModel() + val navController = LocalNavController.current + val osmLocations by viewModel.osmLocations.collectAsState() val imperialUnits by viewModel.imperialUnits.collectAsState() - val hideUncategorized by viewModel.hideUncategorized.collectAsState() val radius by viewModel.radius.collectAsState() - val customOverpassUrl by viewModel.customOverpassUrl.collectAsState() val showMap by viewModel.showMap.collectAsState() val themeMap by viewModel.themeMap.collectAsState() val customTileServerUrl by viewModel.customTileServerUrl.collectAsState() @@ -59,12 +61,15 @@ fun LocationsSettingsScreen() { PreferenceScreen(title = stringResource(R.string.preference_search_locations)) { item { PreferenceCategory { - SwitchPreference( + PreferenceWithSwitch( title = stringResource(R.string.preference_search_osm_locations), summary = stringResource(R.string.preference_search_osm_locations_summary), - value = osmLocations == true, - onValueChanged = { + switchValue = osmLocations == true, + onSwitchChanged = { viewModel.setOsmLocations(it) + }, + onClick = { + navController?.navigate("settings/search/locations/osm") } ) AnimatedVisibility(plugins.isNotEmpty()) { @@ -150,15 +155,6 @@ fun LocationsSettingsScreen() { .metersToLocalizedString(LocalContext.current, imperialUnits) } ) - SwitchPreference( - title = stringResource(R.string.preference_search_locations_hide_uncategorized), - summary = stringResource(R.string.preference_search_locations_hide_uncategorized_summary), - value = hideUncategorized == true, - enabled = anyLocationProviderEnabled, - onValueChanged = { - viewModel.setHideUncategorized(it) - } - ) } } item { @@ -186,22 +182,11 @@ fun LocationsSettingsScreen() { } item { PreferenceCategory(stringResource(R.string.preference_category_advanced)) { - TextPreference( - title = stringResource(R.string.preference_search_location_custom_overpass_url), - value = customOverpassUrl, - placeholder = LocationSearchSettings.DefaultOverpassUrl, - summary = customOverpassUrl.takeIf { it.isNotBlank() } - ?: LocationSearchSettings.DefaultOverpassUrl, - onValueChanged = { - viewModel.setCustomOverpassUrl(it) - }, - enabled = osmLocations == true, - ) TextPreference( title = stringResource(R.string.preference_search_location_custom_tile_server_url), value = customTileServerUrl ?: "", placeholder = LocationSearchSettings.DefaultTileServerUrl, - summary = customTileServerUrl.takeIf { !it.isNullOrBlank() } + summary = customTileServerUrl?.takeIf { it.isNotBlank() } ?: LocationSearchSettings.DefaultTileServerUrl, onValueChanged = { viewModel.setCustomTileServerUrl(it) diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/locations/LocationsSettingsScreenVM.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/locations/LocationsSettingsScreenVM.kt index 825b1937..cc5cc8b6 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/locations/LocationsSettingsScreenVM.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/locations/LocationsSettingsScreenVM.kt @@ -42,21 +42,6 @@ class LocationsSettingsScreenVM : ViewModel(), KoinComponent { settings.setSearchRadius(radius) } - val customOverpassUrl = settings.overpassUrl - .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), "") - - fun setCustomOverpassUrl(customUrl: String) { - var url = customUrl - if (url.endsWith('/')) { - url = url.substringBeforeLast('/') - } - if (url.endsWith("/api/interpreter")) { - url = url.substringBeforeLast("/api/interpreter") - } - - settings.setOverpassUrl(url) - } - val showMap = settings.showMap .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null) @@ -68,14 +53,7 @@ class LocationsSettingsScreenVM : ViewModel(), KoinComponent { .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null) fun setCustomTileServerUrl(customTileServerUrl: String) { - settings.setTileServer(customTileServerUrl) - } - - val hideUncategorized = settings.hideUncategorized - .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null) - - fun setHideUncategorized(hideUncategorized: Boolean) { - settings.setHideUncategorized(hideUncategorized) + settings.setTileServer(customTileServerUrl.takeIf { it.isNotBlank() }) } val themeMap = settings.themeMap diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/nextcloud/owncloudSettingsScreen.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/nextcloud/NextcloudSettingsScreen.kt similarity index 98% rename from app/ui/src/main/java/de/mm20/launcher2/ui/settings/nextcloud/owncloudSettingsScreen.kt rename to app/ui/src/main/java/de/mm20/launcher2/ui/settings/nextcloud/NextcloudSettingsScreen.kt index a2e2f4dc..68246087 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/nextcloud/owncloudSettingsScreen.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/nextcloud/NextcloudSettingsScreen.kt @@ -6,14 +6,12 @@ import androidx.compose.foundation.border import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.rounded.Login import androidx.compose.material.icons.automirrored.rounded.Logout -import androidx.compose.material.icons.rounded.Logout import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.HorizontalDivider diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/osm/OsmSettingsScreen.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/osm/OsmSettingsScreen.kt new file mode 100644 index 00000000..ab3047eb --- /dev/null +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/osm/OsmSettingsScreen.kt @@ -0,0 +1,61 @@ +package de.mm20.launcher2.ui.settings.osm + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.res.stringResource +import androidx.lifecycle.viewmodel.compose.viewModel +import de.mm20.launcher2.preferences.search.LocationSearchSettings +import de.mm20.launcher2.ui.R +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.component.preferences.TextPreference + +@Composable +fun OsmSettingsScreen() { + val viewModel: OsmSettingsScreenVM = viewModel() + val osmLocations by viewModel.osmLocations.collectAsState() + val hideUncategorized by viewModel.hideUncategorized.collectAsState() + val customOverpassUrl by viewModel.customOverpassUrl.collectAsState() + + PreferenceScreen(title = stringResource(R.string.preference_search_osm_locations)) { + item { + PreferenceCategory { + SwitchPreference( + title = stringResource(R.string.preference_search_osm_locations), + summary = stringResource(R.string.preference_search_osm_locations_summary), + value = osmLocations == true, + onValueChanged = { + viewModel.setOsmLocations(it) + }, + ) + SwitchPreference( + title = stringResource(R.string.preference_search_locations_hide_uncategorized), + summary = stringResource(R.string.preference_search_locations_hide_uncategorized_summary), + value = hideUncategorized == true, + enabled = osmLocations == true, + onValueChanged = { + viewModel.setHideUncategorized(it) + } + ) + } + } + + item { + PreferenceCategory(stringResource(R.string.preference_category_advanced)) { + TextPreference( + title = stringResource(R.string.preference_search_location_custom_overpass_url), + value = customOverpassUrl ?: "", + placeholder = LocationSearchSettings.DefaultOverpassUrl, + summary = customOverpassUrl?.takeIf { it.isNotBlank() } + ?: LocationSearchSettings.DefaultOverpassUrl, + onValueChanged = { + viewModel.setCustomOverpassUrl(it) + }, + enabled = osmLocations == true, + ) + } + } + } +} \ No newline at end of file diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/osm/OsmSettingsScreenVM.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/osm/OsmSettingsScreenVM.kt new file mode 100644 index 00000000..b50eb45b --- /dev/null +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/osm/OsmSettingsScreenVM.kt @@ -0,0 +1,36 @@ +package de.mm20.launcher2.ui.settings.osm + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import de.mm20.launcher2.plugins.PluginService +import de.mm20.launcher2.preferences.search.LocationSearchSettings +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.stateIn +import org.koin.core.component.KoinComponent +import org.koin.core.component.inject + +class OsmSettingsScreenVM: ViewModel(), KoinComponent { + private val settings: LocationSearchSettings by inject() + private val pluginService: PluginService by inject() + + val osmLocations = settings.osmLocations + .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null) + + fun setOsmLocations(osmLocations: Boolean) { + settings.setOsmLocations(osmLocations) + } + + val hideUncategorized = settings.hideUncategorized + .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null) + + fun setHideUncategorized(hideUncategorized: Boolean) { + settings.setHideUncategorized(hideUncategorized) + } + + val customOverpassUrl = settings.overpassUrl + .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), "") + + fun setCustomOverpassUrl(customUrl: String) { + settings.setOverpassUrl(customUrl) + } +} \ 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 c6a46af0..94ef7368 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 @@ -141,8 +141,8 @@ data class LauncherSettingsData internal constructor( val locationSearchImperialUnits: Boolean = false, val locationSearchRadius: Int = 1500, val locationSearchHideUncategorized: Boolean = true, - val locationSearchOverpassUrl: String = LocationSearchSettings.DefaultOverpassUrl, - val locationSearchTileServer: String = LocationSearchSettings.DefaultTileServerUrl, + val locationSearchOverpassUrl: String? = null, + val locationSearchTileServer: String? = null, val locationSearchShowMap: Boolean = true, val locationSearchShowPositionOnMap: Boolean = false, val locationSearchThemeMap: Boolean = true, diff --git a/core/preferences/src/main/java/de/mm20/launcher2/preferences/search/LocationSearchSettings.kt b/core/preferences/src/main/java/de/mm20/launcher2/preferences/search/LocationSearchSettings.kt index 01e4b5b0..331c99bc 100644 --- a/core/preferences/src/main/java/de/mm20/launcher2/preferences/search/LocationSearchSettings.kt +++ b/core/preferences/src/main/java/de/mm20/launcher2/preferences/search/LocationSearchSettings.kt @@ -72,18 +72,39 @@ class LocationSearchSettings internal constructor( val overpassUrl get() = launcherDataStore.data.map { it.locationSearchOverpassUrl } - fun setOverpassUrl(overpassUrl: String) { + fun setOverpassUrl(overpassUrl: String?) { + var url = overpassUrl + if (url != null) { + if (!url.startsWith("http://") && !url.startsWith("https://")) { + url = "https://$url" + } + if (url.endsWith('/')) { + url = url.substringBeforeLast('/') + } + if (url.endsWith("/api/interpreter")) { + url = url.substringBeforeLast("/api/interpreter") + } + } launcherDataStore.update { - it.copy(locationSearchOverpassUrl = overpassUrl) + it.copy(locationSearchOverpassUrl = url) } } val tileServer get() = launcherDataStore.data.map { it.locationSearchTileServer } - fun setTileServer(tileServer: String) { + fun setTileServer(tileServer: String?) { + var url = tileServer + if (url != null) { + if (!url.startsWith("http://") && !url.startsWith("https://")) { + url = "https://$url" + } + if (!url.contains("\${z}") || !url.contains("\${x}") || !url.contains("\${y}")) { + url = "$url/\${z}/\${x}/\${y}.png" + } + } launcherDataStore.update { - it.copy(locationSearchTileServer = tileServer) + it.copy(locationSearchTileServer = url) } } @@ -125,8 +146,8 @@ data class LocationSearchSettingsData( val providers: Set = setOf("openstreetmaps"), val searchRadius: Int = 1500, val hideUncategorized: Boolean = true, - val overpassUrl: String = LocationSearchSettings.DefaultOverpassUrl, - val tileServer: String = LocationSearchSettings.DefaultTileServerUrl, + val overpassUrl: String? = null, + val tileServer: String? = null, val imperialUnits: Boolean = false, val showMap: Boolean = false, val showPositionOnMap: Boolean = false, diff --git a/data/locations/src/main/java/de/mm20/launcher2/locations/providers/openstreetmaps/OsmLocationProvider.kt b/data/locations/src/main/java/de/mm20/launcher2/locations/providers/openstreetmaps/OsmLocationProvider.kt index 993370b4..1967ec50 100644 --- a/data/locations/src/main/java/de/mm20/launcher2/locations/providers/openstreetmaps/OsmLocationProvider.kt +++ b/data/locations/src/main/java/de/mm20/launcher2/locations/providers/openstreetmaps/OsmLocationProvider.kt @@ -38,8 +38,7 @@ internal class OsmLocationProvider( try { Retrofit.Builder() .client(HttpClient) - .baseUrl(it.takeIf { it.isNotBlank() } - ?: LocationSearchSettings.DefaultOverpassUrl) + .baseUrl(it?.takeIf { it.isNotBlank() } ?: LocationSearchSettings.DefaultOverpassUrl) .addConverterFactory(OverpassQueryConverterFactory()) .addConverterFactory(GsonConverterFactory.create()) .build()