Serialize updates to the call intent
So that the value advertised in your membership can't desync from the actual value if you toggle video too fast.
This commit is contained in:
@@ -140,6 +140,7 @@ import {
|
|||||||
type SpotlightPortraitLayoutMedia,
|
type SpotlightPortraitLayoutMedia,
|
||||||
} from "./layout-types.ts";
|
} from "./layout-types.ts";
|
||||||
import { ElementCallError, UnknownCallError } from "../utils/errors.ts";
|
import { ElementCallError, UnknownCallError } from "../utils/errors.ts";
|
||||||
|
import { ObservableScope } from "./ObservableScope.ts";
|
||||||
|
|
||||||
export interface CallViewModelOptions {
|
export interface CallViewModelOptions {
|
||||||
encryptionSystem: EncryptionSystem;
|
encryptionSystem: EncryptionSystem;
|
||||||
@@ -1805,18 +1806,19 @@ export class CallViewModel extends ViewModel {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error("Error entering RTC session", e);
|
logger.error("Error entering RTC session", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update our member event when our mute state changes.
|
// Update our member event when our mute state changes.
|
||||||
const muteSubscription = this.muteStates.video.enabled$.subscribe(
|
const intentScope = new ObservableScope();
|
||||||
(videoEnabled) =>
|
intentScope.reconcile(
|
||||||
// TODO: Ensure that these calls are serialized in case of
|
this.muteStates.video.enabled$,
|
||||||
// fast video toggling
|
async (videoEnabled) =>
|
||||||
void this.matrixRTCSession.updateCallIntent(
|
this.matrixRTCSession.updateCallIntent(
|
||||||
videoEnabled ? "video" : "audio",
|
videoEnabled ? "video" : "audio",
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
return async (): Promise<void> => {
|
return async (): Promise<void> => {
|
||||||
muteSubscription.unsubscribe();
|
intentScope.end();
|
||||||
// Only sends Matrix leave event. The LiveKit session will disconnect
|
// Only sends Matrix leave event. The LiveKit session will disconnect
|
||||||
// as soon as either the stopConnection$ handler above gets to it or
|
// as soon as either the stopConnection$ handler above gets to it or
|
||||||
// the view model is destroyed.
|
// the view model is destroyed.
|
||||||
|
|||||||
@@ -114,11 +114,11 @@ export class ObservableScope {
|
|||||||
*/
|
*/
|
||||||
public reconcile<T>(
|
public reconcile<T>(
|
||||||
value$: Behavior<T>,
|
value$: Behavior<T>,
|
||||||
callback: (value: T) => Promise<(() => Promise<void>) | undefined>,
|
callback: (value: T) => Promise<(() => Promise<void>) | void>,
|
||||||
): void {
|
): void {
|
||||||
let latestValue: T | typeof nothing = nothing;
|
let latestValue: T | typeof nothing = nothing;
|
||||||
let reconciledValue: T | typeof nothing = nothing;
|
let reconciledValue: T | typeof nothing = nothing;
|
||||||
let cleanUp: (() => Promise<void>) | undefined = undefined;
|
let cleanUp: (() => Promise<void>) | void = undefined;
|
||||||
value$
|
value$
|
||||||
.pipe(
|
.pipe(
|
||||||
catchError(() => EMPTY), // Ignore errors
|
catchError(() => EMPTY), // Ignore errors
|
||||||
|
|||||||
Reference in New Issue
Block a user