diff --git a/F-DROID.md b/F-DROID.md new file mode 100644 index 0000000..0eeb632 --- /dev/null +++ b/F-DROID.md @@ -0,0 +1,44 @@ +# F-Droid submission notes + +## Anti-features: Play Services dependency + +The app includes `com.google.android.gms:play-services-location:21.3.0` for better location accuracy via `FusedLocationProviderClient`. However, this is **not a hard dependency**: + +- The app checks for Play Services at runtime via `GoogleApiAvailability` +- If unavailable, it falls back to `LocationManager` (standard AOSP API) +- All core functionality (finding shelters, compass navigation, offline maps) works without Play Services + +This was specifically designed to support degoogled devices (LineageOS, GrapheneOS, /e/OS). + +### F-Droid build options + +**Option A: Accept as-is with `NonFreeDep` anti-feature** +The app works fully without Play Services. Mark with `NonFreeDep` anti-feature. + +**Option B: Build flavor without Play Services (recommended)** +Create a `fdroid` product flavor that excludes the Play Services dependency entirely. The fallback code paths already handle the absence — only the dependency and the Fused provider code need to be conditionally included. + +## Metadata structure + +``` +fastlane/metadata/android/ +├── en-US/ # English (default) +├── nb-NO/ # Norwegian Bokmål +└── nn-NO/ # Norwegian Nynorsk +``` + +Each locale contains `title.txt`, `short_description.txt`, `full_description.txt`, and `changelogs/` with per-versionCode files. + +## Screenshots + +Screenshots still need to be added to `images/` directories: +- `phoneScreenshots/` — at least 3 phone screenshots +- `featureGraphic.png` — 1024x500 feature graphic + +## Build instructions + +Standard Gradle build, no custom steps needed: + +``` +./gradlew assembleRelease +``` diff --git a/README.md b/README.md index 0fbbd3f..8ddb151 100644 --- a/README.md +++ b/README.md @@ -77,9 +77,12 @@ Appen er designet etter «offline-first»-prinsippet: - Databaseoppdateringer er atomiske (transaksjon) for å unngå datatap - Ingen persondata lagres — kun tilfluktsromdata og kartfliser +## Opphavsrett + +Copyright (c) Ole-Morten Duesund + ## Lisens Kildekoden er lisensiert under [Mozilla Public License 2.0](LICENSE). -Tilfluktsromdata er åpne data fra Geonorge / Direktoratet for samfunnssikkerhet og beredskap (DSB). -Kartfliser fra OpenStreetMap er lisensiert under [ODbL](https://opendatacommons.org/licenses/odbl/). +Appen bruker åpne data og tjenester fra flere kilder. Se [SOURCES.md](SOURCES.md) for en fullstendig oversikt over datakilder, URL-er og lisenser. diff --git a/SOURCES.md b/SOURCES.md new file mode 100644 index 0000000..203e709 --- /dev/null +++ b/SOURCES.md @@ -0,0 +1,17 @@ +# Data Sources + +Centralized list of all external data sources used by the app. This is the authoritative reference for attribution, licensing, and usage context. + +## Sources + +| Source | Provider | URL | Usage | License | Used in | +|--------|----------|-----|-------|---------|---------| +| Shelter data (GeoJSON) | Geonorge / DSB | [nedlasting.geonorge.no/...](https://nedlasting.geonorge.no/geonorge/Samfunnssikkerhet/TilfluktsromOffentlige/GeoJSON/Samfunnssikkerhet_0000_Norge_25833_TilfluktsromOffentlige_GeoJSON.zip) | Shelter locations, capacity, addresses (~556 shelters) | [NLOD 2.0](https://data.norge.no/nlod/no/2.0) | `app/.../data/ShelterRepository.kt`, `pwa/scripts/fetch-shelters.ts` | +| Map tiles | OpenStreetMap | [tile.openstreetmap.org](https://tile.openstreetmap.org) | Offline-capable map display | [ODbL](https://opendatacommons.org/licenses/odbl/) | `app/` via OSMDroid, `pwa/src/ui/map-view.ts` via Leaflet | +| Civil defense guidelines | DSB (Direktoratet for samfunnssikkerhet og beredskap) | [dsb.no/sikkerhverdag/egenberedskap](https://www.dsb.no/sikkerhverdag/egenberedskap/) | Emergency instructions shown in the civil defense info dialog | Norwegian public sector information | `app/.../res/values/strings.xml` (civil_defense_* strings) | + +## Notes + +- **Shelter data** is downloaded as a ZIP containing GeoJSON in EPSG:25833 (UTM33N) projection. The app converts coordinates to WGS84 at parse time. +- **Map tiles** are cached locally by OSMDroid (Android) and the service worker (PWA) for offline use. OpenStreetMap's [tile usage policy](https://operations.osmfoundation.org/policies/tiles/) applies. +- **Civil defense guidelines** are adapted from official DSB recommendations, not quoted verbatim. Content is available in English, Bokmal, and Nynorsk. diff --git a/app/src/main/java/no/naiv/tilfluktsrom/MainActivity.kt b/app/src/main/java/no/naiv/tilfluktsrom/MainActivity.kt index 0b88d87..af96248 100644 --- a/app/src/main/java/no/naiv/tilfluktsrom/MainActivity.kt +++ b/app/src/main/java/no/naiv/tilfluktsrom/MainActivity.kt @@ -3,6 +3,7 @@ package no.naiv.tilfluktsrom import android.Manifest import android.content.Context import android.content.Intent +import android.view.HapticFeedbackConstants import android.content.pm.PackageManager import android.hardware.Sensor import android.hardware.SensorEvent @@ -202,6 +203,7 @@ class MainActivity : AppCompatActivity(), SensorEventListener { private fun setupButtons() { binding.toggleViewFab.setOnClickListener { + it.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY) isCompassMode = !isCompassMode if (isCompassMode) { binding.mapView.visibility = View.GONE @@ -216,24 +218,29 @@ class MainActivity : AppCompatActivity(), SensorEventListener { // Reset to navigation: re-fit map to show user + selected shelter binding.resetNavigationFab.setOnClickListener { + it.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY) userHasInteractedWithMap = false binding.resetNavigationFab.visibility = View.GONE selectedShelter?.let { highlightShelterOnMap(it) } } binding.infoButton.setOnClickListener { + it.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY) CivilDefenseInfoDialog().show(supportFragmentManager, CivilDefenseInfoDialog.TAG) } binding.refreshButton.setOnClickListener { + it.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY) forceRefresh() } binding.shareButton.setOnClickListener { + it.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY) shareShelter() } binding.cacheRetryButton.setOnClickListener { + it.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY) val loc = currentLocation if (loc == null) { Toast.makeText(this, R.string.status_no_location, Toast.LENGTH_SHORT).show() @@ -489,7 +496,11 @@ class MainActivity : AppCompatActivity(), SensorEventListener { /** Update all UI elements for the currently selected shelter. */ private fun updateSelectedShelterUI() { val selected = selectedShelter ?: return - val distanceText = DistanceUtils.formatDistance(selected.distanceMeters) + val distanceText = if (selected.distanceMeters.isNaN()) { + getString(R.string.status_no_location) + } else { + DistanceUtils.formatDistance(selected.distanceMeters) + } // Update bottom sheet binding.selectedShelterAddress.text = selected.shelter.adresse @@ -829,9 +840,7 @@ class MainActivity : AppCompatActivity(), SensorEventListener { Log.w(TAG, "Compass accuracy degraded: $accuracy") binding.compassAddressText.let { tv -> val current = selectedShelter?.shelter?.adresse ?: "" - if (!current.contains("⚠")) { - tv.text = "⚠ $current" - } + tv.text = getString(R.string.compass_accuracy_warning, current) } } SensorManager.SENSOR_STATUS_ACCURACY_MEDIUM, diff --git a/app/src/main/java/no/naiv/tilfluktsrom/ui/ShelterListAdapter.kt b/app/src/main/java/no/naiv/tilfluktsrom/ui/ShelterListAdapter.kt index 55655f2..f4a7307 100644 --- a/app/src/main/java/no/naiv/tilfluktsrom/ui/ShelterListAdapter.kt +++ b/app/src/main/java/no/naiv/tilfluktsrom/ui/ShelterListAdapter.kt @@ -1,5 +1,6 @@ package no.naiv.tilfluktsrom.ui +import android.view.HapticFeedbackConstants import android.view.LayoutInflater import android.view.ViewGroup import androidx.recyclerview.widget.DiffUtil @@ -52,10 +53,18 @@ class ShelterListAdapter( R.string.shelter_room_nr, item.shelter.romnr ) + binding.root.contentDescription = ctx.getString( + R.string.content_desc_shelter_item, + item.shelter.adresse, + DistanceUtils.formatDistance(item.distanceMeters), + item.shelter.plasser + ) + binding.root.isSelected = isSelected binding.root.alpha = if (isSelected) 1.0f else 0.7f binding.root.setOnClickListener { + it.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY) val pos = adapterPosition if (pos != RecyclerView.NO_POSITION) { selectPosition(pos) diff --git a/app/src/main/java/no/naiv/tilfluktsrom/widget/ShelterWidgetProvider.kt b/app/src/main/java/no/naiv/tilfluktsrom/widget/ShelterWidgetProvider.kt index e13e054..119f475 100644 --- a/app/src/main/java/no/naiv/tilfluktsrom/widget/ShelterWidgetProvider.kt +++ b/app/src/main/java/no/naiv/tilfluktsrom/widget/ShelterWidgetProvider.kt @@ -221,10 +221,11 @@ class ShelterWidgetProvider : AppWidgetProvider() { views.setTextViewText(R.id.widgetTimestamp, formatTimestamp(context)) } - /** Format current time as HH:mm, respecting the user's 12/24h preference. */ + /** Format current time as "Updated HH:mm", respecting the user's 12/24h preference. */ private fun formatTimestamp(context: Context): String { val format = DateFormat.getTimeFormat(context) - return format.format(System.currentTimeMillis()) + val timeStr = format.format(System.currentTimeMillis()) + return context.getString(R.string.widget_updated_at, timeStr) } /** diff --git a/app/src/main/res/layout/dialog_civil_defense.xml b/app/src/main/res/layout/dialog_civil_defense.xml index b598f75..29333d4 100644 --- a/app/src/main/res/layout/dialog_civil_defense.xml +++ b/app/src/main/res/layout/dialog_civil_defense.xml @@ -114,5 +114,14 @@ android:textSize="12sp" android:textStyle="italic" /> + + + diff --git a/app/src/main/res/values-nb/strings.xml b/app/src/main/res/values-nb/strings.xml index 48ccd18..bab61b6 100644 --- a/app/src/main/res/values-nb/strings.xml +++ b/app/src/main/res/values-nb/strings.xml @@ -51,6 +51,7 @@ \u00c5pne appen for posisjon Ingen tilfluktsromdata Trykk for \u00e5 oppdatere + Oppdatert %s Data er oppdatert @@ -64,10 +65,12 @@ Retning til tilfluktsrom, %s unna + %1$s, %2$s, %3$d plasser + Upresist kompass - %s Sivilforsvarsinformasjon - Hva du skal gjøre når alarmen går + Hva du skal gjøre hvis alarmen går 1. Viktig melding-signalet Tre serier med korte støt med ett minutts stillhet mellom hver serie. Dette betyr: søk informasjon umiddelbart. Slå på DAB-radio, TV, eller sjekk offisielle kilder på nett. 2. Flyalarm @@ -79,4 +82,7 @@ 5. Faren over Én sammenhengende tone på omtrent 30 sekunder. Faren eller angrepet er over. Fortsett å følge instruksjoner fra myndighetene. Kilde: DSB (Direktoratet for samfunnssikkerhet og beredskap) + + + Opphavsrett © Ole-Morten Duesund diff --git a/app/src/main/res/values-nn/strings.xml b/app/src/main/res/values-nn/strings.xml index 9a8f085..a4de381 100644 --- a/app/src/main/res/values-nn/strings.xml +++ b/app/src/main/res/values-nn/strings.xml @@ -51,6 +51,7 @@ Opne appen for posisjon Ingen tilfluktsromdata Trykk for \u00e5 oppdatere + Oppdatert %s Data er oppdatert @@ -64,10 +65,12 @@ Retning til tilfluktsrom, %s unna + %1$s, %2$s, %3$d plassar + Upresis kompass - %s Sivilforsvarsinformasjon - Kva du skal gjere når alarmen går + Kva du skal gjere om alarmen går 1. Viktig melding-signalet Tre seriar med korte støyt med eitt minutt stille mellom kvar serie. Dette tyder: søk informasjon med ein gong. Slå på DAB-radio, TV, eller sjekk offisielle kjelder på nett. 2. Flyalarm @@ -79,4 +82,7 @@ 5. Faren over Éin samanhengande tone på omtrent 30 sekund. Faren eller åtaket er over. Hald fram med å følgje instruksjonar frå styresmaktene. Kjelde: DSB (Direktoratet for samfunnstryggleik og beredskap) + + + Opphavsrett © Ole-Morten Duesund diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 0a9d1a1..59aae1f 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -7,7 +7,7 @@ #1A1A2E #16213E - #B0BEC5 + #CFD8DC #1A1A2E #0F0F23 #CC000000 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 03e0e04..43b3945 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -51,6 +51,7 @@ Open app for location No shelter data Tap to refresh + Updated %s Data is up to date @@ -64,10 +65,12 @@ Direction to shelter, %s away + %1$s, %2$s, %3$d places + Low accuracy - %s Civil defense information - What to do when the alarm sounds + What to do if the alarm sounds 1. Important message signal Three series of short blasts with one minute of silence between each series. This means: seek information immediately. Turn on DAB radio, TV, or check official sources online. 2. Air raid alarm @@ -79,4 +82,7 @@ 5. All clear One continuous tone lasting approximately 30 seconds. The danger or attack is over. Continue to follow instructions from authorities. Source: DSB (Norwegian Directorate for Civil Protection) + + + Copyright © Ole-Morten Duesund diff --git a/fastlane/metadata/android/en-US/changelogs/3.txt b/fastlane/metadata/android/en-US/changelogs/3.txt new file mode 100644 index 0000000..8e9bf1e --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/3.txt @@ -0,0 +1,4 @@ +• Hybrid location: uses Play Services when available, falls back to standard Android GPS +• Data freshness indicator shows when shelter data was last updated +• Home screen widget showing nearest shelter with distance +• Bundled shelter data for instant offline use on first launch diff --git a/fastlane/metadata/android/en-US/changelogs/4.txt b/fastlane/metadata/android/en-US/changelogs/4.txt new file mode 100644 index 0000000..2f018ac --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/4.txt @@ -0,0 +1,3 @@ +• Share shelter location with others via any app +• Deep link support — open shared shelters directly in the app +• Tap any marker on the map to select and navigate to it diff --git a/fastlane/metadata/android/en-US/changelogs/5.txt b/fastlane/metadata/android/en-US/changelogs/5.txt new file mode 100644 index 0000000..0dafa07 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/5.txt @@ -0,0 +1,2 @@ +• Widget now updates automatically every 15 minutes via WorkManager +• Fixed widget not showing data without opening the app first diff --git a/fastlane/metadata/android/en-US/changelogs/6.txt b/fastlane/metadata/android/en-US/changelogs/6.txt new file mode 100644 index 0000000..aad04e7 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/6.txt @@ -0,0 +1,4 @@ +• Civil defense information: what to do if the alarm sounds (based on DSB guidelines) +• Improved accessibility: screen reader labels, better contrast, haptic feedback +• Widget shows "Updated 14:32" instead of bare timestamp +• Copyright notice added diff --git a/fastlane/metadata/android/en-US/changelogs/7.txt b/fastlane/metadata/android/en-US/changelogs/7.txt new file mode 100644 index 0000000..72dc0ac --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/7.txt @@ -0,0 +1,6 @@ +• Accessibility: screen reader labels on shelter list, compass, and direction arrows +• Improved contrast on status bar text (WCAG AA) +• Haptic feedback on all buttons and list items +• Widget timestamp now shows "Updated 14:32" +• Softer civil defense dialog title +• Copyright notice added diff --git a/fastlane/metadata/android/en-US/full_description.txt b/fastlane/metadata/android/en-US/full_description.txt new file mode 100644 index 0000000..839991c --- /dev/null +++ b/fastlane/metadata/android/en-US/full_description.txt @@ -0,0 +1,15 @@ +Find the nearest public emergency shelter (tilfluktsrom) in Norway. Built for emergencies — works fully offline after first use. + +Features: +• Shows the 3 nearest shelters with distance and capacity +• Compass navigation — direction arrow points to the selected shelter +• Offline map — map tiles are cached automatically for use without internet +• Select any shelter — tap any marker on the map to navigate there +• Home screen widget — shows nearest shelter at a glance +• Share shelters — send shelter location to others via any app +• Civil defense info — what to do if the alarm sounds +• Multilingual — English, Bokmål, and Nynorsk + +The app uses open data from Geonorge (Norwegian Mapping Authority) covering approximately 556 public shelters across Norway. + +Works on degoogled devices: the app uses Google Play Services for better location accuracy when available, but falls back to standard Android location APIs on devices without Play Services (LineageOS, GrapheneOS, /e/OS, etc.). diff --git a/fastlane/metadata/android/en-US/images/.gitkeep b/fastlane/metadata/android/en-US/images/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/fastlane/metadata/android/en-US/short_description.txt b/fastlane/metadata/android/en-US/short_description.txt new file mode 100644 index 0000000..1c45bf5 --- /dev/null +++ b/fastlane/metadata/android/en-US/short_description.txt @@ -0,0 +1 @@ +Find the nearest public emergency shelter in Norway. Works offline. diff --git a/fastlane/metadata/android/en-US/title.txt b/fastlane/metadata/android/en-US/title.txt new file mode 100644 index 0000000..04599a8 --- /dev/null +++ b/fastlane/metadata/android/en-US/title.txt @@ -0,0 +1 @@ +Tilfluktsrom diff --git a/fastlane/metadata/android/nb-NO/changelogs/3.txt b/fastlane/metadata/android/nb-NO/changelogs/3.txt new file mode 100644 index 0000000..e59b524 --- /dev/null +++ b/fastlane/metadata/android/nb-NO/changelogs/3.txt @@ -0,0 +1,4 @@ +• Hybrid posisjon: bruker Play Services når tilgjengelig, faller tilbake til standard Android-GPS +• Dataferskhetsindikator viser når tilfluktsromdata sist ble oppdatert +• Hjemskjerm-widget som viser nærmeste tilfluktsrom med avstand +• Medfølgende tilfluktsromdata for umiddelbar frakoblet bruk ved første oppstart diff --git a/fastlane/metadata/android/nb-NO/changelogs/4.txt b/fastlane/metadata/android/nb-NO/changelogs/4.txt new file mode 100644 index 0000000..421115d --- /dev/null +++ b/fastlane/metadata/android/nb-NO/changelogs/4.txt @@ -0,0 +1,3 @@ +• Del tilfluktsrom med andre via en hvilken som helst app +• Støtte for dyplenker — åpne delte tilfluktsrom direkte i appen +• Trykk på en markør i kartet for å velge og navigere dit diff --git a/fastlane/metadata/android/nb-NO/changelogs/5.txt b/fastlane/metadata/android/nb-NO/changelogs/5.txt new file mode 100644 index 0000000..f5262c0 --- /dev/null +++ b/fastlane/metadata/android/nb-NO/changelogs/5.txt @@ -0,0 +1,2 @@ +• Widget oppdateres nå automatisk hvert 15. minutt via WorkManager +• Fikset at widget ikke viste data uten å åpne appen først diff --git a/fastlane/metadata/android/nb-NO/changelogs/6.txt b/fastlane/metadata/android/nb-NO/changelogs/6.txt new file mode 100644 index 0000000..a6dfe8c --- /dev/null +++ b/fastlane/metadata/android/nb-NO/changelogs/6.txt @@ -0,0 +1,4 @@ +• Sivilforsvarsinformasjon: hva du skal gjøre hvis alarmen går (basert på DSB-retningslinjer) +• Forbedret tilgjengelighet: skjermleseretiketter, bedre kontrast, haptisk tilbakemelding +• Widget viser «Oppdatert 14:32» i stedet for bare tidsstempel +• Opphavsrettsmelding lagt til diff --git a/fastlane/metadata/android/nb-NO/changelogs/7.txt b/fastlane/metadata/android/nb-NO/changelogs/7.txt new file mode 100644 index 0000000..2e78f0f --- /dev/null +++ b/fastlane/metadata/android/nb-NO/changelogs/7.txt @@ -0,0 +1,6 @@ +• Tilgjengelighet: skjermleseretiketter på tilfluktsromliste, kompass og retningspil +• Forbedret kontrast på statuslinjetekst (WCAG AA) +• Haptisk tilbakemelding på alle knapper og listeelement +• Widget-tidsstempel viser nå «Oppdatert 14:32» +• Mildere tittel på sivilforsvarsdialog +• Opphavsrettsmelding lagt til diff --git a/fastlane/metadata/android/nb-NO/full_description.txt b/fastlane/metadata/android/nb-NO/full_description.txt new file mode 100644 index 0000000..bd4b8b9 --- /dev/null +++ b/fastlane/metadata/android/nb-NO/full_description.txt @@ -0,0 +1,15 @@ +Finn nærmeste offentlige tilfluktsrom i Norge. Bygd for nødsituasjoner — fungerer helt uten internett etter første gangs bruk. + +Funksjoner: +• Viser de 3 nærmeste tilfluktsrommene med avstand og kapasitet +• Kompassnavigasjon — retningspil som peker mot valgt tilfluktsrom +• Frakoblet kart — kartfliser lagres automatisk for bruk uten nett +• Velg fritt — trykk på en markør i kartet for å navigere dit +• Hjemskjerm-widget — viser nærmeste tilfluktsrom med ett blikk +• Del tilfluktsrom — send posisjon til andre via en hvilken som helst app +• Sivilforsvarsinformasjon — hva du skal gjøre hvis alarmen går +• Flerspråklig — engelsk, bokmål og nynorsk + +Appen bruker åpne data fra Geonorge (Kartverket) med ca. 556 offentlige tilfluktsrom i hele Norge. + +Fungerer på de-Google-enheter: appen bruker Google Play Services for bedre posisjonsdata når det er tilgjengelig, men faller tilbake til standard Android-posisjons-API-er på enheter uten Play Services (LineageOS, GrapheneOS, /e/OS osv.). diff --git a/fastlane/metadata/android/nb-NO/images/.gitkeep b/fastlane/metadata/android/nb-NO/images/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/fastlane/metadata/android/nb-NO/short_description.txt b/fastlane/metadata/android/nb-NO/short_description.txt new file mode 100644 index 0000000..d376c35 --- /dev/null +++ b/fastlane/metadata/android/nb-NO/short_description.txt @@ -0,0 +1 @@ +Finn nærmeste offentlige tilfluktsrom i Norge. Fungerer uten nett. diff --git a/fastlane/metadata/android/nb-NO/title.txt b/fastlane/metadata/android/nb-NO/title.txt new file mode 100644 index 0000000..04599a8 --- /dev/null +++ b/fastlane/metadata/android/nb-NO/title.txt @@ -0,0 +1 @@ +Tilfluktsrom diff --git a/fastlane/metadata/android/nn-NO/changelogs/3.txt b/fastlane/metadata/android/nn-NO/changelogs/3.txt new file mode 100644 index 0000000..a5bd8c3 --- /dev/null +++ b/fastlane/metadata/android/nn-NO/changelogs/3.txt @@ -0,0 +1,4 @@ +• Hybrid posisjon: brukar Play Services når tilgjengeleg, fell tilbake til standard Android-GPS +• Dataferskheitsindikator viser når tilfluktsromdata sist vart oppdatert +• Heimeskjerm-widget som viser næraste tilfluktsrom med avstand +• Medfølgjande tilfluktsromdata for umiddelbar fråkopla bruk ved fyrste oppstart diff --git a/fastlane/metadata/android/nn-NO/changelogs/4.txt b/fastlane/metadata/android/nn-NO/changelogs/4.txt new file mode 100644 index 0000000..8195b7f --- /dev/null +++ b/fastlane/metadata/android/nn-NO/changelogs/4.txt @@ -0,0 +1,3 @@ +• Del tilfluktsrom med andre via ei kva som helst app +• Støtte for djuplenker — opne delte tilfluktsrom direkte i appen +• Trykk på ein markør i kartet for å velje og navigere dit diff --git a/fastlane/metadata/android/nn-NO/changelogs/5.txt b/fastlane/metadata/android/nn-NO/changelogs/5.txt new file mode 100644 index 0000000..1cfa5a2 --- /dev/null +++ b/fastlane/metadata/android/nn-NO/changelogs/5.txt @@ -0,0 +1,2 @@ +• Widget oppdaterast no automatisk kvart 15. minutt via WorkManager +• Fiksa at widget ikkje viste data utan å opne appen fyrst diff --git a/fastlane/metadata/android/nn-NO/changelogs/6.txt b/fastlane/metadata/android/nn-NO/changelogs/6.txt new file mode 100644 index 0000000..671a17d --- /dev/null +++ b/fastlane/metadata/android/nn-NO/changelogs/6.txt @@ -0,0 +1,4 @@ +• Sivilforsvarsinformasjon: kva du skal gjere om alarmen går (basert på DSB-retningslinjer) +• Forbetra tilgjenge: skjermlesar-etiketter, betre kontrast, haptisk tilbakemelding +• Widget viser «Oppdatert 14:32» i staden for berre tidsstempel +• Opphavsrettsmelding lagt til diff --git a/fastlane/metadata/android/nn-NO/changelogs/7.txt b/fastlane/metadata/android/nn-NO/changelogs/7.txt new file mode 100644 index 0000000..211d811 --- /dev/null +++ b/fastlane/metadata/android/nn-NO/changelogs/7.txt @@ -0,0 +1,6 @@ +• Tilgjenge: skjermlesar-etiketter på tilfluktsromliste, kompass og retningspil +• Forbetra kontrast på statuslinjetekst (WCAG AA) +• Haptisk tilbakemelding på alle knappar og listeelement +• Widget-tidsstempel viser no «Oppdatert 14:32» +• Mildare tittel på sivilforsvarsdialog +• Opphavsrettsmelding lagt til diff --git a/fastlane/metadata/android/nn-NO/full_description.txt b/fastlane/metadata/android/nn-NO/full_description.txt new file mode 100644 index 0000000..fdc1279 --- /dev/null +++ b/fastlane/metadata/android/nn-NO/full_description.txt @@ -0,0 +1,15 @@ +Finn næraste offentlege tilfluktsrom i Noreg. Bygd for nødsituasjonar — fungerer heilt utan internett etter fyrste gongs bruk. + +Funksjonar: +• Viser dei 3 næraste tilfluktsromma med avstand og kapasitet +• Kompassnavigasjon — retningspil som peikar mot valt tilfluktsrom +• Fråkopla kart — kartfliser lagrast automatisk for bruk utan nett +• Vel fritt — trykk på ein markør i kartet for å navigere dit +• Heimeskjerm-widget — viser næraste tilfluktsrom med eitt blikk +• Del tilfluktsrom — send posisjon til andre via ei kva som helst app +• Sivilforsvarsinformasjon — kva du skal gjere om alarmen går +• Fleirspråkleg — engelsk, bokmål og nynorsk + +Appen brukar opne data frå Geonorge (Kartverket) med ca. 556 offentlege tilfluktsrom i heile Noreg. + +Fungerer på de-Google-einingar: appen brukar Google Play Services for betre posisjonsdata når det er tilgjengeleg, men fell tilbake til standard Android-posisjons-API-ar på einingar utan Play Services (LineageOS, GrapheneOS, /e/OS osb.). diff --git a/fastlane/metadata/android/nn-NO/images/.gitkeep b/fastlane/metadata/android/nn-NO/images/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/fastlane/metadata/android/nn-NO/short_description.txt b/fastlane/metadata/android/nn-NO/short_description.txt new file mode 100644 index 0000000..462d4b2 --- /dev/null +++ b/fastlane/metadata/android/nn-NO/short_description.txt @@ -0,0 +1 @@ +Finn næraste offentlege tilfluktsrom i Noreg. Fungerer utan nett. diff --git a/fastlane/metadata/android/nn-NO/title.txt b/fastlane/metadata/android/nn-NO/title.txt new file mode 100644 index 0000000..04599a8 --- /dev/null +++ b/fastlane/metadata/android/nn-NO/title.txt @@ -0,0 +1 @@ +Tilfluktsrom diff --git a/pwa/index.html b/pwa/index.html index e5e890b..bfbd7e6 100644 --- a/pwa/index.html +++ b/pwa/index.html @@ -43,7 +43,7 @@
- +
diff --git a/pwa/src/app.ts b/pwa/src/app.ts index e1f1038..4bfd68c 100644 --- a/pwa/src/app.ts +++ b/pwa/src/app.ts @@ -76,6 +76,7 @@ function setupButtons(): void { // Toggle map/compass const toggleFab = document.getElementById('toggle-fab')!; toggleFab.addEventListener('click', async () => { + navigator.vibrate?.(10); isCompassMode = !isCompassMode; const mapContainer = document.getElementById('map-container')!; @@ -112,6 +113,7 @@ function setupButtons(): void { const cacheRetryBtn = document.getElementById('cache-retry-btn')!; cacheRetryBtn.textContent = t('action_cache_now'); cacheRetryBtn.addEventListener('click', () => { + navigator.vibrate?.(10); if (currentLocation && navigator.onLine) { startCaching(currentLocation.latitude, currentLocation.longitude); } @@ -120,6 +122,7 @@ function setupButtons(): void { // Reset view button const resetBtn = document.getElementById('reset-view-btn')!; resetBtn.addEventListener('click', () => { + navigator.vibrate?.(10); const selected = nearestShelters[selectedShelterIndex] ?? null; mapView.resetView(selected, currentLocation); resetBtn.classList.remove('visible'); @@ -256,6 +259,8 @@ function updateSelectedShelter(isUserAction: boolean): void { ].join(' \u00B7 '); // Update mini arrow + const miniArrow = document.getElementById('mini-arrow')!; + miniArrow.setAttribute('aria-label', t('direction_arrow_description', dist)); updateMiniArrow(selected.bearingDegrees - deviceHeading); // Update compass view diff --git a/pwa/src/i18n/en.ts b/pwa/src/i18n/en.ts index 1a25dda..0f3fc1f 100644 --- a/pwa/src/i18n/en.ts +++ b/pwa/src/i18n/en.ts @@ -46,4 +46,7 @@ export const en: Record = { 'No cached data available. Connect to the internet to download shelter data.', update_success: 'Shelter data updated', update_failed: 'Update failed \u2014 using cached data', + + // Accessibility + direction_arrow_description: 'Direction to shelter, %s away', }; diff --git a/pwa/src/i18n/nb.ts b/pwa/src/i18n/nb.ts index 6aba9ae..9090128 100644 --- a/pwa/src/i18n/nb.ts +++ b/pwa/src/i18n/nb.ts @@ -41,4 +41,7 @@ export const nb: Record = { 'Ingen lagrede data tilgjengelig. Koble til internett for \u00e5 laste ned tilfluktsromdata.', update_success: 'Tilfluktsromdata oppdatert', update_failed: 'Oppdatering mislyktes \u2014 bruker lagrede data', + + // Tilgjengelighet + direction_arrow_description: 'Retning til tilfluktsrom, %s unna', }; diff --git a/pwa/src/i18n/nn.ts b/pwa/src/i18n/nn.ts index d66097d..39e0a5d 100644 --- a/pwa/src/i18n/nn.ts +++ b/pwa/src/i18n/nn.ts @@ -41,4 +41,7 @@ export const nn: Record = { 'Ingen lagra data tilgjengeleg. Kopla til internett for \u00e5 laste ned tilfluktsromdata.', update_success: 'Tilfluktsromdata oppdatert', update_failed: 'Oppdatering mislukkast \u2014 brukar lagra data', + + // Tilgjenge + direction_arrow_description: 'Retning til tilfluktsrom, %s unna', }; diff --git a/pwa/src/styles/main.css b/pwa/src/styles/main.css index 4623941..fe3d9ff 100644 --- a/pwa/src/styles/main.css +++ b/pwa/src/styles/main.css @@ -40,7 +40,7 @@ html, body { #status-text { flex: 1; - color: #B0BEC5; + color: #CFD8DC; font-size: 12px; white-space: nowrap; overflow: hidden; @@ -50,7 +50,7 @@ html, body { #refresh-btn { background: none; border: none; - color: #B0BEC5; + color: #CFD8DC; cursor: pointer; padding: 4px; font-size: 18px; @@ -142,8 +142,8 @@ html, body { height: 40px; border-radius: 50%; background: #16213E; - border: 2px solid #B0BEC5; - color: #B0BEC5; + border: 2px solid #CFD8DC; + color: #CFD8DC; font-size: 18px; cursor: pointer; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.4); @@ -356,7 +356,7 @@ html, body { } .leaflet-control-attribution a { - color: #B0BEC5 !important; + color: #CFD8DC !important; } .leaflet-popup-content-wrapper { @@ -370,5 +370,5 @@ html, body { } .leaflet-popup-close-button { - color: #B0BEC5 !important; + color: #CFD8DC !important; } diff --git a/pwa/src/ui/shelter-list.ts b/pwa/src/ui/shelter-list.ts index b90755a..c0d6f8d 100644 --- a/pwa/src/ui/shelter-list.ts +++ b/pwa/src/ui/shelter-list.ts @@ -52,6 +52,7 @@ export function updateList( item.appendChild(addressSpan); item.appendChild(detailsSpan); item.addEventListener('click', () => { + navigator.vibrate?.(10); onSelect?.(i); }); container!.appendChild(item); diff --git a/pwa/src/ui/status-bar.ts b/pwa/src/ui/status-bar.ts index 84dd857..d4ab54b 100644 --- a/pwa/src/ui/status-bar.ts +++ b/pwa/src/ui/status-bar.ts @@ -11,5 +11,8 @@ export function setStatus(text: string): void { /** Set the refresh button click handler. */ export function onRefreshClick(handler: () => void): void { const btn = document.getElementById('refresh-btn'); - if (btn) btn.addEventListener('click', handler); + if (btn) btn.addEventListener('click', () => { + navigator.vibrate?.(10); + handler(); + }); } diff --git a/version.properties b/version.properties index 9c5f127..ef64dbc 100644 --- a/version.properties +++ b/version.properties @@ -1,4 +1,4 @@ versionMajor=1 versionMinor=4 -versionPatch=0 -versionCode=6 +versionPatch=1 +versionCode=7