forked from MapComplete/MapComplete
Feature(offline): more offline hardening
This commit is contained in:
parent
f1da97285f
commit
561e4cb009
7 changed files with 103 additions and 69 deletions
|
@ -19,6 +19,7 @@ import LayerConfig from "./LayerConfig"
|
|||
import ComparingTag from "../../Logic/Tags/ComparingTag"
|
||||
import { Unit } from "../Unit"
|
||||
import { Lists } from "../../Utils/Lists"
|
||||
import { IsOnline } from "../../Logic/Web/IsOnline"
|
||||
|
||||
export interface Mapping {
|
||||
readonly if: UploadableTag
|
||||
|
@ -1154,10 +1155,10 @@ export class TagRenderingConfigUtils {
|
|||
const extraMappings = tags.bindD((tags) => {
|
||||
const country = tags._country
|
||||
if (country === undefined) {
|
||||
return undefined
|
||||
return undefined
|
||||
}
|
||||
const center = GeoOperations.centerpointCoordinates(feature)
|
||||
return UIEventSource.fromPromise(
|
||||
return UIEventSource.fromPromiseWithErr(
|
||||
NameSuggestionIndex.generateMappings(
|
||||
config.freeform.key,
|
||||
tags,
|
||||
|
@ -1167,7 +1168,20 @@ export class TagRenderingConfigUtils {
|
|||
)
|
||||
)
|
||||
})
|
||||
return extraMappings.mapD((extraMappings) => {
|
||||
return extraMappings.map((extraMappingsErr) => {
|
||||
if(extraMappingsErr?.["error"]){
|
||||
console.log("Could not download the NSI: ", extraMappingsErr["error"])
|
||||
return config
|
||||
}
|
||||
const extraMappings = extraMappingsErr?.success
|
||||
if(extraMappings === undefined){
|
||||
if(!IsOnline.isOnline.data){
|
||||
// The 'extraMappings' will still attempt to download the NSI - it might be in the service worker's cache
|
||||
// As such, if they happen to come through anyway, they'll be shown
|
||||
return config
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
if (extraMappings.length == 0) {
|
||||
return config
|
||||
}
|
||||
|
@ -1187,6 +1201,6 @@ export class TagRenderingConfigUtils {
|
|||
}) ?? []
|
||||
clone.mappings = [...oldMappingsCloned, ...extraMappings]
|
||||
return clone
|
||||
})
|
||||
}, [IsOnline.isOnline])
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,9 +13,10 @@
|
|||
import Translations from "../i18n/Translations"
|
||||
import Tr from "../Base/Tr.svelte"
|
||||
import AccordionSingle from "../Flowbite/AccordionSingle.svelte"
|
||||
import GlobeAlt from "@babeard/svelte-heroicons/mini/GlobeAlt"
|
||||
import { ComparisonState } from "./ComparisonState"
|
||||
import LoginToggle from "../Base/LoginToggle.svelte"
|
||||
import { IsOnline } from "../../Logic/Web/IsOnline"
|
||||
import GlobeAlt from "@babeard/svelte-heroicons/mini/GlobeAlt"
|
||||
|
||||
export let externalData: Store<
|
||||
| { success: { content: Record<string, string> } }
|
||||
|
@ -33,7 +34,7 @@
|
|||
* A switch that signals that the information should be downloaded.
|
||||
* The actual 'download' code is _not_ implemented here
|
||||
*/
|
||||
export let downloadInformation : UIEventSource<boolean>
|
||||
export let downloadInformation: UIEventSource<boolean>
|
||||
export let collapsed: boolean
|
||||
const t = Translations.t.external
|
||||
|
||||
|
@ -48,45 +49,47 @@
|
|||
let propertyKeysExternal = comparisonState.mapD((ct) => ct.propertyKeysExternal)
|
||||
let hasDifferencesAtStart = comparisonState.mapD((ct) => ct.hasDifferencesAtStart)
|
||||
let enableLogin = state.featureSwitches.featureSwitchEnableLogin
|
||||
const online = IsOnline.isOnline
|
||||
</script>
|
||||
|
||||
<LoginToggle {state} silentFail>
|
||||
{#if !$sourceUrl || !$enableLogin}
|
||||
<!-- empty block -->
|
||||
{#if $online}
|
||||
<LoginToggle {state} hiddenFail>
|
||||
{#if !$sourceUrl || !$enableLogin}
|
||||
<!-- empty block -->
|
||||
{:else if !$downloadInformation}
|
||||
<button on:click={() => downloadInformation.set(true)}>
|
||||
Attempt to download information from the website {$sourceUrl}
|
||||
</button>
|
||||
{:else if $externalData === undefined}
|
||||
<div class="flex justify-center">
|
||||
<Loading />
|
||||
</div>
|
||||
{:else if $externalData["error"] !== undefined}
|
||||
<div class="subtle low-interaction rounded p-2 px-4 italic">
|
||||
<Tr t={Translations.t.external.error} />
|
||||
</div>
|
||||
{:else if $propertyKeysExternal.length === 0 && $knownImages.size + $unknownImages.length === 0}
|
||||
<Tr cls="subtle" t={t.noDataLoaded} />
|
||||
{:else if !$hasDifferencesAtStart}
|
||||
<button on:click={() => downloadInformation.set(true)}>
|
||||
Attempt to download information from the website {$sourceUrl}
|
||||
</button>
|
||||
{:else if $externalData === undefined}
|
||||
<div class="flex justify-center">
|
||||
<Loading />
|
||||
</div>
|
||||
{:else if $externalData["error"] !== undefined}
|
||||
<div class="subtle low-interaction rounded p-2 px-4 italic">
|
||||
<Tr t={Translations.t.external.error} />
|
||||
</div>
|
||||
{:else if $propertyKeysExternal.length === 0 && $knownImages.size + $unknownImages.length === 0}
|
||||
<Tr cls="subtle" t={t.noDataLoaded} />
|
||||
{:else if !$hasDifferencesAtStart}
|
||||
<span class="subtle text-sm">
|
||||
<Tr t={t.allIncluded.Subs({ source: $sourceUrl })} />
|
||||
</span>
|
||||
{:else if $comparisonState !== undefined}
|
||||
<AccordionSingle expanded={!collapsed}>
|
||||
{:else if $comparisonState !== undefined}
|
||||
<AccordionSingle expanded={!collapsed}>
|
||||
<span slot="header" class="flex">
|
||||
<GlobeAlt class="h-6 w-6" />
|
||||
<Tr t={Translations.t.external.title} />
|
||||
</span>
|
||||
<ComparisonTable
|
||||
externalProperties={$externalData["success"]}
|
||||
{state}
|
||||
{feature}
|
||||
{layer}
|
||||
{tags}
|
||||
{readonly}
|
||||
sourceUrl={$sourceUrl}
|
||||
comparisonState={$comparisonState}
|
||||
/>
|
||||
</AccordionSingle>
|
||||
{/if}
|
||||
</LoginToggle>
|
||||
<ComparisonTable
|
||||
externalProperties={$externalData["success"]}
|
||||
{state}
|
||||
{feature}
|
||||
{layer}
|
||||
{tags}
|
||||
{readonly}
|
||||
sourceUrl={$sourceUrl}
|
||||
comparisonState={$comparisonState}
|
||||
/>
|
||||
</AccordionSingle>
|
||||
{/if}
|
||||
</LoginToggle>
|
||||
{/if}
|
||||
|
|
|
@ -93,7 +93,7 @@
|
|||
</Loading>
|
||||
</div>
|
||||
{/if}
|
||||
{#if !$online}
|
||||
{#if !$online && $pending > 0}
|
||||
<div class="alert">
|
||||
<Tr t={t.upload.offline} />
|
||||
</div>
|
||||
|
|
|
@ -17,20 +17,18 @@ export class DeleteFlowState {
|
|||
private readonly _id: OsmId
|
||||
private readonly _allowDeletionAtChangesetCount: number
|
||||
private readonly _osmConnection: OsmConnection
|
||||
private readonly state: SpecialVisualizationState
|
||||
|
||||
constructor(
|
||||
id: OsmId,
|
||||
state: SpecialVisualizationState,
|
||||
allowDeletionAtChangesetCount?: number
|
||||
) {
|
||||
this.state = state
|
||||
this.objectDownloader = state.osmObjectDownloader
|
||||
this._id = id
|
||||
this._osmConnection = state.osmConnection
|
||||
this._allowDeletionAtChangesetCount = allowDeletionAtChangesetCount ?? Number.MAX_VALUE
|
||||
|
||||
this.CheckDeleteability(false)
|
||||
this.checkDeleteability(false)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -39,7 +37,7 @@ export class DeleteFlowState {
|
|||
* @constructor
|
||||
* @private
|
||||
*/
|
||||
public CheckDeleteability(useTheInternet: boolean): void {
|
||||
public checkDeleteability(useTheInternet: boolean): void {
|
||||
console.log("Checking deleteability (internet?", useTheInternet, ")")
|
||||
const t = Translations.t.delete
|
||||
const id = this._id
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
import Invalid from "../../../assets/svg/Invalid.svelte"
|
||||
import { And } from "../../../Logic/Tags/And"
|
||||
import type { UploadableTag } from "../../../Logic/Tags/TagTypes"
|
||||
import { IsOnline } from "../../../Logic/Web/IsOnline"
|
||||
|
||||
export let state: SpecialVisualizationState
|
||||
export let deleteConfig: DeleteConfig
|
||||
|
@ -39,9 +40,10 @@
|
|||
const canBeDeletedReason = deleteAbility.canBeDeletedReason
|
||||
|
||||
const hasSoftDeletion = deleteConfig.softDeletionTags !== undefined
|
||||
const online = IsOnline.isOnline
|
||||
let currentState: "confirm" | "applying" | "deleted" = "confirm"
|
||||
$: {
|
||||
deleteAbility.CheckDeleteability(true)
|
||||
deleteAbility.checkDeleteability(true)
|
||||
}
|
||||
|
||||
const t = Translations.t.delete
|
||||
|
@ -97,8 +99,10 @@
|
|||
currentState = "deleted"
|
||||
}
|
||||
</script>
|
||||
|
||||
<LoginToggle ignoreLoading={true} {state} silentFail>
|
||||
{#if !$online}
|
||||
<div class="subtle">You are offline. Deleting points is not possible</div>
|
||||
{:else}
|
||||
<LoginToggle ignoreLoading={true} {state} hiddenFail>
|
||||
{#if $canBeDeleted === false && !hasSoftDeletion}
|
||||
<div class="low-interaction subtle flex gap-x-1 rounded p-2 text-sm italic">
|
||||
<div class="relative h-fit">
|
||||
|
@ -171,3 +175,4 @@
|
|||
</AccordionSingle>
|
||||
{/if}
|
||||
</LoginToggle>
|
||||
{/if}
|
||||
|
|
|
@ -7,41 +7,45 @@
|
|||
import LoginToggle from "../Base/LoginToggle.svelte"
|
||||
import type { Feature } from "geojson"
|
||||
import LayerConfig from "../../Models/ThemeConfig/LayerConfig"
|
||||
import { IsOnline } from "../../Logic/Web/IsOnline"
|
||||
import { Store } from "../../Logic/UIEventSource.js"
|
||||
|
||||
/**
|
||||
* A full-blown 'mark as favourite'-button
|
||||
*/
|
||||
export let state: SpecialVisualizationState
|
||||
export let feature: Feature
|
||||
export let tags: Record<string, string>
|
||||
export let tags: Store<Record<string, string>>
|
||||
export let layer: LayerConfig
|
||||
let isFavourite = tags?.map((tags) => tags._favourite === "yes")
|
||||
const t = Translations.t.favouritePoi
|
||||
const online = IsOnline.isOnline
|
||||
|
||||
function markFavourite(isFavourite: boolean) {
|
||||
state.favourites.markAsFavourite(feature, layer.id, state.theme.id, tags, isFavourite)
|
||||
}
|
||||
</script>
|
||||
|
||||
<LoginToggle ignoreLoading={true} {state}>
|
||||
{#if $isFavourite}
|
||||
<div class="flex h-fit items-start">
|
||||
<button class="w-full" on:click={() => markFavourite(false)}>
|
||||
<HeartSolidIcon class="mr-2 w-16 shrink-0" on:click={() => markFavourite(false)} />
|
||||
<div class="flex flex-col items-start">
|
||||
<Tr t={t.button.unmark} />
|
||||
<Tr cls="normal-font subtle" t={t.button.unmarkNotDeleted} />
|
||||
{#if $online}
|
||||
<LoginToggle ignoreLoading hiddenFail {state}>
|
||||
{#if $isFavourite}
|
||||
<div class="flex h-fit items-start">
|
||||
<button class="w-full" on:click={() => markFavourite(false)}>
|
||||
<HeartSolidIcon class="mr-2 w-16 shrink-0" on:click={() => markFavourite(false)} />
|
||||
<div class="flex flex-col items-start">
|
||||
<Tr t={t.button.unmark} />
|
||||
<Tr cls="normal-font subtle" t={t.button.unmarkNotDeleted} />
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<Tr cls="font-bold thanks m-2 p-2 block" t={t.button.isFavourite} />
|
||||
{:else}
|
||||
<button class="w-full" on:click={() => markFavourite(true)}>
|
||||
<HeartOutlineIcon class="mr-2 w-16 shrink-0" on:click={() => markFavourite(true)} />
|
||||
<div class="flex w-full flex-col items-start">
|
||||
<Tr t={t.button.markAsFavouriteTitle} />
|
||||
<Tr cls="normal-font subtle" t={t.button.markDescription} />
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<Tr cls="font-bold thanks m-2 p-2 block" t={t.button.isFavourite} />
|
||||
{:else}
|
||||
<button class="w-full" on:click={() => markFavourite(true)}>
|
||||
<HeartOutlineIcon class="mr-2 w-16 shrink-0" on:click={() => markFavourite(true)} />
|
||||
<div class="flex w-full flex-col items-start">
|
||||
<Tr t={t.button.markAsFavouriteTitle} />
|
||||
<Tr cls="normal-font subtle" t={t.button.markDescription} />
|
||||
</div>
|
||||
</button>
|
||||
{/if}
|
||||
</LoginToggle>
|
||||
{/if}
|
||||
</LoginToggle>
|
||||
{/if}
|
||||
|
|
|
@ -71,6 +71,16 @@
|
|||
window.requestIdleCallback(() => {
|
||||
InstallServiceWorker.precache(layer["_usedImages"]?.filter(i => i.startsWith("./")))
|
||||
})
|
||||
|
||||
// The NSI
|
||||
window.requestIdleCallback(() => {
|
||||
InstallServiceWorker.precache(
|
||||
[Constants.nsiLogosEndpoint + "nsi.min.json",
|
||||
Constants.nsiLogosEndpoint + "featureCollection.min.json",
|
||||
],
|
||||
)
|
||||
})
|
||||
|
||||
}
|
||||
}).catch(e => console.error("Could not install service worker:", e))
|
||||
</script>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue