mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-21 14:36:31 +00:00
feat(roadtrip): other ways to drive a leg, on the phone
The desk offers alternative routes from the drive band between two stops; the phone had nothing. A leg in the phone chain now carries one round button that asks the router for other ways and switches to the map, where a bar takes the stage bar's place: the ways as chips with their colour, time, distance and what sets them apart, and a confirm button. On glass there is no hover, so a tap on a chip or on a line only previews that road; confirm writes it. The button shows only where the desk offers it (a routed leg between chosen stops), for someone who may edit the day, and not offline, since vias are written online only. The picker could not have stayed open on a phone at all: the planner closed it whenever road trip mode was off, and that mode is off on a phone by design, so the next render shut it. The close now follows where the picker can be seen (road trip mode on the desk, the road trip tab on a phone), and useRouteAlternatives returns a memoised object. The rules both shells need are shared: legReroutable in the row model, alternativesPhase and alternativeSubline next to the overlays, and the desk bar and sidebar read them too with no visible change. Both map engines take an optional fitPadding, so the phone frames the leg between the day chips and the bar instead of under them.
This commit is contained in:
@@ -40,7 +40,7 @@ import { resolveTrackColor, hasManualTrackColor } from './trackColors'
|
||||
import { buildPoiPopupHtml } from './placePopup'
|
||||
import { pluginsApi, type PluginMapMarker, type PluginMapLayer } from '../../api/client'
|
||||
import { DEFAULT_MAP_CENTER, DEFAULT_MAP_ZOOM, SATELLITE_TILE_URL, SATELLITE_TILE_ATTRIBUTION, SATELLITE_TILE_MAXZOOM } from '../../constants/mapDefaults'
|
||||
import { computeMapViewport, TILE_SIZE_GL } from '../../utils/mapViewport'
|
||||
import { computeMapViewport, TILE_SIZE_GL, type ViewportPadding } from '../../utils/mapViewport'
|
||||
|
||||
function categoryIconSvg(iconName: string | null | undefined, size: number): string {
|
||||
const IconComponent = (iconName && CATEGORY_ICON_MAP[iconName]) || CATEGORY_ICON_MAP['MapPin']
|
||||
@@ -185,6 +185,16 @@ interface Props {
|
||||
* needs that leg on screen, which is neither the day nor the trip.
|
||||
*/
|
||||
focusPoints?: [number, number][]
|
||||
/**
|
||||
* What the caller's own chrome covers while `focusPoints` is framed, in pixels per edge.
|
||||
*
|
||||
* The default padding knows this component's panels and nothing else, and on a phone it
|
||||
* is a flat margin. A shell that lays its own bars over the map passes what they cover,
|
||||
* so the frame lands in the part still visible. Only the fit on `focusPoints` reads it.
|
||||
* Compared by value: the same numbers in a new object do not refit, while new numbers
|
||||
* refit the points already handed over, because the chrome they must clear has moved.
|
||||
*/
|
||||
fitPadding?: ViewportPadding
|
||||
/**
|
||||
* Let markers stay apart longer than usual.
|
||||
*
|
||||
@@ -656,6 +666,7 @@ export function MapViewGL({
|
||||
zoom = DEFAULT_MAP_ZOOM,
|
||||
fitKey = 0,
|
||||
focusPoints,
|
||||
fitPadding,
|
||||
clusterLoosely = false,
|
||||
hazards,
|
||||
dawarichTrack = null,
|
||||
@@ -2206,6 +2217,10 @@ export function MapViewGL({
|
||||
if (routeArrivedForPendingFit) pendingRouteFitRef.current = null
|
||||
}, [fitKey, routeFitKey]) // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
// The caller's padding as a value, so a parent that builds the object inline on every
|
||||
// render does not move the camera each time it renders.
|
||||
const fitPaddingKey = fitPadding ? [fitPadding.top, fitPadding.right, fitPadding.bottom, fitPadding.left].join(' ') : ''
|
||||
|
||||
// Frame whatever was handed over. Nothing happens when it empties, so closing the
|
||||
// picker leaves the map where the user left it rather than snapping back.
|
||||
useEffect(() => {
|
||||
@@ -2217,13 +2232,13 @@ export function MapViewGL({
|
||||
pendingRouteFitRef.current = null
|
||||
try {
|
||||
map.fitBounds(bounds, {
|
||||
padding: paddingOpts,
|
||||
padding: fitPadding ?? paddingOpts,
|
||||
maxZoom: 15,
|
||||
pitch: enableMapbox3d ? 45 : 0,
|
||||
duration: 400,
|
||||
})
|
||||
} catch { /* noop */ }
|
||||
}, [focusPoints]) // eslint-disable-line react-hooks/exhaustive-deps
|
||||
}, [focusPoints, fitPaddingKey]) // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
// flyTo selected place
|
||||
useEffect(() => {
|
||||
|
||||
Reference in New Issue
Block a user