Migrating the video overlay in Svelte (WIP)
This commit is contained in:
parent
e6264948b1
commit
e7b0f859a5
20 changed files with 630 additions and 97 deletions
17
front/src/Stores/GameOverlayStoreVisibility.ts
Normal file
17
front/src/Stores/GameOverlayStoreVisibility.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
import {writable} from "svelte/store";
|
||||
|
||||
/**
|
||||
* A store that contains whether the game overlay is shown or not.
|
||||
* Typically, the overlay is hidden when entering Jitsi meet.
|
||||
*/
|
||||
function createGameOverlayVisibilityStore() {
|
||||
const { subscribe, set, update } = writable(false);
|
||||
|
||||
return {
|
||||
subscribe,
|
||||
showGameOverlay: () => set(true),
|
||||
hideGameOverlay: () => set(false),
|
||||
};
|
||||
}
|
||||
|
||||
export const gameOverlayVisibilityStore = createGameOverlayVisibilityStore();
|
58
front/src/Stores/LayoutStore.ts
Normal file
58
front/src/Stores/LayoutStore.ts
Normal file
|
@ -0,0 +1,58 @@
|
|||
import {derived, get} from "svelte/store";
|
||||
import {ScreenSharingLocalMedia, screenSharingLocalMedia} from "./ScreenSharingStore";
|
||||
import {DivImportance} from "../WebRtc/LayoutManager";
|
||||
import { peerStore, screenSharingStreamStore} from "./PeerStore";
|
||||
import type {RemotePeer} from "../WebRtc/SimplePeer";
|
||||
|
||||
export type DisplayableMedia = RemotePeer | ScreenSharingLocalMedia;
|
||||
|
||||
/**
|
||||
* A store that contains the layout of the streams
|
||||
*/
|
||||
function createLayoutStore() {
|
||||
|
||||
let unsubscribes: (()=>void)[] = [];
|
||||
|
||||
return derived([
|
||||
screenSharingStreamStore,
|
||||
peerStore,
|
||||
screenSharingLocalMedia,
|
||||
], ([
|
||||
$screenSharingStreamStore,
|
||||
$peerStore,
|
||||
$screenSharingLocalMedia,
|
||||
], set) => {
|
||||
for (const unsubscribe of unsubscribes) {
|
||||
unsubscribe();
|
||||
}
|
||||
unsubscribes = [];
|
||||
|
||||
const peers = new Map<DivImportance, Map<string, DisplayableMedia>>();
|
||||
peers.set(DivImportance.Normal, new Map<string, DisplayableMedia>());
|
||||
peers.set(DivImportance.Important, new Map<string, DisplayableMedia>());
|
||||
|
||||
const addPeer = (peer: DisplayableMedia) => {
|
||||
const importance = get(peer.importanceStore);
|
||||
|
||||
peers.get(importance)?.set(peer.uniqueId, peer);
|
||||
|
||||
unsubscribes.push(peer.importanceStore.subscribe((importance) => {
|
||||
peers.forEach((category) => {
|
||||
category.delete(peer.uniqueId);
|
||||
});
|
||||
peers.get(importance)?.set(peer.uniqueId, peer);
|
||||
set(peers);
|
||||
}));
|
||||
};
|
||||
|
||||
$screenSharingStreamStore.forEach(addPeer);
|
||||
$peerStore.forEach(addPeer);
|
||||
if ($screenSharingLocalMedia?.stream) {
|
||||
addPeer($screenSharingLocalMedia);
|
||||
}
|
||||
|
||||
set(peers);
|
||||
});
|
||||
}
|
||||
|
||||
export const layoutStore = createLayoutStore();
|
|
@ -1,13 +1,13 @@
|
|||
import {derived, get, Readable, readable, writable, Writable} from "svelte/store";
|
||||
import {peerStore} from "./PeerStore";
|
||||
import {localUserStore} from "../Connexion/LocalUserStore";
|
||||
import {ITiledMapGroupLayer, ITiledMapObjectLayer, ITiledMapTileLayer} from "../Phaser/Map/ITiledMap";
|
||||
import {userMovingStore} from "./GameStore";
|
||||
import {HtmlUtils} from "../WebRtc/HtmlUtils";
|
||||
import {BrowserTooOldError} from "./Errors/BrowserTooOldError";
|
||||
import {errorStore} from "./ErrorStore";
|
||||
import {isIOS} from "../WebRtc/DeviceUtils";
|
||||
import {WebviewOnOldIOS} from "./Errors/WebviewOnOldIOS";
|
||||
import {gameOverlayVisibilityStore} from "./GameOverlayStoreVisibility";
|
||||
|
||||
/**
|
||||
* A store that contains the camera state requested by the user (on or off).
|
||||
|
@ -50,20 +50,6 @@ export const visibilityStore = readable(document.visibilityState === 'visible',
|
|||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* A store that contains whether the game overlay is shown or not.
|
||||
* Typically, the overlay is hidden when entering Jitsi meet.
|
||||
*/
|
||||
function createGameOverlayVisibilityStore() {
|
||||
const { subscribe, set, update } = writable(false);
|
||||
|
||||
return {
|
||||
subscribe,
|
||||
showGameOverlay: () => set(true),
|
||||
hideGameOverlay: () => set(false),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* A store that contains whether the EnableCameraScene is shown or not.
|
||||
*/
|
||||
|
@ -79,7 +65,6 @@ function createEnableCameraSceneVisibilityStore() {
|
|||
|
||||
export const requestedCameraState = createRequestedCameraState();
|
||||
export const requestedMicrophoneState = createRequestedMicrophoneState();
|
||||
export const gameOverlayVisibilityStore = createGameOverlayVisibilityStore();
|
||||
export const enableCameraSceneVisibilityStore = createEnableCameraSceneVisibilityStore();
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,26 +1,64 @@
|
|||
import { derived, writable, Writable } from "svelte/store";
|
||||
import type {UserSimplePeerInterface} from "../WebRtc/SimplePeer";
|
||||
import type {SimplePeer} from "../WebRtc/SimplePeer";
|
||||
import {derived, get, readable, writable} from "svelte/store";
|
||||
import type {RemotePeer, SimplePeer} from "../WebRtc/SimplePeer";
|
||||
import {VideoPeer} from "../WebRtc/VideoPeer";
|
||||
import {ScreenSharingPeer} from "../WebRtc/ScreenSharingPeer";
|
||||
|
||||
/**
|
||||
* A store that contains the camera state requested by the user (on or off).
|
||||
* A store that contains the list of (video) peers we are connected to.
|
||||
*/
|
||||
function createPeerStore() {
|
||||
let users = new Map<number, UserSimplePeerInterface>();
|
||||
let peers = new Map<number, VideoPeer>();
|
||||
|
||||
const { subscribe, set, update } = writable(users);
|
||||
const { subscribe, set, update } = writable(peers);
|
||||
|
||||
return {
|
||||
subscribe,
|
||||
connectToSimplePeer: (simplePeer: SimplePeer) => {
|
||||
users = new Map<number, UserSimplePeerInterface>();
|
||||
set(users);
|
||||
peers = new Map<number, VideoPeer>();
|
||||
set(peers);
|
||||
simplePeer.registerPeerConnectionListener({
|
||||
onConnect(user: UserSimplePeerInterface) {
|
||||
onConnect(peer: RemotePeer) {
|
||||
if (peer instanceof VideoPeer) {
|
||||
update(users => {
|
||||
users.set(peer.userId, peer);
|
||||
return users;
|
||||
});
|
||||
}
|
||||
console.log('CONNECT VIDEO', peers);
|
||||
},
|
||||
onDisconnect(userId: number) {
|
||||
update(users => {
|
||||
users.set(user.userId, user);
|
||||
users.delete(userId);
|
||||
return users;
|
||||
});
|
||||
console.log('DISCONNECT VIDEO', peers);
|
||||
}
|
||||
})
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* A store that contains the list of screen sharing peers we are connected to.
|
||||
*/
|
||||
function createScreenSharingPeerStore() {
|
||||
let peers = new Map<number, ScreenSharingPeer>();
|
||||
|
||||
const { subscribe, set, update } = writable(peers);
|
||||
|
||||
return {
|
||||
subscribe,
|
||||
connectToSimplePeer: (simplePeer: SimplePeer) => {
|
||||
peers = new Map<number, ScreenSharingPeer>();
|
||||
set(peers);
|
||||
simplePeer.registerPeerConnectionListener({
|
||||
onConnect(peer: RemotePeer) {
|
||||
if (peer instanceof ScreenSharingPeer) {
|
||||
update(users => {
|
||||
users.set(peer.userId, peer);
|
||||
return users;
|
||||
});
|
||||
}
|
||||
},
|
||||
onDisconnect(userId: number) {
|
||||
update(users => {
|
||||
|
@ -34,3 +72,56 @@ function createPeerStore() {
|
|||
}
|
||||
|
||||
export const peerStore = createPeerStore();
|
||||
export const screenSharingPeerStore = createScreenSharingPeerStore();
|
||||
|
||||
/**
|
||||
* A store that contains ScreenSharingPeer, ONLY if those ScreenSharingPeer are emitting a stream towards us!
|
||||
*/
|
||||
function createScreenSharingStreamStore() {
|
||||
let peers = new Map<number, ScreenSharingPeer>();
|
||||
|
||||
return readable<Map<number, ScreenSharingPeer>>(peers, function start(set) {
|
||||
|
||||
let unsubscribes: (()=>void)[] = [];
|
||||
|
||||
const unsubscribe = screenSharingPeerStore.subscribe((screenSharingPeers) => {
|
||||
for (const unsubscribe of unsubscribes) {
|
||||
unsubscribe();
|
||||
}
|
||||
unsubscribes = [];
|
||||
|
||||
peers = new Map<number, ScreenSharingPeer>();
|
||||
|
||||
screenSharingPeers.forEach((screenSharingPeer: ScreenSharingPeer, key: number) => {
|
||||
|
||||
if (screenSharingPeer.isReceivingScreenSharingStream()) {
|
||||
peers.set(key, screenSharingPeer);
|
||||
}
|
||||
|
||||
unsubscribes.push(screenSharingPeer.streamStore.subscribe((stream) => {
|
||||
if (stream) {
|
||||
peers.set(key, screenSharingPeer);
|
||||
} else {
|
||||
peers.delete(key);
|
||||
}
|
||||
set(peers);
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
set(peers);
|
||||
|
||||
});
|
||||
|
||||
return function stop() {
|
||||
unsubscribe();
|
||||
for (const unsubscribe of unsubscribes) {
|
||||
unsubscribe();
|
||||
}
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
export const screenSharingStreamStore = createScreenSharingStreamStore();
|
||||
|
||||
|
||||
|
|
|
@ -1,16 +1,10 @@
|
|||
import {derived, get, Readable, readable, writable, Writable} from "svelte/store";
|
||||
import {peerStore} from "./PeerStore";
|
||||
import {localUserStore} from "../Connexion/LocalUserStore";
|
||||
import {ITiledMapGroupLayer, ITiledMapObjectLayer, ITiledMapTileLayer} from "../Phaser/Map/ITiledMap";
|
||||
import {userMovingStore} from "./GameStore";
|
||||
import {HtmlUtils} from "../WebRtc/HtmlUtils";
|
||||
import {
|
||||
audioConstraintStore, cameraEnergySavingStore,
|
||||
enableCameraSceneVisibilityStore,
|
||||
gameOverlayVisibilityStore, LocalStreamStoreValue, privacyShutdownStore,
|
||||
requestedCameraState,
|
||||
requestedMicrophoneState, videoConstraintStore
|
||||
import type {
|
||||
LocalStreamStoreValue,
|
||||
} from "./MediaStore";
|
||||
import {DivImportance} from "../WebRtc/LayoutManager";
|
||||
import {gameOverlayVisibilityStore} from "./GameOverlayStoreVisibility";
|
||||
|
||||
declare const navigator:any; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
|
||||
|
@ -191,3 +185,35 @@ export const screenSharingAvailableStore = derived(peerStore, ($peerStore, set)
|
|||
|
||||
set($peerStore.size !== 0);
|
||||
});
|
||||
|
||||
export interface ScreenSharingLocalMedia {
|
||||
uniqueId: string;
|
||||
importanceStore: Writable<DivImportance>;
|
||||
stream: MediaStream|null;
|
||||
//subscribe(this: void, run: Subscriber<ScreenSharingLocalMedia>, invalidate?: (value?: ScreenSharingLocalMedia) => void): Unsubscriber;
|
||||
}
|
||||
|
||||
/**
|
||||
* The representation of the screen sharing stream.
|
||||
*/
|
||||
export const screenSharingLocalMedia = readable<ScreenSharingLocalMedia|null>(null, function start(set) {
|
||||
|
||||
const localMedia: ScreenSharingLocalMedia = {
|
||||
uniqueId: "localScreenSharingStream",
|
||||
importanceStore: writable(DivImportance.Normal),
|
||||
stream: null
|
||||
}
|
||||
|
||||
const unsubscribe = screenSharingLocalStreamStore.subscribe((screenSharingLocalStream) => {
|
||||
if (screenSharingLocalStream.type === "success") {
|
||||
localMedia.stream = screenSharingLocalStream.stream;
|
||||
} else {
|
||||
localMedia.stream = null;
|
||||
}
|
||||
set(localMedia);
|
||||
});
|
||||
|
||||
return function stop() {
|
||||
unsubscribe();
|
||||
};
|
||||
})
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue