lotus(#4): focus-participant spotlight via widget action
Adds io.lotus.focus_participant (toWidget): the host can pin a participant to the spotlight by Matrix user id (or clear with userId:null), via a manual override injected into CallViewModel.spotlightSpeaker$. Replaces cinny's fragile DOM .click() tile-selector focus hack. Extracts the action enum into lotusActions.ts (no circular import) and allow-lists Lotus toWidget actions in initializeWidget. Additive: no-op unless the host sends the action. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
444af5f7ac
commit
9d7784b9bc
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Custom widget actions exchanged between the Lotus host (cinny) and this fork.
|
||||
* Kept dependency-free so both `widget.ts` and `lotus/*` can import it without
|
||||
* a circular dependency.
|
||||
*/
|
||||
export enum LotusWidgetActions {
|
||||
/** fromWidget: in-call per-participant speaking / mute state. */
|
||||
CallState = "io.lotus.call_state",
|
||||
/** toWidget: pin/spotlight (or clear, with userId=null) a participant. */
|
||||
FocusParticipant = "io.lotus.focus_participant",
|
||||
/** toWidget: mix an audio clip into the local published mic track. */
|
||||
InjectAudio = "io.lotus.inject_audio",
|
||||
}
|
||||
|
||||
/** toWidget Lotus actions that must be allow-listed in `initializeWidget`. */
|
||||
export const LOTUS_TO_WIDGET_ACTIONS: LotusWidgetActions[] = [
|
||||
LotusWidgetActions.FocusParticipant,
|
||||
LotusWidgetActions.InjectAudio,
|
||||
];
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
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 { type IWidgetApiRequest } from "matrix-widget-api";
|
||||
|
||||
import { type CallViewModel } from "../state/CallViewModel/CallViewModel";
|
||||
import { widget } from "../widget";
|
||||
import { LotusWidgetActions } from "./lotusActions";
|
||||
|
||||
/**
|
||||
* Handle the host's `io.lotus.focus_participant` toWidget action (#4): pin a
|
||||
* participant to the spotlight by Matrix user id, or clear it with
|
||||
* `{ userId: null }`. This replaces cinny's old DOM `.click()` tile-selector
|
||||
* hack with a real, layout-aware spotlight override.
|
||||
*
|
||||
* No effect unless the host actually sends the action, so registering the
|
||||
* handler whenever we're a widget is safe. Returns a teardown function.
|
||||
*/
|
||||
export function startLotusFocus(vm: CallViewModel): () => void {
|
||||
const w = widget;
|
||||
if (!w) return () => undefined;
|
||||
|
||||
const handler = (ev: CustomEvent<IWidgetApiRequest>): void => {
|
||||
// Always reply so the host transport doesn't time out.
|
||||
void w.api.transport.reply(ev.detail, {});
|
||||
const data = ev.detail.data as { userId?: unknown } | undefined;
|
||||
const userId = typeof data?.userId === "string" ? data.userId : null;
|
||||
vm.setManualSpotlight(userId);
|
||||
};
|
||||
|
||||
w.lazyActions.on(LotusWidgetActions.FocusParticipant, handler);
|
||||
return () =>
|
||||
w.lazyActions.off(LotusWidgetActions.FocusParticipant, handler);
|
||||
}
|
||||
@@ -17,16 +17,9 @@ Please see LICENSE in the repository root for full details.
|
||||
import { logger } from "matrix-js-sdk/lib/logger";
|
||||
|
||||
import { widget } from "../widget";
|
||||
import { LotusWidgetActions } from "./lotusActions";
|
||||
|
||||
/** Custom widget actions used between the Lotus host and this fork. */
|
||||
export enum LotusWidgetActions {
|
||||
/** fromWidget: in-call per-participant speaking / mute state. */
|
||||
CallState = "io.lotus.call_state",
|
||||
/** toWidget: pin/spotlight (or clear) a participant. */
|
||||
FocusParticipant = "io.lotus.focus_participant",
|
||||
/** toWidget: mix an audio clip into the local published mic track. */
|
||||
InjectAudio = "io.lotus.inject_audio",
|
||||
}
|
||||
export { LotusWidgetActions } from "./lotusActions";
|
||||
|
||||
let cachedParams: URLSearchParams | undefined;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user