plan 0016 (3/3): prompt for firmware and tracks on connect - #383
Closed
TheAngryRaven wants to merge 3 commits into
Closed
plan 0016 (3/3): prompt for firmware and tracks on connect#383TheAngryRaven wants to merge 3 commits into
TheAngryRaven wants to merge 3 commits into
Conversation
… itself checkForUpdates toasted on every non-update outcome — "up to date", "couldn't read the version", "check failed". That is right when the user pressed the button and wrong for a check that fires on connect: they didn't ask, and being told nothing happened is worse than being told nothing. It now takes a `silent` option, and returns whether an update was actually offered so an automatic caller knows whether it still owns the screen. The snooze is keyed by DEVICE AND VERSION, and checked against the version actually on offer rather than up front. Two consequences, both wanted: the owner's two loggers snooze independently, and a NEW release asks again immediately instead of inheriting yesterday's "tomorrow". Storage is a standalone module in the pendingCheckout.ts shape — a private localStorage key and a pure parse(raw, now) the getters wrap, so the 24h rule is testable without touching the clock. Deliberately NOT AppSettings: that is cloud-synced, and "I'll do it tomorrow" is a decision about this browser and this logger, not something to push to every device the user owns. A future timestamp is treated as live rather than discarded, so winding the clock back can't silently un-snooze everything. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ESkRRtF4vRrANPL6huSgmD
The firmware dialog used to be inline in FirmwareUpdateSection, which mounts only when the drawer is open, on the Device tab, on the settings sub-tab, while connected over BLE. A check that fires on connect had nowhere to show itself. Split the dialog out and give a FirmwareUpdateProvider ownership of the single useFirmwareUpdate instance, rendered once high in the tree. Mounting a second instance instead would mean two device-version reads over GATT and two dialogs racing to be the one on screen. DeviceConnectFlow then runs the two questions in order on each new connection: - FIRMWARE FIRST, because accepting it reboots the device and drops the link — anything queued behind it would be thrown away. It is also the rarer of the two, and "remind me tomorrow" keeps it rare. - THEN TRACKS, and only when the sync plan actually has rows. A prompt that appears on every connect to say "nothing to sync" is worse than silence, and the plan already excludes the rows that could never converge. Declining the track prompt is scoped to the connection: no stored suppression, and the flow only re-runs when a new connection appears. Being asked again after deliberately reconnecting is expected; being asked twice on one connection is nagging. Offline, the firmware step is skipped rather than surfaced — the manifest is a network fetch and that is not this connection's problem. A failure reading the card is logged, not toasted, for the same reason the auto-check went silent: the user didn't ask, and the Device → Tracks tab is still there. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ESkRRtF4vRrANPL6huSgmD
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ESkRRtF4vRrANPL6huSgmD
|
This pull request has been ignored for the connected project Preview Branches by Supabase. |
Coverage SummaryLines: 58.28% (7485/12841) · Statements: 57.43% · Functions: 55.17% · Branches: 55.2% Per-file coverage
|
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
lapwing | e59adfd | Commit Preview URL Branch Preview URL |
Aug 05 2026, 06:37 AM |
10 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Last of three (plan 0016). Targets #382, so the diff shows only this PR's work — retarget as the stack lands.
Connect a logger and two questions run in order:
Declining the track prompt is scoped to the connection: no stored suppression, and the flow only re-runs when a new connection appears. Being asked again after deliberately reconnecting is expected; twice on one connection is nagging.
The snooze
Keyed by device and version, and checked against the version actually on offer rather than up front. So your two loggers snooze independently, and a brand-new release asks again immediately instead of inheriting yesterday's "tomorrow".
Storage is a standalone
src/lib/firmwareUpdateReminder.tsin thependingCheckout.tsshape — private localStorage key, pureparse(raw, now)the getters wrap. Deliberately notAppSettings: that's cloud-synced viaaccountExport.ts, and "I'll do it tomorrow" is a decision about this browser and this logger, not something to push to every device you own.Two changes that made it possible
checkForUpdatesgainedsilentandsuppress, and now returns whether an update was offered. It toasted on every non-update outcome — "up to date", "couldn't read the version", "check failed". Right for a button press, wrong for a check the user didn't ask for.FirmwareUpdateSection, which mounts only with the drawer open, on the Device tab, on the settings sub-tab, over BLE — so an on-connect check had nowhere to render.FirmwareUpdateProvidernow owns the singleuseFirmwareUpdateinstance and rendersFirmwareUpdateDialogonce, high in the tree.Related Issues
Stacked on #382 (plan 0016 2/3), which is stacked on #381.
Type of Change
Checklist
bun run lintpassesbun run typecheckpassesbun run test:runpasses (2719 tests, 190 files)bun run buildsucceedsuseOnlineStatusCHANGELOG.mdNotes for Reviewers
The dialog hoist is the riskiest thing in this PR and it's worth a look even though it's mechanical.
FirmwareUpdateSectionwent from ~200 lines to ~55 — everything removed is now inFirmwareUpdateDialog.tsxunchanged apart from the new snooze button. The alternative (a seconduseFirmwareUpdateinstance for the auto-check) would have meant two GATT version reads per connect and two dialogs racing to be on screen, so I took the refactor instead.Things I'd flag:
nodewith no testing-library — soDeviceConnectFlowand the dialog have no unit tests, only the purefirmwareUpdateRemindermodule does (14 tests). The connect sequencing genuinely needs hardware to verify. The one behaviour I'd specifically watch: after you dismiss or snooze the firmware dialog, the track prompt should follow — that transition keys offconfirmOpengoing back down, which is the least robust thing here.DeviceProvideris mounted twice inIndex.tsx(landing and main), soFirmwareUpdateProvider+DeviceConnectFloware mounted twice too — never simultaneously, since the branches are exclusive, but worth knowing.DeviceDetails.supportsSprintTracksis the seam if you ever want one.Generated by Claude Code