feat(api,viewer): viewer REST shim + rename AnthiasWebview → AnthiasViewer#2907
Conversation
…iewer - Add GET /api/v2/viewer/playlist returning server-evaluated active assets, next deadline, and ``now``; gated by internal token. - Add GET /api/v2/viewer/settings exposing only the viewer-relevant settings subset (shuffle/show_splash/screen_rotation/audio_output/ debug_logging) so the internal-auth path doesn't surface operator credentials. - Rename the C++ binary AnthiasWebview → AnthiasViewer (.pro file, Dockerfile copies, sh.Command spawn, test runner) and the D-Bus service anthias.webview → anthias.viewer (atomic because both endpoints ship in the same image). - Migrate runtime state paths /data/.local/share/AnthiasWebview and /data/.cache/AnthiasWebview to AnthiasViewer with a one-shot symlink so existing devices keep QtWebEngine cookies / local- storage across the upgrade. - Source tree src/anthias_webview/ stays put; the directory rename is deferred to Phase 5 when the Python viewer package is deleted. First step of GH #2906; sets up the contract the C++ viewer will consume in Phase 3. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- ViewerPlaylistViewV2 now reloads anthias.conf on read so an in-flight settings PATCH doesn't shuffle off a stale cached value — mirrors what ViewerSettingsViewV2 already did. - AssetSerializerV2.get_is_active accepts ``now`` via context so ViewerPlaylistViewV2 can render the ``is_active`` field against the same instant the filter used; closes the millisecond race where a row right on a window boundary could be returned in ``assets`` while its ``is_active`` re-evaluated to False. - Simplify the windowed-deadline-cap test assertion: parse the ISO timestamp and compare datetimes directly instead of the awkward dual-format string-prefix check. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Silences SonarCloud python:S5332 on tests/test_viewer_api.py. The fixture URIs are never fetched — they just satisfy the ``uri`` field on Asset.objects.create — but matching the existing test_recheck_endpoint.py convention keeps the linter quiet without sprinkling NOSONAR comments through test data. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Validated on real hardware: a fresh AnthiasViewer cache rebuilds itself on the next page load, so the bookkeeping to preserve cookies / local-storage across the AnthiasWebview → AnthiasViewer rename isn't worth the code. Upgraded devices just get fresh state dirs alongside the (now-orphaned) old AnthiasWebview tree. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
End-to-end verification on real hardwareTagged the build
Symlink-migration follow-upPer discussion, dropped the elaborate symlink-migration block from Video playback (#2905 follow-up on Rock Pi)The Rock Pi 4 was specifically flagged as having had no #2905 validation. Running through it now:
Open
🤖 Generated with Claude Code |
Burn-in update — Rock Pi 4 (1 GB variant), realistic mixFollowed the 1080p HEVC + H.264 baseline with a graduated realistic-mix burn-in: HEVC video → JPG image → webpage. Findings, working from healthiest to most stressful: What works cleanly
Where it falls over
DiagnosisNot a viewer bug, not a regression. This Rock Pi 4 is the 1 GB RAM variant (visible in The video pipeline itself (after #2905) is fine on this hardware as long as the webpage assets in rotation are light. Open follow-ups (separate from this PR)
None of the above gate this PR; everything its diff actually changes (rename, endpoints, simpler 🤖 Generated with Claude Code |



Issues Fixed
First step of #2906. Lands two of the five phases that issue lays
out: Phase 1 (server-side REST shim) and the safe-now subset of
Phase 4 (binary / D-Bus / runtime-path renames). The source-tree
rename
src/anthias_webview/ → src/anthias_viewer/is deferred toPhase 5 because the directory name collides with the still-extant
Python viewer package.
Description
REST shim (Phase 1). Two new endpoints, both internal-auth
gated (same shared token as
/api/v2/assets/<id>/recheck):GET /api/v2/viewer/playlist— server-evaluated active assets,shuffled if
shuffle_playlistis set, plus the nextre-evaluation deadline and the server's notion of
now.Mirrors
anthias_viewer.scheduling.generate_asset_list()butreturns
Assetrows soAssetSerializerV2can render them.GET /api/v2/viewer/settings— viewer-relevant subset only(
shuffle_playlist,show_splash,screen_rotation,audio_output,debug_logging). Narrower thanDeviceSettingsViewV2on purpose: keeps operator credentialfields off the viewer-facing path.
The Python viewer keeps using its own copy of
generate_asset_listfor now — the C++ viewer (Phase 3) will switch to these endpoints
and the Python duplicate goes away in Phase 5.
Rename (partial Phase 4). Binary
AnthiasWebview → AnthiasViewerand D-Bus service
anthias.webview → anthias.viewer, appliedatomically:
.profile renamed; Qt 6 + Qt 5 builder Dockerfiles updated.sh.Command('AnthiasViewer')spawn from the Python viewer; theD-Bus rename is safe because client and service ship in the same
image.
bin/start_viewer.shnow writes to/data/.local/share/AnthiasViewerand/data/.cache/AnthiasViewerwith a one-shot symlink from the old paths so upgraded devices
keep QtWebEngine cookies / local-storage.
bin/test_webview_cpp.sh, comment trail insrc/anthias_viewer/*.py,tests/test_viewer.py/tests/test_media_player.pyassertions,src/anthias_webview/README.md.Test plan
uv run ruff check .anduv run ruff format --check .cleanuv run pytest -m "not integration"— 876 passed, 42 deselectedtests/test_viewer_api.pycovers auth (no token / wrong token),empty playlist, active-only filter, play_order ordering, deadline
= soonest end_date, deadline = scheduled start_date, windowed
60s cap, shuffle membership, settings subset, screen_rotation
clamp (12 cases total)
migration, D-Bus service rename)
Checklist
🤖 Generated with Claude Code