Add OSM search provider (#611)
* add openstreetmaps module in data * fix injection * retrofit2 implementation * tokenization * partial rewrite of OpeningTime.fromOverpassElement * finish rewrite of OpeningTime.fromOverpassElement * fix merge x) * configurable search radius * add settings section and disable setting explicit timeout values for http-client to alleviate issues during debugging * settings screen localization * enable radius slider only when locations are enabled * fix dayRange parsing, add barebones UI * add files to git * add location listener in SearchableItemVM that gets activated by LocationItem * add heading listener * Calculations, UI additions * rename settings to LocationsSettings * use android location library for bearing calculations * location fix * rotation fix, demo UI * working buttons for launching map and website (if available) * finish botched UI * improve overpass query by utilizing regex for fuzzy search results * add link to documentation for further reference * localization comments * remove wikipedia minification setting * schema version, default radius 1.5km * move osm-specific opening-time parsing to OsmLocation * refactor with callbackFlow * remember flow and set minimum distance update to 1m * refactor for replacementIcon, add imperial unit option * 'open until' UI fix * implement serializers * catch errors in deserializer * hacky live sorting by distance * give max priority to bestmatch determined by SearchVM * add yards as additional step to metersToLocalizzedString * move http-client from serializers of osmlocation to companion object for cache updating * add setting for custom URL * round yards to int * add botched map preview * unbotch map tiles, draw user location in map (proof of concept) * - create MapTiles Composable - add border around map - add indicators for location and userlocation, when on map * fix default imperial units setting * fix tint color * add OSM attribution string * display loading animation when tiles can't be shown yet * create compose preview of maptiles * UI work * being glad that API's just return null instead of throwing information * tryStartActivity * aniimate card row placement * Text alignment, padding * Rotation -PI/PI wrap fix * fix direction arrow rotation when screen is upside down * more icons * icons, settings, localization - consider other tags than "amenity" when determining location category - add many more location categories with corresponding icons - add settings to disable map theming and hide search results with LocationCategory.OTHER - add default localizations for settings * catch errors when deserializing location category * move location and heading functions to Context.kt in extensions * fix hideUncategorized criterion * add pre-sorting by distance for location results in SearchVM by injecting Context into search() * specify receiver parameters in ktx.Context lambdas * move pose logic and context dependency to new module devicepose with DevicePoseProvider * git, add the frickin' module * search overpass for nodes and ways include category for parcel_locker already start searching for queries extending length 2 * make openingTimes immutable * OsmRepository changes - include telephone number - don't try to repeatedly update cache if there is no value to be updated to - deduplicate results with same label by category and distance (100m) - include fixmeurl to point to openstreetmaps.org/fixthemap * ask for center in overpass API to compute center coordinates of ways * search for brand * add chemist location category * restaurant / fastfood icon shenanigans * actually add the icons :| * add leisure tag for leisure:fitness_centre * return to 'open until'/'opens in'/'open next' * adding missing UI features - bug report dialog - call button if phone number exists - grid item popup * refactor to handle 24/7 locations more comfortably * hide hours in 'opens_in' when they are zero * show maptiles such that user is always in view * drawing adjustments * cache previous zoom level to speed up tile coordinate calculations * using remember * using MutableIntState * fix logic that determines whether tiles are loading * fix for numTiles == 9 * one plus one is two plus one makes three quick maths * animate user location indicator, remember calculations * fix off by one when determining next opening hour * second attempt to fix upside down arrow rotation (probably fine now) * logging * reconsider declination, inject samplingPeriod * undoing the merge undo * move localization string to i18n * revert reordering by distance * refactor .distanceTo * make Location abstract class to override compareTo with cached distance to correct sort order in search results * when it is if when you could use when * replace Pair with dataclass * condition check order * not creating objects with undefined locations, removing suspend from getCategory() * inject permissionsmanager as constructor parameter * Store OSM settings in decentralized datastore * Update searchable content in database on launch * Refactor, add mechanism to load updated searchable data lazily * Cache all OSM data in launcher database * Add pin to favorites button to location results * Add sealed class UpdateResult that is returned by awaiting updatedSelf of DeferredSearchable - update on success - set flag on temporarily unavailable (TODO add some UI indication) - delete and invalidate VM on permanently unavailable (Display some message window to user?) * Move sorting of Locations from OsmRepository to SearchVM using cached location in DevicePoseProvider, if available * make use of cached location in code * make use of DevicePoseProvider in WeatherRepository * inject via koin * increase getLocation().timeout() to 10 minutes since we are asking for locations only every hour, so 10 minutes seem reasonable (?) * poll new location every time * add icon for cached results where results are temporarily unavailable * Refactor DeferredSearchable to UpdatableSearchable that receives a closure to retrieve an updated self. - moved timestamp (formerly `updatedAt`) to UpdatableSearchable - moved logic whether to update searchable to `requestUpdatedSearchable` in SearchableItemVM, which gets triggered every time the details of the item are shown - keep track in SearchableVM whether we should retry updating, possibly bypassing a timestamp value that is not old enough - show toast upon permanently unavailable - animate "cached_searchable" icon - make "cached_searchable" icon clickable to show toast explaining the situation * logging on PermanentlyUnavailable * refactor OsmRepository.update() * MapTheming adjustments. There is now darkmode, hooray! * remove outdated comment * code tidying * remove unnecessary LaunchedEffect * make outdated badge only clickable when actually outdated * deserialize opening schedule * set deserialized props to null if strings are blank * also consider contact:* tagging scheme for website & phone * tweaks * git add Result.kt * don't search for locations if network is not allowed * merge fixes * Move location search settings to preferences module * Change wording and order of location search preferences * Limit location search results * Order location search results by distance * Use a sequence * Android Studio's suggestion wasn't as fleshed out as one would hope * Add proguard rules * Rename TileMapRepository to MapTileLoader --------- Co-authored-by: MM20 <15646950+MM2-0@users.noreply.github.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package de.mm20.launcher2.preferences
|
||||
|
||||
import android.content.Context
|
||||
import androidx.core.graphics.blue
|
||||
import de.mm20.launcher2.ktx.isAtLeastApiLevel
|
||||
import de.mm20.launcher2.preferences.LegacySettings.SearchBarSettings.SearchBarColors
|
||||
import de.mm20.launcher2.preferences.ktx.toSettingsColorsScheme
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package de.mm20.launcher2.preferences
|
||||
|
||||
import android.content.Context
|
||||
import de.mm20.launcher2.preferences.search.LocationSearchSettings
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import java.util.UUID
|
||||
@@ -124,11 +125,23 @@ data class LauncherSettingsData(
|
||||
val weatherProviderSettings: Map<String, ProviderSettings> = emptyMap(),
|
||||
val weatherImperialUnits: Boolean = false,
|
||||
|
||||
val locationSearchEnabled: Boolean = false,
|
||||
val locationSearchImperialUnits: Boolean = false,
|
||||
val locationSearchRadius: Int = 1500,
|
||||
val locationSearchHideUncategorized: Boolean = true,
|
||||
val locationSearchOverpassUrl: String = LocationSearchSettings.DefaultOverpassUrl,
|
||||
val locationSearchTileServer: String = LocationSearchSettings.DefaultTileServerUrl,
|
||||
val locationSearchShowMap: Boolean = false,
|
||||
val locationSearchShowPositionOnMap: Boolean = false,
|
||||
val locationSearchThemeMap: Boolean = true,
|
||||
|
||||
|
||||
) {
|
||||
constructor(
|
||||
context: Context,
|
||||
) : this(
|
||||
weatherImperialUnits = context.resources.getBoolean(R.bool.default_imperialUnits),
|
||||
locationSearchImperialUnits = context.resources.getBoolean(R.bool.default_imperialUnits),
|
||||
gridColumnCount = context.resources.getInteger(R.integer.config_columnCount),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import de.mm20.launcher2.preferences.search.CalculatorSearchSettings
|
||||
import de.mm20.launcher2.preferences.search.CalendarSearchSettings
|
||||
import de.mm20.launcher2.preferences.search.FavoritesSettings
|
||||
import de.mm20.launcher2.preferences.search.FileSearchSettings
|
||||
import de.mm20.launcher2.preferences.search.LocationSearchSettings
|
||||
import de.mm20.launcher2.preferences.search.RankingSettings
|
||||
import de.mm20.launcher2.preferences.search.ShortcutSearchSettings
|
||||
import de.mm20.launcher2.preferences.search.UnitConverterSettings
|
||||
@@ -47,4 +48,5 @@ val preferencesModule = module {
|
||||
factory { GestureSettings(get()) }
|
||||
factory { CalculatorSearchSettings(get()) }
|
||||
factory { ClockWidgetSettings(get()) }
|
||||
factory { LocationSearchSettings(get()) }
|
||||
}
|
||||
+123
@@ -0,0 +1,123 @@
|
||||
package de.mm20.launcher2.preferences.search
|
||||
|
||||
import de.mm20.launcher2.preferences.LauncherDataStore
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
||||
class LocationSearchSettings internal constructor(
|
||||
private val launcherDataStore: LauncherDataStore,
|
||||
) {
|
||||
|
||||
val data
|
||||
get() = launcherDataStore.data.map {
|
||||
LocationSearchSettingsData(
|
||||
enabled = it.locationSearchEnabled,
|
||||
searchRadius = it.locationSearchRadius,
|
||||
hideUncategorized = it.locationSearchHideUncategorized,
|
||||
overpassUrl = it.locationSearchOverpassUrl,
|
||||
tileServer = it.locationSearchTileServer,
|
||||
imperialUnits = it.locationSearchImperialUnits,
|
||||
showMap = it.locationSearchShowMap,
|
||||
showPositionOnMap = it.locationSearchShowPositionOnMap,
|
||||
themeMap = it.locationSearchThemeMap,
|
||||
)
|
||||
}
|
||||
|
||||
val enabled
|
||||
get() = launcherDataStore.data.map { it.locationSearchEnabled }
|
||||
|
||||
fun setEnabled(enabled: Boolean) {
|
||||
launcherDataStore.update {
|
||||
it.copy(locationSearchEnabled = enabled)
|
||||
}
|
||||
}
|
||||
|
||||
val searchRadius
|
||||
get() = launcherDataStore.data.map { it.locationSearchRadius }
|
||||
|
||||
fun setSearchRadius(searchRadius: Int) {
|
||||
launcherDataStore.update {
|
||||
it.copy(locationSearchRadius = searchRadius)
|
||||
}
|
||||
}
|
||||
|
||||
val hideUncategorized
|
||||
get() = launcherDataStore.data.map { it.locationSearchHideUncategorized }
|
||||
|
||||
fun setHideUncategorized(hideUncategorized: Boolean) {
|
||||
launcherDataStore.update {
|
||||
it.copy(locationSearchHideUncategorized = hideUncategorized)
|
||||
}
|
||||
}
|
||||
|
||||
val overpassUrl
|
||||
get() = launcherDataStore.data.map { it.locationSearchOverpassUrl }
|
||||
|
||||
fun setOverpassUrl(overpassUrl: String) {
|
||||
launcherDataStore.update {
|
||||
it.copy(locationSearchOverpassUrl = overpassUrl)
|
||||
}
|
||||
}
|
||||
|
||||
val tileServer
|
||||
get() = launcherDataStore.data.map { it.locationSearchTileServer }
|
||||
|
||||
fun setTileServer(tileServer: String) {
|
||||
launcherDataStore.update {
|
||||
it.copy(locationSearchTileServer = tileServer)
|
||||
}
|
||||
}
|
||||
|
||||
val showMap
|
||||
get() = launcherDataStore.data.map { it.locationSearchShowMap }
|
||||
|
||||
fun setShowMap(showMap: Boolean) {
|
||||
launcherDataStore.update {
|
||||
it.copy(locationSearchShowMap = showMap)
|
||||
}
|
||||
}
|
||||
|
||||
val showPositionOnMap
|
||||
get() = launcherDataStore.data.map { it.locationSearchShowPositionOnMap }
|
||||
|
||||
fun setShowPositionOnMap(showPositionOnMap: Boolean) {
|
||||
launcherDataStore.update {
|
||||
it.copy(locationSearchShowPositionOnMap = showPositionOnMap)
|
||||
}
|
||||
}
|
||||
|
||||
val themeMap
|
||||
get() = launcherDataStore.data.map { it.locationSearchThemeMap }
|
||||
|
||||
fun setThemeMap(themeMap: Boolean) {
|
||||
launcherDataStore.update {
|
||||
it.copy(locationSearchThemeMap = themeMap)
|
||||
}
|
||||
}
|
||||
|
||||
val imperialUnits
|
||||
get() = launcherDataStore.data.map { it.locationSearchImperialUnits }
|
||||
|
||||
fun setImperialUnits(imperialUnits: Boolean) {
|
||||
launcherDataStore.update {
|
||||
it.copy(locationSearchImperialUnits = imperialUnits)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val DefaultTileServerUrl = "https://tile.openstreetmap.org"
|
||||
const val DefaultOverpassUrl = "https://overpass-api.de/"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
data class LocationSearchSettingsData(
|
||||
val enabled: Boolean = false,
|
||||
val searchRadius: Int = 1500,
|
||||
val hideUncategorized: Boolean = true,
|
||||
val overpassUrl: String = LocationSearchSettings.DefaultOverpassUrl,
|
||||
val tileServer: String = LocationSearchSettings.DefaultTileServerUrl,
|
||||
val imperialUnits: Boolean = false,
|
||||
val showMap: Boolean = false,
|
||||
val showPositionOnMap: Boolean = false,
|
||||
val themeMap: Boolean = true,
|
||||
)
|
||||
Reference in New Issue
Block a user