From 23153e163ec1b30f5bbeb033a90fd662cf8917d2 Mon Sep 17 00:00:00 2001 From: OPbagelBites Date: Mon, 11 Mar 2024 10:46:45 -0500 Subject: [PATCH 01/10] Stop Callout --- app/components/map/StopCallout.tsx | 97 ++++++++++++++++++------------ 1 file changed, 59 insertions(+), 38 deletions(-) diff --git a/app/components/map/StopCallout.tsx b/app/components/map/StopCallout.tsx index 4004b80..599ad82 100644 --- a/app/components/map/StopCallout.tsx +++ b/app/components/map/StopCallout.tsx @@ -1,52 +1,73 @@ import React, { memo, useState, useCallback } from 'react' -import { View, Text, LayoutChangeEvent } from 'react-native' +import { View, Text, LayoutChangeEvent, FlatList } from 'react-native' import { Callout } from 'react-native-maps' import BusIcon from '../ui/BusIcon' import { IDirection, IMapRoute, IStop } from '../../../utils/interfaces' -import AmenityRow from "../ui/AmenityRow"; import { useStopEstimate } from 'app/data/api_query' +import TimeBubble from '../ui/TimeBubble' +import moment from 'moment' interface Props { - stop: IStop - tintColor: string - route: IMapRoute - direction: IDirection + stop: IStop + tintColor: string + route: IMapRoute + direction: IDirection } -// Stop callout with amentities +// Stop callout with time bubbles const StopCallout: React.FC = ({ stop, tintColor, route, direction }) => { - // Calculate size of callout based on the contentSize - const [contentSize, setContentSize] = useState([100, 15]); - - const { data: estimate } = useStopEstimate(route.key, direction.key, stop.stopCode); - - const handleLayout = useCallback((event: LayoutChangeEvent) => { - const { width, height } = event.nativeEvent.layout; - - setContentSize([width, height]); - }, [setContentSize]); - - return ( - - - - - {stop.name} - - - - - - ) + // Calculate size of callout based on the contentSize + const [contentSize, setContentSize] = useState([100, 15]); + + const { data: estimate } = useStopEstimate(route.key, direction.key, stop.stopCode); + + const handleLayout = useCallback((event: LayoutChangeEvent) => { + const { width, height } = event.nativeEvent.layout; + + setContentSize([width, height]); + }, [setContentSize]); + + return ( + + + + + {stop.name} + + + + index.toString()} + renderItem={({ item: departureTime, index }) => { + const date = moment(departureTime.estimatedDepartTimeUtc ?? departureTime.scheduledDepartTimeUtc ?? ""); + const relative = date.diff(moment(), "minutes"); + return ( + + ) + }} + + + + ) } export default memo(StopCallout); \ No newline at end of file From 6b830caa83bd8f37b114f9ac91b9ba2ecbb4c95c Mon Sep 17 00:00:00 2001 From: bwees Date: Mon, 11 Mar 2024 13:37:48 -0500 Subject: [PATCH 02/10] fixed callout formatting --- app/components/map/StopCallout.tsx | 96 +++++++++++++------------ app/components/ui/CalloutTimeBubble.tsx | 37 ++++++++++ 2 files changed, 86 insertions(+), 47 deletions(-) create mode 100644 app/components/ui/CalloutTimeBubble.tsx diff --git a/app/components/map/StopCallout.tsx b/app/components/map/StopCallout.tsx index 599ad82..7eded7b 100644 --- a/app/components/map/StopCallout.tsx +++ b/app/components/map/StopCallout.tsx @@ -1,11 +1,12 @@ import React, { memo, useState, useCallback } from 'react' -import { View, Text, LayoutChangeEvent, FlatList } from 'react-native' +import { View, Text, LayoutChangeEvent } from 'react-native' import { Callout } from 'react-native-maps' import BusIcon from '../ui/BusIcon' import { IDirection, IMapRoute, IStop } from '../../../utils/interfaces' import { useStopEstimate } from 'app/data/api_query' -import TimeBubble from '../ui/TimeBubble' import moment from 'moment' +import CalloutTimeBubble from '../ui/CalloutTimeBubble' +import { lightMode } from 'app/theme' interface Props { stop: IStop @@ -17,57 +18,58 @@ interface Props { // Stop callout with time bubbles const StopCallout: React.FC = ({ stop, tintColor, route, direction }) => { - // Calculate size of callout based on the contentSize - const [contentSize, setContentSize] = useState([100, 15]); + // Calculate size of callout based on the contentSize + const [contentSize, setContentSize] = useState([100, 15]); - const { data: estimate } = useStopEstimate(route.key, direction.key, stop.stopCode); + const { data: estimate } = useStopEstimate(route.key, direction.key, stop.stopCode); - const handleLayout = useCallback((event: LayoutChangeEvent) => { - const { width, height } = event.nativeEvent.layout; + const handleLayout = useCallback((event: LayoutChangeEvent) => { + const { width, height } = event.nativeEvent.layout; - setContentSize([width, height]); - }, [setContentSize]); + setContentSize([width, height]); + }, [setContentSize]); - return ( - - - - - {stop.name} - + return ( + + + + + {stop.name} + - - index.toString()} - renderItem={({ item: departureTime, index }) => { - const date = moment(departureTime.estimatedDepartTimeUtc ?? departureTime.scheduledDepartTimeUtc ?? ""); - const relative = date.diff(moment(), "minutes"); - return ( - - ) - }} + + { estimate?.routeDirectionTimes[0]?.nextDeparts.map((departureTime, index) => { + const date = moment(departureTime.estimatedDepartTimeUtc ?? departureTime.scheduledDepartTimeUtc ?? ""); + const relative = date.diff(moment(), "minutes"); + return ( + + ) + })} + - - - ) + + ) } export default memo(StopCallout); \ No newline at end of file diff --git a/app/components/ui/CalloutTimeBubble.tsx b/app/components/ui/CalloutTimeBubble.tsx new file mode 100644 index 0000000..37d3a57 --- /dev/null +++ b/app/components/ui/CalloutTimeBubble.tsx @@ -0,0 +1,37 @@ +import React from 'react' +import { View, Text } from 'react-native' +import { MaterialCommunityIcons } from '@expo/vector-icons'; + +interface Props { + time: string + color: string, + textColor?: string, + live?: boolean +} + +const CalloutTimeBubble: React.FC = ({time, color, textColor, live}) => { + return ( + + + {time} + + + { live && + + } + + ) +} + +export default CalloutTimeBubble; \ No newline at end of file From 11860530c3f0f7bbb826450494ec2d45ff28c41d Mon Sep 17 00:00:00 2001 From: bwees Date: Wed, 13 Mar 2024 21:55:55 -0400 Subject: [PATCH 03/10] fix spacing when no estimates --- app/components/map/StopCallout.tsx | 50 ++++++++++++++++-------------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/app/components/map/StopCallout.tsx b/app/components/map/StopCallout.tsx index 7eded7b..5d8e3aa 100644 --- a/app/components/map/StopCallout.tsx +++ b/app/components/map/StopCallout.tsx @@ -40,34 +40,36 @@ const StopCallout: React.FC = ({ stop, tintColor, route, direction }) => elevation: 1000 }} > - - + + {stop.name} - + - - { estimate?.routeDirectionTimes[0]?.nextDeparts.map((departureTime, index) => { - const date = moment(departureTime.estimatedDepartTimeUtc ?? departureTime.scheduledDepartTimeUtc ?? ""); - const relative = date.diff(moment(), "minutes"); - return ( - - ) - })} + { estimate?.routeDirectionTimes[0]?.nextDeparts.length !== 0 && + + { estimate?.routeDirectionTimes[0]?.nextDeparts.map((departureTime, index) => { + const date = moment(departureTime.estimatedDepartTimeUtc ?? departureTime.scheduledDepartTimeUtc ?? ""); + const relative = date.diff(moment(), "minutes"); + return ( + + ) + })} + + } - ) } From 56f772b10d0472d1ecb4d2d5b6f1cde59476d49f Mon Sep 17 00:00:00 2001 From: bwees Date: Wed, 13 Mar 2024 21:56:10 -0400 Subject: [PATCH 04/10] formatting --- app/components/map/StopCallout.tsx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/app/components/map/StopCallout.tsx b/app/components/map/StopCallout.tsx index 5d8e3aa..1f21ec4 100644 --- a/app/components/map/StopCallout.tsx +++ b/app/components/map/StopCallout.tsx @@ -31,14 +31,14 @@ const StopCallout: React.FC = ({ stop, tintColor, route, direction }) => return ( From da7589f51a219cb6b72bf4f18bac73a60044a581 Mon Sep 17 00:00:00 2001 From: bwees Date: Fri, 15 Mar 2024 18:31:20 -0400 Subject: [PATCH 05/10] fix wording and sizing of callouts --- app/components/map/StopCallout.tsx | 34 +++++++++++++++--------------- app/components/ui/StopCell.tsx | 12 +++++------ 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/app/components/map/StopCallout.tsx b/app/components/map/StopCallout.tsx index 1f21ec4..e9bb36f 100644 --- a/app/components/map/StopCallout.tsx +++ b/app/components/map/StopCallout.tsx @@ -1,5 +1,5 @@ -import React, { memo, useState, useCallback } from 'react' -import { View, Text, LayoutChangeEvent } from 'react-native' +import React, { memo } from 'react' +import { View, Text, ActivityIndicator } from 'react-native' import { Callout } from 'react-native-maps' import BusIcon from '../ui/BusIcon' import { IDirection, IMapRoute, IStop } from '../../../utils/interfaces' @@ -7,6 +7,7 @@ import { useStopEstimate } from 'app/data/api_query' import moment from 'moment' import CalloutTimeBubble from '../ui/CalloutTimeBubble' import { lightMode } from 'app/theme' +import AmenityRow from '../ui/AmenityRow' interface Props { stop: IStop @@ -18,35 +19,27 @@ interface Props { // Stop callout with time bubbles const StopCallout: React.FC = ({ stop, tintColor, route, direction }) => { - // Calculate size of callout based on the contentSize - const [contentSize, setContentSize] = useState([100, 15]); - - const { data: estimate } = useStopEstimate(route.key, direction.key, stop.stopCode); - - const handleLayout = useCallback((event: LayoutChangeEvent) => { - const { width, height } = event.nativeEvent.layout; - - setContentSize([width, height]); - }, [setContentSize]); + const { data: estimate, isLoading } = useStopEstimate(route.key, direction.key, stop.stopCode); return ( - + - {stop.name} + {stop.name} + - { estimate?.routeDirectionTimes[0]?.nextDeparts.length !== 0 && + { estimate?.routeDirectionTimes[0]?.nextDeparts.length !== 0 ? = ({ stop, tintColor, route, direction }) => alignSelf: "flex-start", marginTop: 8 }}> + { estimate?.routeDirectionTimes[0]?.nextDeparts.map((departureTime, index) => { const date = moment(departureTime.estimatedDepartTimeUtc ?? departureTime.scheduledDepartTimeUtc ?? ""); const relative = date.diff(moment(), "minutes"); @@ -67,7 +61,13 @@ const StopCallout: React.FC = ({ stop, tintColor, route, direction }) => /> ) })} + + : ( isLoading ? + + : + No upcoming departures + ) } diff --git a/app/components/ui/StopCell.tsx b/app/components/ui/StopCell.tsx index 6badeed..8480210 100644 --- a/app/components/ui/StopCell.tsx +++ b/app/components/ui/StopCell.tsx @@ -34,7 +34,7 @@ const StopCell: React.FC = ({ stop, route, direction, color, disabled, se const estimate = stopEstimate.routeDirectionTimes[0]!; - let totalDeviation = 0; + let deviation = 0; for (const departTime of estimate.nextDeparts) { const estimatedTime = moment(departTime.estimatedDepartTimeUtc ?? ""); @@ -43,23 +43,23 @@ const StopCell: React.FC = ({ stop, route, direction, color, disabled, se const delayLength = estimatedTime.diff(scheduledTime, "seconds"); if (!isNaN(delayLength)) { - totalDeviation += delayLength; + deviation = delayLength; + break; } } - const avgDeviation = totalDeviation / estimate.nextDeparts.length / (60); - const roundedDeviation = Math.round(avgDeviation); + const roundedDeviation = Math.round(deviation / 60); if (estimate.directionKey === "") { setStatus('Loading'); } else if (estimate.nextDeparts.length === 0) { - setStatus("No times to show"); + setStatus("No upcoming departures"); } else if (roundedDeviation > 0) { setStatus(`${roundedDeviation} ${roundedDeviation > 1 ? "minutes" : "minute"} late`); } else if (roundedDeviation < 0) { setStatus(`${Math.abs(roundedDeviation)} ${Math.abs(roundedDeviation) > 1 ? "minutes" : "minute"} early`); } else { - setStatus('On Time'); + setStatus('On time'); } }, [stopEstimate]); From 9053563063e82fbeff77f21bce9363c21b082f54 Mon Sep 17 00:00:00 2001 From: bwees Date: Fri, 15 Mar 2024 18:50:39 -0400 Subject: [PATCH 06/10] scroll to cell when tap title in callout --- app/components/map/StopCallout.tsx | 17 ++++++++++++++--- app/components/sheets/RouteDetails.tsx | 16 +++++++++++++++- app/data/app_state.ts | 12 +++++++++--- 3 files changed, 38 insertions(+), 7 deletions(-) diff --git a/app/components/map/StopCallout.tsx b/app/components/map/StopCallout.tsx index e9bb36f..2706634 100644 --- a/app/components/map/StopCallout.tsx +++ b/app/components/map/StopCallout.tsx @@ -1,5 +1,5 @@ import React, { memo } from 'react' -import { View, Text, ActivityIndicator } from 'react-native' +import { View, Text, ActivityIndicator, TouchableOpacity } from 'react-native' import { Callout } from 'react-native-maps' import BusIcon from '../ui/BusIcon' import { IDirection, IMapRoute, IStop } from '../../../utils/interfaces' @@ -8,6 +8,7 @@ import moment from 'moment' import CalloutTimeBubble from '../ui/CalloutTimeBubble' import { lightMode } from 'app/theme' import AmenityRow from '../ui/AmenityRow' +import useAppStore from 'app/data/app_state' interface Props { stop: IStop @@ -19,6 +20,8 @@ interface Props { // Stop callout with time bubbles const StopCallout: React.FC = ({ stop, tintColor, route, direction }) => { + const scrollToStop = useAppStore(state => state.scrollToStop); + const { data: estimate, isLoading } = useStopEstimate(route.key, direction.key, stop.stopCode); return ( @@ -33,11 +36,19 @@ const StopCallout: React.FC = ({ stop, tintColor, route, direction }) => }} > - + { scrollToStop(stop) }} + > {stop.name} - + { estimate?.routeDirectionTimes[0]?.nextDeparts.length !== 0 ? = ({ sheetRef }) => { + + const flatListRef = React.useRef(null); + const currentSelectedRoute = useAppStore((state) => state.selectedRoute); const clearSelectedRoute = useAppStore((state) => state.clearSelectedRoute); @@ -25,6 +28,7 @@ const RouteDetails: React.FC = ({ sheetRef }) => { const setSelectedStop = useAppStore(state => state.setSelectedStop); const setPoppedUpStopCallout = useAppStore(state => state.setPoppedUpStopCallout); const selectedRouteDirection = useAppStore(state => state.selectedRouteDirection); + const setScrollToStop = useAppStore(state => state.setScrollToStop); const theme = useAppStore(state => state.theme); const { data: stopEstimates } = useStopEstimate( @@ -33,6 +37,15 @@ const RouteDetails: React.FC = ({ sheetRef }) => { currentSelectedRoute?.patternPaths[0]?.patternPoints[0]?.stop?.stopCode ?? "" ) + setScrollToStop((stop) => { + sheetRef.current?.snapToIndex(2); + const index = processedStops.findIndex(st => st.stopCode === stop.stopCode); + setTimeout(() => { + console.log("FADSFSA") + flatListRef.current?.scrollToIndex({ index, animated: true }); + }, 450) + }) + // Controls SegmentedControl const [selectedDirectionIndex, setSelectedDirectionIndex] = useState(0); @@ -158,6 +171,7 @@ const RouteDetails: React.FC = ({ sheetRef }) => { { selectedRoute && void, - // TODO: Switch to Provider Functions + // TODO: Switch to ContextProvider Functions presentSheet: (sheet: "routeDetails" | "alerts" | "stopTimetable" | "settings" | "alertsDetail") => void setPresentSheet: (presentSheet: (sheet: "routeDetails" | "alerts" | "stopTimetable" | "settings" | "alertsDetail") => void) => void @@ -32,12 +32,15 @@ interface AppState { selectedTimetableDate: Date | null, setSelectedTimetableDate: (selectedTimetableDate: Date | null) => void - // TODO: Switch to Provider Functions + // TODO: Switch to Context Provider Functions zoomToStopLatLng: (lat: number, lng: number) => void setZoomToStopLatLng: (zoomToStopLatLng: (lat: number, lng: number) => void) => void poppedUpStopCallout: IStop | null, setPoppedUpStopCallout: (poppedUpStopCallout: IStop | null) => void + + scrollToStop: (stop: IStop) => void + setScrollToStop: (scrollToStop: (stop: IStop) => void) => void } const useAppStore = create()((set) => ({ @@ -74,7 +77,10 @@ const useAppStore = create()((set) => ({ setZoomToStopLatLng: (zoomToStopLatLng) => set(() => ({ zoomToStopLatLng })), poppedUpStopCallout: null, - setPoppedUpStopCallout: (poppedUpStopCallout) => set(() => ({ poppedUpStopCallout })) + setPoppedUpStopCallout: (poppedUpStopCallout) => set(() => ({ poppedUpStopCallout })), + + scrollToStop: (stop) => {console.log(stop)}, + setScrollToStop: (scrollToStop) => set(() => ({ scrollToStop: scrollToStop })) })); export default useAppStore; \ No newline at end of file From b069bf8516035c178d45ab43969053ceb327c66c Mon Sep 17 00:00:00 2001 From: bwees Date: Fri, 15 Mar 2024 18:52:30 -0400 Subject: [PATCH 07/10] remove print statement --- app/components/sheets/RouteDetails.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/app/components/sheets/RouteDetails.tsx b/app/components/sheets/RouteDetails.tsx index a160911..e97db1a 100644 --- a/app/components/sheets/RouteDetails.tsx +++ b/app/components/sheets/RouteDetails.tsx @@ -41,7 +41,6 @@ const RouteDetails: React.FC = ({ sheetRef }) => { sheetRef.current?.snapToIndex(2); const index = processedStops.findIndex(st => st.stopCode === stop.stopCode); setTimeout(() => { - console.log("FADSFSA") flatListRef.current?.scrollToIndex({ index, animated: true }); }, 450) }) From eb81a5316d9e0c5b25303a9f74b521917a660c8f Mon Sep 17 00:00:00 2001 From: bwees Date: Sat, 16 Mar 2024 11:23:44 -0400 Subject: [PATCH 08/10] font sizing --- app/components/map/StopCallout.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/components/map/StopCallout.tsx b/app/components/map/StopCallout.tsx index 2706634..6600703 100644 --- a/app/components/map/StopCallout.tsx +++ b/app/components/map/StopCallout.tsx @@ -77,7 +77,7 @@ const StopCallout: React.FC = ({ stop, tintColor, route, direction }) => : ( isLoading ? : - No upcoming departures + No upcoming departures ) } From 0f89ec022de2219890a486b7692af5c0e9233be2 Mon Sep 17 00:00:00 2001 From: bwees Date: Sat, 16 Mar 2024 11:23:53 -0400 Subject: [PATCH 09/10] fix scroll animation timing --- app/components/sheets/RouteDetails.tsx | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/app/components/sheets/RouteDetails.tsx b/app/components/sheets/RouteDetails.tsx index e97db1a..fa82249 100644 --- a/app/components/sheets/RouteDetails.tsx +++ b/app/components/sheets/RouteDetails.tsx @@ -24,6 +24,8 @@ const RouteDetails: React.FC = ({ sheetRef }) => { const currentSelectedRoute = useAppStore((state) => state.selectedRoute); const clearSelectedRoute = useAppStore((state) => state.clearSelectedRoute); + const [futurePosition, setFuturePosition] = useState(-1); + const setSelectedRouteDirection = useAppStore(state => state.setSelectedRouteDirection); const setSelectedStop = useAppStore(state => state.setSelectedStop); const setPoppedUpStopCallout = useAppStore(state => state.setPoppedUpStopCallout); @@ -40,9 +42,8 @@ const RouteDetails: React.FC = ({ sheetRef }) => { setScrollToStop((stop) => { sheetRef.current?.snapToIndex(2); const index = processedStops.findIndex(st => st.stopCode === stop.stopCode); - setTimeout(() => { - flatListRef.current?.scrollToIndex({ index, animated: true }); - }, 450) + + setFuturePosition(index); }) @@ -133,6 +134,12 @@ const RouteDetails: React.FC = ({ sheetRef }) => { enablePanDownToClose={false} backgroundStyle={{ backgroundColor: theme.background }} handleIndicatorStyle={{backgroundColor: theme.divider}} + onChange={() => { + if (futurePosition !== -1) { + flatListRef.current?.scrollToIndex({ index: futurePosition, animated: true }); + setFuturePosition(-1); + } + }} > {selectedRoute && From 078c6de1a5ce1b410c8ab5e481530c941d448de1 Mon Sep 17 00:00:00 2001 From: bwees Date: Sat, 16 Mar 2024 16:35:29 -0400 Subject: [PATCH 10/10] 2 line callout --- app/components/map/StopCallout.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/components/map/StopCallout.tsx b/app/components/map/StopCallout.tsx index 6600703..3d685a2 100644 --- a/app/components/map/StopCallout.tsx +++ b/app/components/map/StopCallout.tsx @@ -46,7 +46,7 @@ const StopCallout: React.FC = ({ stop, tintColor, route, direction }) => onPress={() => { scrollToStop(stop) }} > - {stop.name} + {stop.name}