lotus(#2): address review — ack contract, rate, param precedence
- Document that io.lotus.call_state is request/response and the host must
ack it (cinny listenAction replies {}) to avoid 10s-timeout churn (H1).
- Throttle 150ms -> 250ms to reduce widget traffic (M1).
- lotusParam: hash fragment wins over query, matching EC's ParamParser (L1).
- Fix the misleading "opaque" id comment; id is userId:deviceId (L2).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
9d7784b9bc
commit
0f90600a59
@@ -11,7 +11,13 @@ Please see LICENSE in the repository root for full details.
|
|||||||
* a circular dependency.
|
* a circular dependency.
|
||||||
*/
|
*/
|
||||||
export enum LotusWidgetActions {
|
export enum LotusWidgetActions {
|
||||||
/** fromWidget: in-call per-participant speaking / mute state. */
|
/**
|
||||||
|
* fromWidget: in-call per-participant speaking / mute state.
|
||||||
|
* NOTE: matrix-widget-api `transport.send` is request/response — the host
|
||||||
|
* MUST reply/ack each one (cinny's `listenAction` does, replying `{}`),
|
||||||
|
* otherwise every send sits pending for the 10s transport timeout and then
|
||||||
|
* rejects, producing continuous churn + log noise for the whole call.
|
||||||
|
*/
|
||||||
CallState = "io.lotus.call_state",
|
CallState = "io.lotus.call_state",
|
||||||
/** toWidget: pin/spotlight (or clear, with userId=null) a participant. */
|
/** toWidget: pin/spotlight (or clear, with userId=null) a participant. */
|
||||||
FocusParticipant = "io.lotus.focus_participant",
|
FocusParticipant = "io.lotus.focus_participant",
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import { type CallViewModel } from "../state/CallViewModel/CallViewModel";
|
|||||||
import { LotusWidgetActions, lotusFlag, lotusSendToHost } from "./lotusWidget";
|
import { LotusWidgetActions, lotusFlag, lotusSendToHost } from "./lotusWidget";
|
||||||
|
|
||||||
interface ParticipantState {
|
interface ParticipantState {
|
||||||
/** Opaque media id (stable per tile). */
|
/** EC media id (`${userId}:${deviceId}`), stable per participant device. */
|
||||||
id: string;
|
id: string;
|
||||||
/** Matrix user id this media belongs to. */
|
/** Matrix user id this media belongs to. */
|
||||||
userId: string;
|
userId: string;
|
||||||
@@ -59,7 +59,9 @@ export function startLotusCallState(vm: CallViewModel): () => void {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
// `speaking` flips rapidly; cap the send rate and drop no-op repeats.
|
// `speaking` flips rapidly; cap the send rate and drop no-op repeats.
|
||||||
throttleTime(150, undefined, { leading: true, trailing: true }),
|
// 250ms is plenty for speaking rings / mute badges and keeps the
|
||||||
|
// request/response widget traffic modest.
|
||||||
|
throttleTime(250, undefined, { leading: true, trailing: true }),
|
||||||
distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b)),
|
distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b)),
|
||||||
)
|
)
|
||||||
.subscribe((participants) => {
|
.subscribe((participants) => {
|
||||||
|
|||||||
@@ -30,10 +30,12 @@ let cachedParams: URLSearchParams | undefined;
|
|||||||
*/
|
*/
|
||||||
export function lotusParam(name: string): string | null {
|
export function lotusParam(name: string): string | null {
|
||||||
if (!cachedParams) {
|
if (!cachedParams) {
|
||||||
cachedParams = new URLSearchParams(window.location.search);
|
// Match EC's own ParamParser precedence: the hash fragment wins over the
|
||||||
|
// query string. So seed from the fragment first, then fill gaps from query.
|
||||||
const hash = window.location.hash.replace(/^#\/?/, "");
|
const hash = window.location.hash.replace(/^#\/?/, "");
|
||||||
const hashQuery = hash.includes("?") ? hash.slice(hash.indexOf("?") + 1) : "";
|
const hashQuery = hash.includes("?") ? hash.slice(hash.indexOf("?") + 1) : "";
|
||||||
for (const [k, v] of new URLSearchParams(hashQuery)) {
|
cachedParams = new URLSearchParams(hashQuery);
|
||||||
|
for (const [k, v] of new URLSearchParams(window.location.search)) {
|
||||||
if (!cachedParams.has(k)) cachedParams.append(k, v);
|
if (!cachedParams.has(k)) cachedParams.append(k, v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user