From 7e666c77d1e9b29a5b8d6334113e4bf3a80f052a Mon Sep 17 00:00:00 2001 From: Pietro Bonaldo Date: Wed, 8 Oct 2025 21:52:41 +0200 Subject: [PATCH] Allow restricting world map to visited region --- client/components/WorldMap.tsx | 47 +++++++++++++++++++++++++++++++++ client/pages/New.tsx | 2 +- client/pages/Settings.tsx | 8 ++++++ client/storage/configStorage.ts | 7 +++-- 4 files changed, 61 insertions(+), 3 deletions(-) diff --git a/client/components/WorldMap.tsx b/client/components/WorldMap.tsx index 881d351..1d32e0b 100644 --- a/client/components/WorldMap.tsx +++ b/client/components/WorldMap.tsx @@ -5,6 +5,19 @@ import API from '../api'; import ConfigStorage from '../storage/configStorage'; import { Coord, Trajectory } from '../models'; +interface BoundsInterface { + south: number; + north: number; + west: number; + east: number; +} +const defaultBounds: BoundsInterface = { + south: -90, + north: 90, + west: -180, + east: 180 +} + interface MapGeographiesProps { lines: Trajectory[]; markers: Coord[]; @@ -83,13 +96,45 @@ function MapFeatures({ lines, markers, zoom }: MapGeographiesProps) { export default function WorldMap() { const [lines, setLines] = useState([]); const [markers, setMarkers] = useState([]); + const [initialZoom, setInitialZoom] = useState(1); const [zoom, setZoom] = useState(1); + const [center, setCenter] = useState<[number, number]>([0, 0]) useEffect(() => { API.get("/geography/decorations") .then((data: [Trajectory[], Coord[]]) => { setLines(data[0]); setMarkers(data[1]); + + if (data[1] && data[1].length > 1 && ConfigStorage.getSetting("restrictWorldMap") === "true") { + // find bounding box defined by visited airports + // i.e. get southernmost, eastmost, northmost, westmost + // visited airports + const latitudes = data[1].map(coord => coord.latitude); + const longitudes = data[1].map(coord => coord.longitude); + + const south = Math.min(...latitudes); + const north = Math.max(...latitudes); + const west = Math.min(...longitudes); + const east = Math.max(...longitudes); + + // compute center + const centerLon = (west + east) / 2; + const centerLat = (south + north) / 2; + setCenter([centerLon, centerLat]); + + // compute zoom + const lonSpan = east - west; + const latSpan = north - south; + const maxSpan = Math.max(lonSpan, latSpan); + const computedZoom = Math.min(150 / maxSpan, 3); + setInitialZoom(computedZoom); + + if (computedZoom < 1) { + setInitialZoom(1); + setCenter([0, 0]); + } + } }); }, []); @@ -98,6 +143,8 @@ export default function WorldMap() { { if (newZoom != zoom) setZoom(newZoom) }}> diff --git a/client/pages/New.tsx b/client/pages/New.tsx index fc2665c..eefb304 100644 --- a/client/pages/New.tsx +++ b/client/pages/New.tsx @@ -143,7 +143,7 @@ export default function New() { if (payload.length == 1) { API.post(`/flights?timezones=${localAirportTime}`, payload[0]) - .then(flightID => navigate(`/flights?id=${flightID})`)); + .then(flightID => navigate(`/flights?id=${flightID}`)); } else { API.post(`/flights/many?timezones=${localAirportTime}`, payload) .then(creatorFlightID => navigate(`/flights?id=${creatorFlightID}`)); diff --git a/client/pages/Settings.tsx b/client/pages/Settings.tsx index 57f39ff..87e4f58 100644 --- a/client/pages/Settings.tsx +++ b/client/pages/Settings.tsx @@ -246,6 +246,14 @@ export default function Settings() { onChange={changeOption} /> +
+
+
diff --git a/client/storage/configStorage.ts b/client/storage/configStorage.ts index 57148d5..53d670b 100644 --- a/client/storage/configStorage.ts +++ b/client/storage/configStorage.ts @@ -5,12 +5,14 @@ export interface ConfigInterface { showVisitedCountries: string; metricUnits: string; localAirportTime: string; + restrictWorldMap: string; } const ConfigKeys = ["frequencyBasedMarker", "frequencyBasedLine", "showVisitedCountries", "metricUnits", - "localAirportTime"]; + "localAirportTime", + "restrictWorldMap"]; type Config = typeof ConfigKeys[number]; const defaultConfig: ConfigInterface = { @@ -18,7 +20,8 @@ const defaultConfig: ConfigInterface = { frequencyBasedLine: "false", showVisitedCountries: "false", metricUnits: "true", - localAirportTime: "true" + localAirportTime: "true", + restrictWorldMap: "false", } class ConfigStorageClass {