feat(prefs): drop redundant unit-override; distances auto m/ft under a km/mi, else km/mi
All checks were successful
CI / test-and-build (push) Successful in 41s
All checks were successful
CI / test-and-build (push) Successful in 41s
This commit is contained in:
parent
149d7942dd
commit
f46d604546
15
README.md
15
README.md
@ -224,9 +224,12 @@ The matcher:
|
|||||||
|
|
||||||
## Preferences & Units
|
## Preferences & Units
|
||||||
|
|
||||||
Click **⚙ Preferences** in the top bar to choose **Metric** or **Imperial** units.
|
Click **⚙ Preferences** in the top bar to choose the **unit system** — **Metric**
|
||||||
Your choice (and the granular unit override) is saved to `localStorage`, so it
|
or **Imperial**. The choice is saved to `localStorage`, so it persists across
|
||||||
persists across reloads and is shared by the Directions panel.
|
reloads and is shared by the Directions panel.
|
||||||
|
|
||||||
|
Units are auto-selected within the chosen system: **m/ft under a kilometer/mile,
|
||||||
|
otherwise km/mi** (e.g. `820 m`, `1.9 km`; `900 ft`, `1.2 mi`).
|
||||||
|
|
||||||
## Directions & Routing
|
## Directions & Routing
|
||||||
|
|
||||||
@ -237,9 +240,9 @@ button appears in the top bar. Opening it lets you:
|
|||||||
- **Avoid certain POI categories** along the route (schools, fire stations,
|
- **Avoid certain POI categories** along the route (schools, fire stations,
|
||||||
fuel stations, parking, restaurants, …).
|
fuel stations, parking, restaurants, …).
|
||||||
- **Compute** a route and **draw it** on the map.
|
- **Compute** a route and **draw it** on the map.
|
||||||
- Choose a **unit system** (Metric or Imperial) and **units** (`m`/`km` or
|
- Choose a **unit system** (Metric or Imperial; distances auto-switch between
|
||||||
`ft`/`mi`, or `Auto` — which uses the small unit for short routes and the
|
m/ft and km/mi at the km/mile boundary), plus a **travel mode** (Drive or
|
||||||
large one for long routes), plus a **travel mode** (Drive or Walk).
|
Walk).
|
||||||
- See the route's **distance** and an **estimated travel time** (computed from
|
- See the route's **distance** and an **estimated travel time** (computed from
|
||||||
the mode's average speed).
|
the mode's average speed).
|
||||||
- **Turn-by-turn directions** (*Head north*, *Turn right*, *Arrive at destination*,
|
- **Turn-by-turn directions** (*Head north*, *Turn right*, *Arrive at destination*,
|
||||||
|
|||||||
@ -42,45 +42,28 @@
|
|||||||
];
|
];
|
||||||
const selected = $state<Record<string, boolean>>({});
|
const selected = $state<Record<string, boolean>>({});
|
||||||
|
|
||||||
// Format a metric distance (meters) into the chosen unit system.
|
// Format a metric distance (meters) for a given unit system, auto-selecting
|
||||||
function formatDistance(m: number): string {
|
// the small/large unit: use ft/m under a mile/km, otherwise mi/km.
|
||||||
if ($prefs.system === 'imperial') {
|
function fmtFor(m: number, sys: 'metric' | 'imperial'): string {
|
||||||
|
if (sys === 'imperial') {
|
||||||
const ft = m * 3.28084;
|
const ft = m * 3.28084;
|
||||||
|
if (ft < 5280) return `${ft < 10 ? ft.toFixed(1) : Math.round(ft)} ft`;
|
||||||
const mi = m / 1609.344;
|
const mi = m / 1609.344;
|
||||||
const useFt = $prefs.unit === 'ft' || ($prefs.unit === 'auto' && ft < 528);
|
|
||||||
if (useFt) {
|
|
||||||
const v = ft < 10 ? ft.toFixed(1) : Math.round(ft).toString();
|
|
||||||
return `${v} ft`;
|
|
||||||
}
|
|
||||||
return mi < 10 ? `${mi.toFixed(2)} mi` : `${mi.toFixed(1)} mi`;
|
return mi < 10 ? `${mi.toFixed(2)} mi` : `${mi.toFixed(1)} mi`;
|
||||||
}
|
}
|
||||||
const useM = $prefs.unit === 'm' || ($prefs.unit === 'auto' && m < 1000);
|
if (m < 1000) return `${m < 10 ? m.toFixed(1) : Math.round(m)} m`;
|
||||||
if (useM) {
|
|
||||||
const v = m < 10 ? m.toFixed(1) : Math.round(m).toString();
|
|
||||||
return `${v} m`;
|
|
||||||
}
|
|
||||||
const km = m / 1000;
|
const km = m / 1000;
|
||||||
return km < 10 ? `${km.toFixed(2)} km` : `${km.toFixed(1)} km`;
|
return km < 10 ? `${km.toFixed(2)} km` : `${km.toFixed(1)} km`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formatDistance(m: number): string {
|
||||||
|
return fmtFor(m, $prefs.system);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show the same distance in the OTHER unit system (e.g. "3.31 mi (5.33 km)").
|
||||||
function formatAlt(m: number): string | null {
|
function formatAlt(m: number): string | null {
|
||||||
if ($prefs.unit !== 'auto') {
|
const other: 'metric' | 'imperial' = $prefs.system === 'metric' ? 'imperial' : 'metric';
|
||||||
if ($prefs.system === 'metric') {
|
return fmtFor(m, other);
|
||||||
if ($prefs.unit === 'm') return `${(m / 1000).toFixed(2)} km`;
|
|
||||||
if ($prefs.unit === 'km') return m < 1000 ? `${Math.round(m)} m` : null;
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
if ($prefs.unit === 'ft') return `${(m / 1609.344).toFixed(2)} mi`;
|
|
||||||
if ($prefs.unit === 'mi') return ftAlt(m);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($prefs.system === 'metric') return m >= 1000 ? `${Math.round(m)} m` : null;
|
|
||||||
return m >= 160.934 ? `${Math.round(m * 3.28084)} ft` : null;
|
|
||||||
}
|
|
||||||
function ftAlt(m: number): string | null {
|
|
||||||
const ft = m * 3.28084;
|
|
||||||
return ft >= 528 ? null : `${Math.round(ft)} ft`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatTime(m: number): string {
|
function formatTime(m: number): string {
|
||||||
@ -227,19 +210,6 @@
|
|||||||
<option value="imperial">Imperial</option>
|
<option value="imperial">Imperial</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
|
||||||
<label for="dir-unit">Units</label>
|
|
||||||
<select id="dir-unit" bind:value={$prefs.unit}>
|
|
||||||
<option value="auto">Auto</option>
|
|
||||||
{#if $prefs.system === 'metric'}
|
|
||||||
<option value="m">m</option>
|
|
||||||
<option value="km">km</option>
|
|
||||||
{:else}
|
|
||||||
<option value="ft">ft</option>
|
|
||||||
<option value="mi">mi</option>
|
|
||||||
{/if}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label for="dir-mode">Mode</label>
|
<label for="dir-mode">Mode</label>
|
||||||
<select id="dir-mode" bind:value={mode}>
|
<select id="dir-mode" bind:value={mode}>
|
||||||
|
|||||||
@ -394,20 +394,7 @@
|
|||||||
<option value="imperial">Imperial (ft / mi)</option>
|
<option value="imperial">Imperial (ft / mi)</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="pref-row">
|
<div class="pref-hint">Distances use m/ft under a km/mile, otherwise km/mi. Saved to this browser (localStorage).</div>
|
||||||
<span class="pref-label">Default units</span>
|
|
||||||
<select bind:value={$prefs.unit}>
|
|
||||||
<option value="auto">Auto</option>
|
|
||||||
{#if $prefs.system === 'metric'}
|
|
||||||
<option value="m">m</option>
|
|
||||||
<option value="km">km</option>
|
|
||||||
{:else}
|
|
||||||
<option value="ft">ft</option>
|
|
||||||
<option value="mi">mi</option>
|
|
||||||
{/if}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="pref-hint">Saved to this browser (localStorage).</div>
|
|
||||||
<button class="pref-close" onclick={() => (showPrefs = false)}>Done</button>
|
<button class="pref-close" onclick={() => (showPrefs = false)}>Done</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,9 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* prefs.ts — shared, persisted user preferences (Svelte writable store).
|
* prefs.ts — shared, persisted user preferences (Svelte writable store).
|
||||||
* ----------------------------------------------------------------------
|
* ----------------------------------------------------------------------
|
||||||
* Currently stores the unit system (Metric/Imperial) and the granular unit
|
* Currently stores the unit system (Metric/Imperial) for distance display.
|
||||||
* override used by the Directions panel. Values are persisted to localStorage
|
* Values are persisted to localStorage so they survive reloads.
|
||||||
* so they survive reloads.
|
|
||||||
*
|
*
|
||||||
* Usage in runes mode:
|
* Usage in runes mode:
|
||||||
* import { prefs } from '$lib/prefs';
|
* import { prefs } from '$lib/prefs';
|
||||||
@ -14,22 +13,17 @@
|
|||||||
import { writable } from 'svelte/store';
|
import { writable } from 'svelte/store';
|
||||||
|
|
||||||
export type UnitSystem = 'metric' | 'imperial';
|
export type UnitSystem = 'metric' | 'imperial';
|
||||||
export type UnitOverride = 'auto' | 'm' | 'km' | 'ft' | 'mi';
|
|
||||||
|
|
||||||
export interface Prefs {
|
export interface Prefs {
|
||||||
system: UnitSystem;
|
system: UnitSystem;
|
||||||
unit: UnitOverride;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const KEY = 'navigator.prefs.v1';
|
const KEY = 'navigator.prefs.v1';
|
||||||
const DEFAULTS: Prefs = { system: 'metric', unit: 'auto' };
|
const DEFAULTS: Prefs = { system: 'metric' };
|
||||||
|
|
||||||
function isValidSystem(v: unknown): v is UnitSystem {
|
function isValidSystem(v: unknown): v is UnitSystem {
|
||||||
return v === 'metric' || v === 'imperial';
|
return v === 'metric' || v === 'imperial';
|
||||||
}
|
}
|
||||||
function isValidUnit(v: unknown): v is UnitOverride {
|
|
||||||
return v === 'auto' || v === 'm' || v === 'km' || v === 'ft' || v === 'mi';
|
|
||||||
}
|
|
||||||
|
|
||||||
function load(): Prefs {
|
function load(): Prefs {
|
||||||
try {
|
try {
|
||||||
@ -37,8 +31,7 @@ function load(): Prefs {
|
|||||||
if (!raw) return { ...DEFAULTS };
|
if (!raw) return { ...DEFAULTS };
|
||||||
const parsed = JSON.parse(raw) as Partial<Prefs>;
|
const parsed = JSON.parse(raw) as Partial<Prefs>;
|
||||||
return {
|
return {
|
||||||
system: isValidSystem(parsed.system) ? parsed.system : DEFAULTS.system,
|
system: isValidSystem(parsed.system) ? parsed.system : DEFAULTS.system
|
||||||
unit: isValidUnit(parsed.unit) ? parsed.unit : DEFAULTS.unit
|
|
||||||
};
|
};
|
||||||
} catch {
|
} catch {
|
||||||
return { ...DEFAULTS };
|
return { ...DEFAULTS };
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user