fix tile flicker on video mute/unmute

(only pass rtcBackendIdenitity instead of full rtcMember)
This commit is contained in:
Timo K
2026-01-09 19:31:40 +01:00
parent 1a9e4a1a5c
commit 735c17d3e6
5 changed files with 24 additions and 27 deletions

View File

@@ -724,6 +724,7 @@ export function createCallViewModel$(
localMatrixLivekitMember;
localUserMediaId = `${userId}:${membership$.value.deviceId}`;
const rtcBackendIdentity = membership$.value.rtcBackendIdentity;
for (let dup = 0; dup < 1 + duplicateTiles; dup++) {
yield {
keys: [
@@ -732,7 +733,7 @@ export function createCallViewModel$(
userId,
participant satisfies TaggedParticipant as TaggedParticipant, // Widen the type safely
connection$,
membership$.value,
rtcBackendIdentity,
],
data: undefined,
};
@@ -746,8 +747,10 @@ export function createCallViewModel$(
membership$,
} of matrixLivekitMembers.value) {
const userMediaId = `${userId}:${membership$.value.deviceId}`;
const rtcBackendIdentity = membership$.value.rtcBackendIdentity;
// skip local user as we added them manually before
if (userMediaId === localUserMediaId) continue;
for (let dup = 0; dup < 1 + duplicateTiles; dup++) {
yield {
keys: [
@@ -756,7 +759,7 @@ export function createCallViewModel$(
userId,
participant,
connection$,
membership$.value,
rtcBackendIdentity,
],
data: undefined,
};
@@ -771,7 +774,7 @@ export function createCallViewModel$(
userId,
participant,
connection$,
membership,
rtcBackendIdentity,
) => {
const livekitRoom$ = scope.behavior(
connection$.pipe(map((c) => c?.livekitRoom)),
@@ -789,7 +792,7 @@ export function createCallViewModel$(
scope,
`${userMediaId}:${dup}`,
userId,
membership,
rtcBackendIdentity,
participant,
options.encryptionSystem,
livekitRoom$,

View File

@@ -44,7 +44,6 @@ import {
throttleTime,
distinctUntilChanged,
} from "rxjs";
import { type CallMembership } from "matrix-js-sdk/lib/matrixrtc";
import { alwaysShowSelf } from "../settings/settings";
import { showConnectionStats } from "../settings/settings";
@@ -258,7 +257,7 @@ abstract class BaseMediaViewModel {
* The Matrix user to which this media belongs.
*/
public readonly userId: string,
public readonly rtcMembership: CallMembership,
public readonly rtcBackendIdentity: string,
// We don't necessarily have a participant if a user connects via MatrixRTC but not (yet) through
// livekit.
protected readonly participant$: Observable<
@@ -404,13 +403,11 @@ abstract class BaseUserMediaViewModel extends BaseMediaViewModel {
*/
public readonly cropVideo$: Behavior<boolean> = this._cropVideo$;
public readonly rtcBackendIdentity = this.rtcMembership.rtcBackendIdentity;
public constructor(
scope: ObservableScope,
id: string,
userId: string,
rtcMembership: CallMembership,
rtcBackendIdentity: string,
participant$: Observable<LocalParticipant | RemoteParticipant | null>,
encryptionSystem: EncryptionSystem,
livekitRoom$: Behavior<LivekitRoom | undefined>,
@@ -424,7 +421,7 @@ abstract class BaseUserMediaViewModel extends BaseMediaViewModel {
scope,
id,
userId,
rtcMembership,
rtcBackendIdentity,
participant$,
encryptionSystem,
Track.Source.Microphone,
@@ -550,7 +547,7 @@ export class LocalUserMediaViewModel extends BaseUserMediaViewModel {
scope: ObservableScope,
id: string,
userId: string,
rtcMembership: CallMembership,
rtcBackendIdentity: string,
participant$: Behavior<LocalParticipant | null>,
encryptionSystem: EncryptionSystem,
livekitRoom$: Behavior<LivekitRoom | undefined>,
@@ -565,7 +562,7 @@ export class LocalUserMediaViewModel extends BaseUserMediaViewModel {
scope,
id,
userId,
rtcMembership,
rtcBackendIdentity,
participant$,
encryptionSystem,
livekitRoom$,
@@ -679,7 +676,7 @@ export class RemoteUserMediaViewModel extends BaseUserMediaViewModel {
scope: ObservableScope,
id: string,
userId: string,
rtcMembership: CallMembership,
rtcBackendIdentity: string,
participant$: Observable<RemoteParticipant | null>,
encryptionSystem: EncryptionSystem,
livekitRoom$: Behavior<LivekitRoom | undefined>,
@@ -694,7 +691,7 @@ export class RemoteUserMediaViewModel extends BaseUserMediaViewModel {
scope,
id,
userId,
rtcMembership,
rtcBackendIdentity,
participant$,
encryptionSystem,
livekitRoom$,
@@ -782,7 +779,7 @@ export class ScreenShareViewModel extends BaseMediaViewModel {
scope: ObservableScope,
id: string,
userId: string,
rtcMembership: CallMembership,
rtcBackendIdentity: string,
participant$: Observable<LocalParticipant | RemoteParticipant>,
encryptionSystem: EncryptionSystem,
livekitRoom$: Behavior<LivekitRoom | undefined>,
@@ -796,7 +793,7 @@ export class ScreenShareViewModel extends BaseMediaViewModel {
scope,
id,
userId,
rtcMembership,
rtcBackendIdentity,
participant$,
encryptionSystem,
Track.Source.ScreenShareAudio,

View File

@@ -10,7 +10,6 @@ import {
type RemoteParticipant,
type Room as LivekitRoom,
} from "livekit-client";
import { type CallMembership } from "matrix-js-sdk/lib/matrixrtc/CallMembership";
import { type ObservableScope } from "./ObservableScope.ts";
import { ScreenShareViewModel } from "./MediaViewModel.ts";
@@ -29,7 +28,7 @@ export class ScreenShare {
private readonly scope: ObservableScope,
id: string,
userId: string,
rtcMember: CallMembership,
rtcBackendIdentity: string,
participant: LocalParticipant | RemoteParticipant,
encryptionSystem: EncryptionSystem,
livekitRoom$: Behavior<LivekitRoom | undefined>,
@@ -42,7 +41,7 @@ export class ScreenShare {
this.scope,
id,
userId,
rtcMember,
rtcBackendIdentity,
of(participant),
encryptionSystem,
livekitRoom$,

View File

@@ -13,7 +13,6 @@ import {
type Room as LivekitRoom,
} from "livekit-client";
import { observeParticipantEvents } from "@livekit/components-core";
import { type CallMembership } from "matrix-js-sdk/lib/matrixrtc/CallMembership";
import { type ObservableScope } from "./ObservableScope.ts";
import {
@@ -76,7 +75,7 @@ export class UserMedia {
this.scope,
this.id,
this.userId,
this.rtcMembership,
this.rtcBackendIdentity,
this.participant.value$,
this.encryptionSystem,
this.livekitRoom$,
@@ -91,7 +90,7 @@ export class UserMedia {
this.scope,
this.id,
this.userId,
this.rtcMembership,
this.rtcBackendIdentity,
this.participant.value$,
this.encryptionSystem,
this.livekitRoom$,
@@ -143,7 +142,7 @@ export class UserMedia {
scope,
`${this.id}:${key}`,
this.userId,
this.rtcMembership,
this.rtcBackendIdentity,
p,
this.encryptionSystem,
this.livekitRoom$,
@@ -195,8 +194,7 @@ export class UserMedia {
private readonly scope: ObservableScope,
public readonly id: string,
private readonly userId: string,
// TODO evaluate if this should just be the rtcBackendIdentity
private readonly rtcMembership: CallMembership,
private readonly rtcBackendIdentity: string,
private readonly participant: TaggedParticipant,
private readonly encryptionSystem: EncryptionSystem,
private readonly livekitRoom$: Behavior<LivekitRoom | undefined>,

View File

@@ -334,7 +334,7 @@ export function createLocalMedia(
testScope(),
"local",
member.userId,
rtcMember,
rtcMember.rtcBackendIdentity,
constant(localParticipant),
{
kind: E2eeType.PER_PARTICIPANT,
@@ -380,7 +380,7 @@ export function createRemoteMedia(
testScope(),
"remote",
member.userId,
rtcMember,
rtcMember.rtcBackendIdentity,
constant(participant),
{
kind: E2eeType.PER_PARTICIPANT,