From 265dcd047ad01e137de64b91b6f69115c0170418 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Wed, 22 Jan 2025 09:11:22 +0200 Subject: [PATCH 1/4] feat: compute remaining current leg distance at navi root It seems that we need the length of current leg tail in many places. Compute it once and pass to children as a prop. --- app/component/itinerary/navigator/NaviCard.js | 18 +++++++++----- .../itinerary/navigator/NaviCardContainer.js | 11 ++++----- .../itinerary/navigator/NaviContainer.js | 6 ++--- .../itinerary/navigator/NaviInstructions.js | 24 ++++--------------- .../itinerary/navigator/NaviUtils.js | 15 +++++++----- .../navigator/hooks/useRealtimeLegs.js | 7 ++++-- 6 files changed, 37 insertions(+), 44 deletions(-) diff --git a/app/component/itinerary/navigator/NaviCard.js b/app/component/itinerary/navigator/NaviCard.js index c2443ca2f8..9f4aed3cae 100644 --- a/app/component/itinerary/navigator/NaviCard.js +++ b/app/component/itinerary/navigator/NaviCard.js @@ -27,7 +27,16 @@ const iconMap = { }; export default function NaviCard( - { leg, nextLeg, legType, cardExpanded, startTime, time, position, origin }, + { + leg, + nextLeg, + legType, + cardExpanded, + startTime, + time, + position, + tailLength, + }, { config }, ) { let mainCardContent; @@ -83,7 +92,7 @@ export default function NaviCard( legType={legType} time={time} position={position} - origin={origin} + tailLength={tailLength} />
@@ -116,10 +125,7 @@ NaviCard.propTypes = { lat: PropTypes.number, lon: PropTypes.number, }), - origin: PropTypes.shape({ - x: PropTypes.number.isRequired, - y: PropTypes.number.isRequired, - }).isRequired, + tailLength: PropTypes.number.isRequired, }; NaviCard.defaultProps = { cardExpanded: false, diff --git a/app/component/itinerary/navigator/NaviCardContainer.js b/app/component/itinerary/navigator/NaviCardContainer.js index 698a046948..b57ccc3d94 100644 --- a/app/component/itinerary/navigator/NaviCardContainer.js +++ b/app/component/itinerary/navigator/NaviCardContainer.js @@ -59,7 +59,7 @@ function NaviCardContainer( time, legs, position, - origin, + tailLength, mapLayerRef, currentLeg, nextLeg, @@ -131,7 +131,7 @@ function NaviCardContainer( legs, time, position, - origin, + tailLength, intl, messages, makeNewItinerarySearch, @@ -273,7 +273,7 @@ function NaviCardContainer( startTime={legTimeStr(firstLeg.start)} time={time} position={position} - origin={origin} + tailLength={tailLength} /> {activeMessages.length > 0 && ( @@ -296,10 +296,7 @@ NaviCardContainer.propTypes = { }), mapLayerRef: PropTypes.oneOfType([PropTypes.func, PropTypes.object]) .isRequired, - origin: PropTypes.shape({ - x: PropTypes.number.isRequired, - y: PropTypes.number.isRequired, - }).isRequired, + tailLength: PropTypes.number.isRequired, currentLeg: legShape, nextLeg: legShape, firstLeg: legShape, diff --git a/app/component/itinerary/navigator/NaviContainer.js b/app/component/itinerary/navigator/NaviContainer.js index b9fc8c9a14..9f14690f9c 100644 --- a/app/component/itinerary/navigator/NaviContainer.js +++ b/app/component/itinerary/navigator/NaviContainer.js @@ -43,13 +43,13 @@ function NaviContainer( const { realTimeLegs, time, - origin, + tailLength, firstLeg, lastLeg, previousLeg, currentLeg, nextLeg, - } = useRealtimeLegs(relayEnvironment, legs); + } = useRealtimeLegs(relayEnvironment, legs, position); useEffect(() => { mapRef?.enableMapTracking(); // try always, shows annoying notifier @@ -100,7 +100,7 @@ function NaviContainer( time={time} position={position} mapLayerRef={mapLayerRef} - origin={origin} + tailLength={tailLength} currentLeg={time > arrivalTime ? previousLeg : currentLeg} nextLeg={nextLeg} firstLeg={firstLeg} diff --git a/app/component/itinerary/navigator/NaviInstructions.js b/app/component/itinerary/navigator/NaviInstructions.js index e2286aae82..5c3cb2e78b 100644 --- a/app/component/itinerary/navigator/NaviInstructions.js +++ b/app/component/itinerary/navigator/NaviInstructions.js @@ -6,17 +6,12 @@ import { displayDistance } from '../../../util/geo-utils'; import { legShape, configShape } from '../../../util/shapes'; import { legDestination, legTimeStr, legTime } from '../../../util/legUtils'; import RouteNumber from '../../RouteNumber'; -import { - LEGTYPE, - getLocalizedMode, - getToLocalizedMode, - getRemainingTraversal, -} from './NaviUtils'; +import { LEGTYPE, getLocalizedMode, getToLocalizedMode } from './NaviUtils'; import { durationToString } from '../../../util/timeUtils'; import { getRouteMode } from '../../../util/modeUtils'; export default function NaviInstructions( - { leg, nextLeg, instructions, legType, time, position, origin }, + { leg, nextLeg, instructions, legType, time, position, tailLength }, { intl, config }, ) { const withRealTime = (rt, children) => ( @@ -24,14 +19,6 @@ export default function NaviInstructions( ); if (legType === LEGTYPE.MOVE) { - const remainingTraversal = getRemainingTraversal( - leg, - position, - origin, - time, - ); - const distance = remainingTraversal * leg.distance; - return ( <>
@@ -41,7 +28,7 @@ export default function NaviInstructions(
- {displayDistance(distance, config, intl.formatNumber)}  + {displayDistance(tailLength, config, intl.formatNumber)}  {durationToString(legTime(leg.end) - time)}
@@ -177,10 +164,7 @@ NaviInstructions.propTypes = { lat: PropTypes.number, lon: PropTypes.number, }), - origin: PropTypes.shape({ - x: PropTypes.number.isRequired, - y: PropTypes.number.isRequired, - }).isRequired, + tailLength: PropTypes.number.isRequired, }; NaviInstructions.defaultProps = { diff --git a/app/component/itinerary/navigator/NaviUtils.js b/app/component/itinerary/navigator/NaviUtils.js index 5dc612f84e..19b44072a0 100644 --- a/app/component/itinerary/navigator/NaviUtils.js +++ b/app/component/itinerary/navigator/NaviUtils.js @@ -111,6 +111,9 @@ export function pathProgress(pos, geom) { } export function getRemainingTraversal(leg, pos, origin, time) { + if (!leg) { + return 0; + } if (pos) { // TODO: maybe apply only when distance is close enough to the path const posXY = GeodeticToEnu(pos.lat, pos.lon, origin); @@ -122,7 +125,7 @@ export function getRemainingTraversal(leg, pos, origin, time) { return Math.min(Math.max((legTime(leg.end) - time) / duration, 0), 1.0); } -function findTransferProblems(legs, time, position, origin) { +function findTransferProblems(legs, time, position, tailLength) { const transfers = []; for (let i = 1; i < legs.length - 1; i++) { @@ -182,15 +185,15 @@ function findTransferProblems(legs, time, position, origin) { // has transit walk already started ? if (time > legTime(leg.start)) { // compute how transit is proceeding - toGo = getRemainingTraversal(leg, position, origin, time); + toGo = tailLength; timeLeft = (t2 - time) / 1000; } else { - toGo = 1.0; + toGo = leg.distance; timeLeft = duration / 1000; // should we consider also transfer slack here? } if (toGo > 0) { const originalSpeed = leg.distance / leg.duration; - const newSpeed = (toGo * leg.distance) / (timeLeft + 0.0001); + const newSpeed = toGo / (timeLeft + 0.0001); if (newSpeed > 1.5 * originalSpeed) { // too high speed compared to user's routing preference severity = 'ALERT'; @@ -401,7 +404,7 @@ export const getItineraryAlerts = ( legs, time, position, - origin, + tailLength, intl, messages, itinerarySearchCallback, @@ -475,7 +478,7 @@ export const getItineraryAlerts = ( } }); } else { - const transfers = findTransferProblems(legs, time, position, origin); + const transfers = findTransferProblems(legs, time, position, tailLength); if (transfers.length) { const prob = transfers.find(p => p.severity === 'ALERT') || diff --git a/app/component/itinerary/navigator/hooks/useRealtimeLegs.js b/app/component/itinerary/navigator/hooks/useRealtimeLegs.js index 17e03f2b46..4d5661e557 100644 --- a/app/component/itinerary/navigator/hooks/useRealtimeLegs.js +++ b/app/component/itinerary/navigator/hooks/useRealtimeLegs.js @@ -7,6 +7,7 @@ import { GeodeticToEcef, GeodeticToEnu } from '../../../../util/geo-utils'; import { legTime } from '../../../../util/legUtils'; import { epochToIso } from '../../../../util/timeUtils'; import { legQuery } from '../../queries/LegQuery'; +import { getRemainingTraversal } from '../NaviUtils'; function nextTransitIndex(legs, i) { for (let j = i; j < legs.length; j++) { @@ -147,7 +148,7 @@ function getInitialState(legs) { }; } -const useRealtimeLegs = (relayEnvironment, initialLegs) => { +const useRealtimeLegs = (relayEnvironment, initialLegs, position) => { const [{ origin, time, realTimeLegs }, setTimeAndRealTimeLegs] = useState( () => getInitialState(initialLegs), ); @@ -237,10 +238,12 @@ const useRealtimeLegs = (relayEnvironment, initialLegs) => { const { firstLeg, lastLeg, currentLeg, nextLeg, previousLeg } = getLegsOfInterest(realTimeLegs, time); + const tailLength = getRemainingTraversal(currentLeg, position, origin, time); + return { realTimeLegs, time, - origin, + tailLength, firstLeg, lastLeg, previousLeg, From 38f614de7ca0e2d00aead456b429dea45225e6a6 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Wed, 22 Jan 2025 09:19:32 +0200 Subject: [PATCH 2/4] fix: estimate journey ending more carefully --- app/component/itinerary/navigator/NaviContainer.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/app/component/itinerary/navigator/NaviContainer.js b/app/component/itinerary/navigator/NaviContainer.js index 9f14690f9c..46cc9f3f30 100644 --- a/app/component/itinerary/navigator/NaviContainer.js +++ b/app/component/itinerary/navigator/NaviContainer.js @@ -1,4 +1,3 @@ -import distance from '@digitransit-search-util/digitransit-search-util-distance'; import { routerShape } from 'found'; import PropTypes from 'prop-types'; import React, { useEffect, useRef } from 'react'; @@ -79,12 +78,11 @@ function NaviContainer( } const arrivalTime = legTime(lastLeg.end); - const isDestinationReached = - position && distance(position, lastLeg.to) <= DESTINATION_RADIUS; - + (currentLeg === lastLeg || time > arrivalTime) && + position && + tailLength <= DESTINATION_RADIUS; const isPastExpectedArrival = time > arrivalTime + ADDITIONAL_ARRIVAL_TIME; - const isJourneyCompleted = isDestinationReached || isPastExpectedArrival; if (LEGLOG) { From 7258a05f60f521c6dc92c241db437aa170036bef Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Wed, 22 Jan 2025 09:51:34 +0200 Subject: [PATCH 3/4] fix: compute distance --- app/component/itinerary/navigator/NaviUtils.js | 3 --- app/component/itinerary/navigator/hooks/useRealtimeLegs.js | 5 ++++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/component/itinerary/navigator/NaviUtils.js b/app/component/itinerary/navigator/NaviUtils.js index 19b44072a0..a49ad47c69 100644 --- a/app/component/itinerary/navigator/NaviUtils.js +++ b/app/component/itinerary/navigator/NaviUtils.js @@ -111,9 +111,6 @@ export function pathProgress(pos, geom) { } export function getRemainingTraversal(leg, pos, origin, time) { - if (!leg) { - return 0; - } if (pos) { // TODO: maybe apply only when distance is close enough to the path const posXY = GeodeticToEnu(pos.lat, pos.lon, origin); diff --git a/app/component/itinerary/navigator/hooks/useRealtimeLegs.js b/app/component/itinerary/navigator/hooks/useRealtimeLegs.js index 4d5661e557..d9434b05f0 100644 --- a/app/component/itinerary/navigator/hooks/useRealtimeLegs.js +++ b/app/component/itinerary/navigator/hooks/useRealtimeLegs.js @@ -238,7 +238,10 @@ const useRealtimeLegs = (relayEnvironment, initialLegs, position) => { const { firstLeg, lastLeg, currentLeg, nextLeg, previousLeg } = getLegsOfInterest(realTimeLegs, time); - const tailLength = getRemainingTraversal(currentLeg, position, origin, time); + const tailLength = currentLeg + ? getRemainingTraversal(currentLeg, position, origin, time) * + currentLeg.distance + : 0; return { realTimeLegs, From a7fc9192109da2ce037ff45f90391d83ef2b5ee7 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Wed, 22 Jan 2025 10:05:19 +0200 Subject: [PATCH 4/4] fix: update navi immediately when message bar changes --- app/component/itinerary/navigator/NaviContainer.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/app/component/itinerary/navigator/NaviContainer.js b/app/component/itinerary/navigator/NaviContainer.js index 46cc9f3f30..8fb260d5df 100644 --- a/app/component/itinerary/navigator/NaviContainer.js +++ b/app/component/itinerary/navigator/NaviContainer.js @@ -1,3 +1,4 @@ +import connectToStores from 'fluxible-addons-react/connectToStores'; import { routerShape } from 'found'; import PropTypes from 'prop-types'; import React, { useEffect, useRef } from 'react'; @@ -144,4 +145,12 @@ NaviContainer.defaultProps = { isNavigatorIntroDismissed: false, }; -export default NaviContainer; +const connectedComponent = connectToStores( + NaviContainer, + ['MessageStore'], + context => ({ + messages: context.getStore('MessageStore').getMessages(), + }), +); + +export default connectedComponent;