Add a text widget (rich text: bold/italic/underline, per-run color/highlight)
A new self-contained widget type showing user-authored rich text -- no
live upstream to poll, like the static image widget, just word-wrapped
styled text instead of an uploaded image.
The dialog's contenteditable HTML is never stored or replayed as HTML:
app/text_content.py parses it server-side (on save) into a plain
paragraphs-of-styled-runs structure -- the actual sanitization
boundary, since raw HTML never round-trips back into any browser DOM
(the dialog rebuilds its editor from that same JSON via
createElement/textContent). app/widgets/text.py renders it with a
custom word-wrap/shrink-to-fit layout, using real vendored font weights
(app/fonts/NotoSans-{Regular,Bold,Italic,BoldItalic}.ttf, OFL-licensed
like the emoji fonts already there) rather than every other widget's
single ImageFont.load_default() -- the one widget type where that
distinction matters.
This commit is contained in:
@@ -35,6 +35,7 @@ from ..models import (
|
||||
PhotoWidgetConfig,
|
||||
StaticWidgetConfig,
|
||||
TaskWidgetConfig,
|
||||
TextWidgetConfig,
|
||||
User,
|
||||
UserFrame,
|
||||
WhiteboardWidgetConfig,
|
||||
@@ -245,6 +246,12 @@ def widget_dialog(frame_id: int, widget_id: int, request: Request, db: Session =
|
||||
"display_mode_labels": {k: v for k, v in DISPLAY_MODE_LABELS.items() if k in STATIC_DISPLAY_MODES},
|
||||
})
|
||||
|
||||
if widget.widget_type == "text":
|
||||
text_cfg = db.get(TextWidgetConfig, widget.id)
|
||||
return templates.TemplateResponse("_widget_dialog_text.html", {
|
||||
"request": request, "frame": frame, "widget": widget, "text_cfg": text_cfg,
|
||||
})
|
||||
|
||||
if widget.widget_type == "whiteboard":
|
||||
whiteboard_cfg = db.get(WhiteboardWidgetConfig, widget.id)
|
||||
viewer_has_webdav_creds = bool(
|
||||
|
||||
Reference in New Issue
Block a user