Widget system Phase 2: full cutover to widget-based rendering
Build and push server image / test (push) Successful in 49s
Build and push server image / build-and-push (push) Successful in 1m56s

device.py's mode-keyed dispatch is replaced by a real compositor:
load a frame's widgets, compute pixel rects via app/grid.py, render
each through its widget module, and composite with render_panel.
Physical NEXT/BACK buttons now execute each frame's assigned
FrameButtonAction rows instead of one hardcoded per-mode action.

api_frames.py, manage.py, and common.py's build_manage_content are
repointed to read/write the frame's widget config rows instead of
the old Frame columns, and every settings page (Photos/Calendar/
Whiteboard tabs) now pre-fills its form from the same widget config
the write endpoints actually save to -- previously the read and
write sides would have silently diverged. The old mode selector and
photo-inlay checkbox are removed along with their now-inert wiring;
arbitrary widget placement subsumes what the fixed inlay split did.

Ships together with Phase 1 (per-type render/action modules) since
splitting the read/write cutover across deploys would have left
settings changes with no visible effect.
This commit is contained in:
2026-07-24 09:26:28 -04:00
parent f48daa71c8
commit 37bd657299
26 changed files with 1070 additions and 791 deletions
+25
View File
@@ -100,3 +100,28 @@ def test_back_action_decrements_browse_offset(db_session):
widgets.calendar.ACTIONS["back"](db_session, frame, widget)
cfg = db_session.get(CalendarWidgetConfig, widget.id)
assert cfg.browse_offset == 2
def test_normal_wake_resets_browse_offset_to_zero(db_session, monkeypatch):
"""A plain /frame/image GET (is_normal_wake=True, the default) should
snap browse_offset back to "today" if a previous button press had
moved it -- mirrors the old _render_calendar_mode's identical
behavior. A button-triggered render (is_normal_wake=False) must NOT
do this, or every button press would immediately erase its own
effect on the very next render."""
frame, widget = _make_widget(db_session, view="week", browse_offset=5)
_stub_fetches(monkeypatch)
widgets.calendar.render(db_session, frame, widget, 400, 300, is_normal_wake=True)
assert db_session.get(CalendarWidgetConfig, widget.id).browse_offset == 0
def test_button_triggered_render_does_not_reset_browse_offset(db_session, monkeypatch):
frame, widget = _make_widget(db_session, view="week", browse_offset=0)
_stub_fetches(monkeypatch)
widgets.calendar.ACTIONS["advance"](db_session, frame, widget)
assert db_session.get(CalendarWidgetConfig, widget.id).browse_offset == 1
widgets.calendar.render(db_session, frame, widget, 400, 300, is_normal_wake=False)
assert db_session.get(CalendarWidgetConfig, widget.id).browse_offset == 1