Commit graph

36 commits

Author SHA1 Message Date
f0c4a1f5b4 Actionable banner når posisjon ikke er tilgjengelig
Tidligere sto statusteksten igjen på «Venter på GPS…» uansett om
årsaken var manglende tillatelse, avslåtte stedstjenester eller
bare at GPS-en ikke hadde fått fix ennå. For en nødsituasjonsapp
er det en reell feilmodus: brukeren får ingen hint om hva som kan
gjøres for å finne nærmeste tilfluktsrom.

Ny noLocationBanner plasseres øverst i innholdsområdet (rett under
statuslinjen) slik at den ikke kolliderer med de flytende
handlingsknappene over bunnarket, og viser én av tre tilstander:

1. Tillatelse avslått eller ikke gitt — «Posisjonstilgang
   nødvendig for å finne nærmeste tilfluktsrom. Du kan også
   trykke på et merke i kartet.» + «Gi tilgang» som åpner
   ACTION_APPLICATION_DETAILS_SETTINGS.
2. Tillatelse gitt, men stedstjenester slått av — «Stedstjenester
   er slått av. Aktiver dem eller velg et tilfluktsrom fra
   kartet.» + «Aktiver» som åpner ACTION_LOCATION_SOURCE_SETTINGS.
3. Begge OK — banner er skjult og den eksisterende «Venter på
   GPS…»-teksten gjelder.

Helperen updateLocationStatusBanner() kalles fra loadData(),
permission-result-kallbacket og onResume(), slik at banneret
oppdaterer seg både ved appstart, umiddelbart etter avslag, og
når brukeren kommer tilbake fra systeminnstillingene.
AlertDialog-en ved permanent avslag er fjernet til fordel for det
ikke-modale banneret, som lar brukeren fortsatt pan-ne kartet og
velge tilfluktsrom manuelt. Toasten på mykt avslag er beholdt som
en kort bekreftelse. API-nivå-fallbacket bruker
LocationManager.isLocationEnabled på API 28+, isProviderEnabled
for GPS/Network på API 26–27.

Verifisert på emulator i alle fire tilstander (avslag → App
Settings, tjeneste-av → Posisjonsinnstillinger, gjenopprettet).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 10:32:02 +02:00
0743eac9dd Fjern hjemmeskjerm-widget
Widgeten har vært en vedlikeholdskostnad uten et klart produktformål:
den duplikerte lokasjonslogikken fra hovedappen, kunne vise inntil
24 timer gammel GPS-posisjon uten alderindikator, og krevde en egen
WorkManager-periodisk oppdatering. Den strategiske vurderingen
(2026-04-17) konkluderte med at den samme nytten kan leveres via
app-åpning eller en lettere mekanisme senere, og at flaten bør
krympes før pitch mot offentlig sektor.

Denne endringen fjerner widget/-pakken for begge flavors
(standard + fdroid), AppWidgetProvider-mottakeren i manifestet,
WidgetUpdateWorker, androidx.work:work-runtime-ktx-avhengigheten,
widget_prefs SharedPreferences-lagringen i MainActivity, samt
widget_*-strenger og linjen om «for hjemmeskjerm-widgeten» i
about-dialogen. Dokumentasjonen i CLAUDE.md, ARCHITECTURE.md,
README.md, STANDING_ON_SHOULDERS.md og fastlane-beskrivelsene
er justert tilsvarende. Historiske changelogs (v3, v5, v6, v7)
er bevisst urørt — de beskriver korrekt hva som ble levert i
de versjonene.

Eksisterende widget-plasseringer på brukernes hjemmeskjerm
forsvinner automatisk neste gang appen oppdateres; Android
fjerner foreldreløse provider-komponenter uten migreringskode.
Begge debug-flavors bygger rent etter endringen.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 09:57:45 +02:00
4e6c03c301 Bump versjon til v1.9.1 (versionCode 14)
Patch-utgave som inneholder rettelsen av N-indikatoren i
kompassvisningen. User-Agent og «Dato for siste gjennomgang» i
ACCESSIBILITY.md oppdatert i samsvar.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 19:13:56 +02:00
1303a74d25 Fiks klipping av N-indikator i kompassvisning
Nordindikatoren («N»-merket) ble plassert på en sirkel med radius
min(w,h) * 0,54 fra senter. I stående kompassvisning er dette
bredere enn viewporten, så indikatoren havnet utenfor skjermen når
brukeren vendte omtrent 90° eller 270°.

Ny hjelpefunksjon clampIndicatorRadius finner avstanden fra
sentrum til nærmeste viewport-kant i nordretningen, og klamper
radiusen slik at hele «N»-etiketten holder seg innenfor rammen
uansett rotasjonsvinkel. Seks nye unittester dekker
grensetilfeller, inkludert en sweep over alle 360° som fanget opp
en float-presisjonsartefakt ved 240°.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 19:13:27 +02:00
0efb599b8c Bump versjon til v1.9.0 (versionCode 13)
Publiserer a11y-utbedringene fra forrige commit. User-Agent i
ShelterRepository er oppdatert til å matche versjonen.

I ACCESSIBILITY.md er de fire utbedrede WCAG-avvikene flyttet
fra §3.1 til et nytt §7 Historikk under versjon 1.9.0. §3.1
slår nå fast at ingen gjenværende avvik er identifisert utover
§3.2 (uforholdsmessig byrde på Leaflet-kartet). Uutilsynet/Digdir
er bekreftet som riktig tilsynsmyndighet.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 19:05:46 +02:00
e4f44ede97 Utbedre WCAG 2.2 AA-avvik og legg til tilgjengelighetserklæring
Fire WCAG-avvik utbedret før appen kan lisensieres til offentlig
sektor (WAD / EN 301 549):

- SC 1.4.3: Advarselsbanner til #BF360C (~5,5:1 mot hvit, var 3,75:1).
- SC 2.4.7: defaultFocusHighlightEnabled i temaet; ikonknapper
  bruker bundet selectableItemBackground.
- SC 4.1.2: DirectionArrowView rapporterer ImageView-rolle og
  annonserer retning + avstand til TalkBack når en 45°-sektor
  krysses, med 750 ms-struping mot spam.
- SC 2.3.3: Snapper til nærmeste 45° når brukeren har slått av
  animasjoner (ANIMATOR_DURATION_SCALE=0).

Nye retningsstrenger i nb/nn/en. JVM-unittester for
sektoraritmetikken sikrer grensetilfeller (negative vinkler,
360°-overgang, vilkårlige vinkler).

ACCESSIBILITY.md dokumenterer tilgjengelighetserklæring etter
WAD artikkel 7, i bokmål med engelsk preambel og
vedlikeholdsjekkliste.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 19:02:55 +02:00
029cfa45f9 Bump versjon til v1.8.0 (versionCode 12)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 16:39:16 +01:00
015bc0d926 Bytt djuplenkjer frå tilfluktsrom:// til HTTPS App Links
SMS-appar gjenkjenner ikkje eigendefinerte URI-skjema som klikkbare
lenkjer. Brukar no https://tilfluktsrom.naiv.no/shelter/{id} som
opnar appen direkte (Android App Links med autoVerify) eller fell
tilbake til PWA i nettlesaren.

Android: DEEP_LINK_DOMAIN i build.gradle.kts, HTTPS intent-filter,
oppdatert handleDeepLinkIntent og shareShelter med HTTPS-URL.

PWA: assetlinks.json for Android-verifisering, djuplenkjehandtering
i app.ts, base-sti endra frå './' til '/', config.ts for domene.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 16:37:13 +01:00
97225d1e77 Bump versjon til v1.7.0 (versionCode 11)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 15:03:19 +01:00
b34408bc7b Rett datakjelde: tilfluktsromdata kjem frå DSB, ikkje Geonorge
Geonorge er distribusjonsplattforma, men dataeigar er DSB
(Direktoratet for samfunnstryggleik og beredskap). Oppdatert
om-side og personverntekst i alle tre språk (en/nb/nn) for
både Android og PWA.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 14:31:47 +01:00
c1ac68e746 Legg til om-side, personvernerklæring og sikkerheitsforbetring
Om-side (Android + PWA):
- Ny AboutDialog med personvernerklæring, datakjelder og opphavsrett
- Opphavsrett flytta frå sivilforsvardialogen til om-sida
- Tilgjengeleg via «Om denne appen»-lenke i sivilforsvarsdialogen (Android)
  og ny om-knapp i statuslinja (PWA)
- Lokalisert til en/nb/nn

Personvern og sikkerheit:
- Lagra GPS-posisjon utløper etter 24 timar (widget_prefs)
- Widget viser «Trykk for å oppdatere» når posisjon manglar eller er utløpt
- Eigendefinert User-Agent (Tilfluktsrom/1.6.1) i OkHttp
- Content Security Policy (CSP) meta-tag i PWA
- Tenararbeidar bufrar berre HTTP 200-svar (ikkje opake)
- Kartbuffer-metadata runda til ~11km presisjon i localStorage
- crossorigin="anonymous" på Leaflet CSS

i18n-opprydding:
- Unicode-escapes erstatta med UTF-8-teikn i nb.ts og nn.ts

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 14:27:45 +01:00
6ba35add2f Legg til TalkBack-støtte og nordindikator på kompasset
Tilgjengelegheit (Android + PWA):
- Semantiske landemerke (header, main, aside, role=dialog)
- aria-live-regionar for statusoppdateringar og lasteoverlegg
- Fokusindikatorar (:focus-visible) og prefers-reduced-motion
- Auka trykkmål til 48dp (infoknapp, oppdater, del, widget)
- contentDescription på kart, kompass og framdriftsindikator
- aria-current og role=listitem på tilfluktsromliste
- Fokusfangst og fokusgjenoppretting i lasteoverlegg
- Ikkje-farge-indikator (▶) for valt tilfluktsrom
- Dynamisk lang-attributt basert på oppdaga språk
- Lokaliserte aria-label (en/nb/nn)

Nordindikator:
- DirectionArrowView teiknar diskret «N»-markør på omkrinsen
- Roterer uavhengig av hovudpila for kompasskalibrering
- Berre på stor kompassvisning, ikkje minipila

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 14:02:32 +01:00
f5c064ab92 Bump versjon til v1.6.1 (versionCode 10)
- Fjern dependency metadata frå APK-signeringsblokka (dependenciesInfo)
  for F-Droid-kompatibilitet

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 13:15:14 +01:00
8e684f868e Flytt versjon direkte inn i build.gradle.kts for F-Droid-kompatibilitet
fdroidserver parser build.gradle.kts med regex for å finne versionCode
og versionName. Den dynamiske Properties-lastingen fra version.properties
ga "Couldn't find any version information". Erstatt med literale verdier
som fdroidserver kan lese.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 21:16:05 +01:00
6903fb7e70 Flytt signeringskonfigurasjon til gitignorert keystore.properties
Passord og keystoresti var hardkodet i build.gradle.kts og synlig i
det offentlige repoet. Flyttet til keystore.properties som er
gitignorert. Bygget hopper over signering om filen mangler, slik at
F-Droid kan bygge og signere med sin egen nøkkel.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 20:29:53 +01:00
ff4b3245f5 Legg til fdroid-byggvariant uten Google Play Services
Splitt LocationProvider, ShelterWidgetProvider og WidgetUpdateWorker i
to varianter: standard (med Play Services for bedre GPS) og fdroid
(kun AOSP LocationManager). Play Services-avhengigheten er nå begrenset
til standardImplementation.

Begge varianter bygger og har identisk funksjonalitet — fdroid-varianten
mangler bare FusedLocationProviderClient som en ekstra lokasjonskilde.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 20:25:47 +01:00
15c6797fcd Vis ventestatus i botnark når GPS ikkje er tilgjengeleg
Når tilfluktsromdata er lasta men GPS-posisjon manglar, viser
botnaka no «Ventar på GPS…» i staden for å vera tom. Posisjonsfiks
erstattar ventestatusen automatisk når han kjem.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 19:17:07 +01:00
3c1da8adec Legg til haptisk tilbakemelding på knappetrykk og listeval (#11)
Android: HapticFeedbackConstants.VIRTUAL_KEY på alle knappar og
listeelement. PWA: navigator.vibrate(10ms) på same interaksjonar.

Closes #11

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 10:01:58 +01:00
c35ccb91bf Mjuk opp tonen i sivilforsvarsdialog-tittelen
Endrar «når alarmen går» til «hvis/om alarmen går» for å unngå
å implisere at ein nødsituasjon faktisk skjer.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 09:57:58 +01:00
d4364379ab Legg til opphavsrettsmelding
Legg til copyright-notis i README og i sivilforsvarsdialogen i appen.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 09:54:06 +01:00
7ca06948f1 Gjer widget-tidsstempel tydelegare med «Oppdatert»-prefiks
Endrar widget-tidsstempel frå berre «14:32» til «Oppdatert 14:32»
slik at det er tydeleg at dette er siste oppdateringstidspunkt.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 09:53:43 +01:00
fa4c379176 Forbetr kontrast på statustekst for WCAG AA
Endrar status_text frå #B0BEC5 (~4.5:1) til #CFD8DC (~6.5:1) mot
#16213E-bakgrunnen, i både Android-appen og PWA-en.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 09:52:54 +01:00
a3728798b8 Legg til tilgjengelegheitsetiketter og skjermlesar-fiksar (Android)
- Legg til contentDescription på tilfluktsrom-listeelement for TalkBack
- Erstatt emoji-kompassåtvaring med tilgjengeleg tekstresurs
- Vis «Ventar på GPS…» i staden for «—» ved ukjend avstand
- Legg til content_desc_shelter_item og compass_accuracy_warning-strengar (en/nb/nn)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 09:52:39 +01:00
fca34f893b Legg til sivilforsvarsinformasjon med offisielle DSB-retningslinjer (v1.4.0)
Ny info-knapp (ℹ) i statuslinja opnar ein dialog med sivilforsvars-
instruksjonar: viktig melding-signal, flyalarm, søk dekning, lytt til
NRK P1 på DAB-radio, og faren over-signal. Alt innhald er verifisert
mot offisielle DSB-retningslinjer og fungerer utan nett. Støttar alle
tre språk (en, nb, nn).

Fixes #4

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 09:32:55 +01:00
e61f503c81 Fiks widget som ikkje viser data utan å opne appen først
Widgeten kunne ikkje hente posisjonsdata i bakgrunnen fordi Android
avgrenser GPS-tilgang for bakgrunnsprosessar (BroadcastReceiver) frå
og med Android 8+. Både FusedLocationProviderClient og LocationManager
returnerte null umiddelbart ved aktiv førespurnad frå bakgrunnen.

Løysinga er å lagre siste GPS-posisjon til SharedPreferences kvar gong
MainActivity får ei ny posisjonsfiks. Widgeten og WidgetUpdateWorker
les denne som siste utveg etter at system-API-ar har feila.

Endringane i detalj:

Widget (ShelterWidgetProvider):
- Brukar goAsync() + bakgrunnstråd for asynkron oppdatering
- Prøver FusedLocationProvider (Play Services), så LocationManager
  (AOSP), og til slutt SharedPreferences som fallback
- Ny metode requestUpdateWithLocation() for å sende posisjon via
  intent extras (unngår separate posisjonsbuffertar)
- Viser tidsstempel (HH:mm) for å sjå når widgeten sist vart oppdatert

WidgetUpdateWorker:
- Aktivt ber om ny posisjonsfiks (getCurrentLocation) i staden for
  berre å lese passiv buffer
- Sender oppnådd posisjon direkte til widgeten via broadcast
- Fallback til SharedPreferences viss aktiv førespurnad feilar
- Ny runOnce()-metode for eingongsoppdatering

MainActivity:
- Lagrar GPS-posisjon til SharedPreferences ved kvar oppdatering
  (saveLastLocation) så widgeten kan bruke den i bakgrunnen

Relatert: #3

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 23:08:32 +01:00
3c49dbdcde Legg til automatisk widgetoppdatering og de-Google-retningslinjer (v1.3.1)
Widget oppdaterer seg sjølv via WorkManager kvar 15. min i bakgrunnen,
og i sanntid når appen er open og mottek GPS-oppdateringar.
Oppdaterer CLAUDE.md med de-Google-kompatibilitetsprinsipp.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 22:34:33 +01:00
a813edc0c3 Legg til deling av tilfluktsrom og deep link-støtte (v1.3.0)
Del tilfluktsrom via SMS/meldingsapper med adresse, kapasitet,
koordinatar og geo:-URI. Støttar tilfluktsrom://shelter/{id}
deep link for direkte navigering til eit tilfluktsrom.

Closes #3

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 22:23:28 +01:00
57a9072b4c Legg til hybrid lokasjon, dataferskheit, widget og personvern (v1.2.0)
- Hybrid LocationProvider: prøver Play Services først, faller tilbake
  til LocationManager for degooglede einingar (F-Droid-kompatibel)
- Dataferskheitsindikator i statuslinja med tre nivå (fersk/veke/gammal)
- Heimeskjerm-widget som viser næraste tilfluktsrom med avstand
- Personvernerklæring (PRIVACY.md) på engelsk og norsk

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 19:10:57 +01:00
27801f1dfc Legg til release-signeringskonfigurasjon
Konfigurerer release-signering med keystore i ~/.android/ slik at
release-APK kan bygges og distribueres direkte.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 18:44:19 +01:00
d0460cd686 Bundle shelter data in APK and add shared versioning
- Add scripts/fetch-shelters.sh: downloads Geonorge data, converts
  UTM33N→WGS84 via PWA script, copies to both Android assets and
  PWA public dirs
- Bundle pre-processed shelters.json (556 shelters) in APK assets
  so the app works immediately on first launch with no network
- ShelterRepository.seedFromAsset(): seeds Room DB from bundled
  JSON on first launch, marks as stale so network refresh is
  attempted in the background
- MainActivity.loadData(): seeds from asset before trying network,
  always attempts background refresh when data is stale
- Add version.properties (1.1.0, versionCode=2) as single source
  of truth for versioning
- build.gradle.kts reads version from properties file and exposes
  via BuildConfig
- Bump PWA version to 1.1.0 to match

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 18:33:38 +01:00
c129de0a12 Improve error visibility and eliminate silent failures
- LocationProvider: close Flow with SecurityException when permission
  is missing (instead of silently completing), log trySend failures,
  handle lastLocation failure callback
- loadData(): wrap in top-level try-catch so database errors don't
  leave the app in a broken loading state
- Cache retry button: show "Waiting for GPS" toast when location is
  null instead of silently doing nothing
- selectShelterByData: use NaN for distance/bearing when no GPS fix
  yet, so UI shows "—" instead of misleading "0 m"
- DistanceUtils.formatDistance: handle NaN gracefully
- GeoJSON parser: require valid lokalId (primary key) — reject
  shelters with missing ID to prevent DB collisions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 17:56:54 +01:00
55761718e1 Improve lifecycle management, compass reliability, and accessibility
- Use repeatOnLifecycle(STARTED) for location updates so GPS stops
  when Activity is paused (battery conservation)
- Pair enableMyLocation/disableMyLocation with onResume/onPause
- Add low-pass filter for accelerometer+magnetometer compass fallback
  to reduce arrow jitter
- Detect missing compass sensors and show warning instead of frozen
  arrow
- Monitor compass accuracy via onAccuracyChanged and indicate
  degraded readings
- Show permission rationale dialog using existing i18n strings
- Guide user to Settings when location permission is permanently
  denied
- Check cacheMapArea return value and show banner on failure
- Add error handling around shelter Flow and location Flow collection
- Add contentDescription to direction arrow views for screen readers
- Use safe casts for system services (as? instead of as)
- Use explicit dark theme parent (Theme.Material3.Dark.NoActionBar)
  instead of DayNight with hardcoded dark colors
- Add error_no_compass and direction_arrow_description strings in
  en/nb/nn

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 17:54:06 +01:00
e93273bff4 Fix data safety, security, and coroutine correctness
- Wrap deleteAll+insertAll in Room transaction to prevent data loss
  on crash during refresh
- Add CancellationException rethrow in ShelterRepository and
  MapCacheManager to preserve structured concurrency
- Close OkHttp response body on error paths (response.use{})
- Add ZIP bomb protection (10MB cap) in GeoJSON parser
- Add per-feature error handling — skip malformed records instead of
  losing all shelters
- Validate coordinates within Norway's bounding box
- Enforce HTTPS-only via network_security_config (remove cleartext
  allowance for tile.openstreetmap.org)
- Disable android:allowBackup to prevent DB extraction via ADB
- Strip Log.v/d/i in release builds via ProGuard to prevent location
  data leakage
- Restore map position in MapCacheManager.finally block on
  cancellation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 17:53:51 +01:00
46365b713b Add per-app language selection (Android 13+)
Declare supported locales (en, nb, nn) via localeConfig so users can
pick the app language from system settings without changing their
device locale. Accessed via long-press → App Info → Language.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 17:41:23 +01:00
92531ee971 Improve map interaction, shelter selection, and offline caching
- Rework selection model so any shelter marker can be tapped to select,
  not just the nearest three in the bottom sheet list
- Highlight selected shelter with a distinct amber marker icon
- Track user map interaction (pan/zoom) to prevent auto-recentering
- Add reset navigation FAB to re-fit map to user + selected shelter
- Add offline map cache prompt (OK/Skip) with warning banner and retry
- Rewrite MapCacheManager to use passive tile caching via map panning
- Respect system status bar with fitsSystemWindows

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 17:41:15 +01:00
27cad094e7 Initial commit: Norwegian emergency shelter finder app
Android app (Kotlin) that locates the nearest public shelter (tilfluktsrom)
in Norway. Designed for offline-first emergency use.

Features:
- Downloads and caches all 556 Norwegian shelter locations from Geonorge
- GPS-based nearest shelter finding with distance and bearing
- OSMDroid map with offline tile caching for surroundings
- Large directional compass arrow pointing to selected shelter
- Compass sensor integration for real-time direction updates
- Shows 3 nearest shelters with distance, capacity, and address
- Toggle between map view and compass/arrow view
- Auto-caches map tiles on first launch for offline use
- Weekly background data refresh with manual force-update
- i18n: Norwegian Bokmål, Nynorsk, and English

Technical:
- EPSG:25833 (UTM33N) → WGS84 coordinate conversion
- Haversine distance and bearing calculations
- Room database for shelter persistence
- Fused Location Provider for precise GPS
- Sensor fusion (rotation vector with accel+mag fallback) for compass

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 16:14:19 +01:00