Add a country-based region picker for offline data
CI / check (push) Successful in 17s
CI / deploy (push) Successful in 12s

Replaces "regenerate for the current viewport" with what Locus/OsmAnd-
style apps give you: tick which countries you want offline (a Natural
Earth-derived checklist, public domain, vendored), Apply rebuilds
offline.pmtiles/terrain.pmtiles to cover the whole selection at once.
Multiple regions can be offline simultaneously (e.g. Slovakia + Austria
for a trip that crosses the border) — the selection itself is the
source of truth (data/offline_regions.json), not a set of per-country
files, so "remove a country" and "refresh a country" are both just
"change the selection, then Apply."

Confirmed against go-pmtiles' own source (not just its docs) before
committing to this shape: `extract --region=<geojson>` treats a
FeatureCollection's features as their union already (no dissolve/union
math needed on our side — pmtiles/region.go's UnmarshalRegion just
concatenates every feature's rings), and `merge` hard-errors on any
overlapping tile id between inputs (merge.go's prepareInputs). That
second fact rules out "extract each country separately, merge them
all" — adjacent countries' region-extracts would share border tiles,
since extraction copies whole tiles rather than clipping vector
content to the polygon. The actual fix: extract per *source archive*
(the Protomaps build, each intersecting Mapterhorn chunk), each call
covering the whole current selection via one --region= file — the
terrain pipeline already extracted-then-merged per source this way, it
just needed a multi-country region instead of a single bbox.
This commit is contained in:
randy committed 2026-09-11 12:55:56 +02:00
1 parent f89dea5805
commit 53c9a82af2
10 files changed
+442 -170

No files matched your search

+38 -12
View File
@@ -401,39 +401,65 @@ html, body {
padding: 8px 12px;
}
.offline-data-panel__row + .offline-data-panel__row {
margin-top: 10px;
padding-top: 10px;
border-top: 1px solid #eee;
.offline-data-panel__regions-label {
margin: 0 0 4px;
font-weight: 600;
}
.offline-data-panel__row-header {
.offline-data-panel__region-list {
list-style: none;
margin: 0;
padding: 0;
max-height: 220px;
overflow-y: auto;
border: 1px solid #eee;
border-radius: 4px;
}
.offline-data-panel__region-list label {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
gap: 6px;
padding: 4px 8px;
cursor: pointer;
}
.offline-data-panel__build {
flex-shrink: 0;
.offline-data-panel__region-list label:hover {
background: #f0f0f0;
}
.offline-data-panel__region-status {
padding: 6px 8px;
color: #888;
}
.offline-data-panel__apply {
margin-top: 8px;
width: 100%;
border: 1px solid #ccc;
border-radius: 4px;
background: #fff;
padding: 4px 8px;
padding: 6px 8px;
font: inherit;
font-size: 12px;
cursor: pointer;
}
.offline-data-panel__build:hover {
.offline-data-panel__apply:hover {
background: #f0f0f0;
}
.offline-data-panel__build:disabled {
.offline-data-panel__apply:disabled {
opacity: 0.5;
cursor: default;
}
.offline-data-panel__row {
margin-top: 14px;
padding-top: 10px;
border-top: 1px solid #eee;
}
.offline-data-panel__status {
margin: 6px 0 0;
color: #666;