feat(lotus): layout, settings and reactions over the widget API (cinny #43)

The Lotus host drove these by clicking EC's hidden controls in our DOM and
read screenshare/layout state from it, which only works while the frame is
same-origin and breaks whenever a data-testid changes. New actions:

- toWidget io.lotus.set_layout { layout: "grid" | "spotlight" } → the layout
  switch view model's setLayout.
- toWidget io.lotus.open_settings { open?: boolean } → setSettingsOpen
  (toggle when `open` is omitted).
- toWidget io.lotus.toggle_reactions → a window event the reactions button
  listens for.
- fromWidget io.lotus.controls_state { screensharing, layout } on change; its
  arrival tells the host the fork supports the actions above.

Screensharing stays host-driven for now: getDisplayMedia needs the user's
click to reach this frame (Capability Delegation), which a widget message
doesn't carry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
This commit is contained in:
Lotus CI
2026-09-24 22:16:24 -04:00
co-authored by Claude Opus 5.5
parent d8880daca5
commit 6beebd3ea7
6 changed files with 180 additions and 0 deletions
+6
View File
@@ -27,6 +27,9 @@ describe("LotusWidgetActions", () => {
LotusWidgetActions.Decorations,
LotusWidgetActions.SetDeafen,
LotusWidgetActions.SetAudioOutput,
LotusWidgetActions.SetLayout,
LotusWidgetActions.OpenSettings,
LotusWidgetActions.ToggleReactions,
];
expect(new Set(LOTUS_TO_WIDGET_ACTIONS)).toEqual(new Set(expectedToWidget));
@@ -44,5 +47,8 @@ describe("LotusWidgetActions", () => {
expect(LOTUS_TO_WIDGET_ACTIONS).not.toContain(
LotusWidgetActions.DenoiseState,
);
expect(LOTUS_TO_WIDGET_ACTIONS).not.toContain(
LotusWidgetActions.ControlsState,
);
});
});