mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-11-12 23:31:02 +00:00
e28bd2fc99
MapLibre 6 and Mapbox GL 3 both throw out of their Map constructor without WebGL2. Every place that builds a GL map now asks one helper first, components/Map/glSupport.ts, and a browser without WebGL2 gets the Leaflet map with the user's tiles instead of a map that fails to start: - the trip map (MapViewAuto) and the journey maps (JourneyMapAuto) pick their renderer through useGlRenderer, which folds in the Mapbox token rule they each had; - the settings preview, desktop and phone, shows the Leaflet preview through useMapSettingsForm and says why under it; - the tour planner keeps the 2D map when 3D is asked for and says that 3D needs WebGL2; - the PDF route map and the Leaflet vector basemap already fell back and now report a GPU failure too. Behind the probe, buildGlMap wraps each constructor (MapViewGL, JourneyMapGL, the settings preview, the terrain map, the PDF map). A GPU that claims WebGL2 and still refuses the context is reported through utils/webgl, which turns the answer to no and tells every mounted map, so they switch to Leaflet without a reload; any other error is still thrown. Two new strings, map.webgl2.fallback and map.webgl2.terrain, in all 27 locales.
57 lines
3.1 KiB
TypeScript
57 lines
3.1 KiB
TypeScript
import { Suspense } from 'react'
|
|
import { AlertTriangle, Clock, Info } from 'lucide-react'
|
|
import { Tooltip } from '../shared/Tooltip'
|
|
import { useSettingsStore } from '../../store/settingsStore'
|
|
import { MapView } from './MapView'
|
|
import ErrorBoundary from '../shared/ErrorBoundary'
|
|
import { MapViewGLMapbox, MapViewGLMaplibre } from './glLazy'
|
|
import { useGlRenderer } from './glSupport'
|
|
import { useRoadtripHazards } from './useRoadtripHazards'
|
|
import { useTranslation } from '../../i18n/TranslationContext'
|
|
import type { MapViewAutoProps, MapViewProps } from './mapViewContract'
|
|
|
|
// Auto-selects the map renderer based on user settings. Keeps the existing
|
|
// Leaflet MapView untouched so the Mapbox GL variant can mature iteratively
|
|
// behind a toggle. Atlas is not affected — it imports Leaflet directly.
|
|
//
|
|
// Offline maps: only the Leaflet renderer supports full pre-download (raster
|
|
// tiles via sync/tilePrefetcher.ts). GL maps are best-effort offline — their
|
|
// vector tiles are cached opportunistically by the Service Worker as you view
|
|
// them online (see the GL tile rules in vite.config.js), not prefetched.
|
|
export function MapViewAuto(props: MapViewAutoProps) {
|
|
const { t } = useTranslation()
|
|
const hazards = useRoadtripHazards(props.tripId, !!props.clusterLoosely)
|
|
// `dawarichTrack` arrives as a prop rather than being fetched here: the pill
|
|
// that switches it on lives at page level and needs the load status, so the
|
|
// fetch sits in useTripPlanner and both shells read the same one.
|
|
// The one cast between what callers pass and what the renderers type: pins
|
|
// without trip_id (see MapViewAutoProps). Neither renderer reads trip_id.
|
|
const mapProps = { ...props, hazards: hazards.feed?.hazards } as MapViewProps
|
|
const provider = useSettingsStore(s => s.settings.map_provider)
|
|
const token = useSettingsStore(s => s.settings.mapbox_access_token)
|
|
// Fall back to Leaflet when Mapbox is selected but no token is set, or when the
|
|
// browser has no WebGL2 (both GL engines need it), so the trip planner never
|
|
// shows an empty map or one that fails to start.
|
|
const glProvider = useGlRenderer(provider, token)
|
|
// One chunk per engine: picking the binding here is what keeps mapbox-gl and
|
|
// maplibre-gl out of each other's downloads.
|
|
const MapViewGL = glProvider === 'maplibre-gl' ? MapViewGLMaplibre : MapViewGLMapbox
|
|
if (glProvider) {
|
|
// Render the previous Leaflet map as the fallback so there's no blank flash
|
|
// while the GL chunk loads on first use.
|
|
return (
|
|
// Outside the Suspense on purpose: Suspense handles the pending promise,
|
|
// a rejected one (chunk gone after a deploy) throws past it. Falling back
|
|
// to Leaflet keeps a usable map instead of an error card.
|
|
// resetKeys: with two engine chunks, a failure under one provider must not
|
|
// keep showing Leaflet after the user switches to the other.
|
|
<ErrorBoundary boundaryId="map:gl" resetKeys={[glProvider]} fallback={<MapView {...mapProps} />}>
|
|
<Suspense fallback={<MapView {...mapProps} />}>
|
|
<MapViewGL {...mapProps} glProvider={glProvider} />
|
|
</Suspense>
|
|
</ErrorBoundary>
|
|
)
|
|
}
|
|
return <MapView {...mapProps} />
|
|
}
|