Skip to content

Refresh stale source_dir on already-queued rows#17

Merged
RobXYZ merged 1 commit into
RobXYZ:mainfrom
jusii:pr/ro-source-dir-fix
Jun 12, 2026
Merged

Refresh stale source_dir on already-queued rows#17
RobXYZ merged 1 commit into
RobXYZ:mainfrom
jusii:pr/ro-source-dir-fix

Conversation

@jusii

@jusii jusii commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Summary

reconcile() in web/services/queue.py short-circuits on if filename in existing: continue, so an already-queued row's source_dir is never refreshed. When the user locks a clip on the dashcam between sync cycles the file moves from /DCIM/Movie to /DCIM/Movie/RO; the queue still points at the old path and the worker burns its full retry budget on HTTP 404 until the row is marked failed — and the clip never syncs.

The fix: when a fresh listing carries a different filepath for an already-queued filename, update source_dir — but only while the row is pending or failed. done/downloading/gone rows are left alone since their path is historical at that point. The reconcile summary dict gains a refreshed_source_dir count.

When this triggers

Sync only runs while the dashcam is reachable over WiFi (typically parked at home in station mode), so the window is any active sync session:

  1. Manual lock (rec button) while a sync session is running or between cycles
  2. A parking-mode G-sensor event that locks a clip an earlier listing pass in the same session had already queued

Clips locked while driving are unaffected — by the next sync they're already under /RO and get queued with the correct path from the start.

Test plan

  • New regression test test_refresh_updates_source_dir_when_clip_moves_to_ro — fails on the unfixed reconcile, passes with the fix
  • Full suite green
  • Live-verified on a 3-camera A329: pressed the lock button mid-sync; the next reconcile picked up the path change for all three affected files (front/rear/telephoto) with attempts=0 — no retry budget burned, downloads proceeded from the new /RO path

When a user locks a clip on the dashcam the file moves from
/DCIM/Movie to /DCIM/Movie/RO. reconcile() previously short-
circuited on "filename already in queue" and never picked up the
new path, so the sync worker kept hitting the old URL and burned
its retry budget on HTTP 404 until the row was marked failed.

The fresh listing already has the correct path; just propagate
it to the existing row when state is pending or failed. done /
downloading / gone rows are intentionally left alone — the
source_dir is historical at that point.
@RobXYZ RobXYZ merged commit 16eff70 into RobXYZ:main Jun 12, 2026
1 check passed
@RobXYZ

RobXYZ commented Jun 12, 2026

Copy link
Copy Markdown
Owner

Good spot, thanks for this!

jusii added a commit to jusii/viofosync that referenced this pull request Jun 12, 2026
@RobXYZ RobXYZ mentioned this pull request Jun 17, 2026
Merged
RobXYZ added a commit that referenced this pull request Jun 18, 2026
### Added

#### Camera Control

A new **Camera** tab reads the dashcam's current settings and lets you adjust the safely-changeable ones over Wi-Fi — on/off toggles, drop-downs, and a recording indicator — each validated against the camera's own option list and read back to confirm it stuck. Destructive commands (format SD, factory reset, firmware update, delete, reboot) are hard-blocked and never shown, and the few record-only settings auto-pause then resume recording. Settings for 29 Viofo models are mapped from the official app's command database; the A329S is validated on hardware. Contributed by [@droomurray](https://github.com/droomurray) (#21).

#### Three-Camera Support (Telephoto / Interior)

Telephoto (`T`) and interior/cabin (`I`) clips are now first-class alongside front and rear. They sync, index, and pair into the same capture group, so a three-camera day shows a third thumbnail in the archive and a third track on the timeline. New exports cover them: **Join Tele** / **Join Interior**, plus picture-in-picture with the third camera fullscreen and the front camera as the inset (the front clip stays the audio source, so the microphone track is preserved). The clip viewer's camera key cycles through every camera present at a timestamp. Two-camera setups are visually unchanged. Contributed by [@jusii](https://github.com/jusii) (#18).

#### Background Thumbnails & Filmstrips

Thumbnails and timeline filmstrips are now produced by a background worker as clips download — and existing clips are backfilled — so the archive and timeline populate as soon as footage arrives instead of after a sync cycle finishes. A new **Thumbnails** settings section controls it: thumbnail pre-generation is on by default, while the heavier filmstrip pre-generation is opt-in and otherwise falls back to generating on demand the first time a clip is viewed.

#### Per-Segment Picture-in-Picture in the Editor

The timeline editor's switched-camera cut can now carry a picture-in-picture inset on a per-segment basis. With a segment selected, press the PiP button (or **P**) to cycle the inset through your other cameras — it skips the segment's own camera — and a green placeholder shows where it will sit. The choice is remembered per segment and composited into the export, in the corner set by the global picture-in-picture position setting. A segment whose chosen camera has no overlapping footage simply exports without the inset.

#### Skip Downloads

You can now skip clips you don't want to sync. Select them in the download queue and choose **Skip** from the **Actions** menu; skipped clips get their own badge and are never downloaded. **Clear skip** returns them to the queue with a fresh set of retry attempts. Queue selection now spans pending, failed, and skipped clips, so one Actions menu — Download next / Skip / Clear skip / Retry failed — drives the whole list.

### Changed

- On/off controls across the app are now toggle switches, with one tooltip style used app-wide that works on hover, keyboard focus, and tap.
- The sync **pause** state is remembered across restarts instead of resetting to running.
- The download queue's per-action buttons are now a single **Actions** menu with **Apply**; selection-based **Retry failed** replaces the old retry-all button, while **Download recent hours next** is unchanged.
- Archive thumbnails animate on hover, scrubbing the clip's filmstrip — the same preview the Export Jobs list already offered. They fall back to the static thumbnail when no filmstrip is available, and respect reduced-motion.

### Fixed

- Locking a clip on the dashcam between sync cycles moves it into the camera's `/RO` folder; the download queue now refreshes the clip's source path when the camera re-reports it there, instead of exhausting its retry budget against the stale path and never syncing the clip. The dashcam-delete lock guard benefits too, since it keys off the same refreshed `/RO` path. Contributed by [@jusii](https://github.com/jusii) (#17).
- The Logs view now shows the date alongside the time and stays readable on a phone — long lines wrap rather than being clipped off-screen.
- Tapping a drop-down or text field no longer zooms the page in on mobile, and the interface no longer pinch-zooms — it behaves like a fixed app viewport.
- Auto-detected journeys on the timeline no longer miss the start of a drive or cut short on arrival — the journey window is padded past the GPS stop radius to take in the pull-away and pull-in clips, bounded by the surrounding parking footage.
@jusii jusii deleted the pr/ro-source-dir-fix branch June 18, 2026 12:41
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.

2 participants