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>
This commit is contained in:
parent
57a9072b4c
commit
a813edc0c3
8 changed files with 127 additions and 2 deletions
|
|
@ -23,11 +23,20 @@
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
|
android:launchMode="singleTop"
|
||||||
android:windowSoftInputMode="adjustPan">
|
android:windowSoftInputMode="adjustPan">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
|
<data
|
||||||
|
android:scheme="tilfluktsrom"
|
||||||
|
android:host="shelter" />
|
||||||
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<receiver
|
<receiver
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,9 @@ class MainActivity : AppCompatActivity(), SensorEventListener {
|
||||||
// Whether a compass sensor is available on this device
|
// Whether a compass sensor is available on this device
|
||||||
private var hasCompassSensor = false
|
private var hasCompassSensor = false
|
||||||
|
|
||||||
|
// Deep link: shelter ID to select once data is loaded
|
||||||
|
private var pendingDeepLinkShelterId: String? = null
|
||||||
|
|
||||||
// The currently selected shelter — can be any shelter, not just one from nearestShelters
|
// The currently selected shelter — can be any shelter, not just one from nearestShelters
|
||||||
private var selectedShelter: ShelterWithDistance? = null
|
private var selectedShelter: ShelterWithDistance? = null
|
||||||
// When true, location updates won't auto-select the nearest shelter
|
// When true, location updates won't auto-select the nearest shelter
|
||||||
|
|
@ -127,6 +130,33 @@ class MainActivity : AppCompatActivity(), SensorEventListener {
|
||||||
setupShelterList()
|
setupShelterList()
|
||||||
setupButtons()
|
setupButtons()
|
||||||
loadData()
|
loadData()
|
||||||
|
handleDeepLinkIntent(intent)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNewIntent(intent: Intent) {
|
||||||
|
super.onNewIntent(intent)
|
||||||
|
setIntent(intent)
|
||||||
|
handleDeepLinkIntent(intent)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle tilfluktsrom://shelter/{lokalId} deep link.
|
||||||
|
* If shelters are already loaded, select immediately; otherwise store as pending.
|
||||||
|
*/
|
||||||
|
private fun handleDeepLinkIntent(intent: Intent?) {
|
||||||
|
val uri = intent?.data ?: return
|
||||||
|
if (uri.scheme != "tilfluktsrom" || uri.host != "shelter") return
|
||||||
|
|
||||||
|
val lokalId = uri.lastPathSegment ?: return
|
||||||
|
// Clear intent data so config changes don't re-trigger
|
||||||
|
intent.data = null
|
||||||
|
|
||||||
|
val shelter = allShelters.find { it.lokalId == lokalId }
|
||||||
|
if (shelter != null) {
|
||||||
|
selectShelterByData(shelter)
|
||||||
|
} else {
|
||||||
|
pendingDeepLinkShelterId = lokalId
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupMap() {
|
private fun setupMap() {
|
||||||
|
|
@ -193,6 +223,10 @@ class MainActivity : AppCompatActivity(), SensorEventListener {
|
||||||
forceRefresh()
|
forceRefresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
binding.shareButton.setOnClickListener {
|
||||||
|
shareShelter()
|
||||||
|
}
|
||||||
|
|
||||||
binding.cacheRetryButton.setOnClickListener {
|
binding.cacheRetryButton.setOnClickListener {
|
||||||
val loc = currentLocation
|
val loc = currentLocation
|
||||||
if (loc == null) {
|
if (loc == null) {
|
||||||
|
|
@ -240,6 +274,17 @@ class MainActivity : AppCompatActivity(), SensorEventListener {
|
||||||
binding.statusText.text = getString(R.string.status_shelters_loaded, shelters.size)
|
binding.statusText.text = getString(R.string.status_shelters_loaded, shelters.size)
|
||||||
updateFreshnessIndicator()
|
updateFreshnessIndicator()
|
||||||
updateShelterMarkers()
|
updateShelterMarkers()
|
||||||
|
|
||||||
|
// Process pending deep links now that shelter data is available
|
||||||
|
pendingDeepLinkShelterId?.let { id ->
|
||||||
|
pendingDeepLinkShelterId = null
|
||||||
|
val shelter = shelters.find { it.lokalId == id }
|
||||||
|
if (shelter != null) {
|
||||||
|
selectShelterByData(shelter)
|
||||||
|
} else {
|
||||||
|
Toast.makeText(this@MainActivity, R.string.error_shelter_not_found, Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
currentLocation?.let { updateNearestShelters(it) }
|
currentLocation?.let { updateNearestShelters(it) }
|
||||||
}
|
}
|
||||||
} catch (e: CancellationException) {
|
} catch (e: CancellationException) {
|
||||||
|
|
@ -598,6 +643,35 @@ class MainActivity : AppCompatActivity(), SensorEventListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Share the currently selected shelter via ACTION_SEND.
|
||||||
|
* Includes address, capacity, geo: URI (for non-app recipients),
|
||||||
|
* and a tilfluktsrom:// deep link (for app users).
|
||||||
|
*/
|
||||||
|
private fun shareShelter() {
|
||||||
|
val selected = selectedShelter
|
||||||
|
if (selected == null) {
|
||||||
|
Toast.makeText(this, R.string.share_no_shelter, Toast.LENGTH_SHORT).show()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val shelter = selected.shelter
|
||||||
|
val body = getString(
|
||||||
|
R.string.share_body,
|
||||||
|
shelter.adresse,
|
||||||
|
shelter.plasser,
|
||||||
|
shelter.latitude,
|
||||||
|
shelter.longitude
|
||||||
|
)
|
||||||
|
|
||||||
|
val shareIntent = Intent(Intent.ACTION_SEND).apply {
|
||||||
|
type = "text/plain"
|
||||||
|
putExtra(Intent.EXTRA_SUBJECT, getString(R.string.share_subject))
|
||||||
|
putExtra(Intent.EXTRA_TEXT, body)
|
||||||
|
}
|
||||||
|
startActivity(Intent.createChooser(shareIntent, getString(R.string.action_share)))
|
||||||
|
}
|
||||||
|
|
||||||
/** Update the freshness indicator below the status bar with color-coded age. */
|
/** Update the freshness indicator below the status bar with color-coded age. */
|
||||||
private fun updateFreshnessIndicator() {
|
private fun updateFreshnessIndicator() {
|
||||||
val lastUpdate = repository.getLastUpdateMs()
|
val lastUpdate = repository.getLastUpdateMs()
|
||||||
|
|
|
||||||
11
app/src/main/res/drawable/ic_share.xml
Normal file
11
app/src/main/res/drawable/ic_share.xml
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Material Design share icon -->
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFF"
|
||||||
|
android:pathData="M18,16.08c-0.76,0 -1.44,0.3 -1.96,0.77L8.91,12.7c0.05,-0.23 0.09,-0.46 0.09,-0.7s-0.04,-0.47 -0.09,-0.7l7.05,-4.11c0.54,0.5 1.25,0.81 2.04,0.81 1.66,0 3,-1.34 3,-3s-1.34,-3 -3,-3 -3,1.34 -3,3c0,0.24 0.04,0.47 0.09,0.7L8.04,9.81C7.5,9.31 6.79,9 6,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3c0.79,0 1.5,-0.31 2.04,-0.81l7.12,4.16c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.61 1.31,2.92 2.92,2.92 1.61,0 2.92,-1.31 2.92,-2.92s-1.31,-2.92 -2.92,-2.92z" />
|
||||||
|
</vector>
|
||||||
|
|
@ -211,6 +211,16 @@
|
||||||
android:textSize="13sp"
|
android:textSize="13sp"
|
||||||
tools:text="1.2 km - 400 plasser - Rom 776" />
|
tools:text="1.2 km - 400 plasser - Rom 776" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/shareButton"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:background="?attr/selectableItemBackgroundBorderless"
|
||||||
|
android:contentDescription="@string/action_share"
|
||||||
|
android:src="@drawable/ic_share"
|
||||||
|
app:tint="@color/text_secondary" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<!-- Nearest shelters list -->
|
<!-- Nearest shelters list -->
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@
|
||||||
<string name="action_cache_ok">Lagre kart</string>
|
<string name="action_cache_ok">Lagre kart</string>
|
||||||
<string name="action_cache_now">Lagre nå</string>
|
<string name="action_cache_now">Lagre nå</string>
|
||||||
<string name="action_reset_navigation">Tilbakestill navigasjonsvisning</string>
|
<string name="action_reset_navigation">Tilbakestill navigasjonsvisning</string>
|
||||||
|
<string name="action_share">Del tilfluktsrom</string>
|
||||||
<string name="warning_no_map_cache">Ingen frakoblet kart lagret. Kartet krever internett.</string>
|
<string name="warning_no_map_cache">Ingen frakoblet kart lagret. Kartet krever internett.</string>
|
||||||
|
|
||||||
<!-- Tillatelser -->
|
<!-- Tillatelser -->
|
||||||
|
|
@ -41,6 +42,7 @@
|
||||||
<string name="error_download_failed">Kunne ikke laste ned tilfluktsromdata. Sjekk internettforbindelsen.</string>
|
<string name="error_download_failed">Kunne ikke laste ned tilfluktsromdata. Sjekk internettforbindelsen.</string>
|
||||||
<string name="error_no_data_offline">Ingen lagrede data tilgjengelig. Koble til internett for å laste ned tilfluktsromdata.</string>
|
<string name="error_no_data_offline">Ingen lagrede data tilgjengelig. Koble til internett for å laste ned tilfluktsromdata.</string>
|
||||||
<string name="error_no_compass">Kompass er ikke tilgjengelig på denne enheten</string>
|
<string name="error_no_compass">Kompass er ikke tilgjengelig på denne enheten</string>
|
||||||
|
<string name="error_shelter_not_found">Fant ikke tilfluktsrommet</string>
|
||||||
<string name="update_success">Tilfluktsromdata oppdatert</string>
|
<string name="update_success">Tilfluktsromdata oppdatert</string>
|
||||||
<string name="update_failed">Oppdatering mislyktes — bruker lagrede data</string>
|
<string name="update_failed">Oppdatering mislyktes — bruker lagrede data</string>
|
||||||
|
|
||||||
|
|
@ -55,6 +57,11 @@
|
||||||
<string name="freshness_week">Data er %d dager gammel</string>
|
<string name="freshness_week">Data er %d dager gammel</string>
|
||||||
<string name="freshness_old">Data er utdatert</string>
|
<string name="freshness_old">Data er utdatert</string>
|
||||||
|
|
||||||
|
<!-- Deling -->
|
||||||
|
<string name="share_subject">Tilfluktsrom</string>
|
||||||
|
<string name="share_body">Tilfluktsrom: %1$s\n%2$d plasser\n%3$.6f, %4$.6f\ngeo:%3$.6f,%4$.6f</string>
|
||||||
|
<string name="share_no_shelter">Ingen tilfluktsrom valgt</string>
|
||||||
|
|
||||||
<!-- Tilgjengelighet -->
|
<!-- Tilgjengelighet -->
|
||||||
<string name="direction_arrow_description">Retning til tilfluktsrom, %s unna</string>
|
<string name="direction_arrow_description">Retning til tilfluktsrom, %s unna</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@
|
||||||
<string name="action_cache_ok">Lagre kart</string>
|
<string name="action_cache_ok">Lagre kart</string>
|
||||||
<string name="action_cache_now">Lagre no</string>
|
<string name="action_cache_now">Lagre no</string>
|
||||||
<string name="action_reset_navigation">Tilbakestill navigasjonsvising</string>
|
<string name="action_reset_navigation">Tilbakestill navigasjonsvising</string>
|
||||||
|
<string name="action_share">Del tilfluktsrom</string>
|
||||||
<string name="warning_no_map_cache">Ingen fråkopla kart lagra. Kartet krev internett.</string>
|
<string name="warning_no_map_cache">Ingen fråkopla kart lagra. Kartet krev internett.</string>
|
||||||
|
|
||||||
<!-- Løyve -->
|
<!-- Løyve -->
|
||||||
|
|
@ -41,6 +42,7 @@
|
||||||
<string name="error_download_failed">Kunne ikkje laste ned tilfluktsromdata. Sjekk internettilkoplinga.</string>
|
<string name="error_download_failed">Kunne ikkje laste ned tilfluktsromdata. Sjekk internettilkoplinga.</string>
|
||||||
<string name="error_no_data_offline">Ingen lagra data tilgjengeleg. Kopla til internett for å laste ned tilfluktsromdata.</string>
|
<string name="error_no_data_offline">Ingen lagra data tilgjengeleg. Kopla til internett for å laste ned tilfluktsromdata.</string>
|
||||||
<string name="error_no_compass">Kompass er ikkje tilgjengeleg på denne eininga</string>
|
<string name="error_no_compass">Kompass er ikkje tilgjengeleg på denne eininga</string>
|
||||||
|
<string name="error_shelter_not_found">Fann ikkje tilfluktsrommet</string>
|
||||||
<string name="update_success">Tilfluktsromdata oppdatert</string>
|
<string name="update_success">Tilfluktsromdata oppdatert</string>
|
||||||
<string name="update_failed">Oppdatering mislukkast — brukar lagra data</string>
|
<string name="update_failed">Oppdatering mislukkast — brukar lagra data</string>
|
||||||
|
|
||||||
|
|
@ -55,6 +57,11 @@
|
||||||
<string name="freshness_week">Data er %d dagar gammal</string>
|
<string name="freshness_week">Data er %d dagar gammal</string>
|
||||||
<string name="freshness_old">Data er utdatert</string>
|
<string name="freshness_old">Data er utdatert</string>
|
||||||
|
|
||||||
|
<!-- Deling -->
|
||||||
|
<string name="share_subject">Tilfluktsrom</string>
|
||||||
|
<string name="share_body">Tilfluktsrom: %1$s\n%2$d plassar\n%3$.6f, %4$.6f\ngeo:%3$.6f,%4$.6f</string>
|
||||||
|
<string name="share_no_shelter">Ingen tilfluktsrom valt</string>
|
||||||
|
|
||||||
<!-- Tilgjenge -->
|
<!-- Tilgjenge -->
|
||||||
<string name="direction_arrow_description">Retning til tilfluktsrom, %s unna</string>
|
<string name="direction_arrow_description">Retning til tilfluktsrom, %s unna</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@
|
||||||
<string name="action_cache_ok">Cache map</string>
|
<string name="action_cache_ok">Cache map</string>
|
||||||
<string name="action_cache_now">Cache now</string>
|
<string name="action_cache_now">Cache now</string>
|
||||||
<string name="action_reset_navigation">Reset navigation view</string>
|
<string name="action_reset_navigation">Reset navigation view</string>
|
||||||
|
<string name="action_share">Share shelter</string>
|
||||||
<string name="warning_no_map_cache">No offline map cached. Map requires internet.</string>
|
<string name="warning_no_map_cache">No offline map cached. Map requires internet.</string>
|
||||||
|
|
||||||
<!-- Permissions -->
|
<!-- Permissions -->
|
||||||
|
|
@ -41,6 +42,7 @@
|
||||||
<string name="error_download_failed">Could not download shelter data. Check your internet connection.</string>
|
<string name="error_download_failed">Could not download shelter data. Check your internet connection.</string>
|
||||||
<string name="error_no_data_offline">No cached data available. Connect to the internet to download shelter data.</string>
|
<string name="error_no_data_offline">No cached data available. Connect to the internet to download shelter data.</string>
|
||||||
<string name="error_no_compass">Compass not available on this device</string>
|
<string name="error_no_compass">Compass not available on this device</string>
|
||||||
|
<string name="error_shelter_not_found">Shelter not found</string>
|
||||||
<string name="update_success">Shelter data updated</string>
|
<string name="update_success">Shelter data updated</string>
|
||||||
<string name="update_failed">Update failed — using cached data</string>
|
<string name="update_failed">Update failed — using cached data</string>
|
||||||
|
|
||||||
|
|
@ -55,6 +57,11 @@
|
||||||
<string name="freshness_week">Data is %d days old</string>
|
<string name="freshness_week">Data is %d days old</string>
|
||||||
<string name="freshness_old">Data is outdated</string>
|
<string name="freshness_old">Data is outdated</string>
|
||||||
|
|
||||||
|
<!-- Sharing -->
|
||||||
|
<string name="share_subject">Emergency shelter</string>
|
||||||
|
<string name="share_body">Shelter: %1$s\n%2$d places\n%3$.6f, %4$.6f\ngeo:%3$.6f,%4$.6f</string>
|
||||||
|
<string name="share_no_shelter">No shelter selected</string>
|
||||||
|
|
||||||
<!-- Accessibility -->
|
<!-- Accessibility -->
|
||||||
<string name="direction_arrow_description">Direction to shelter, %s away</string>
|
<string name="direction_arrow_description">Direction to shelter, %s away</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
versionMajor=1
|
versionMajor=1
|
||||||
versionMinor=2
|
versionMinor=3
|
||||||
versionPatch=0
|
versionPatch=0
|
||||||
versionCode=3
|
versionCode=4
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue