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:
co-authored by
Claude Opus 5.5
parent
d8880daca5
commit
6beebd3ea7
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
Copyright 2026 Lotus Guild
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { parseLayoutPayload, parseSettingsPayload } from "./lotusControls";
|
||||
|
||||
describe("parseLayoutPayload", () => {
|
||||
it("accepts grid and spotlight", () => {
|
||||
expect(parseLayoutPayload({ layout: "grid" })).toBe("grid");
|
||||
expect(parseLayoutPayload({ layout: "spotlight" })).toBe("spotlight");
|
||||
});
|
||||
it("rejects anything else", () => {
|
||||
expect(parseLayoutPayload({ layout: "pip" })).toBeUndefined();
|
||||
expect(parseLayoutPayload({})).toBeUndefined();
|
||||
expect(parseLayoutPayload(null)).toBeUndefined();
|
||||
expect(parseLayoutPayload("grid")).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe("parseSettingsPayload", () => {
|
||||
it("uses an explicit open flag", () => {
|
||||
expect(parseSettingsPayload({ open: true }, true)).toBe(true);
|
||||
expect(parseSettingsPayload({ open: false }, false)).toBe(false);
|
||||
});
|
||||
it("toggles when open is missing or not a boolean", () => {
|
||||
expect(parseSettingsPayload({}, false)).toBe(true);
|
||||
expect(parseSettingsPayload(undefined, true)).toBe(false);
|
||||
expect(parseSettingsPayload({ open: "yes" }, true)).toBe(false);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user