Widget system Phase 3: calendar widgets become size-aware
Build and push server image / test (push) Successful in 19s
Build and push server image / build-and-push (push) Successful in 1m58s

calendar_render.py's _build_* functions now take a real target box
and pick font sizes/margins from three discrete size tiers (nearest
pixel-area fit) instead of always laying out at full panel size and
resizing after the fact -- a calendar widget placed smaller than the
full panel gets an actually-legible layout instead of shrunk text.
Month view falls back to agenda below the smallest tier, where 7
columns can no longer stay readable.

The old photo-inlay split (inlay_region/_content_region/_paste_inlay)
is deleted along with it -- arbitrary widget placement already
subsumes what a fixed half-panel split did, and every call site has
passed photo_inlay=None since the Phase 2 cutover.

Also adds HTTP-level test coverage for GET .../preview/calendar,
which had none before this -- it's what caught a stale photo_inlay
kwarg left over from the _build signature change that would have
TypeError'd on every request.
This commit is contained in:
2026-07-24 09:38:10 -04:00
parent 37bd657299
commit 99069ba5fe
7 changed files with 288 additions and 170 deletions
+7 -7
View File
@@ -39,13 +39,13 @@ def compute_face_labels(preview_bytes: bytes, faces: list[dict], display_mode: s
computed here won't match what's actually on screen.
`region` is (x0, y0, w, h): where in the logical canvas the photo
actually landed, if not the whole thing -- e.g. calendar mode's
agenda photo-inlay only occupies half the panel (see
calendar_render.inlay_region), and without this a label would be
placed as if the photo filled the entire canvas, landing well off
where the inlaid photo actually is. None (the default) means the
photo fills the whole logical canvas, matching every other caller
(photos mode always renders full-panel).
actually landed, if not the whole thing -- e.g. a photo widget placed
in one corner of the panel rather than full-screen (see
routers/common.py's build_manage_content, which passes each photo
widget's own placement rect) -- without this a label would be placed
as if the photo filled the entire canvas, landing well off where the
widget actually is. None (the default) means the photo fills the
whole logical canvas.
The placement math matches render_frame()'s own composition step
exactly (see image_pipeline._placement_transform, shared so the two