Skip to content

feat: add background auto-booking with Android notifications#57

Merged
RickyNotaro merged 2 commits intodevfrom
claude/background-auto-booking-notifications-uJZ1U
Mar 30, 2026
Merged

feat: add background auto-booking with Android notifications#57
RickyNotaro merged 2 commits intodevfrom
claude/background-auto-booking-notifications-uJZ1U

Conversation

@RickyNotaro
Copy link
Copy Markdown
Owner

Extract auto-booking logic from Radar.vue into a standalone composable
(useBackgroundAutoBook) that manages its own scan interval independently
of the view lifecycle. On native Android, shows a persistent notification
while scanning and a success notification when a car is booked.

  • Add notificationService wrapping @capacitor/local-notifications
  • Add useBackgroundAutoBook composable with self-contained scan loop
  • Add car icon drawable for notification small icon
  • Update Radar.vue to use the new background-capable auto-book

https://claude.ai/code/session_01X8qDQPShmdBGbUnvtXVSjZ

Extract auto-booking logic from Radar.vue into a standalone composable
(useBackgroundAutoBook) that manages its own scan interval independently
of the view lifecycle. On native Android, shows a persistent notification
while scanning and a success notification when a car is booked.

- Add notificationService wrapping @capacitor/local-notifications
- Add useBackgroundAutoBook composable with self-contained scan loop
- Add car icon drawable for notification small icon
- Update Radar.vue to use the new background-capable auto-book

https://claude.ai/code/session_01X8qDQPShmdBGbUnvtXVSjZ
Copilot AI review requested due to automatic review settings March 30, 2026 05:38
@RickyNotaro RickyNotaro changed the base branch from master to dev March 30, 2026 05:38
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extracts the Radar auto-booking feature into a standalone background-capable composable and adds Android local notifications so scanning/book events are visible when the app is backgrounded.

Changes:

  • Introduces useBackgroundAutoBook composable with its own scan loop and booking attempts.
  • Adds a notificationService wrapper around @capacitor/local-notifications for scanning/success/error notifications on native Android.
  • Updates the Radar view to use the new composable and adds an Android notification small icon drawable.

Reviewed changes

Copilot reviewed 6 out of 8 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/views/Radar.vue Switches the UI and start/stop handlers to the background auto-book composable.
src/composables/useBackgroundAutoBook.ts New singleton composable implementing background-capable scanning + booking logic.
src/services/notificationService.ts New notification helper for scanning/success/error notifications via Capacitor.
package.json Adds @capacitor/local-notifications dependency (web app package).
package-lock.json Locks the added Capacitor local notifications dependency.
APK/package.json Adds @capacitor/local-notifications dependency for the Android build package.
APK/android/app/src/main/res/drawable/ic_stat_directions_car.xml Adds the Android drawable used as the notification small icon.
Files not reviewed (1)
  • APK/package-lock.json: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


// Run immediately, then on interval
await scan(userLocation, radius, electricFilter);

Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

start() always schedules scanTimer after the initial await scan(...), even if that first scan called stop() (e.g., uid missing or a hard error). In that case active becomes false but a live interval still gets created, causing unnecessary background wakeups. Consider checking active.value after the initial scan (or using a runId/token) and only creating the interval when the auto-booker is still active.

Suggested change
// `scan` may call `stop()` (which sets `active` to false). Only schedule
// the interval if the auto-booker is still active after the first run.
if (!active.value) {
return;
}

Copilot uses AI. Check for mistakes.
Comment on lines +118 to +122
for (const car of candidates) {
try {
const res = await createBooking(uid, car.CarId);
const data = res.data?.d ?? res.data;

Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Calling stop() while a scan() is in progress does not prevent the current scan from continuing into the booking loop; it can still call createBooking(...) after the user has stopped auto-booking. Add additional active/cancellation checks after awaited steps and inside the booking loop (or use a scan run token/AbortController) so a stop request reliably aborts the current scan before any booking attempts.

Copilot uses AI. Check for mistakes.
clearInterval(scanTimer);
scanTimer = null;
}
await clearScanningNotification();
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stop() awaits clearScanningNotification(), which can reject (plugin errors, permission issues). Since callers trigger stop() from a click handler without awaiting/catching, a rejection here can become an unhandled promise rejection. Consider wrapping the notification clear in a try/catch inside stop() (and/or making notificationService swallow/return errors) so stop is always safe to call from the UI.

Suggested change
await clearScanningNotification();
try {
await clearScanningNotification();
} catch (e) {
// Swallow notification clearing errors to avoid unhandled promise rejections
// when stop() is triggered from the UI without awaiting/catching.
// eslint-disable-next-line no-console
console.error('Failed to clear scanning notification', e);
}

Copilot uses AI. Check for mistakes.
Comment on lines +18 to +22
export async function showScanningNotification(radius: number) {
if (!isNative) return;
await LocalNotifications.schedule({
notifications: [
{
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All LocalNotifications.* calls are awaited without any error handling. If permissions are denied (notably on newer Android versions) or the plugin call fails, these functions will throw and can leave auto-booking in a broken state. Consider handling permission denial explicitly and wrapping schedule/cancel in try/catch (returning a boolean/status) so notification failures don’t break the scan loop.

Copilot uses AI. Check for mistakes.
@RickyNotaro RickyNotaro merged commit 7a9f916 into dev Mar 30, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants