forked from MapComplete/MapComplete
UX: indicate incomplete search in offline mode
This commit is contained in:
parent
76dbf50db1
commit
b6366412ea
13 changed files with 69 additions and 5 deletions
|
|
@ -6,6 +6,8 @@ export default class CombinedSearcher implements GeocodingProvider {
|
|||
public readonly name = "CombinedSearcher"
|
||||
private _providers: ReadonlyArray<GeocodingProvider>
|
||||
private _providersWithSuggest: ReadonlyArray<GeocodingProvider>
|
||||
public readonly needsInternet
|
||||
|
||||
|
||||
/**
|
||||
* Merges the various providers together; ignores errors.
|
||||
|
|
@ -15,6 +17,7 @@ export default class CombinedSearcher implements GeocodingProvider {
|
|||
constructor(...providers: ReadonlyArray<GeocodingProvider>) {
|
||||
this._providers = Utils.NoNull(providers)
|
||||
this._providersWithSuggest = this._providers.filter((pr) => pr.suggest !== undefined)
|
||||
this.needsInternet = this._providers.some(p => p.needsInternet)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ import CoordinateParser from "coordinate-parser"
|
|||
*/
|
||||
export default class CoordinateSearch implements GeocodingProvider {
|
||||
public readonly name = "CoordinateSearch"
|
||||
public readonly needsInternet = false
|
||||
|
||||
private static readonly latLonRegexes: ReadonlyArray<RegExp> = [
|
||||
/^ *(-?[0-9]+\.[0-9]+)[ ,;/\\]+(-?[0-9]+\.[0-9]+)/,
|
||||
/^ *(-?[0-9]+,[0-9]+)[ ;/\\]+(-?[0-9]+,[0-9]+)/,
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ export interface GeocodingOptions {
|
|||
|
||||
export default interface GeocodingProvider {
|
||||
readonly name: string
|
||||
readonly needsInternet: boolean
|
||||
|
||||
/**
|
||||
* Performs search.
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ export default class LocalElementSearch implements GeocodingProvider {
|
|||
private readonly _state: ThemeViewState
|
||||
private readonly _limit: number
|
||||
public readonly name = "LocalElementSearch"
|
||||
public readonly needsInternet = false
|
||||
|
||||
constructor(state: ThemeViewState, limit: number) {
|
||||
this._state = state
|
||||
this._limit = limit
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ export class NominatimGeocoding implements GeocodingProvider {
|
|||
private readonly _host
|
||||
private readonly limit: number
|
||||
public readonly name = "Nominatim"
|
||||
public readonly needsInternet = true
|
||||
|
||||
constructor(limit: number = 3, host: string = Constants.nominatimEndpoint) {
|
||||
this.limit = limit
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ import GeocodingProvider, { GeocodeResult, GeocodingOptions } from "./GeocodingP
|
|||
import { decode as pluscode_decode } from "pluscodes"
|
||||
|
||||
export default class OpenLocationCodeSearch implements GeocodingProvider {
|
||||
public readonly needsInternet = false
|
||||
|
||||
/**
|
||||
* A regex describing all plus-codes
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import OsmObjectDownloader from "../Osm/OsmObjectDownloader"
|
|||
export default class OpenStreetMapIdSearch implements GeocodingProvider {
|
||||
private static readonly regex =
|
||||
/((https?:\/\/)?(www.)?(osm|openstreetmap).org\/)?(n|node|w|way|r|relation)[/ ]?([0-9]+)/
|
||||
public readonly needsInternet = true
|
||||
public readonly name = "OpenStreetMapId"
|
||||
private static readonly types: Readonly<Record<string, "node" | "way" | "relation">> = {
|
||||
n: "node",
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import GeocodingProvider, {
|
|||
GeocodingOptions,
|
||||
GeocodingUtils,
|
||||
ReverseGeocodingProvider,
|
||||
ReverseGeocodingResult,
|
||||
ReverseGeocodingResult
|
||||
} from "./GeocodingProvider"
|
||||
import { Utils } from "../../Utils"
|
||||
import { Feature, FeatureCollection } from "geojson"
|
||||
|
|
@ -15,6 +15,7 @@ import { Store, Stores } from "../UIEventSource"
|
|||
|
||||
export default class PhotonSearch implements GeocodingProvider, ReverseGeocodingProvider {
|
||||
private readonly _endpoint: string
|
||||
public readonly needsInternet = true
|
||||
public readonly name = "photon"
|
||||
private supportedLanguages = ["en", "de", "fr"]
|
||||
private static readonly types = {
|
||||
|
|
@ -23,17 +24,14 @@ export default class PhotonSearch implements GeocodingProvider, ReverseGeocoding
|
|||
N: "node",
|
||||
}
|
||||
private readonly ignoreBounds: boolean
|
||||
private readonly suggestionLimit: number = 5
|
||||
private readonly searchLimit: number = 1
|
||||
|
||||
constructor(
|
||||
ignoreBounds: boolean = false,
|
||||
suggestionLimit: number = 5,
|
||||
searchLimit: number = 1,
|
||||
endpoint?: string
|
||||
) {
|
||||
this.ignoreBounds = ignoreBounds
|
||||
this.suggestionLimit = suggestionLimit
|
||||
this.searchLimit = searchLimit
|
||||
this._endpoint = endpoint ?? Constants.photonEndpoint ?? "https://photon.komoot.io/"
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import { BBox } from "../BBox"
|
|||
import { QueryParameters } from "../Web/QueryParameters"
|
||||
import { Utils } from "../../Utils"
|
||||
import { NominatimGeocoding } from "../Search/NominatimGeocoding"
|
||||
import { IsOnline } from "../Web/IsOnline"
|
||||
|
||||
export default class SearchState {
|
||||
public readonly feedback: UIEventSource<Translation> = new UIEventSource<Translation>(undefined)
|
||||
|
|
@ -62,7 +63,9 @@ export default class SearchState {
|
|||
if (search.length === 0) {
|
||||
return undefined
|
||||
}
|
||||
return this.locationSearchers.map((ls) => ({
|
||||
return this.locationSearchers
|
||||
.filter(ls => !ls.needsInternet || IsOnline.isOnline.data)
|
||||
.map((ls) => ({
|
||||
source: ls,
|
||||
results: ls.suggest(search, { bbox: bounds.data }),
|
||||
}))
|
||||
|
|
|
|||
15
src/UI/Base/CrossedOut.svelte
Normal file
15
src/UI/Base/CrossedOut.svelte
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<!-- Shows a red cross at the bottom of the icon-->
|
||||
<script>
|
||||
import Cross_bottom_right from "../../assets/svg/Cross_bottom_right.svelte"
|
||||
|
||||
export let size = "w-12 h-12"
|
||||
</script>
|
||||
<div class={size+" relative"}>
|
||||
<div class="absolute top-0 left-0">
|
||||
|
||||
<slot />
|
||||
</div>
|
||||
<div class="absolute top-0 left-0">
|
||||
<Cross_bottom_right class={size} color="red" />
|
||||
</div>
|
||||
</div>
|
||||
22
src/UI/BigComponents/ServiceWorkerStatus.svelte
Normal file
22
src/UI/BigComponents/ServiceWorkerStatus.svelte
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<script lang="ts">
|
||||
|
||||
import { UIEventSource } from "../../Logic/UIEventSource"
|
||||
import { Utils } from "../../Utils"
|
||||
import Loading from "../Base/Loading.svelte"
|
||||
|
||||
let loadedAssets = new UIEventSource<any>(undefined)
|
||||
|
||||
async function update() {
|
||||
loadedAssets.set(await Utils.downloadJson("./service-worker/status.json"))
|
||||
}
|
||||
|
||||
update()
|
||||
|
||||
</script>
|
||||
|
||||
{#if $loadedAssets === undefined}
|
||||
<Loading />
|
||||
{:else}
|
||||
<button on:click={() => update()}>Update</button>
|
||||
{JSON.stringify($loadedAssets)}
|
||||
{/if}
|
||||
|
|
@ -12,6 +12,7 @@
|
|||
import type { GeocodeResult } from "../../Logic/Search/GeocodingProvider"
|
||||
import type { MapProperties } from "../../Models/MapProperties"
|
||||
import { ExclamationTriangle } from "@babeard/svelte-heroicons/solid/ExclamationTriangle"
|
||||
import { IsOnline } from "../../Logic/Web/IsOnline"
|
||||
|
||||
export let state: {
|
||||
searchState: {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,9 @@
|
|||
import DotMenu from "../Base/DotMenu.svelte"
|
||||
import type { GeocodeResult } from "../../Logic/Search/GeocodingProvider"
|
||||
import { default as GeocodeResultSvelte } from "./GeocodeResult.svelte"
|
||||
import { IsOnline } from "../../Logic/Web/IsOnline"
|
||||
import CrossedOut from "../Base/CrossedOut.svelte"
|
||||
import Wifi from "@babeard/svelte-heroicons/solid/Wifi"
|
||||
|
||||
/**
|
||||
* The big overview of all search bar results
|
||||
|
|
@ -41,6 +44,7 @@
|
|||
|
||||
let allowOtherThemes = state.featureSwitches.featureSwitchBackToThemeOverview
|
||||
let allowFilters = state.featureSwitches.featureSwitchFilter
|
||||
let isOnline = IsOnline.isOnline
|
||||
</script>
|
||||
|
||||
<div class="low-interaction flex flex-col gap-y-2 p-4">
|
||||
|
|
@ -55,6 +59,15 @@
|
|||
</div>
|
||||
{/if}
|
||||
|
||||
{#if !$isOnline}
|
||||
<div class="alert flex items-center">
|
||||
<CrossedOut size="w-8 h-8">
|
||||
<Wifi class="w-8 h-8" />
|
||||
</CrossedOut>
|
||||
Your device is currently offline. This impacts search results
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if $allowFilters}
|
||||
<FilterResults {state} />
|
||||
{/if}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue