From 2a0c9b49ce4ea7498a85917db6f9dc951e8a0dce Mon Sep 17 00:00:00 2001 From: Ole-Morten Duesund Date: Mon, 17 Aug 2026 12:50:56 +0200 Subject: [PATCH] =?UTF-8?q?PWA:=20absolutte=20stier=20s=C3=A5=20dyplenker?= =?UTF-8?q?=20virker=20ved=20kald=20f=C3=B8rstelast?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit shelter-repository.ts hentet './data/shelters.json' relativt. Under /shelter/{romnr} løses det til /shelter/data/shelters.json; SPA-fallback svarer med index.html (200 text/html), response.json() kaster, refreshData() returnerer false og loadData() avbryter før handleDeepLink() — førstegangsbesøkende via delt lenke fikk «Fant ikke tilfluktsrommet» og tom liste. Samme rotårsak i index.html (manifest.webmanifest, icons/icon-192.png) og i manifestet (start_url/scope ".", icons "icons/…"): under en dyplenke-rute ble manifestet index.html og «legg til på startskjerm» uteble. - shelter-repository.ts: `${import.meta.env.BASE_URL}data/shelters.json` - index.html: /manifest.webmanifest, /icons/icon-192.png - manifest.webmanifest: start_url "/", scope "/", icons "/icons/…" Verifisert i ny Playwright-kontekst (tom IndexedDB): /shelter/1681 laster /data/shelters.json (200 application/json), lista fylles og rommet velges. Forgejo: #19 Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01FrDGDmN2WAXvNPS85rWJGK --- .beads/issues.jsonl | 1 + pwa/index.html | 6 +++--- pwa/public/manifest.webmanifest | 8 ++++---- pwa/src/data/shelter-repository.ts | 8 +++++++- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/.beads/issues.jsonl b/.beads/issues.jsonl index f04a57a..a2dba64 100644 --- a/.beads/issues.jsonl +++ b/.beads/issues.jsonl @@ -1,3 +1,4 @@ +{"id":"tilfluktsrom-vu2","title":"PWA: dyplenke feiler ved kald førstelast — relativ shelters.json-sti","description":"Mirror av Forgejo-issue #19.\n\nshelter-repository.ts bruker relativ sti './data/shelters.json'. Under /shelter/{romnr} løses den til /shelter/data/shelters.json → SPA-fallback gir index.html → JSON-parse feiler → loadData() avbryter → 'Fant ikke tilfluktsrommet'. Dyplenker virker dermed kun for brukere som allerede har data i IndexedDB.\n\nFiks: absolutt sti via import.meta.env.BASE_URL + 'data/shelters.json'.\n\nForgejo: https://kode.naiv.no/olemd/tilfluktsrom/issues/19","acceptance_criteria":"Kald førstelast (tom IndexedDB, ingen SW) av /shelter/1681 i nettleser laster shelters.json, viser lista og velger rommet. Verifisert i Playwright med ny browser-kontekst.","status":"closed","priority":2,"issue_type":"bug","assignee":"Ole-Morten Duesund","owner":"olemd@glemt.net","created_at":"2026-08-17T10:49:11Z","created_by":"Ole-Morten Duesund","updated_at":"2026-08-17T10:50:55Z","started_at":"2026-08-17T10:49:22Z","closed_at":"2026-08-17T10:50:55Z","close_reason":"Fikset: SHELTERS_JSON_PATH bruker import.meta.env.BASE_URL; manifest/ikon-lenker i index.html og start_url/scope/icons i manifest.webmanifest gjort absolutte. Verifisert kald førstelast av /shelter/1681 i ny Playwright-kontekst.","dependency_count":0,"dependent_count":0,"comment_count":0} {"id":"tilfluktsrom-7zc","title":"Badge-kontrast under WCAG 2.2 AA — bytt shelter_primary til warning_bg","description":"Mirror av Forgejo-issue #18.\n\nBadge introdusert i 1fb9f14 (#13) bruker hvit fet 11sp tekst på shelter_primary (#FF6B35). Målt kontrast: ~2.84:1.\n\nWCAG 2.2 AA SC 1.4.3:\n- Normaltekst: ≥4.5:1\n- Large text (≥14pt fet eller ≥18pt regular): ≥3.0:1\n\n11sp fet teller som normaltekst → feiler AA-terskelen, og marginalt også 3:1 for large text.\n\nFiks: én linje i app/src/main/res/layout/item_shelter.xml — bytt @color/shelter_primary til @color/warning_bg (#BF360C, dokumentert ~5.5:1 vs hvit i colors.xml-kommentar).\n\nAlternativer som ikke fungerer:\n- shelter_primary_dark (#E55A2B) ~3.6:1 — fortsatt under AA normaltekst\n- Svart tekst på orange — ~7:1, men bryter visuell konsistens\n\nRelevant for offentlig-sektor-godkjenning (Uutilsynet/WAD/EN 301 549).\n\nForgejo: https://kode.naiv.no/olemd/tilfluktsrom/issues/18","acceptance_criteria":"Badge-bakgrunnen på item_shelter.xml outsideNearestBadge er endret til warning_bg. Visuelt verifisert at hvit fet 11sp tekst på den nye bakgrunnen gir ≥4.5:1 målt kontrast (med en kontrast-sjekker eller WCAG-verktøy).","status":"closed","priority":2,"issue_type":"bug","assignee":"Ole-Morten Duesund","owner":"olemd@glemt.net","created_at":"2026-04-29T14:54:00Z","created_by":"Ole-Morten Duesund","updated_at":"2026-04-29T14:55:09Z","started_at":"2026-04-29T14:54:56Z","closed_at":"2026-04-29T14:55:09Z","close_reason":"Bytta @color/shelter_primary til @color/warning_bg på outsideNearestBadge i item_shelter.xml. Kontrast: ~2.84:1 → ~5.6:1 (over WCAG 2.2 AA SC 1.4.3 4.5:1-terskel). Visuell verifisering på enhet/emulator gjenstår.","dependency_count":0,"dependent_count":0,"comment_count":0} {"id":"tilfluktsrom-efo","title":"PWA: dyplenket tilfluktsrom utenfor topp-N vises som om det er nærmest","description":"Mirror av Forgejo-issue #17.\n\nParallell til Android-fiksen i 1fb9f14 (#13).\n\nNåværende oppførsel: når dyplenken peker på et tilfluktsrom utenfor de N nærmeste, gjør pwa/src/app.ts:266-285 unshift() inn på indeks 0 og setter selectedShelterIndex=0. Resultat: det dyplenkede vises *som om* det er det nærmeste — uten badge, uten separator, uten forklaring. Lista bryter sin egen sort-på-avstand-invariant.\n\nHybrid-fiks (parallell til Android):\n1. Append (push) i stedet for unshift på app.ts:274\n2. Badge i shelter-list.ts på den appendede raden — bruk samme nøkkel shelter_outside_nearest_badge i pwa/src/i18n/{en,nb,nn}.ts\n3. updateList() får outsideNearestRomnr-parameter (eller wrap-objekt parallelt med Android sin ShelterListItem)\n4. Badge-teksten suffikses i aria-label (skjermleser-paritet med Android)\n5. selectedItem.scrollIntoView({block:'nearest', behavior:'smooth'}) etter updateList\n6. Tilgjengelighet: badge ≥4.5:1 kontrast (WCAG 2.2 AA SC 1.4.3). #FF6B35+hvit tekst er ~3.5:1 — *under terskel*. Bruk shelter_primary_dark #E55A2B som badge-bakgrunn, eller svart tekst på orange (~7:1)\n\nUt av skopet: endring av selve dyplenke-formatet (fortsatt /shelter/{romnr}), klyngevisning (#10).\n\nForgejo: https://kode.naiv.no/olemd/tilfluktsrom/issues/17","acceptance_criteria":"Dyplenket tilfluktsrom utenfor topp-N appendes på siste rad i lista (ikke unshift). Den appendede raden har et synlig 'Valgt – utenfor nærområdet'-badge med ≥4.5:1 kontrast. Lista scroller automatisk til valgt rad. Skjermleser leser badge-teksten som del av aria-label. Verifisert manuelt med en deep-link til et tilfluktsrom langt fra brukerens posisjon.","status":"closed","priority":2,"issue_type":"bug","assignee":"Ole-Morten Duesund","owner":"olemd@glemt.net","created_at":"2026-04-29T14:52:08Z","created_by":"Ole-Morten Duesund","updated_at":"2026-08-17T10:48:32Z","started_at":"2026-08-17T10:42:26Z","closed_at":"2026-08-17T10:48:32Z","close_reason":"Fikset: push i stedet for unshift, badge (#BF360C, ~5.6:1) + aria-prefiks + scrollIntoView i shelter-list.ts. Verifisert i Chromium via Playwright med dyplenke /shelter/1681 fra Oslo-posisjon.","dependency_count":0,"dependent_count":0,"comment_count":0} {"id":"tilfluktsrom-5vc","title":"Brukerens retningspil i kartet er hvit og forsvinner på lyse underlag","description":"Mirror av Forgejo-issue #16.\n\nNår brukeren beveger seg raskt nok til at OSMDroid bytter fra person- til retningspil-ikonet i MyLocationNewOverlay, blir pilen tilnærmet usynlig: heltrukken hvit uten kontur eller skygge. På lyse tiles (snø, sand, brede veifyll, lyse OSM-temaer) forsvinner den helt.\n\nÅrsak: MainActivity.kt:190 instansierer MyLocationNewOverlay uten å overstyre setDirectionIcon()/setPersonIcon() — OSMDroid bruker da stock hvite bitmaps.\n\nForslag:\n- Egen vector i res/drawable/ic_user_direction.xml med kontrastfarget fyll + motsatt-farge kontur\n- Kall myLocationOverlay.setDirectionIcon(...) + setPersonIcon(...) eksplisitt\n- Vurder halo-ring (blå pil i hvit ring, Google Maps-stil) for variert underlag\n- Sjekk PWA-en (Leaflet) for samme problem\n\nTilgjengelighet:\n- ≥3:1 kontrast mot både lyse og mørke tiles (WCAG 2.2 AA, ikke-tekstlig innhold)\n- Ikke avhengig av farge alene; konturen sikrer at formen faktisk synes\n\nForgejo: https://kode.naiv.no/olemd/tilfluktsrom/issues/16","acceptance_criteria":"Pilen og person-ikonet i MyLocationNewOverlay er tydelig synlig mot både lyse og mørke kartunderlag (≥3:1 kontrast). Verifisert manuelt på minst ett lyst og ett mørkt kartområde, både stillestående (person) og i bevegelse (pil).","status":"closed","priority":2,"issue_type":"bug","assignee":"Ole-Morten Duesund","owner":"olemd@glemt.net","created_at":"2026-04-29T14:06:57Z","created_by":"Ole-Morten Duesund","updated_at":"2026-04-29T14:15:13Z","started_at":"2026-04-29T14:09:43Z","closed_at":"2026-04-29T14:15:13Z","close_reason":"Fikset i d2291a2 — egne ikoner i res/drawable/ic_user_dot.xml og ic_user_arrow.xml, satt på MyLocationNewOverlay med setPersonIcon/setDirectionIcon + (0.5, 0.5)-anker. Visuell verifisering på enhet/emulator gjenstår.","dependency_count":0,"dependent_count":0,"comment_count":0} diff --git a/pwa/index.html b/pwa/index.html index 1a66208..7657b22 100644 --- a/pwa/index.html +++ b/pwa/index.html @@ -15,9 +15,9 @@ Tilfluktsrom - - - + + +
diff --git a/pwa/public/manifest.webmanifest b/pwa/public/manifest.webmanifest index 37b1419..b9aa4d2 100644 --- a/pwa/public/manifest.webmanifest +++ b/pwa/public/manifest.webmanifest @@ -2,21 +2,21 @@ "name": "Tilfluktsrom", "short_name": "Tilfluktsrom", "description": "Find the nearest public shelter in Norway", - "start_url": ".", - "scope": ".", + "start_url": "/", + "scope": "/", "display": "standalone", "orientation": "portrait", "theme_color": "#1A1A2E", "background_color": "#1A1A2E", "icons": [ { - "src": "icons/icon-192.png", + "src": "/icons/icon-192.png", "sizes": "192x192", "type": "image/png", "purpose": "any maskable" }, { - "src": "icons/icon-512.png", + "src": "/icons/icon-512.png", "sizes": "512x512", "type": "image/png", "purpose": "any maskable" diff --git a/pwa/src/data/shelter-repository.ts b/pwa/src/data/shelter-repository.ts index 1dcc676..5ca190a 100644 --- a/pwa/src/data/shelter-repository.ts +++ b/pwa/src/data/shelter-repository.ts @@ -14,7 +14,13 @@ import { isDataStale, } from './shelter-db'; -const SHELTERS_JSON_PATH = './data/shelters.json'; +// Absolute path anchored at Vite's base URL — NOT a relative './data/...'. +// The app is also entered via /shelter/{romnr} deep links, and a relative +// path would resolve to /shelter/data/shelters.json there; the SPA fallback +// answers that with index.html and the JSON parse fails, so a first-time +// visitor following a shared link would see "shelter not found". Using +// BASE_URL keeps this correct even if the app is ever hosted under a prefix. +const SHELTERS_JSON_PATH = `${import.meta.env.BASE_URL}data/shelters.json`; /** Fetch shelters.json and cache in IndexedDB. Returns success. */ export async function refreshData(): Promise {