feat!: improve saving locations
All checks were successful
TrafficCue CI / check (push) Successful in 1m6s
TrafficCue CI / build (push) Successful in 48s

Shows saved home and work locations with a marker on the map and provides a better API for saved locations opening room for more locations in the future

BREAKING CHANGE: no longer uses saved.home, saved.work localStorage entries, locations need to be re-entered to use the saved entry instead
This commit is contained in:
Cfp
2025-07-12 10:54:22 +02:00
parent 4b20143480
commit 4b520be5f9
7 changed files with 61 additions and 15 deletions

BIN
public/img/saved/home.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

BIN
public/img/saved/work.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

View File

@ -15,6 +15,7 @@
} from "$lib/services/navigation/routing.svelte";
import { location } from "./location.svelte";
import { protocol } from "$lib/services/OfflineTiles";
import { saved } from "$lib/saved.svelte";
onMount(() => {
window.addEventListener("resize", map.updateMapPadding);
@ -23,6 +24,8 @@
let locationDot: HTMLDivElement | undefined = $state();
let locationAccuracyCircle: HTMLDivElement | undefined = $state();
let homeMarker: HTMLImageElement | undefined = $state();
let workMarker: HTMLImageElement | undefined = $state();
const DEBUG_POINTS = false; // Set to true to show debug points on the map
</script>
@ -63,6 +66,7 @@
class="w-full h-full"
style="/style.json"
bind:map={map.value}
bind:zoom={map.zoom}
padding={map.padding}
onload={async () => {
map.updateMapPadding();
@ -119,7 +123,7 @@
enableHighAccuracy: true,
}}
trackUserLocation={true}
autoTrigger={true}
autoTrigger={true}""
ongeolocate={(e: GeolocationPosition) => {
const speed = Math.round((e.coords.speed || 0) * 3.6); // In km/h
const accuracy = Math.round(e.coords.accuracy);
@ -133,6 +137,36 @@
{#if pin.isDropped}
<Marker lnglat={{ lat: pin.lat, lng: pin.lng }} />
{/if}
{#if saved.home && map.zoom > 9}
<img
src="/img/saved/home.png"
alt="Home Marker"
bind:this={homeMarker}
style="width: 32px;"
/>
<Marker
lnglat={{
lat: saved.home.lat,
lng: saved.home.lon,
}}
element={homeMarker}
/>
{/if}
{#if saved.work && map.zoom > 9}
<img
src="/img/saved/work.png"
alt="Work Marker"
bind:this={workMarker}
style="width: 32px;"
/>
<Marker
lnglat={{
lat: saved.work.lat,
lng: saved.work.lon,
}}
element={workMarker}
/>
{/if}
{#if routing.geojson.routePast}
<GeoJSONSource id="route-past" data={routing.geojson.routePast}>

View File

@ -7,6 +7,7 @@ import { view } from "./sidebar.svelte";
export const map = $state({
value: undefined as maplibregl.Map | undefined,
zoom: 0,
updateMapPadding: () => {
if (document.querySelector<HTMLDivElement>("#sidebar") == null) {
map._setPadding({

View File

@ -21,6 +21,7 @@
import Reviews from "../info/Reviews.svelte";
import MapAi from "../info/MapAI.svelte";
import RequiresCapability from "../RequiresCapability.svelte";
import { saved, saveLocations } from "$lib/saved.svelte";
// let { feature }: { feature: Feature } = $props();
@ -170,10 +171,12 @@
<Button
variant="outline"
onclick={() => {
localStorage.setItem(
"saved.home",
JSON.stringify({ lat, lon: lng }),
);
// localStorage.setItem(
// "saved.home",
// JSON.stringify({ lat, lon: lng }),
// );
saved.home = { lat, lon: lng };
saveLocations();
}}
>
<HomeIcon />
@ -182,10 +185,12 @@
<Button
variant="outline"
onclick={() => {
localStorage.setItem(
"saved.work",
JSON.stringify({ lat, lon: lng }),
);
// localStorage.setItem(
// "saved.work",
// JSON.stringify({ lat, lon: lng }),
// );
saved.work = { lat, lon: lng };
saveLocations();
}}
>
<BriefcaseIcon />

View File

@ -7,6 +7,7 @@
import VehicleSelector from "../VehicleSelector.svelte";
import Post from "../Post.svelte";
import RequiresCapability from "../RequiresCapability.svelte";
import { saved } from "$lib/saved.svelte";
</script>
<div
@ -18,12 +19,11 @@
variant="secondary"
class="flex-1"
onclick={() => {
const home = localStorage.getItem("saved.home");
if (!home) {
const { lat, lon } = saved.home;
if (!lat || !lon) {
alert("No home location saved.");
return;
}
const { lat, lon } = JSON.parse(home);
pin.dropPin(lat, lon);
pin.showInfo();
map.value?.flyTo({
@ -39,12 +39,11 @@
variant="secondary"
class="flex-1"
onclick={() => {
const work = localStorage.getItem("saved.work");
if (!work) {
const { lat, lon } = saved.work;
if (!lat || !lon) {
alert("No work location saved.");
return;
}
const { lat, lon } = JSON.parse(work);
pin.dropPin(lat, lon);
pin.showInfo();
map.value?.flyTo({

7
src/lib/saved.svelte.ts Normal file
View File

@ -0,0 +1,7 @@
export const saved: Record<string, WorldLocation> = $state(
JSON.parse(localStorage.getItem("saved") ?? "{}"),
);
export function saveLocations() {
localStorage.setItem("saved", JSON.stringify(saved));
}