tighten the remaining voice outline review items

- One place-name key for server and tiles, so "St. Paul" and "Saint Paul"
  agree in Nominatim name checks.
- Tile street names: a lone letter is a direction only beside another name
  word ("E Street" is not "East Street"), and a trailing quadrant ("E St NW")
  may go unsaid in the ask.
- A building cut at the tile edge that is nearer the point than any whole
  one leaves the point instead of a farther neighbour standing in; an edge
  without a tile buffer counts as a cut, so a cut area never answers grounds.
- A batch building install re-judges only results that installed; a late
  timeout during caption conversion keeps the pending point drawn; a failed
  plain recaption keeps the old mark addressable.
- An interrupted Nominatim dispatch is reclaimed by the next lock owner ten
  minutes after the start its marker names; node:sqlite loads on first use
  without its experimental warning.
- PHOTON_URL accepts only https, which the page's connect-src allows.
- Shared OpenFreeMap tiles decode each layer when a consumer first selects
  it; outline selection reuses the shared ring area and simplification, and
  ground probes the shared ring centroid; the grounds word list lives once.
This commit is contained in:
Sameh Khamis committed 2026-11-02 08:50:05 -08:00
1 parent a38a065c5c
commit a61d0f4c2a
24 files changed
+422 -128

No files matched your search

+8 -2
View File
@@ -411,6 +411,8 @@ export function createAnnotationEngine({
const results = [];
const ids = [];
const installations = [];
// Result slots an installation settles; only these are re-validated after the await.
const installed = new Set();
const trackBuildingInstall = (
anno,
resolved,
@@ -423,6 +425,7 @@ export function createAnnotationEngine({
ensureTicking();
const index = results.length;
results.push(null);
installed.add(index);
const record = beginBuildingInstall(anno);
installations.push(
Promise.resolve(completion)
@@ -589,6 +592,7 @@ export function createAnnotationEngine({
}
const index = results.length;
results.push(null);
installed.add(index);
anno.pendingOutline = true;
installations.push(
Promise.resolve(completion)
@@ -642,11 +646,12 @@ export function createAnnotationEngine({
);
continue;
}
// Remove before delete: a failed cleanup stays addressable through the old slot.
removeRendered(dup);
annotations.delete(dup.id);
annotations.set(anno.id, anno);
syncAnnotationHold();
try {
removeRendered(dup);
renderer.add(anno);
} catch (swapError) {
// Same contract as the fresh path: a renderer/WebGL throw must
@@ -690,6 +695,7 @@ export function createAnnotationEngine({
if (record) {
const index = results.length;
results.push(null);
installed.add(index);
installations.push(
(async () => {
do {
@@ -788,7 +794,7 @@ export function createAnnotationEngine({
await Promise.all(installations);
for (let index = 0; index < results.length; index += 1) {
const result = results[index];
if (!result?.ok) continue;
if (!result?.ok || !installed.has(index)) continue;
const current = annotations.get(result.id);
if (
!current ||