diff --git a/example-config.yml b/example-config.yml index 6f534b86a..ee1008107 100644 --- a/example-config.yml +++ b/example-config.yml @@ -115,6 +115,7 @@ persistence: map: initLat: 45.52 initLon: -122.682 + # autoFlyOnTripFormUpdate: false baseLayers: - name: Streets # These tiles are free to use, but not in production diff --git a/lib/actions/map.js b/lib/actions/map.js index 17cb19a69..933457b2f 100644 --- a/lib/actions/map.js +++ b/lib/actions/map.js @@ -22,7 +22,7 @@ export function setMapCenter(map /* MapRef */, location) { const { lat, lon } = location if (map && !isNaN(lat) && !isNaN(lon)) { const center = [lon, lat] - map.panTo(center) + map.panTo(center, { speed: 0.8 }) } } } diff --git a/lib/components/app/responsive-webapp.js b/lib/components/app/responsive-webapp.js index 74fea9add..dc7d26f72 100644 --- a/lib/components/app/responsive-webapp.js +++ b/lib/components/app/responsive-webapp.js @@ -58,10 +58,12 @@ class ResponsiveWebapp extends Component { componentDidUpdate(prevProps) { const { activeSearchId, + autoFly, currentPosition, formChanged, intl, location, + mainPanelContent, map, matchContentToUrl, query, @@ -98,15 +100,17 @@ class ResponsiveWebapp extends Component { setLocationToCurrent({ locationType: 'from' }, intl) setMapCenter(map, pt) } - } else if (query.from && query.to) { - map?.fitBounds([query.from, query.to], { - duration: 500, - padding: getFitBoundsPadding(map, 0.2) - }) - } else if (query.from && !query.to) { - setMapCenter(map, query.from) - } else if (query.to && !query.from) { - setMapCenter(map, query.to) + } else if (mainPanelContent === null && autoFly !== false) { + if (query.from && query.to) { + map?.fitBounds([query.from, query.to], { + duration: 600, + padding: getFitBoundsPadding(map, 0.2) + }) + } else if (query.from && !query.to) { + setMapCenter(map, query.from) + } else if (query.to && !query.from) { + setMapCenter(map, query.to) + } } // If the path changes (e.g., via a back button press) check whether the @@ -259,6 +263,7 @@ const mapStateToProps = (state) => { activeSearchId: state.otp.activeSearchId, currentPosition: state.otp.location.currentPosition, locale: state.otp.ui.locale, + mainPanelContent: state.otp.ui.mainPanelContent, mobileScreen: state.otp.ui.mobileScreen, modeGroups: state.otp.config.modeGroups, popupContent: state.otp.ui.popup, @@ -415,9 +420,10 @@ class RouterWrapperWithAuth0 extends Component { } const mapStateToWrapperProps = (state) => { - const { homeTimezone, persistence, reactRouter } = state.otp.config + const { homeTimezone, map, persistence, reactRouter } = state.otp.config return { auth0Config: getAuth0Config(persistence), + autoFly: map.autoFlyOnTripFormUpdate, defaultLocale: getDefaultLocale(state.otp.config, state.user.loggedInUser), homeTimezone, locale: state.otp.ui.locale, diff --git a/lib/components/map/route-preview-overlay.tsx b/lib/components/map/route-preview-overlay.tsx index 77aa5fa96..1e071c0c3 100644 --- a/lib/components/map/route-preview-overlay.tsx +++ b/lib/components/map/route-preview-overlay.tsx @@ -15,6 +15,7 @@ import { type Props = { from: Location geometries: string[] + mainPanelContent: number | null to: Location visible?: boolean } @@ -22,17 +23,23 @@ type Props = { * This overlay will display thin gray lines for a set of geometries. It's to be used * as a stopgap until we make full use of Transitive! */ -const RoutePreviewOverlay = ({ from, geometries, to, visible }: Props) => { +const RoutePreviewOverlay = ({ + from, + geometries, + mainPanelContent, + to, + visible +}: Props) => { // Center the map over the endpoints when this overlay is shown. const { current: map } = useMap() useEffect(() => { - if (visible) { + if (visible && mainPanelContent === null) { map?.fitBounds([from, to], { - duration: 500, + duration: 600, padding: getFitBoundsPadding(map, 0.2) }) } - }, [map, visible, from, to]) + }, [map, visible, from, to, mainPanelContent]) if (!geometries || !visible) return <> @@ -77,7 +84,7 @@ const RoutePreviewOverlay = ({ from, geometries, to, visible }: Props) => { // TODO: Typescript state const mapStateToProps = (state: any) => { - const { activeSearchId, config } = state.otp + const { activeSearchId, config, ui } = state.otp // Only show this overlay if the metro UI is explicitly enabled if (config.itinerary?.showFirstResultByDefault !== false) { return {} @@ -103,6 +110,7 @@ const mapStateToProps = (state: any) => { return { from, geometries, + mainPanelContent: ui.mainPanelContent, to, visible: // We need an explicit check for undefined and null because 0 diff --git a/lib/util/config-types.ts b/lib/util/config-types.ts index 89f060b1f..22530305e 100644 --- a/lib/util/config-types.ts +++ b/lib/util/config-types.ts @@ -220,6 +220,7 @@ export type SupportedOverlays = | MapTileLayerConfig export interface MapConfig { + autoFlyOnTripFormUpdate?: boolean baseLayers?: BaseLayerConfig[] initLat?: number initLon?: number