Skip to content
This repository was archived by the owner on Oct 18, 2024. It is now read-only.

Commit b664a9e

Browse files
committed
fix: video bug behavior
1 parent f44870d commit b664a9e

File tree

11 files changed

+147
-17
lines changed

11 files changed

+147
-17
lines changed

src/common/types/participant.types.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export type Slot = {
1717
export interface Participant {
1818
id: string;
1919
name?: string;
20-
type?: ParticipantType;
20+
type?: ParticipantType | `${ParticipantType}`;
2121
slot?: Slot;
2222
avatar?: Avatar;
2323
isHost?: boolean;

src/common/types/stores.types.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { useGlobalStore } from '../../services/stores';
2+
import { useCoreStore } from '../../services/stores/core';
23
import { usePresence3DStore } from '../../services/stores/presence3D';
34
import { useVideoStore } from '../../services/stores/video';
45
import { useWhoIsOnlineStore } from '../../services/stores/who-is-online/index';
@@ -9,6 +10,7 @@ export enum StoreType {
910
WHO_IS_ONLINE = 'who-is-online-store',
1011
VIDEO = 'video-store',
1112
PRESENCE_3D = 'presence-3d-store',
13+
CORE = 'core-store',
1214
}
1315

1416
type Subject<T extends (...args: any[]) => any, K extends keyof ReturnType<T>> = ReturnType<T>[K];
@@ -24,13 +26,13 @@ type IncompleteStoreApi<T extends (...args: any[]) => any> = {
2426

2527
type StoreApi<T extends (...args: any[]) => any> = IncompleteStoreApi<T> & {
2628
destroy(): void;
27-
restart(): void;
2829
};
2930

3031
type GlobalStore = StoreType.GLOBAL | `${StoreType.GLOBAL}`;
3132
type WhoIsOnlineStore = StoreType.WHO_IS_ONLINE | 'who-is-online-store';
3233
type VideoStore = StoreType.VIDEO | 'video-store';
3334
type Presence3DStore = StoreType.PRESENCE_3D | 'presence-3d-store';
35+
type CoreStore = StoreType.CORE | 'core-store';
3436

3537
export type Store<T> = T extends GlobalStore
3638
? StoreApi<typeof useGlobalStore>
@@ -40,5 +42,7 @@ export type Store<T> = T extends GlobalStore
4042
? StoreApi<typeof useVideoStore>
4143
: T extends Presence3DStore
4244
? StoreApi<typeof usePresence3DStore>
45+
: T extends CoreStore
46+
? StoreApi<typeof useCoreStore>
4347
: never;
4448
export type StoresTypes = typeof StoreType;

src/common/utils/use-store.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { PublicSubject } from '../../services/stores/common/types';
2+
import { useCoreStore } from '../../services/stores/core';
23
import { useGlobalStore } from '../../services/stores/global';
34
import { usePresence3DStore } from '../../services/stores/presence3D';
45
import { useVideoStore } from '../../services/stores/video';
@@ -10,6 +11,7 @@ const stores = {
1011
[StoreType.WHO_IS_ONLINE]: useWhoIsOnlineStore,
1112
[StoreType.VIDEO]: useVideoStore,
1213
[StoreType.PRESENCE_3D]: usePresence3DStore,
14+
[StoreType.CORE]: useCoreStore,
1315
};
1416

1517
/**

src/components/video/index.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,7 @@ describe('VideoConference', () => {
520520
VideoConferenceInstance['onParticipantLeft'](MOCK_LOCAL_PARTICIPANT);
521521
expect(VideoConferenceInstance['publish']).toHaveBeenCalledWith(
522522
MeetingEvent.MY_PARTICIPANT_LEFT,
523-
MOCK_LOCAL_PARTICIPANT,
523+
{ ...MOCK_LOCAL_PARTICIPANT, type: ParticipantType.HOST },
524524
);
525525
});
526526

src/components/video/index.ts

+6-4
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import { ComponentNames } from '../types';
3838

3939
import { ParticipantToFrame, VideoComponentOptions } from './types';
4040
import { MEETING_COLORS } from '../../common/types/meeting-colors.types';
41+
import { coreBridge } from '../../services/core-bridge';
4142

4243
const KICK_PARTICIPANTS_TIME = 1000 * 60;
4344
let KICK_PARTICIPANTS_TIMEOUT: ReturnType<typeof setTimeout> | null = null;
@@ -331,6 +332,7 @@ export class VideoConference extends BaseComponent {
331332
this.localParticipant = {
332333
...this.localParticipant,
333334
...participant,
335+
type: this.params.userType,
334336
};
335337
});
336338

@@ -542,13 +544,13 @@ export class VideoConference extends BaseComponent {
542544
joinedMeeting: true,
543545
});
544546

545-
localParticipant.publish({
547+
coreBridge.updateLocalParticipant({
546548
...localParticipant.value,
547549
avatar: participant.avatar,
548550
name: participant.name,
549551
});
550552

551-
participants.publish({
553+
coreBridge.updateParticipantsList({
552554
...participants.value,
553555
[participant.id]: {
554556
...participants.value[participant.id],
@@ -560,12 +562,12 @@ export class VideoConference extends BaseComponent {
560562
return;
561563
}
562564

563-
localParticipant.publish({
565+
coreBridge.updateLocalParticipant({
564566
...localParticipant.value,
565567
name: newParticipantName,
566568
});
567569

568-
participants.publish({
570+
coreBridge.updateParticipantsList({
569571
...participants.value,
570572
[participant.id]: {
571573
...participants.value[participant.id],

src/components/video/types.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,6 @@ export type ParticipantToFrame = {
5454
name: string;
5555
isHost: boolean;
5656
avatar?: Avatar;
57-
type: ParticipantType;
57+
type: ParticipantType | `${ParticipantType}`;
5858
slot: Slot;
5959
};

src/core/launcher/index.ts

+26-8
Original file line numberDiff line numberDiff line change
@@ -41,25 +41,33 @@ export class Launcher extends Observable implements DefaultLauncher {
4141
super();
4242
this.logger = new Logger('@superviz/sdk/launcher');
4343

44-
const { localParticipant, group, isDomainWhitelisted } = this.useStore(StoreType.GLOBAL);
45-
46-
localParticipant.publish({ ...participant });
44+
const {
45+
localParticipant: globalParticipant,
46+
group,
47+
isDomainWhitelisted,
48+
} = this.useStore(StoreType.GLOBAL);
49+
const { localParticipant, participants } = this.useStore(StoreType.CORE);
50+
51+
globalParticipant.publish({ ...participant });
4752
isDomainWhitelisted.subscribe(this.onAuthentication);
48-
localParticipant.subscribe(this.onLocalParticipantUpdateOnStore);
53+
globalParticipant.subscribe(this.onLocalParticipantUpdateOnStore);
54+
55+
localParticipant.subscribe(this.onLocalParticipantUpdateOnCore);
56+
participants.subscribe(this.onParticipantsListUpdateOnCore);
4957

5058
group.publish(participantGroup);
51-
this.ioc = new IOC(localParticipant.value);
59+
this.ioc = new IOC(globalParticipant.value);
5260
this.room = this.ioc.createRoom('launcher', 'unlimited');
5361

5462
// Assign a slot to the participant
5563
this.slotService = new SlotService(this.room, this.useStore);
56-
localParticipant.publish({
57-
...localParticipant.value,
64+
globalParticipant.publish({
65+
...globalParticipant.value,
5866
slot: this.slotService.slot,
5967
activeComponents: [],
6068
});
6169

62-
this.participant = localParticipant.value;
70+
this.participant = globalParticipant.value;
6371

6472
// internal events without realtime
6573
this.eventBus = new EventBus();
@@ -272,6 +280,16 @@ export class Launcher extends Observable implements DefaultLauncher {
272280
this.activeComponents = participant.activeComponents || [];
273281
};
274282

283+
private onLocalParticipantUpdateOnCore = (participant: Participant): void => {
284+
if (!this.room) return;
285+
this.room.presence.update(participant);
286+
};
287+
288+
private onParticipantsListUpdateOnCore = (list: Record<string, Participant>): void => {
289+
const { participants } = this.useStore(StoreType.GLOBAL);
290+
participants.publish(list);
291+
};
292+
275293
private onSameAccount = (): void => {
276294
this.publish(ParticipantEvent.SAME_ACCOUNT_ERROR);
277295
this.destroy();
+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { coreBridge } from '.';
2+
3+
const localParticipantSpy = jest.fn();
4+
const participantsSpy = jest.fn();
5+
jest.mock('../../common/utils/use-store', () => ({
6+
useStore: () => ({
7+
localParticipant: {
8+
publish: localParticipantSpy,
9+
},
10+
participants: {
11+
publish: participantsSpy,
12+
},
13+
}),
14+
}));
15+
16+
describe('coreBridge', () => {
17+
describe('updateLocalParticipant', () => {
18+
test('should log "updateLocalParticipant" and call localParticipant.publish', () => {
19+
const data = { id: '1' };
20+
const logSpy = jest.spyOn(coreBridge['logger'], 'log');
21+
22+
coreBridge.updateLocalParticipant(data);
23+
24+
expect(logSpy).toHaveBeenCalledWith('updateLocalParticipant', data);
25+
expect(localParticipantSpy).toHaveBeenCalledWith(data);
26+
});
27+
});
28+
29+
describe('updateParticipantsList', () => {
30+
test('should log "updateParticipantsList" and call participants.publish', () => {
31+
const data = { 1: { id: '1' } };
32+
const logSpy = jest.spyOn(coreBridge['logger'], 'log');
33+
34+
coreBridge.updateParticipantsList(data);
35+
36+
expect(logSpy).toHaveBeenCalledWith('updateParticipantsList', data);
37+
expect(participantsSpy).toHaveBeenCalledWith(data);
38+
});
39+
});
40+
});

src/services/core-bridge/index.ts

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { Participant } from '../../common/types/participant.types';
2+
import { StoreType } from '../../common/types/stores.types';
3+
import { Logger } from '../../common/utils';
4+
import { useStore } from '../../common/utils/use-store';
5+
6+
class CoreBridge {
7+
private logger: Logger;
8+
constructor() {
9+
this.logger = new Logger('@superviz/sdk/core-bridge');
10+
this.logger.log('CoreBridge initialized');
11+
}
12+
13+
public updateLocalParticipant(data: Participant) {
14+
this.logger.log('updateLocalParticipant', data);
15+
const { localParticipant } = useStore(StoreType.CORE);
16+
localParticipant.publish(data);
17+
}
18+
19+
public updateParticipantsList(data: Record<Participant['id'], Participant>) {
20+
this.logger.log('updateParticipantsList', data);
21+
const { participants } = useStore(StoreType.CORE);
22+
participants.publish(data);
23+
}
24+
}
25+
26+
export const coreBridge = new CoreBridge();

src/services/presence-3d-manager/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ export class Presence3DManager {
142142
private onJoinedPresence = (event: PresenceEvent<Participant>): void => {
143143
if (event.id !== this.localParticipant.id) return;
144144

145-
this.logger.log('participant joined 3D room', event.id);
145+
this.logger.log('participant joined 3D room', event.id, this.localParticipant);
146146
this.onLocalParticipantJoined(this.localParticipant);
147147
};
148148

src/services/stores/core/index.ts

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { Participant } from '../../../common/types/participant.types';
2+
import { Singleton } from '../common/types';
3+
import { CreateSingleton } from '../common/utils';
4+
import subject from '../subject';
5+
6+
const instance: Singleton<CoreStore> = CreateSingleton<CoreStore>();
7+
8+
class CoreStore {
9+
public localParticipant = subject<Participant>({} as Participant);
10+
public participants = subject<Record<Participant['id'], Participant>>({});
11+
12+
constructor() {
13+
if (instance.value) {
14+
throw new Error('CoreStore is a singleton. There can only be one instance of it.');
15+
}
16+
17+
instance.value = this;
18+
}
19+
20+
public destroy() {
21+
this.localParticipant.destroy();
22+
this.participants.destroy();
23+
}
24+
}
25+
26+
const store = new CoreStore();
27+
const destroy = store.destroy.bind(store);
28+
29+
const localParticipant = store.localParticipant.expose();
30+
const participants = store.participants.expose();
31+
32+
export function useCoreStore() {
33+
return {
34+
localParticipant,
35+
participants,
36+
destroy,
37+
};
38+
}

0 commit comments

Comments
 (0)