Found during a targeted code review, not from a user report:
- _run_jpeg_loop()/_run_h264_loop() operated directly on the shared
self._proc_jpeg/self._proc_h264 instance attributes in their cleanup,
unlike _run_mjpeg_loop() (already fixed for exactly this) which uses a
local `proc` reference. If a loop's task is cancelled - e.g. by
CameraCache.reset() after the printer rotates its stream URL on reboot -
while a new task has already started and assigned its own process to the
shared attribute, the cancelled task's cleanup killed the NEWER process
instead of its own, leaking its own ffmpeg child as an orphan. Applied
the same local-variable + identity-check pattern already used by
_run_mjpeg_loop.
- handle_api_settings_post and handle_api_update_apply were the only two
of ~84 handlers that called `await request.json()` without a try/except -
every other handler follows the established pattern of returning a clean
400 for a malformed body. A trivial malformed request to either endpoint
produced an unhandled 500 with a full traceback instead.
New tests in tests/test_camera_process_race.py,
tests/test_settings.py, and tests/test_update_check.py cover both.
Replace the fixed dashboard layout with a fully customizable GridStack.js
grid (12-col snap grid, vendored + inlined so it also works in OrcaSlicer's
embedded webview). Cards can be dragged, resized, hidden and rearranged;
layout persists per browser. Includes two built-in presets (Standard,
Wide desktop per the original Issue #89 proposal) plus the ability to
save/apply/delete named custom presets.
fix(camera): stream freeze after ~15-30min from non-monotonic FLV
timestamps — ffmpeg's realtime pacing stalls on PTS jumps in the printer's
stream. Fixed with -use_wallclock_as_timestamps on both ffmpeg call sites
(CameraCache._input_args, _run_h264_loop). Issue #90.
test: fix tests/conftest.py referencing a stale bridge/ subfolder path and
missing args.data_dir (pre-existing breakage, unrelated to this feature);
rewrite the two test_settings.py cases that still mocked the removed
_find_env_path from the old .env-based settings storage.