FIX: fixed a circular dependancy in stores by rewriting createPeerStore() and createScreenSharingPeerStore()

This commit is contained in:
kharhamel 2021-09-03 15:16:21 +02:00
parent 6cb0f14e5a
commit ba5fa06306
9 changed files with 63 additions and 114 deletions

View file

@ -12,7 +12,9 @@
<div class="main-section"> <div class="main-section">
{#if $videoFocusStore } {#if $videoFocusStore }
<MediaBox streamable={$videoFocusStore}></MediaBox> {#key $videoFocusStore.uniqueId}
<MediaBox streamable={$videoFocusStore}></MediaBox>
{/key}
{/if} {/if}
</div> </div>
<aside class="sidebar"> <aside class="sidebar">

View file

@ -715,25 +715,8 @@ export class GameScene extends DirtyScene {
// When connection is performed, let's connect SimplePeer // When connection is performed, let's connect SimplePeer
this.simplePeer = new SimplePeer(this.connection); this.simplePeer = new SimplePeer(this.connection);
peerStore.connectToSimplePeer(this.simplePeer);
screenSharingPeerStore.connectToSimplePeer(this.simplePeer);
videoFocusStore.connectToSimplePeer(this.simplePeer);
userMessageManager.setReceiveBanListener(this.bannedUser.bind(this)); userMessageManager.setReceiveBanListener(this.bannedUser.bind(this));
const self = this;
this.simplePeer.registerPeerConnectionListener({
onConnect(peer) {
//self.openChatIcon.setVisible(true);
audioManagerVolumeStore.setTalking(true);
},
onDisconnect(userId: number) {
if (self.simplePeer.getNbConnections() === 0) {
//self.openChatIcon.setVisible(false);
audioManagerVolumeStore.setTalking(false);
}
},
});
//listen event to share position of user //listen event to share position of user
this.CurrentPlayer.on(hasMovedEventName, this.pushPlayerPosition.bind(this)); this.CurrentPlayer.on(hasMovedEventName, this.pushPlayerPosition.bind(this));
this.CurrentPlayer.on(hasMovedEventName, this.outlineItem.bind(this)); this.CurrentPlayer.on(hasMovedEventName, this.outlineItem.bind(this));

View file

@ -1,4 +1,5 @@
import { get, writable } from "svelte/store"; import { get, writable } from "svelte/store";
import { peerStore } from "./PeerStore";
export interface audioManagerVolume { export interface audioManagerVolume {
muted: boolean; muted: boolean;
@ -103,3 +104,7 @@ export const audioManagerVisibilityStore = writable(false);
export const audioManagerVolumeStore = createAudioManagerVolumeStore(); export const audioManagerVolumeStore = createAudioManagerVolumeStore();
export const audioManagerFileStore = createAudioManagerFileStore(); export const audioManagerFileStore = createAudioManagerFileStore();
peerStore.subscribe((peers) => {
audioManagerVolumeStore.setTalking(peers.size > 0);
});

View file

@ -1,4 +1,4 @@
import { derived, get, Readable, readable, writable, Writable } from "svelte/store"; import { derived, get, Readable, readable, writable } from "svelte/store";
import { localUserStore } from "../Connexion/LocalUserStore"; import { localUserStore } from "../Connexion/LocalUserStore";
import { userMovingStore } from "./GameStore"; import { userMovingStore } from "./GameStore";
import { HtmlUtils } from "../WebRtc/HtmlUtils"; import { HtmlUtils } from "../WebRtc/HtmlUtils";

View file

@ -1,38 +1,30 @@
import { readable, writable } from "svelte/store"; import { readable, writable } from "svelte/store";
import type { RemotePeer, SimplePeer } from "../WebRtc/SimplePeer"; import type { VideoPeer } from "../WebRtc/VideoPeer";
import { VideoPeer } from "../WebRtc/VideoPeer"; import type { ScreenSharingPeer } from "../WebRtc/ScreenSharingPeer";
import { ScreenSharingPeer } from "../WebRtc/ScreenSharingPeer";
/** /**
* A store that contains the list of (video) peers we are connected to. * A store that contains the list of (video) peers we are connected to.
*/ */
function createPeerStore() { function createPeerStore() {
let peers = new Map<number, VideoPeer>(); const { subscribe, set, update } = writable(new Map<number, VideoPeer>());
const { subscribe, set, update } = writable(peers);
return { return {
subscribe, subscribe,
connectToSimplePeer: (simplePeer: SimplePeer) => { pushNewPeer(peer: VideoPeer) {
peers = new Map<number, VideoPeer>(); update((users) => {
set(peers); users.set(peer.userId, peer);
simplePeer.registerPeerConnectionListener({ return users;
onConnect(peer: RemotePeer) {
if (peer instanceof VideoPeer) {
update((users) => {
users.set(peer.userId, peer);
return users;
});
}
},
onDisconnect(userId: number) {
update((users) => {
users.delete(userId);
return users;
});
},
}); });
}, },
removePeer(userId: number) {
update((users) => {
users.delete(userId);
return users;
});
},
cleanupStore() {
set(new Map<number, VideoPeer>());
},
}; };
} }
@ -40,32 +32,25 @@ function createPeerStore() {
* A store that contains the list of screen sharing peers we are connected to. * A store that contains the list of screen sharing peers we are connected to.
*/ */
function createScreenSharingPeerStore() { function createScreenSharingPeerStore() {
let peers = new Map<number, ScreenSharingPeer>(); const { subscribe, set, update } = writable(new Map<number, ScreenSharingPeer>());
const { subscribe, set, update } = writable(peers);
return { return {
subscribe, subscribe,
connectToSimplePeer: (simplePeer: SimplePeer) => { pushNewPeer(peer: ScreenSharingPeer) {
peers = new Map<number, ScreenSharingPeer>(); update((users) => {
set(peers); users.set(peer.userId, peer);
simplePeer.registerPeerConnectionListener({ return users;
onConnect(peer: RemotePeer) {
if (peer instanceof ScreenSharingPeer) {
update((users) => {
users.set(peer.userId, peer);
return users;
});
}
},
onDisconnect(userId: number) {
update((users) => {
users.delete(userId);
return users;
});
},
}); });
}, },
removePeer(userId: number) {
update((users) => {
users.delete(userId);
return users;
});
},
cleanupStore() {
set(new Map<number, ScreenSharingPeer>());
},
}; };
} }

View file

@ -175,6 +175,7 @@ export const screenSharingAvailableStore = derived(peerStore, ($peerStore, set)
export interface ScreenSharingLocalMedia { export interface ScreenSharingLocalMedia {
uniqueId: string; uniqueId: string;
stream: MediaStream | null; stream: MediaStream | null;
userId?: undefined;
} }
/** /**

View file

@ -1,14 +1,12 @@
import { writable } from "svelte/store"; import { get, writable } from "svelte/store";
import type { RemotePeer, SimplePeer } from "../WebRtc/SimplePeer";
import { VideoPeer } from "../WebRtc/VideoPeer";
import { ScreenSharingPeer } from "../WebRtc/ScreenSharingPeer";
import type { Streamable } from "./StreamableCollectionStore"; import type { Streamable } from "./StreamableCollectionStore";
import { peerStore } from "./PeerStore";
/** /**
* A store that contains the peer / media that has currently the "importance" focus. * A store that contains the peer / media that has currently the "importance" focus.
*/ */
function createVideoFocusStore() { function createVideoFocusStore() {
const { subscribe, set, update } = writable<Streamable | null>(null); const { subscribe, set } = writable<Streamable | null>(null);
let focusedMedia: Streamable | null = null; let focusedMedia: Streamable | null = null;
@ -23,27 +21,17 @@ function createVideoFocusStore() {
set(null); set(null);
}, },
toggleFocus: (media: Streamable) => { toggleFocus: (media: Streamable) => {
if (media !== focusedMedia) { focusedMedia = media !== focusedMedia ? media : null;
focusedMedia = media;
} else {
focusedMedia = null;
}
set(focusedMedia); set(focusedMedia);
}, },
connectToSimplePeer: (simplePeer: SimplePeer) => {
simplePeer.registerPeerConnectionListener({
onConnect(peer: RemotePeer) {},
onDisconnect(userId: number) {
if (
(focusedMedia instanceof VideoPeer || focusedMedia instanceof ScreenSharingPeer) &&
focusedMedia.userId === userId
) {
set(null);
}
},
});
},
}; };
} }
export const videoFocusStore = createVideoFocusStore(); export const videoFocusStore = createVideoFocusStore();
peerStore.subscribe((peers) => {
const focusedMedia: Streamable | null = get(videoFocusStore);
if (focusedMedia && focusedMedia.userId !== undefined && !peers.get(focusedMedia.userId)) {
videoFocusStore.removeFocus();
}
});

View file

@ -10,6 +10,7 @@ import { blackListManager } from "./BlackListManager";
import { get } from "svelte/store"; import { get } from "svelte/store";
import { screenSharingLocalStreamStore } from "../Stores/ScreenSharingStore"; import { screenSharingLocalStreamStore } from "../Stores/ScreenSharingStore";
import { playersStore } from "../Stores/PlayersStore"; import { playersStore } from "../Stores/PlayersStore";
import { peerStore, screenSharingPeerStore } from "../Stores/PeerStore";
export interface UserSimplePeerInterface { export interface UserSimplePeerInterface {
userId: number; userId: number;
@ -20,12 +21,6 @@ export interface UserSimplePeerInterface {
export type RemotePeer = VideoPeer | ScreenSharingPeer; export type RemotePeer = VideoPeer | ScreenSharingPeer;
export interface PeerConnectionListener {
onConnect(user: RemotePeer): void;
onDisconnect(userId: number): void;
}
/** /**
* This class manages connections to all the peers in the same group as me. * This class manages connections to all the peers in the same group as me.
*/ */
@ -37,12 +32,14 @@ export class SimplePeer {
private readonly sendLocalScreenSharingStreamCallback: StartScreenSharingCallback; private readonly sendLocalScreenSharingStreamCallback: StartScreenSharingCallback;
private readonly stopLocalScreenSharingStreamCallback: StopScreenSharingCallback; private readonly stopLocalScreenSharingStreamCallback: StopScreenSharingCallback;
private readonly unsubscribers: (() => void)[] = []; private readonly unsubscribers: (() => void)[] = [];
private readonly peerConnectionListeners: Array<PeerConnectionListener> = new Array<PeerConnectionListener>();
private readonly userId: number; private readonly userId: number;
private lastWebrtcUserName: string | undefined; private lastWebrtcUserName: string | undefined;
private lastWebrtcPassword: string | undefined; private lastWebrtcPassword: string | undefined;
constructor(private Connection: RoomConnection) { constructor(private Connection: RoomConnection) {
//we make sure we don't get any old peer.
peerStore.cleanupStore();
screenSharingPeerStore.cleanupStore();
// We need to go through this weird bound function pointer in order to be able to "free" this reference later. // We need to go through this weird bound function pointer in order to be able to "free" this reference later.
this.sendLocalScreenSharingStreamCallback = this.sendLocalScreenSharingStream.bind(this); this.sendLocalScreenSharingStreamCallback = this.sendLocalScreenSharingStream.bind(this);
this.stopLocalScreenSharingStreamCallback = this.stopLocalScreenSharingStream.bind(this); this.stopLocalScreenSharingStreamCallback = this.stopLocalScreenSharingStream.bind(this);
@ -73,14 +70,6 @@ export class SimplePeer {
this.initialise(); this.initialise();
} }
public registerPeerConnectionListener(peerConnectionListener: PeerConnectionListener) {
this.peerConnectionListeners.push(peerConnectionListener);
}
public getNbConnections(): number {
return this.Users.length;
}
/** /**
* permit to listen when user could start visio * permit to listen when user could start visio
*/ */
@ -164,9 +153,7 @@ export class SimplePeer {
} }
this.PeerConnectionArray.set(user.userId, peer); this.PeerConnectionArray.set(user.userId, peer);
for (const peerConnectionListener of this.peerConnectionListeners) { peerStore.pushNewPeer(peer);
peerConnectionListener.onConnect(peer);
}
return peer; return peer;
} }
@ -214,9 +201,7 @@ export class SimplePeer {
); );
this.PeerScreenSharingConnectionArray.set(user.userId, peer); this.PeerScreenSharingConnectionArray.set(user.userId, peer);
for (const peerConnectionListener of this.peerConnectionListeners) { screenSharingPeerStore.pushNewPeer(peer);
peerConnectionListener.onConnect(peer);
}
return peer; return peer;
} }
@ -255,12 +240,11 @@ export class SimplePeer {
for (const userId of this.PeerScreenSharingConnectionArray.keys()) { for (const userId of this.PeerScreenSharingConnectionArray.keys()) {
this.closeScreenSharingConnection(userId); this.closeScreenSharingConnection(userId);
this.PeerScreenSharingConnectionArray.delete(userId); this.PeerScreenSharingConnectionArray.delete(userId);
screenSharingPeerStore.removePeer(userId);
} }
} }
for (const peerConnectionListener of this.peerConnectionListeners) { peerStore.removePeer(userId);
peerConnectionListener.onDisconnect(userId);
}
} }
/** /**
@ -302,6 +286,8 @@ export class SimplePeer {
for (const unsubscriber of this.unsubscribers) { for (const unsubscriber of this.unsubscribers) {
unsubscriber(); unsubscriber();
} }
peerStore.cleanupStore();
screenSharingPeerStore.cleanupStore();
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
@ -325,7 +311,6 @@ export class SimplePeer {
private receiveWebrtcScreenSharingSignal(data: WebRtcSignalReceivedMessageInterface) { private receiveWebrtcScreenSharingSignal(data: WebRtcSignalReceivedMessageInterface) {
const uuid = playersStore.getPlayerById(data.userId)?.userUuid || ""; const uuid = playersStore.getPlayerById(data.userId)?.userUuid || "";
if (blackListManager.isBlackListed(uuid)) return; if (blackListManager.isBlackListed(uuid)) return;
console.log("receiveWebrtcScreenSharingSignal", data);
const streamResult = get(screenSharingLocalStreamStore); const streamResult = get(screenSharingLocalStreamStore);
let stream: MediaStream | null = null; let stream: MediaStream | null = null;
if (streamResult.type === "success" && streamResult.stream !== null) { if (streamResult.type === "success" && streamResult.stream !== null) {

View file

@ -4,7 +4,7 @@ import type { RoomConnection } from "../Connexion/RoomConnection";
import { blackListManager } from "./BlackListManager"; import { blackListManager } from "./BlackListManager";
import type { Subscription } from "rxjs"; import type { Subscription } from "rxjs";
import type { UserSimplePeerInterface } from "./SimplePeer"; import type { UserSimplePeerInterface } from "./SimplePeer";
import { get, readable, Readable, Unsubscriber } from "svelte/store"; import { readable, Readable, Unsubscriber } from "svelte/store";
import { import {
localStreamStore, localStreamStore,
obtainedMediaConstraintIsMobileStore, obtainedMediaConstraintIsMobileStore,
@ -12,7 +12,7 @@ import {
ObtainedMediaStreamConstraints, ObtainedMediaStreamConstraints,
} from "../Stores/MediaStore"; } from "../Stores/MediaStore";
import { playersStore } from "../Stores/PlayersStore"; import { playersStore } from "../Stores/PlayersStore";
import { chatMessagesStore, chatVisibilityStore, newChatMessageStore } from "../Stores/ChatStore"; import { chatMessagesStore, newChatMessageStore } from "../Stores/ChatStore";
import { getIceServersConfig } from "../Components/Video/utils"; import { getIceServersConfig } from "../Components/Video/utils";
import { isMobile } from "../Enum/EnvironmentVariable"; import { isMobile } from "../Enum/EnvironmentVariable";