fix(lotus): call_state skips standalone mode; dedupe before throttle
startLotusCallState gated only on the URL flag, so a standalone (non-widget) load built the whole per-member pipeline and stringified it at up to 8 Hz for a host that doesn't exist. Add the same `if (!widget)` guard the sibling modules use. Also move distinctUntilChanged ahead of throttleTime so an unchanged value no longer spends a throttle window (first half of #20). Fixes #31 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
This commit is contained in:
co-authored by
Claude Opus 5
parent
37c9348ee8
commit
fd957badff
@@ -6,9 +6,15 @@ Please see LICENSE in the repository root for full details.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { combineLatest, of, type Subscription } from "rxjs";
|
import { combineLatest, of, type Subscription } from "rxjs";
|
||||||
import { distinctUntilChanged, map, switchMap, throttleTime } from "rxjs/operators";
|
import {
|
||||||
|
distinctUntilChanged,
|
||||||
|
map,
|
||||||
|
switchMap,
|
||||||
|
throttleTime,
|
||||||
|
} from "rxjs/operators";
|
||||||
|
|
||||||
import { type CallViewModel } from "../state/CallViewModel/CallViewModel";
|
import { type CallViewModel } from "../state/CallViewModel/CallViewModel";
|
||||||
|
import { widget } from "../widget";
|
||||||
import { LotusWidgetActions, lotusFlag, lotusSendToHost } from "./lotusWidget";
|
import { LotusWidgetActions, lotusFlag, lotusSendToHost } from "./lotusWidget";
|
||||||
|
|
||||||
interface ParticipantState {
|
interface ParticipantState {
|
||||||
@@ -32,6 +38,10 @@ interface ParticipantState {
|
|||||||
*/
|
*/
|
||||||
export function startLotusCallState(vm: CallViewModel): () => void {
|
export function startLotusCallState(vm: CallViewModel): () => void {
|
||||||
if (!lotusFlag("lotusCallState")) return () => undefined;
|
if (!lotusFlag("lotusCallState")) return () => undefined;
|
||||||
|
// [lotus] Standalone (non-widget) mode has no host to send state to;
|
||||||
|
// skip building the whole stream pipeline, mirroring lotusFocus.ts /
|
||||||
|
// lotusDecorations.ts.
|
||||||
|
if (!widget) return () => undefined;
|
||||||
|
|
||||||
const sub: Subscription = vm.userMedia$
|
const sub: Subscription = vm.userMedia$
|
||||||
.pipe(
|
.pipe(
|
||||||
@@ -46,7 +56,11 @@ export function startLotusCallState(vm: CallViewModel): () => void {
|
|||||||
m.videoEnabled$,
|
m.videoEnabled$,
|
||||||
]).pipe(
|
]).pipe(
|
||||||
map(
|
map(
|
||||||
([speaking, audioEnabled, videoEnabled]): ParticipantState => ({
|
([
|
||||||
|
speaking,
|
||||||
|
audioEnabled,
|
||||||
|
videoEnabled,
|
||||||
|
]): ParticipantState => ({
|
||||||
id: m.id,
|
id: m.id,
|
||||||
userId: m.userId,
|
userId: m.userId,
|
||||||
speaking,
|
speaking,
|
||||||
@@ -58,11 +72,12 @@ export function startLotusCallState(vm: CallViewModel): () => void {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// `speaking` flips rapidly; cap the send rate and drop no-op repeats.
|
// `speaking` flips rapidly; drop no-op repeats BEFORE throttling so
|
||||||
// 250ms is plenty for speaking rings / mute badges and keeps the
|
// the throttle window isn't spent re-emitting an unchanged value, then
|
||||||
// request/response widget traffic modest.
|
// cap the send rate. 250ms is plenty for speaking rings / mute badges
|
||||||
throttleTime(250, undefined, { leading: true, trailing: true }),
|
// and keeps the request/response widget traffic modest.
|
||||||
distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b)),
|
distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b)),
|
||||||
|
throttleTime(250, undefined, { leading: true, trailing: true }),
|
||||||
)
|
)
|
||||||
.subscribe((participants) => {
|
.subscribe((participants) => {
|
||||||
lotusSendToHost(LotusWidgetActions.CallState, { participants });
|
lotusSendToHost(LotusWidgetActions.CallState, { participants });
|
||||||
|
|||||||
Reference in New Issue
Block a user