Skip to content

Commit d682b88

Browse files
authored
v0.0.16 clean (#44)
* clean changes * added fallback vehicle avatar png
1 parent 224f516 commit d682b88

24 files changed

+674
-443
lines changed
27 KB
Loading

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@fleetbase/storefront-app",
3-
"version": "0.0.15",
3+
"version": "0.0.16",
44
"private": true,
55
"scripts": {
66
"android": "react-native run-android",

src/components/AbsoluteTabBarScreenWrapper.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React from 'react';
22
import { View, ScrollView } from 'react-native';
33
import { useTheme } from 'tamagui';
4-
import { useBottomTabBarHeight } from '@react-navigation/bottom-tabs';
4+
import { useSafeTabBarHeight as useBottomTabBarHeight } from '../hooks/use-safe-tab-bar-height';
55
import Spacer from './Spacer';
66

77
const AbsoluteTabBarScreenWrapper = ({ children, scrollable = false, ...props }) => {

src/components/DeliveryRoutePreview.tsx

Lines changed: 54 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@ import { faStore, faPerson } from '@fortawesome/free-solid-svg-icons';
66
import MapView, { Marker, PROVIDER_GOOGLE, PROVIDER_DEFAULT } from 'react-native-maps';
77
import MapViewDirections from 'react-native-maps-directions';
88
import { Vehicle } from '@fleetbase/sdk';
9+
import { FoodTruck } from '@fleetbase/storefront';
910
import { restoreFleetbasePlace, getCoordinatesObject, createFauxPlace, formattedAddressFromPlace, makeCoordinatesFloat } from '../utils/location';
10-
import { config, storefrontConfig, getFoodTruckById, isArray } from '../utils';
11+
import { config, storefrontConfig, getFoodTruckById, isArray, isObject } from '../utils';
1112
import LocationMarker from './LocationMarker';
1213
import VehicleMarker from './VehicleMarker';
1314
import LoadingOverlay from './LoadingOverlay';
@@ -17,7 +18,6 @@ import useStorefront from '../hooks/use-storefront';
1718
import { adapter as fleetbaseAdapter } from '../hooks/use-fleetbase';
1819

1920
/* ---------- Helpers ---------- */
20-
2121
const DEFAULT_REGION = {
2222
latitude: 37.7749,
2323
longitude: -122.4194,
@@ -74,11 +74,10 @@ const DeliveryRoutePreview = ({ children, zoom = 1, width = '100%', height = '10
7474

7575
const [bearing, setBearing] = useState(0);
7676
const [findingOrigin, setFindingOrigin] = useState(false);
77-
const [dontFindOrigin, setDontFindOrigin] = useState(false);
7877
const [ready, setReady] = useState(false);
7978

8079
// -------- Origin & destination --------
81-
const initialOrigin = useMemo(
80+
const initialStart = useMemo(
8281
() =>
8382
currentStoreLocation === undefined
8483
? createFauxPlace()
@@ -89,7 +88,17 @@ const DeliveryRoutePreview = ({ children, zoom = 1, width = '100%', height = '10
8988
[currentStoreLocation]
9089
);
9190

92-
const [start, setStart] = useState(initialOrigin);
91+
// REFACTORED: Handle object customOrigin immediately without async
92+
const resolvedStart = useMemo(() => {
93+
// If customOrigin is an object with id, use it directly
94+
if (isObject(customOrigin) && customOrigin.id) {
95+
return customOrigin;
96+
}
97+
// Otherwise use initial start (will be fetched async if it's a string ID)
98+
return initialStart;
99+
}, [customOrigin, initialStart]);
100+
101+
const [start, setStart] = useState(resolvedStart);
93102
const end = useMemo(() => restoreFleetbasePlace(currentLocation), [currentLocation]);
94103
const origin = useMemo(() => getCoordinatesObject(start), [start]);
95104
const destination = useMemo(() => getCoordinatesObject(end), [end]);
@@ -99,7 +108,7 @@ const DeliveryRoutePreview = ({ children, zoom = 1, width = '100%', height = '10
99108
const [mapRegion, setMapRegion] = useState(() => getSafeInitialRegion(origin, initialDeltas));
100109
const [zoomLevel, setZoomLevel] = useState(() => calculateZoomLevel(mapRegion.latitudeDelta));
101110
const markerOffset = useMemo(() => calculateOffset(zoomLevel), [zoomLevel]);
102-
const isOriginFoodTruck = useMemo(() => start?.resource === 'food-truck' || start?.getAttribute?.('resource') === 'food-truck', [start]);
111+
const isOriginFoodTruck = useMemo(() => start instanceof FoodTruck || start?.resource === 'food-truck', [start]);
103112
const providerIsGoogle = Platform.OS === 'android' || PROVIDER_DEFAULT === PROVIDER_GOOGLE;
104113

105114
/* ---------- Bearing polling ---------- */
@@ -232,67 +241,69 @@ const DeliveryRoutePreview = ({ children, zoom = 1, width = '100%', height = '10
232241
[destination, mapRegion, initialDeltas]
233242
);
234243

235-
/* ---------- customOrigin resolution ---------- */
236-
const updateOriginFromCustomOrigin = useCallback(async () => {
237-
if (dontFindOrigin || findingOrigin) return;
244+
const handleMovement = useCallback(
245+
({ coordinates }) => {
246+
if (coordinates) focusMoving(coordinates);
247+
},
248+
[focusMoving]
249+
);
238250

239-
// No custom origin: we’re done (we already seeded start)
240-
if (!customOrigin) {
241-
setFindingOrigin(false);
251+
/* ---------- REFACTORED: Async fetch for string IDs only ---------- */
252+
const fetchOriginFromStringId = useCallback(async () => {
253+
// Only fetch if customOrigin is a string ID (not an object)
254+
if (!customOrigin || typeof customOrigin !== 'string') {
255+
setReady(true);
256+
return;
257+
}
258+
259+
// Already fetched
260+
if (start?.id === customOrigin || start?.store_location_id === customOrigin) {
242261
setReady(true);
243262
return;
244263
}
245264

246265
setFindingOrigin(true);
247266

248267
try {
249-
if (typeof customOrigin !== 'string') {
250-
if (customOrigin.id && customOrigin.id !== start?.id) {
251-
setStart(customOrigin);
252-
}
253-
} else if (customOrigin.startsWith('food_truck')) {
268+
if (customOrigin.startsWith('food_truck')) {
254269
const cachedFoodTruck = getFoodTruckById(customOrigin);
255270
if (cachedFoodTruck) {
256271
setStart(cachedFoodTruck);
257-
setDontFindOrigin(true);
258272
} else if (storefront) {
259273
const foodTruck = await storefront.foodTrucks.queryRecord({
260274
public_id: customOrigin,
261275
with_deleted: true,
262276
});
263-
setStart(isArray(foodTruck) && foodTruck.length ? foodTruck[0] : foodTruck);
264-
setDontFindOrigin(true);
277+
const resolvedFoodTruck = isArray(foodTruck) && foodTruck.length ? foodTruck[0] : foodTruck;
278+
setStart(resolvedFoodTruck);
265279
}
266280
} else if (customOrigin.startsWith('store_location')) {
267-
if (store && customOrigin !== start?.store_location_id) {
281+
if (store) {
268282
const storeLocation = await store.getLocation(customOrigin);
269283
setStart(
270284
restoreFleetbasePlace({
271285
...storeLocation.getAttribute('place'),
272286
store_location_id: storeLocation.id,
273287
})
274288
);
275-
setDontFindOrigin(true);
276289
}
277290
}
278291
} catch (error) {
279-
setDontFindOrigin(true);
280292
console.error('Error fetching custom origin:', error);
281293
} finally {
282294
setFindingOrigin(false);
283295
setReady(true);
284296
}
285-
}, [customOrigin, dontFindOrigin, start?.id, start?.store_location_id, storefront, store]);
297+
}, [customOrigin, start?.id, start?.store_location_id, storefront, store]);
286298

287299
useEffect(() => {
288300
if (!storefront || !store) {
289-
setFindingOrigin(false);
290301
setReady(true);
291302
return;
292303
}
293304

294-
updateOriginFromCustomOrigin(customOrigin);
295-
}, [storefront, store, customOrigin, updateOriginFromCustomOrigin]);
305+
fetchOriginFromStringId();
306+
}, [storefront, store, customOrigin, fetchOriginFromStringId]);
296307

297308
// Keep initial region sane if origin becomes available later
298309
useEffect(() => {
@@ -309,6 +320,15 @@ const DeliveryRoutePreview = ({ children, zoom = 1, width = '100%', height = '10
309320
}
310321
}, [origin, initialDeltas]);
311322

323+
// Cleanup on unmount
324+
useEffect(() => {
325+
return () => {
326+
stopBearingPoll();
327+
isPollingBearing.current = false;
328+
lastFollowTsRef.current = 0;
329+
};
330+
}, [stopBearingPoll]);
331+
312332
// -------- Render --------
313333
const initialRegion = useMemo(() => getSafeInitialRegion(origin, initialDeltas), [origin, initialDeltas]);
314334

@@ -327,7 +347,7 @@ const DeliveryRoutePreview = ({ children, zoom = 1, width = '100%', height = '10
327347
onRegionChangeComplete={handleRegionChangeComplete}
328348
mapType={storefrontConfig('defaultMapType', 'standard')}
329349
showsCompass={false}
330-
onRegionChange={startBearingPoll}
350+
onRegionChange={() => startBearingPoll()}
331351
onRegionChangeComplete={(region) => {
332352
stopBearingPoll();
333353
handleRegionChangeComplete(region);
@@ -341,13 +361,7 @@ const DeliveryRoutePreview = ({ children, zoom = 1, width = '100%', height = '10
341361
vehicle={new Vehicle(start.getAttribute('vehicle'), fleetbaseAdapter)}
342362
mapBearing={bearing}
343363
providerIsGoogle={providerIsGoogle}
344-
onMovement={({ coordinates }) => {
345-
// VehicleMarker internally animates marker;
346-
// here we make the map follow its movement.
347-
if (coordinates) {
348-
focusMoving(coordinates);
349-
}
350-
}}
364+
onMovement={handleMovement}
351365
>
352366
<YStack opacity={0.9} mt='$2' bg='$background' borderRadius='$6' px='$2' py='$1' alignItems='center' justifyContent='center'>
353367
<Text fontSize={14} color='$textPrimary' numberOfLines={1}>
@@ -392,7 +406,7 @@ const DeliveryRoutePreview = ({ children, zoom = 1, width = '100%', height = '10
392406
)}
393407

394408
{/* DESTINATION (User) */}
395-
{destination && Number.isFinite(destination.latitude) && Number.isFinite(destination.longitude) && (
409+
{ready && destination && Number.isFinite(destination.latitude) && Number.isFinite(destination.longitude) && (
396410
<Marker coordinate={makeCoordinatesFloat(destination)} centerOffset={markerOffset}>
397411
<YStack
398412
mb={8}
@@ -426,12 +440,14 @@ const DeliveryRoutePreview = ({ children, zoom = 1, width = '100%', height = '10
426440
)}
427441

428442
{/* ROUTE */}
429-
{origin &&
443+
{ready &&
444+
origin &&
430445
destination &&
431446
Number.isFinite(origin.latitude) &&
432447
Number.isFinite(origin.longitude) &&
433448
Number.isFinite(destination.latitude) &&
434-
Number.isFinite(destination.longitude) && (
449+
Number.isFinite(destination.longitude) &&
450+
!findingOrigin && (
435451
<MapViewDirections
436452
origin={makeCoordinatesFloat(origin)}
437453
destination={makeCoordinatesFloat(destination)}

src/components/DriverMarker.tsx

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ const DriverMarker = ({ driver, onPositionChange, onHeadingChange, onMovement, .
99
const markerRef = useRef();
1010
const listenerRef = useRef();
1111
const lastCoordinatesRef = useRef(null);
12+
const addEventRef = useRef(addEvent);
13+
const clearEventsRef = useRef(clearEvents);
1214

1315
const handleEvent = useCallback(
1416
(data) => {
@@ -80,8 +82,7 @@ const DriverMarker = ({ driver, onPositionChange, onHeadingChange, onMovement, .
8082
useCallback(() => {
8183
const trackDriverMovement = async () => {
8284
const listener = await listen(`driver.${driver.id}`, (event) => {
83-
console.log(`[Socket Channel: driver.${driver.id}]`, event);
84-
addEvent(event);
85+
addEventRef.current(event);
8586
});
8687
if (listener) {
8788
listenerRef.current = listener;
@@ -97,11 +98,14 @@ const DriverMarker = ({ driver, onPositionChange, onHeadingChange, onMovement, .
9798
clearEvents();
9899
lastCoordinatesRef.current = null; // Reset on unmount
99100
};
100-
}, [listen, driver.id, addEvent, clearEvents])
101+
}, [listen, driver.id])
101102
);
102103

103104
const { latitude, longitude } = driver;
105+
const heading = driver.getAttribute('heading') ?? 0;
104106
const coord = makeCoordinatesFloat({ latitude, longitude });
107+
const avatarUrl = driver.getAttribute('avatar_url');
108+
const avatarSource = avatarUrl ? { uri: avatarUrl } : require('../../assets/images/vehicles/light_commercial_van.png');
105109

106110
// Initialize last coordinates with the vehicle's initial position
107111
useEffect(() => {
@@ -110,7 +114,13 @@ const DriverMarker = ({ driver, onPositionChange, onHeadingChange, onMovement, .
110114
}
111115
}, [latitude, longitude]);
112116

113-
return <TrackingMarker ref={markerRef} coordinate={coord} imageSource={{ uri: driver.getAttribute('avatar_url') }} size={{ width: 50, height: 50 }} {...props} />;
117+
// Event buffer method refs
118+
useEffect(() => {
119+
addEventRef.current = addEvent;
120+
clearEventsRef.current = clearEvents;
121+
}, [addEvent, clearEvents]);
122+
123+
return <TrackingMarker ref={markerRef} coordinate={coord} initialRotation={heading} imageSource={avatarSource} size={{ width: 50, height: 50 }} {...props} />;
114124
};
115125

116126
export default DriverMarker;

0 commit comments

Comments
 (0)