File size: 4,158 Bytes
9d2d895 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | // Map provider/theme preferences. Pure config: NO maplibre/pmtiles/protomaps
// runtime deps live here so the preferences UI (UnifiedSettings → preferences-content)
// can render without dragging maplibre+deck.gl into the entry bundle.
// maplibre-using helpers live in `./basemap-styles.ts` and are loaded
// lazily alongside MapContainer/DeckGLMap when the map panel mounts.
const R2_PROXY = import.meta.env.VITE_PMTILES_URL ?? '';
const R2_PUBLIC = import.meta.env.VITE_PMTILES_URL_PUBLIC ?? '';
const isTauri = typeof window !== 'undefined' && '__TAURI__' in window;
export const R2_BASE = isTauri && R2_PUBLIC ? R2_PUBLIC : R2_PROXY;
const hasTilesUrl = !!R2_BASE;
export type PMTilesTheme = 'black' | 'dark' | 'grayscale' | 'light' | 'white';
export type OpenFreeMapTheme = 'dark' | 'positron';
export type CartoTheme = 'dark-matter' | 'voyager' | 'positron';
export const FALLBACK_DARK_STYLE = 'https://tiles.openfreemap.org/styles/dark';
export const FALLBACK_LIGHT_STYLE = 'https://tiles.openfreemap.org/styles/positron';
export type MapProvider = 'auto' | 'pmtiles' | 'openfreemap' | 'carto';
const STORAGE_KEY = 'wm-map-provider';
const THEME_STORAGE_PREFIX = 'wm-map-theme:';
export { hasTilesUrl as hasPMTilesUrl };
function readStorageValue(key: string): string | null {
try {
return localStorage.getItem(key);
} catch {
return null;
}
}
function writeStorageValue(key: string, value: string): void {
try {
localStorage.setItem(key, value);
} catch {
// Map preferences remain at their in-memory defaults for this session.
}
}
export const MAP_PROVIDER_OPTIONS: { value: MapProvider; label: string }[] = (() => {
const opts: { value: MapProvider; label: string }[] = [];
if (hasTilesUrl) {
opts.push({ value: 'auto', label: 'Auto (PMTiles → OpenFreeMap fallback)' });
opts.push({ value: 'pmtiles', label: 'PMTiles (self-hosted)' });
}
opts.push({ value: 'openfreemap', label: 'OpenFreeMap' });
opts.push({ value: 'carto', label: 'CARTO' });
return opts;
})();
const PMTILES_THEMES: { value: string; label: string }[] = [
{ value: 'black', label: 'Black (deepest dark)' },
{ value: 'dark', label: 'Dark' },
{ value: 'grayscale', label: 'Grayscale' },
{ value: 'light', label: 'Light' },
{ value: 'white', label: 'White' },
];
export const MAP_THEME_OPTIONS: Record<MapProvider, { value: string; label: string }[]> = {
pmtiles: PMTILES_THEMES,
auto: PMTILES_THEMES,
openfreemap: [
{ value: 'dark', label: 'Dark' },
{ value: 'positron', label: 'Positron (light)' },
],
carto: [
{ value: 'dark-matter', label: 'Dark Matter' },
{ value: 'voyager', label: 'Voyager (light)' },
{ value: 'positron', label: 'Positron (light)' },
],
};
const DEFAULT_THEME: Record<MapProvider, string> = {
pmtiles: 'black',
auto: 'black',
openfreemap: 'dark',
carto: 'dark-matter',
};
export function getMapProvider(): MapProvider {
const stored = readStorageValue(STORAGE_KEY) as MapProvider | null;
if (stored) {
if (stored === 'pmtiles' || stored === 'auto') {
return hasTilesUrl ? stored : 'openfreemap';
}
return stored;
}
return hasTilesUrl ? 'auto' : 'openfreemap';
}
export function setMapProvider(provider: MapProvider): void {
writeStorageValue(STORAGE_KEY, provider);
}
export function getMapTheme(provider: MapProvider): string {
const stored = readStorageValue(THEME_STORAGE_PREFIX + provider);
const options = MAP_THEME_OPTIONS[provider];
if (stored && options.some(o => o.value === stored)) return stored;
return DEFAULT_THEME[provider];
}
export function setMapTheme(provider: MapProvider, theme: string): void {
const options = MAP_THEME_OPTIONS[provider];
if (!options.some(o => o.value === theme)) return;
writeStorageValue(THEME_STORAGE_PREFIX + provider, theme);
}
export function isLightMapTheme(mapTheme: string): boolean {
return ['light', 'white', 'positron', 'voyager'].includes(mapTheme);
}
export function asPMTilesTheme(mapTheme: string): PMTilesTheme {
const valid = PMTILES_THEMES.some(o => o.value === mapTheme);
return (valid ? mapTheme : 'black') as PMTilesTheme;
}
|