mirror of https://github.com/OpenVidu/openvidu.git
ov-components: enhance local participant update logic with snapshot tracking
parent
34e34ee078
commit
ebac5b30c2
|
|
@ -55,6 +55,7 @@ export class ParticipantService {
|
||||||
private remoteParticipantsWritableSignal: WritableSignal<ParticipantModel[]> = signal<ParticipantModel[]>([]);
|
private remoteParticipantsWritableSignal: WritableSignal<ParticipantModel[]> = signal<ParticipantModel[]>([]);
|
||||||
|
|
||||||
private localParticipant: ParticipantModel | undefined;
|
private localParticipant: ParticipantModel | undefined;
|
||||||
|
private lastLocalParticipantSnapshot: ParticipantModel | undefined;
|
||||||
private remoteParticipants: ParticipantModel[] = [];
|
private remoteParticipants: ParticipantModel[] = [];
|
||||||
private log: ILogger;
|
private log: ILogger;
|
||||||
|
|
||||||
|
|
@ -85,6 +86,7 @@ export class ParticipantService {
|
||||||
*/
|
*/
|
||||||
clear(): void {
|
clear(): void {
|
||||||
this.localParticipant = undefined;
|
this.localParticipant = undefined;
|
||||||
|
this.lastLocalParticipantSnapshot = undefined;
|
||||||
this.remoteParticipants = [];
|
this.remoteParticipants = [];
|
||||||
this.localParticipantWritableSignal.set(undefined);
|
this.localParticipantWritableSignal.set(undefined);
|
||||||
this.remoteParticipantsWritableSignal.set([]);
|
this.remoteParticipantsWritableSignal.set([]);
|
||||||
|
|
@ -410,18 +412,55 @@ export class ParticipantService {
|
||||||
* Forces to update the local participant object and fire a new `localParticipant$` Observable event.
|
* Forces to update the local participant object and fire a new `localParticipant$` Observable event.
|
||||||
*/
|
*/
|
||||||
updateLocalParticipant() {
|
updateLocalParticipant() {
|
||||||
|
const localParticipantFromSignal = this.localParticipantWritableSignal();
|
||||||
|
|
||||||
|
// Backward compatibility: if the consumer mutated the last emitted snapshot and
|
||||||
|
// then calls updateLocalParticipant(), keep the internal source of truth in sync.
|
||||||
|
// Only sync when the emitted snapshot actually diverged after emission; otherwise,
|
||||||
|
// a stale observable/signal snapshot would overwrite newer canonical state.
|
||||||
|
if (
|
||||||
|
this.localParticipant &&
|
||||||
|
localParticipantFromSignal &&
|
||||||
|
this.lastLocalParticipantSnapshot &&
|
||||||
|
localParticipantFromSignal !== this.localParticipant &&
|
||||||
|
localParticipantFromSignal.sid === this.localParticipant.sid &&
|
||||||
|
this.hasParticipantSnapshotMutations(localParticipantFromSignal, this.lastLocalParticipantSnapshot)
|
||||||
|
) {
|
||||||
|
Object.assign(this.localParticipant, localParticipantFromSignal);
|
||||||
|
}
|
||||||
|
|
||||||
// Update Signal - create new reference to trigger reactivity
|
// Update Signal - create new reference to trigger reactivity
|
||||||
// The Observable will automatically emit via toObservable()
|
// The Observable will automatically emit via toObservable()
|
||||||
if (this.localParticipant) {
|
if (this.localParticipant) {
|
||||||
const updatedParticipant = Object.assign(Object.create(Object.getPrototypeOf(this.localParticipant)), {
|
const updatedParticipant = this.cloneParticipant(this.localParticipant);
|
||||||
...this.localParticipant
|
|
||||||
});
|
|
||||||
this.localParticipantWritableSignal.set(updatedParticipant);
|
this.localParticipantWritableSignal.set(updatedParticipant);
|
||||||
|
this.lastLocalParticipantSnapshot = this.cloneParticipant(updatedParticipant);
|
||||||
} else {
|
} else {
|
||||||
this.localParticipantWritableSignal.set(undefined);
|
this.localParticipantWritableSignal.set(undefined);
|
||||||
|
this.lastLocalParticipantSnapshot = undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private hasParticipantSnapshotMutations(current: ParticipantModel, previous: ParticipantModel): boolean {
|
||||||
|
const currentState = current as unknown as Record<string, unknown>;
|
||||||
|
const previousState = previous as unknown as Record<string, unknown>;
|
||||||
|
const keys = new Set([...Object.keys(currentState), ...Object.keys(previousState)]);
|
||||||
|
|
||||||
|
for (const key of keys) {
|
||||||
|
if (!Object.is(currentState[key], previousState[key])) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private cloneParticipant<T extends ParticipantModel>(participant: T): T {
|
||||||
|
return Object.assign(Object.create(Object.getPrototypeOf(participant)), {
|
||||||
|
...participant
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the last screen element as pinned
|
* Sets the last screen element as pinned
|
||||||
* @internal
|
* @internal
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue