fix(customer-app): support real-time GPS tracking for truck marker with smooth interpolation #448#522
Conversation
…and Supabase auth support
|
🎉 Thank you for your contribution! Your pull request has been received and will be reviewed shortly. If you enjoy the project, please consider giving the repository a ⭐. You can also follow my GitHub profile to stay updated on future open-source projects. Thanks for being part of the community! 🚀 |
|
![Review Change Stack [link removed for security]]([link removed for security]) Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (4)
📝 WalkthroughWalkthroughAdds an optional onConnect callback and urlFactory to ResilientWebSocket; updates LiveTrackingScreen to subscribe to a tracking WebSocket, parse location_update messages, and interpolate/animate truck position; and extends backend tracker auth to accept Supabase or Firebase tokens while capping telemetry buffer size. ChangesReal-time Truck Tracking with Dual-Auth
Sequence DiagramsequenceDiagram
participant Screen as LiveTrackingScreen
participant WS as ResilientWebSocket
participant Backend as TrackerSocket
participant UI as MarkerLayer
Screen->>WS: connect(tracking URL + token)
WS->>Backend: WebSocket handshake / subscribe_tracking
Backend->>Backend: jwt.decode(token) -> determine issuer
Backend->>Backend: verify token (Supabase OR Firebase)
Backend-->>WS: auth success (assign ws.user, ws.driverId)
WS->>Screen: onConnect callback
Backend->>WS: send location_update {lat,lng}
WS->>Screen: deliver location_update message
Screen->>Screen: _updateTruckPosition(previous <- current, current <- new)
Screen->>Screen: _movementController.forward(from:0.0)
Screen->>UI: buildTruckMarkers() -> interpolated position
UI-->>Screen: render animated truck marker
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment
|
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds resilient live tracking over WebSockets on the customer app, and updates the backend WebSocket auth flow to support Supabase tokens in addition to Firebase.
Changes:
- Backend: detect Supabase vs Firebase tokens and validate accordingly before loading user profiles.
- Customer app: connect to a tracking WebSocket, subscribe to location updates, and animate marker movement.
- Core: add an
onConnecthook toResilientWebSocketto send subscription messages on (re)connect.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| backend/api/src/sockets/tracker.js | Adds Supabase-token path + keeps Firebase path for WebSocket authentication/profile lookup. |
| apps/customer/lib/screens/live_tracking_screen.dart | Connects to tracking WS, parses location events, and animates truck marker movement. |
| apps/customer/lib/core/offline/websocket/resilient_websocket.dart | Extends resilient WS wrapper with onConnect callback. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…destructuring, safe URI builder, and redacted logs
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
backend/api/src/sockets/tracker.js (1)
174-179:⚠️ Potential issue | 🔴 Critical | ⚡ Quick winDo not grant non-drivers a telemetry publisher identity.
This now authenticates customer sockets too, but still sets
ws.driverId = profile.idfor every role.handleLocationPing()later treats any socket withws.driverIdas an authorized publisher and never checksws.user.role, so an authenticated customer can open/ws/tracking, sendlocation_pingfor anorder_display_id, and broadcast/store fake truck positions.🔒 Suggested direction
ws.user = { id: profile.id, uid: profile.firebase_uid, role: profile.role, }; - ws.driverId = profile.id; + ws.driverId = profile.role === 'driver' ? profile.id : null;Also reject
location_pingunlessws.user?.role === 'driver'before accepting or broadcasting telemetry.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@backend/api/src/sockets/tracker.js` around lines 174 - 179, The code incorrectly assigns ws.driverId to every authenticated user, allowing non-drivers to publish telemetry; only set ws.driverId when profile.role === 'driver' and remove or avoid setting it for other roles (change the assignment around ws.driverId to be conditional on profile.role === 'driver'), and add an explicit authorization check in handleLocationPing() to reject/ignore incoming 'location_ping' events unless ws.user?.role === 'driver' (and/or ws.driverId is present) before accepting, storing, or broadcasting telemetry for an order_display_id.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/customer/lib/screens/live_tracking_screen.dart`:
- Line 77: The current debugPrint calls leak sensitive data by printing the full
wsUrl (which includes the Supabase access token) and the raw tracking payload;
update the logging in live_tracking_screen.dart to redact tokens and avoid
printing full payloads: when logging wsUrl (the wsUrl variable) build and log a
redacted endpoint (e.g., remove or replace the access_token query param or log
only the origin + path), and when logging incoming messages (the raw tracking
payload at the second debugPrint) log only non-sensitive metadata such as the
event type or a sanitized summary (e.g., payload['event'] or payload['type']),
not the full location or token fields; replace the two debugPrint calls at the
locations shown with these redacted/sanitized logs.
- Around line 433-449: AnimatedBuilder is still listening to _truckController
and forcing FlutterMap rebuilds each tick even though _buildTruckMarkers() no
longer reads _truckController; change the widget tree so the map is not rebuilt
unnecessarily by either (a) replacing the AnimatedBuilder that uses
_truckController with one that uses _movementController (the controller actually
driving marker interpolation) or (b) remove the AnimatedBuilder/_truckController
entirely and only rebuild markers via a smaller builder around the marker layer
(or use a ValueListenableBuilder tied to the actual value used). Locate the
AnimatedBuilder that wraps FlutterMap and stop listening to _truckController (or
move the animation listening down to the marker creation) so FlutterMap is not
repainted on every _truckController tick while keeping _buildTruckMarkers,
_movementController and marker interpolation logic unchanged.
- Around line 127-131: The marker jumps because on receiving newPosition you set
_previousPosition = _currentPosition (the last target) instead of the marker's
current rendered/interpolated position; compute the current rendered position by
interpolating between _previousPosition and _currentPosition using
_movementController.value (or treat value as 0 if controller is dismissed) and
assign that interpolated LatLng to _previousPosition before setting
_currentPosition = newPosition, then restart _movementController.forward(from:
0.0); apply this change in the update path that currently sets
_previousPosition/_currentPosition and calls _movementController.forward.
- Around line 68-80: _subscribeToTracking currently builds a wsUrl with a
one-time snapshot of Supabase.instance.client.auth.currentSession?.accessToken
and passes it to ResilientWebSocket, causing reconnects to reuse a stale JWT;
change the code so reconnects request a fresh token (either by passing a
reconnect/url-provider callback to ResilientWebSocket or by recreating
_trackingWebSocket inside an auth-change listener) instead of storing the
original wsUrl in _trackingWebSocket. Also remove or redact inbound payloads
from the debugPrint line that logs "Tracking WebSocket message received:
$message" to avoid leaking location data. Fix the interpolation jump in
_updateTruckPosition by setting _previousPosition to the last
rendered/interpolated position (not the last target) and avoid restarting the
animation from t=0; instead update the animation target while preserving
progress or use forward(from: currentValue) so movement is smooth. Finally, stop
unnecessary rebuilds by having the AnimatedBuilder that calls _buildTruckMarkers
listen to _movementController (the controller driving marker interpolation)
rather than _truckController so only marker-related UI updates rebuild.
---
Outside diff comments:
In `@backend/api/src/sockets/tracker.js`:
- Around line 174-179: The code incorrectly assigns ws.driverId to every
authenticated user, allowing non-drivers to publish telemetry; only set
ws.driverId when profile.role === 'driver' and remove or avoid setting it for
other roles (change the assignment around ws.driverId to be conditional on
profile.role === 'driver'), and add an explicit authorization check in
handleLocationPing() to reject/ignore incoming 'location_ping' events unless
ws.user?.role === 'driver' (and/or ws.driverId is present) before accepting,
storing, or broadcasting telemetry for an order_display_id.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 21c85281-9c42-4329-b2d1-9f28400f8345
📒 Files selected for processing (3)
apps/customer/lib/core/offline/websocket/resilient_websocket.dartapps/customer/lib/screens/live_tracking_screen.dartbackend/api/src/sockets/tracker.js
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/customer/lib/screens/live_tracking_screen.dart (1)
417-439:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winRemove unused
_pointAlongRoutemethod.The pipeline reports
_pointAlongRouteis unreferenced. This method computed a position along the route polyline, but the PR replaced that logic with real-time GPS positioning via_currentPosition/_previousPosition. Remove this dead code to clear the warning.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/customer/lib/screens/live_tracking_screen.dart` around lines 417 - 439, Remove the unused dead method _pointAlongRoute from the class: delete the entire function definition (including its use of _routePoints, _interpolatePoint, _fallbackPickupPoint, and _fallbackDropPoint) since routing now uses _currentPosition/_previousPosition; ensure no other code references _pointAlongRoute and run analyzer to confirm the warning is gone.Source: Pipeline failures
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@apps/customer/lib/screens/live_tracking_screen.dart`:
- Around line 417-439: Remove the unused dead method _pointAlongRoute from the
class: delete the entire function definition (including its use of _routePoints,
_interpolatePoint, _fallbackPickupPoint, and _fallbackDropPoint) since routing
now uses _currentPosition/_previousPosition; ensure no other code references
_pointAlongRoute and run analyzer to confirm the warning is gone.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: ec9601bf-9beb-487e-bf06-aa0987a74a80
📒 Files selected for processing (2)
apps/customer/lib/screens/live_tracking_screen.dartbackend/api/src/sockets/tracker.js
🚧 Files skipped from review as they are similar to previous changes (1)
- backend/api/src/sockets/tracker.js
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/customer/lib/screens/live_tracking_screen.dart (1)
55-60:⚠️ Potential issue | 🟠 Major | ⚡ Quick winCancel the tracking stream before disposing
_movementController.
_trackingSubscriptionstill drives_updateTruckPosition(), and that path reads_movementController. Disposing the controller first leaves a teardown window where an in-flight websocket event can hit a disposed controller while the state is still mounted.Proposed fix
`@override` void dispose() { - _movementController.dispose(); _ordersChannel?.unsubscribe(); - _trackingSubscription?.cancel(); - _trackingWebSocket?.close(); + unawaited(_trackingSubscription?.cancel()); + unawaited(_trackingWebSocket?.close()); + _movementController.dispose(); super.dispose(); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/customer/lib/screens/live_tracking_screen.dart` around lines 55 - 60, Dispose currently disposes _movementController before cancelling _trackingSubscription, which allows in-flight websocket events to call _updateTruckPosition() and access a disposed controller; change the order in dispose() so that _trackingSubscription is cancelled (call _trackingSubscription?.cancel()) before disposing _movementController, keeping the other teardown steps (_ordersChannel?.unsubscribe(), _trackingWebSocket?.close(), super.dispose()) but ensuring cancellation of _trackingSubscription happens prior to calling _movementController.dispose() so no callbacks run against the disposed controller.
🧹 Nitpick comments (2)
apps/customer/lib/screens/live_tracking_screen.dart (1)
64-72: Fix websocket path construction to match/ws/trackingexactly:backend/api/src/sockets/tracker.jsupgrades only whenpathname === '/ws/tracking', butlive_tracking_screen.dartbuilds the client path asbaseUri.path + '/ws/tracking'. This will fail ifTRUXIFY_API_BASE_URLincludes a path prefix (e.g./api), because the client would connect to/api/ws/trackinginstead. DefaultdefaultApiBaseUrlis host-only (http://localhost:5000), so it works in that config; still, make the builder forcewsPath = '/ws/tracking'(or otherwise strip any existingbaseUri.path).🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/customer/lib/screens/live_tracking_screen.dart` around lines 64 - 72, The websocket path construction in live_tracking_screen.dart currently appends baseUri.path to '/ws/tracking' which breaks when TRUXIFY_API_BASE_URL has a path prefix; update the logic that sets wsPath (variables apiBaseUrl, baseUri, wsScheme, wsPath) to always use the exact pathname '/ws/tracking' (i.e., set wsPath = '/ws/tracking') or strip any existing baseUri.path before appending so the client connects to '/ws/tracking' exactly.docs/wiki/Automation-&-Voice-AI.md (1)
15-40: ⚡ Quick winUnlabeled fenced diagrams need a language tag. All of these blocks are plain diagrams, so markdownlint flags them until they declare a language. Use
textif you want to keep the ASCII art, ormermaidwhere you want rendered flowcharts.
docs/wiki/Automation-&-Voice-AI.md#L15-L40: label the first diagram fence.docs/wiki/Automation-&-Voice-AI.md#L64-L81: label the second diagram fence.docs/wiki/Blockchain-&-Trust-Layer.md#L23-L40: label the contract-flow fence.docs/wiki/Home.md#L26-L47: label the system-overview fence.docs/wiki/Machine-Learning-Layer.md#L84-L103: label the retraining-flow fence.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/wiki/Automation-`&-Voice-AI.md around lines 15 - 40, Label each unlabeled fenced diagram by changing the opening ``` to include a language tag; for these ASCII art diagrams prefer ```text (or convert to a mermaid flowchart and use ```mermaid if you want rendering). Specifically: in docs/wiki/Automation-&-Voice-AI.md lines 15-40 change the opening fence to ```text (or ```mermaid if converting), in docs/wiki/Automation-&-Voice-AI.md lines 64-81 change the opening fence to ```text (or ```mermaid), in docs/wiki/Blockchain-&-Trust-Layer.md lines 23-40 change the opening fence to ```text (or ```mermaid), in docs/wiki/Home.md lines 26-47 change the opening fence to ```text (or ```mermaid), and in docs/wiki/Machine-Learning-Layer.md lines 84-103 change the opening fence to ```text (or ```mermaid); leave the closing fences as-is.Source: Linters/SAST tools
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/wiki/Architecture-`&-Tech-Stack.md:
- Around line 167-170: Update the security section to document the tracker
WebSocket's dual JWT path: keep the Firebase Auth description (phone/OTP → JWT →
Authorization: Bearer <token>) and the Node.js auth.js middleware flow, then add
a new bullet that the tracker WebSocket upgrade handler also accepts and
verifies Supabase JWTs (in addition to Firebase tokens) during the WebSocket
handshake and binds the resulting user/role to the socket context; note that
Supabase verification uses the SUPABASE_SERVICE_ROLE_KEY for server-side
validation and that both JWTs are treated as valid authentication sources for
API/socket access.
In `@docs/wiki/Blockchain-`&-Trust-Layer.md:
- Line 64: Fix the typos in the sentence that currently reads "If a driver
alters a document scan on their phone or if an database entry is modified, the
file's hash will not match the on-chain registry, flaggin the account." Change
"an database" to "a database" and "flaggin" to "flagging" so the sentence reads
correctly (preserve the rest of the wording).
In `@docs/wiki/Home.md`:
- Line 17: The document uses both "decentralized" and "decentralised"; choose
one spelling and make it consistent across the wiki—e.g., replace
"decentralised" with "decentralized" in the line "* **[Blockchain & Trust
Layer](Blockchain-&-Trust-Layer)**: Trustless escrow, document hash integrity,
decentralised ratings, and Polygon/Solidity smart contracts." and run a
repo-wide search/replace for the alternate spelling to update every occurrence.
In `@docs/wiki/Machine-Learning-Layer.md`:
- Around line 55-67: Update the docs for the POST /train/demand endpoint to
match the trainer contract: state that the trainer uses synthetic data only
(remove or reword the claim about archived MongoDB telemetry logs) and update
the example JSON response to include the feature_names field returned by the
trainer (e.g., add "feature_names": [...]) alongside status and metrics; ensure
the text and sample response under the POST /train/demand section reflect these
exact changes so the documentation matches the trainer behavior.
---
Outside diff comments:
In `@apps/customer/lib/screens/live_tracking_screen.dart`:
- Around line 55-60: Dispose currently disposes _movementController before
cancelling _trackingSubscription, which allows in-flight websocket events to
call _updateTruckPosition() and access a disposed controller; change the order
in dispose() so that _trackingSubscription is cancelled (call
_trackingSubscription?.cancel()) before disposing _movementController, keeping
the other teardown steps (_ordersChannel?.unsubscribe(),
_trackingWebSocket?.close(), super.dispose()) but ensuring cancellation of
_trackingSubscription happens prior to calling _movementController.dispose() so
no callbacks run against the disposed controller.
---
Nitpick comments:
In `@apps/customer/lib/screens/live_tracking_screen.dart`:
- Around line 64-72: The websocket path construction in
live_tracking_screen.dart currently appends baseUri.path to '/ws/tracking' which
breaks when TRUXIFY_API_BASE_URL has a path prefix; update the logic that sets
wsPath (variables apiBaseUrl, baseUri, wsScheme, wsPath) to always use the exact
pathname '/ws/tracking' (i.e., set wsPath = '/ws/tracking') or strip any
existing baseUri.path before appending so the client connects to '/ws/tracking'
exactly.
In `@docs/wiki/Automation-`&-Voice-AI.md:
- Around line 15-40: Label each unlabeled fenced diagram by changing the opening
``` to include a language tag; for these ASCII art diagrams prefer ```text (or
convert to a mermaid flowchart and use ```mermaid if you want rendering).
Specifically: in docs/wiki/Automation-&-Voice-AI.md lines 15-40 change the
opening fence to ```text (or ```mermaid if converting), in
docs/wiki/Automation-&-Voice-AI.md lines 64-81 change the opening fence to
```text (or ```mermaid), in docs/wiki/Blockchain-&-Trust-Layer.md lines 23-40
change the opening fence to ```text (or ```mermaid), in docs/wiki/Home.md lines
26-47 change the opening fence to ```text (or ```mermaid), and in
docs/wiki/Machine-Learning-Layer.md lines 84-103 change the opening fence to
```text (or ```mermaid); leave the closing fences as-is.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 11bb5c61-65d9-4953-a1d8-e8e02e0c9aa0
⛔ Files ignored due to path filters (1)
backend/ml/models_storage/demand_forecast.pklis excluded by!**/*.pkl
📒 Files selected for processing (12)
apps/customer/lib/core/offline/websocket/resilient_websocket.dartapps/customer/lib/screens/live_tracking_screen.dartbackend/api/src/sockets/tracker.jsbackend/api/test/unit/tracker.test.jsbackend/ml/models_storage/demand_forecast_meta.jsondocs/wiki/Architecture-&-Tech-Stack.mddocs/wiki/Automation-&-Voice-AI.mddocs/wiki/Blockchain-&-Trust-Layer.mddocs/wiki/Database-Schema.mddocs/wiki/Getting-Started-&-Local-Setup.mddocs/wiki/Home.mddocs/wiki/Machine-Learning-Layer.md
✅ Files skipped from review due to trivial changes (3)
- docs/wiki/Database-Schema.md
- backend/ml/models_storage/demand_forecast_meta.json
- docs/wiki/Getting-Started-&-Local-Setup.md
dd19313
into
KanishJebaMathewM:main
|
🎉 Thank you for your contribution! Your pull request has been merged successfully. We appreciate your work and look forward to your future contributions. 🚀 |
fix(customer-app): support real-time GPS tracking for truck marker with smooth interpolation #448
Closes #448
#What
How
Summary by CodeRabbit
New Features
Improvements
Bug Fixes
Tests
Documentation