PWA: vis dyplenket tilfluktsrom nederst i lista med badge (hybrid)
Speiler Android-fiksen i 1fb9f14/337e9b9. Når en dyplenke eller markørtap velger et tilfluktsrom utenfor de N nærmeste, ble det tidligere unshift-et inn på indeks 0 og framstod som nærmest — uten forklaring. Nå: - app.ts: push i stedet for unshift på begge steder, valgt indeks = siste; ny modultilstand outsideNearestRomnr og renderShelterList()-helper - shelter-list.ts: updateList() tar outsideNearestRomnr, tegner badge på den raden, prefikser badge-teksten i aria-label (samme rekkefølge som contentDescription i ShelterListAdapter.kt) og scrollIntoView() til valgt rad (auto i stedet for smooth ved prefers-reduced-motion) - main.css: .shelter-item-badge med #BF360C (= warning_bg på Android, ~5.6:1 mot hvit → WCAG 2.2 AA SC 1.4.3) - i18n en/nb/nn: shelter_outside_nearest_badge Verifisert i Chromium (Playwright): posisjon Oslo, dyplenke /shelter/1681 (Vardø) → tre nærmeste først, fjerde rad med badge, selected og aria-label "Selected (outside nearest). Kaigaten 8 …, 1487.1 km …". Forgejo: #17 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FrDGDmN2WAXvNPS85rWJGK
This commit is contained in:
parent
5365c99bf5
commit
6a50d86266
7 changed files with 98 additions and 10 deletions
|
|
@ -28,6 +28,11 @@ const NEAREST_COUNT = 3;
|
|||
let allShelters: Shelter[] = [];
|
||||
let nearestShelters: ShelterWithDistance[] = [];
|
||||
let selectedShelterIndex = 0;
|
||||
// romnr of a user-selected shelter that has been appended to the list because
|
||||
// it is outside the geographic top-N (deep link, marker tap). null when the
|
||||
// selection is a genuine top-N entry. Drives the "outside nearest" badge in
|
||||
// the list — mirrors ShelterListItem.isOutsideNearest in the Android app.
|
||||
let outsideNearestRomnr: number | null = null;
|
||||
let currentLocation: LatLon | null = null;
|
||||
let deviceHeading = 0;
|
||||
let isCompassMode = false;
|
||||
|
|
@ -248,6 +253,15 @@ function startLocationUpdates(): void {
|
|||
);
|
||||
}
|
||||
|
||||
/** Re-render the bottom-sheet list from current module state. */
|
||||
function renderShelterList(): void {
|
||||
shelterList.updateList(
|
||||
nearestShelters,
|
||||
selectedShelterIndex,
|
||||
outsideNearestRomnr,
|
||||
);
|
||||
}
|
||||
|
||||
function updateNearestShelters(location: LatLon): void {
|
||||
if (allShelters.length === 0) return;
|
||||
|
||||
|
|
@ -268,10 +282,14 @@ function updateNearestShelters(location: LatLon): void {
|
|||
);
|
||||
if (inList >= 0) {
|
||||
selectedShelterIndex = inList;
|
||||
outsideNearestRomnr = null;
|
||||
} else {
|
||||
const shelter = allShelters.find((s) => s.romnr === selectedRomnr);
|
||||
if (shelter) {
|
||||
nearestShelters.unshift({
|
||||
// Append (not prepend) so the list keeps its sorted-by-distance
|
||||
// invariant; the badge explains why this row is here. Same hybrid
|
||||
// approach as MainActivity.rebuildShelterList() on Android.
|
||||
nearestShelters.push({
|
||||
shelter,
|
||||
distanceMeters: distanceMeters(
|
||||
location.latitude, location.longitude,
|
||||
|
|
@ -282,20 +300,23 @@ function updateNearestShelters(location: LatLon): void {
|
|||
shelter.latitude, shelter.longitude,
|
||||
),
|
||||
});
|
||||
selectedShelterIndex = 0;
|
||||
selectedShelterIndex = nearestShelters.length - 1;
|
||||
outsideNearestRomnr = shelter.romnr;
|
||||
} else {
|
||||
// Selected shelter no longer exists in the dataset (e.g. DSB
|
||||
// decommissioned it). Fall back to nearest.
|
||||
selectedRomnr = null;
|
||||
userSelectedShelter = false;
|
||||
selectedShelterIndex = 0;
|
||||
outsideNearestRomnr = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
selectedShelterIndex = 0;
|
||||
outsideNearestRomnr = null;
|
||||
}
|
||||
|
||||
shelterList.updateList(nearestShelters, selectedShelterIndex);
|
||||
renderShelterList();
|
||||
updateSelectedShelter(false);
|
||||
|
||||
statusBar.setStatus(t('status_shelters_loaded', allShelters.length));
|
||||
|
|
@ -337,7 +358,7 @@ function updateSelectedShelter(isUserAction: boolean): void {
|
|||
compassView.setNorthAngle(-deviceHeading);
|
||||
|
||||
// Update shelter list selection
|
||||
shelterList.updateList(nearestShelters, selectedShelterIndex);
|
||||
renderShelterList();
|
||||
|
||||
// Update map: highlight selected and optionally fit view
|
||||
if (isUserAction) {
|
||||
|
|
@ -503,13 +524,15 @@ function selectShelterByData(shelter: Shelter): void {
|
|||
)
|
||||
: NaN;
|
||||
|
||||
nearestShelters.unshift({
|
||||
// Append rather than prepend — see updateNearestShelters().
|
||||
nearestShelters.push({
|
||||
shelter,
|
||||
distanceMeters: dist,
|
||||
bearingDegrees: bearing,
|
||||
});
|
||||
selectedShelterIndex = 0;
|
||||
shelterList.updateList(nearestShelters, selectedShelterIndex);
|
||||
selectedShelterIndex = nearestShelters.length - 1;
|
||||
outsideNearestRomnr = shelter.romnr;
|
||||
renderShelterList();
|
||||
}
|
||||
|
||||
updateSelectedShelter(true);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue