Next/back button assignment moves from a frame-level "Button assignments" card into each widget's own gear-icon dialog, prefilled with a sane default at creation (photos/calendar -> advance/back, whiteboard/weather -> check_now, others -> none). At most one binding per (widget, button) now -- cross-widget execution order never mattered since each widget's action only touches its own state. New firmware capability: holding NEXT or BACK past a configurable duration (min 3s, server-side default) triggers a frame-wide action instead of the per-widget short-press one -- cycling saved layouts, refreshing all widgets, or freezing/unfreezing every photo widget (see app/global_actions.py). Firmware next/back checks gain the same hold-duration polling the combo button already had; the threshold comes from the previous wake's /frame/config fetch (persisted in NVS), since this wake's button decision happens before that request. Not done here: firmware/version.txt is intentionally left unbumped -- this hasn't been built or hardware-tested (no ESP-IDF toolchain in this environment), so no firmware release build should be triggered yet.
80 lines
3.7 KiB
Python
80 lines
3.7 KiB
Python
"""Registry mapping a Widget's widget_type to its render/action module --
|
|
the widget-system's analogue of routers/device.py's old RENDERERS/
|
|
ADVANCE_RENDERERS/BACK_RENDERERS dicts, generalized from "one mode owns
|
|
the whole panel" to "each widget renders into its own region and
|
|
optionally responds to named button actions."
|
|
|
|
Each module in this package exposes:
|
|
|
|
render(db, frame, widget, target_w, target_h, is_normal_wake=True) -> Image.Image
|
|
An RGB image exactly target_w x target_h, unquantized -- the
|
|
widget's content composed into its own region. Never returns
|
|
packed panel bytes or raises for a foreseeable failure (a
|
|
widget's own fetch hiccup shows a small placeholder instead) --
|
|
image_pipeline.render_panel composites every widget's own
|
|
render() result onto one shared canvas and quantizes/packs the
|
|
whole thing once (see its own docstring). is_normal_wake
|
|
distinguishes an ordinary /frame/image GET from a button-
|
|
triggered re-render -- only app/widgets/calendar.py's render()
|
|
actually uses it (resetting browse_offset back to "today" on a
|
|
normal wake), but every module accepts it for one uniform call
|
|
signature regardless.
|
|
|
|
ACTIONS: dict[str, Callable[[Session, Frame, Widget], None]]
|
|
Named button actions this widget type supports (e.g. "advance",
|
|
"back", "check_now") -- see models.FrameButtonAction. Each
|
|
function mutates the widget's own state via db.widget_locked
|
|
internally; none return a value or re-render themselves --
|
|
whatever dispatches a button press (routers/device.py, once the
|
|
widget-system cutover lands) re-renders the whole panel once
|
|
after running every assigned action.
|
|
|
|
ACTION_LABELS: dict[str, str]
|
|
Human-readable labels for ACTIONS' keys, for the button-
|
|
assignment UI.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from ..models import FrameButtonAction
|
|
from . import battery, calendar, photos, static_image, tasks, text, weather, whiteboard
|
|
|
|
WIDGET_TYPES = {
|
|
"photos": photos,
|
|
"calendar": calendar,
|
|
"whiteboard": whiteboard,
|
|
"tasks": tasks,
|
|
"static": static_image,
|
|
"text": text,
|
|
"weather": weather,
|
|
"battery": battery,
|
|
}
|
|
|
|
|
|
def default_button_actions(frame_id: int, widget_id: int, widget_type: str) -> list[FrameButtonAction]:
|
|
"""NEXT/BACK -> whatever this widget's own advance/back concept is.
|
|
Called both when backfilling pre-widget-system frames (see
|
|
app/migration.py) and when a widget is newly created (see
|
|
routers/api_widgets.py's api_widget_create) -- a widget is never left
|
|
without a sane starting binding, so the physical buttons always do
|
|
something reasonable for it until someone deliberately reassigns
|
|
them in that widget's own config dialog."""
|
|
if widget_type == "whiteboard":
|
|
# No real "next"/"back" concept for a static board -- both
|
|
# buttons mean "check now".
|
|
return [
|
|
FrameButtonAction(frame_id=frame_id, button="next", widget_id=widget_id, action="check_now"),
|
|
FrameButtonAction(frame_id=frame_id, button="back", widget_id=widget_id, action="check_now"),
|
|
]
|
|
if widget_type == "weather":
|
|
return [
|
|
FrameButtonAction(frame_id=frame_id, button="next", widget_id=widget_id, action="check_now"),
|
|
FrameButtonAction(frame_id=frame_id, button="back", widget_id=widget_id, action="check_now"),
|
|
]
|
|
if widget_type in ("photos", "calendar"):
|
|
return [
|
|
FrameButtonAction(frame_id=frame_id, button="next", widget_id=widget_id, action="advance"),
|
|
FrameButtonAction(frame_id=frame_id, button="back", widget_id=widget_id, action="back"),
|
|
]
|
|
return []
|