180 lines
5.3 KiB
TypeScript
180 lines
5.3 KiB
TypeScript
import { persisted } from 'svelte-persisted-store';
|
|
|
|
export interface GeoLocation {
|
|
id: number;
|
|
name: string;
|
|
latitude: number;
|
|
longitude: number;
|
|
elevation: number;
|
|
feature_code: string;
|
|
country_code: string | undefined;
|
|
admin1_id: number | undefined;
|
|
admin3_id?: number | undefined;
|
|
admin4_id?: number | undefined;
|
|
timezone: string;
|
|
population: number | undefined;
|
|
postcodes: string[] | undefined;
|
|
country_id: number | undefined;
|
|
country: string | undefined;
|
|
admin1: string | undefined;
|
|
admin3?: string | undefined;
|
|
admin4?: string | undefined;
|
|
}
|
|
|
|
export const defaultLocation: GeoLocation = {
|
|
id: 2950159,
|
|
name: 'Berlin',
|
|
latitude: 52.52437,
|
|
longitude: 13.41053,
|
|
elevation: 74,
|
|
feature_code: 'PPLC',
|
|
country_code: 'DE',
|
|
admin1_id: 2950157,
|
|
admin3_id: 6547383,
|
|
admin4_id: 6547539,
|
|
timezone: 'Europe/Berlin',
|
|
population: 3426354,
|
|
postcodes: ['10967', '13347'],
|
|
country_id: 2921044,
|
|
country: 'Germany',
|
|
admin1: 'Land Berlin',
|
|
admin3: 'Berlin, Stadt',
|
|
admin4: 'Berlin'
|
|
};
|
|
|
|
export const storedLocation = persisted('stored_location', defaultLocation as GeoLocation);
|
|
|
|
export type Theme = 'system' | 'light' | 'dark';
|
|
|
|
export const storedTheme = persisted<Theme>('theme', 'system');
|
|
|
|
/** Selected forecast model, shared across the whole site. */
|
|
export const storedModel = persisted<string>('selected_model', 'best_match');
|
|
|
|
/** Which variables are visible in the hourly table and the meteograms. */
|
|
export interface VariablePrefs {
|
|
table: Record<string, boolean>;
|
|
charts: Record<string, boolean>;
|
|
}
|
|
|
|
export const defaultVariablePrefs: VariablePrefs = {
|
|
table: {
|
|
icons: true,
|
|
temperature: true,
|
|
feels: true,
|
|
wind: true,
|
|
humidity: true,
|
|
clouds: true,
|
|
precipitation: true,
|
|
// extra rows, off by default
|
|
dew_point: false,
|
|
gusts: false,
|
|
pressure: false,
|
|
uv: false,
|
|
visibility: false,
|
|
snowfall: false
|
|
},
|
|
charts: {
|
|
temperature: true,
|
|
cloud_cover: true,
|
|
precipitation: true,
|
|
precipitation_probability: true,
|
|
wind: true,
|
|
humidity: true
|
|
}
|
|
};
|
|
|
|
export const storedVariablePrefs = persisted<VariablePrefs>('variable_prefs', defaultVariablePrefs);
|
|
|
|
/** Order of the hourly-table rows (visibility is the separate toggle above). */
|
|
export const defaultTableRowOrder: string[] = [
|
|
'icons',
|
|
'temperature',
|
|
'feels',
|
|
'dew_point',
|
|
'wind',
|
|
'gusts',
|
|
'humidity',
|
|
'clouds',
|
|
'pressure',
|
|
'uv',
|
|
'visibility',
|
|
'precipitation',
|
|
'snowfall'
|
|
];
|
|
|
|
export const storedTableRowOrder = persisted<string[]>('table_row_order_v1', defaultTableRowOrder);
|
|
|
|
/**
|
|
* Normalizes a stored row order against the known rows: drops keys that no
|
|
* longer exist and appends new rows (added after the user last saved) at the
|
|
* end, so stored orders survive app updates.
|
|
*/
|
|
export function mergeTableRowOrder(stored: string[]): string[] {
|
|
return [
|
|
...stored.filter((k) => defaultTableRowOrder.includes(k)),
|
|
...defaultTableRowOrder.filter((k) => !stored.includes(k))
|
|
];
|
|
}
|
|
|
|
/** Hourly table interval: 3-hourly (default) or 1-hourly. */
|
|
export const storedHourlyInterval = persisted<1 | 3>('hourly_interval', 3);
|
|
|
|
/**
|
|
* Meteogram layout: an ordered list of chart panels, each holding an ordered
|
|
* list of variable keys (see the chart variable registry). Users drag
|
|
* variables between panels to fully customise the meteograms.
|
|
*/
|
|
export interface ChartPanel {
|
|
id: string;
|
|
variables: string[];
|
|
}
|
|
|
|
export const defaultChartLayout: ChartPanel[] = [
|
|
{ id: 'panel-1', variables: ['temperature', 'weather_icons'] },
|
|
{ id: 'panel-2', variables: ['precipitation', 'precipitation_probability', 'cloud_cover'] },
|
|
{ id: 'panel-3', variables: ['wind', 'wind_gusts', 'wind_direction'] }
|
|
];
|
|
|
|
export const storedChartLayout = persisted<ChartPanel[]>('chart_layout_v1', defaultChartLayout);
|
|
|
|
/**
|
|
* Time range the meteograms open on. 'auto' narrows to three days on a phone,
|
|
* where a full week of hours is too dense to read, and shows everything on
|
|
* roomier screens.
|
|
*/
|
|
export type ChartRangePref = 'auto' | 'today' | '3d' | '5d' | 'all';
|
|
|
|
export const storedChartRange = persisted<ChartRangePref>('chart_range_v1', 'auto');
|
|
|
|
/** Selected ensemble model for the 14-day spread forecast. */
|
|
export const storedEnsembleModel = persisted<string>('ensemble_model', 'ncep_gefs_seamless');
|
|
|
|
/** Reanalysis used on the historical page, and the seasonal model. */
|
|
export const storedArchiveModel = persisted<string>('archive_model', 'best_match');
|
|
export const storedSeasonalModel = persisted<string>('seasonal_model', 'best_match');
|
|
|
|
/** Measurement units, shared across every forecast page and persisted. */
|
|
export interface UnitPrefs {
|
|
temperature_unit: 'celsius' | 'fahrenheit';
|
|
wind_speed_unit: 'kmh' | 'ms' | 'mph' | 'kn';
|
|
precipitation_unit: 'mm' | 'inch';
|
|
}
|
|
|
|
export const defaultUnits: UnitPrefs = {
|
|
temperature_unit: 'celsius',
|
|
wind_speed_unit: 'kmh',
|
|
precipitation_unit: 'mm'
|
|
};
|
|
|
|
export const storedUnits = persisted<UnitPrefs>('units_v1', defaultUnits);
|
|
|
|
/** Recently visited and starred locations, shown in the search dropdown. */
|
|
export const storedRecentLocations = persisted<GeoLocation[]>('recent_locations_v1', []);
|
|
export const storedFavoriteLocations = persisted<GeoLocation[]>('favorite_locations_v1', []);
|
|
|
|
/** Stable key for de-duping locations (geocoding id, or rounded coordinates). */
|
|
export function locationKey(l: GeoLocation): string {
|
|
return l.id && l.id !== 0 ? `id:${l.id}` : `c:${l.latitude.toFixed(3)},${l.longitude.toFixed(3)}`;
|
|
}
|