forked from MapComplete/MapComplete
Feature: improve offline data management
This commit is contained in:
parent
6f44fe31d0
commit
77ef3a3572
1 changed files with 104 additions and 74 deletions
|
|
@ -18,8 +18,9 @@
|
||||||
import ShowDataLayer from "../Map/ShowDataLayer"
|
import ShowDataLayer from "../Map/ShowDataLayer"
|
||||||
import StaticFeatureSource from "../../Logic/FeatureSource/Sources/StaticFeatureSource"
|
import StaticFeatureSource from "../../Logic/FeatureSource/Sources/StaticFeatureSource"
|
||||||
import LayerConfig from "../../Models/ThemeConfig/LayerConfig"
|
import LayerConfig from "../../Models/ThemeConfig/LayerConfig"
|
||||||
import AccordionSingle from "../Flowbite/AccordionSingle.svelte"
|
|
||||||
import { DownloadIcon, TrashIcon } from "@rgossiaux/svelte-heroicons/solid"
|
import { DownloadIcon, TrashIcon } from "@rgossiaux/svelte-heroicons/solid"
|
||||||
|
import { Accordion, AccordionItem } from "flowbite-svelte"
|
||||||
|
import ServiceWorkerStatus from "./ServiceWorkerStatus.svelte"
|
||||||
|
|
||||||
|
|
||||||
export let state: ThemeViewState & SpecialVisualizationState = undefined
|
export let state: ThemeViewState & SpecialVisualizationState = undefined
|
||||||
|
|
@ -35,7 +36,7 @@
|
||||||
|
|
||||||
|
|
||||||
const offlineMapManager = new OfflineBasemapManager("https://cache.mapcomplete.org/")
|
const offlineMapManager = new OfflineBasemapManager("https://cache.mapcomplete.org/")
|
||||||
let installedMeta: UIEventSource<AreaDescription[]> = new UIEventSource()
|
let installedMeta: UIEventSource<AreaDescription[]> = new UIEventSource([])
|
||||||
|
|
||||||
|
|
||||||
function updateMeta() {
|
function updateMeta() {
|
||||||
|
|
@ -43,15 +44,7 @@
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function pingServiceWorker() {
|
|
||||||
const l = window.location
|
|
||||||
const sw = await Utils.downloadJson(l.protocol + "//" + l.host + "/service-worker/offline-basemapM/update")
|
|
||||||
console.log("Service worker has data:", sw)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
updateMeta()
|
updateMeta()
|
||||||
pingServiceWorker()
|
|
||||||
|
|
||||||
let installing = new UIEventSource<string[]>([])
|
let installing = new UIEventSource<string[]>([])
|
||||||
|
|
||||||
|
|
@ -62,7 +55,6 @@
|
||||||
const descr = OfflineBasemapManager.getAreaDescriptionForMapcomplete(key + ".pmtiles")
|
const descr = OfflineBasemapManager.getAreaDescriptionForMapcomplete(key + ".pmtiles")
|
||||||
await offlineMapManager.installArea(descr)
|
await offlineMapManager.installArea(descr)
|
||||||
updateMeta()
|
updateMeta()
|
||||||
pingServiceWorker()
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
installing.set(installing.data.filter(k => k !== key))
|
installing.set(installing.data.filter(k => k !== key))
|
||||||
} finally {
|
} finally {
|
||||||
|
|
@ -71,13 +63,14 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let installed: Store<Feature<Polygon>> = installedMeta.map(meta =>
|
let installed: Store<Feature<Polygon>[]> = installedMeta.map(meta =>
|
||||||
(meta ?? [])
|
(meta ?? [])
|
||||||
.map(area => {
|
.map(area => {
|
||||||
const f = Tiles.asGeojson(area.minzoom, area.x, area.y)
|
const f = Tiles.asGeojson(area.minzoom, area.x, area.y)
|
||||||
f.properties = {
|
f.properties = {
|
||||||
id: area.minzoom + "-" + area.x + "-" + area.y,
|
id: area.minzoom + "-" + area.x + "-" + area.y,
|
||||||
downloaded: "yes"
|
downloaded: "yes",
|
||||||
|
text: area.name + " " + area.dataVersion + " " + Utils.toHumanByteSize(Number(area.size))
|
||||||
}
|
}
|
||||||
return f
|
return f
|
||||||
}
|
}
|
||||||
|
|
@ -104,7 +97,7 @@
|
||||||
|
|
||||||
async function download() {
|
async function download() {
|
||||||
const areasToInstall = Array.from(offlineMapManager.getInstallCandidates(focusTile.data))
|
const areasToInstall = Array.from(offlineMapManager.getInstallCandidates(focusTile.data))
|
||||||
for (const area: AreaDescription of areasToInstall) {
|
for (const area of areasToInstall) {
|
||||||
console.log("Attempting to install", area)
|
console.log("Attempting to install", area)
|
||||||
await install(area)
|
await install(area)
|
||||||
}
|
}
|
||||||
|
|
@ -135,7 +128,14 @@
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}],
|
}],
|
||||||
pointRendering: null
|
pointRendering: [
|
||||||
|
{
|
||||||
|
location: ["point", "centroid"],
|
||||||
|
label: "{text}",
|
||||||
|
labelCss: "width: w-min",
|
||||||
|
labelCssClasses: "bg-white rounded px-2"
|
||||||
|
}
|
||||||
|
]
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -173,11 +173,17 @@
|
||||||
{#if $installedMeta === undefined}
|
{#if $installedMeta === undefined}
|
||||||
<Loading />
|
<Loading />
|
||||||
{:else}
|
{:else}
|
||||||
<div class="relative w-full h-3/4">
|
<div class="h-full overflow-auto pb-16">
|
||||||
|
|
||||||
|
<Accordion class="" inactiveClass="text-black">
|
||||||
|
<AccordionItem paddingDefault="p-2">
|
||||||
|
<div slot="header">Map</div>
|
||||||
|
<div class="relative leave-room">
|
||||||
<div class="rounded-lg absolute top-0 left-0 h-full w-full">
|
<div class="rounded-lg absolute top-0 left-0 h-full w-full">
|
||||||
<MaplibreMap {map} {mapProperties} />
|
<MaplibreMap {map} {mapProperties} />
|
||||||
</div>
|
</div>
|
||||||
<div class="absolute top-0 left-0 h-full w-full flex flex-col justify-center items-center pointer-events-none">
|
<div
|
||||||
|
class="absolute top-0 left-0 h-full w-full flex flex-col justify-center items-center pointer-events-none">
|
||||||
<div class="w-16 h-32 mb-16"></div>
|
<div class="w-16 h-32 mb-16"></div>
|
||||||
{#if $focusTileIsInstalling}
|
{#if $focusTileIsInstalling}
|
||||||
<div class="normal-background rounded-lg">
|
<div class="normal-background rounded-lg">
|
||||||
|
|
@ -194,12 +200,16 @@
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</AccordionItem>
|
||||||
|
|
||||||
<AccordionSingle>
|
<AccordionItem paddingDefault="p-2">
|
||||||
<div slot="header">
|
<div slot="header">
|
||||||
Offline tile management
|
Offline tile management
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="leave-room">
|
||||||
|
|
||||||
|
|
||||||
{Utils.toHumanByteSize(Utils.sum($installedMeta.map(area => area.size)))}
|
{Utils.toHumanByteSize(Utils.sum($installedMeta.map(area => area.size)))}
|
||||||
<button on:click={() => {
|
<button on:click={() => {
|
||||||
installedMeta?.data?.forEach(area => del(area))
|
installedMeta?.data?.forEach(area => del(area))
|
||||||
|
|
@ -207,7 +217,7 @@
|
||||||
<TrashIcon class="w-6" />
|
<TrashIcon class="w-6" />
|
||||||
Delete all
|
Delete all
|
||||||
</button>
|
</button>
|
||||||
<table class="w-full">
|
<table class="w-full ">
|
||||||
<tr>
|
<tr>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
<th>Map generation date</th>
|
<th>Map generation date</th>
|
||||||
|
|
@ -237,7 +247,27 @@
|
||||||
{/each}
|
{/each}
|
||||||
|
|
||||||
</table>
|
</table>
|
||||||
</AccordionSingle>
|
</div>
|
||||||
|
|
||||||
|
</AccordionItem>
|
||||||
|
<AccordionItem paddingDefault="p-2">
|
||||||
|
<div slot="header">
|
||||||
|
Service worker status
|
||||||
|
</div>
|
||||||
|
<div class="leave-room">
|
||||||
|
<ServiceWorkerStatus />
|
||||||
|
</div>
|
||||||
|
</AccordionItem>
|
||||||
|
</Accordion>
|
||||||
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.leave-room {
|
||||||
|
height: calc(100vh - 18rem);
|
||||||
|
overflow-x: auto;
|
||||||
|
width: 100%;
|
||||||
|
color: var(--foreground-color);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue