diff --git a/front/src/Components/App.svelte b/front/src/Components/App.svelte
index c973a6c2..1d492ab7 100644
--- a/front/src/Components/App.svelte
+++ b/front/src/Components/App.svelte
@@ -1,5 +1,5 @@
@@ -66,6 +69,7 @@
-->
{#if $gameOverlayVisibilityStore}
+
diff --git a/front/src/Components/EnableCamera/HorizontalSoundMeterWidget.svelte b/front/src/Components/EnableCamera/HorizontalSoundMeterWidget.svelte
index a22da2fa..79ad1810 100644
--- a/front/src/Components/EnableCamera/HorizontalSoundMeterWidget.svelte
+++ b/front/src/Components/EnableCamera/HorizontalSoundMeterWidget.svelte
@@ -58,7 +58,7 @@
- {#each [...Array(NB_BARS).keys()] as i}
+ {#each [...Array(NB_BARS).keys()] as i (i)}
{/each}
diff --git a/front/src/Components/SoundMeterWidget.svelte b/front/src/Components/SoundMeterWidget.svelte
index 30650e3f..94e0cdd2 100644
--- a/front/src/Components/SoundMeterWidget.svelte
+++ b/front/src/Components/SoundMeterWidget.svelte
@@ -23,7 +23,7 @@
timeout = setInterval(() => {
try{
- volume = parseInt((soundMeter.getVolume() / 100 * NB_BARS).toFixed(0));
+ volume = soundMeter.getVolume();
//console.log(volume);
}catch(err){
@@ -45,9 +45,9 @@
- 1}>
- 2}>
- 3}>
- 4}>
5}>
+ 10}>
+ 15}>
+ 40}>
+ 70}>
diff --git a/front/src/Components/Video/LocalStreamMedia.svelte b/front/src/Components/Video/LocalStreamMedia.svelte
new file mode 100644
index 00000000..43b1d117
--- /dev/null
+++ b/front/src/Components/Video/LocalStreamMedia.svelte
@@ -0,0 +1,20 @@
+
+
+
+
+
+
diff --git a/front/src/Components/Video/Peer.svelte b/front/src/Components/Video/Peer.svelte
new file mode 100644
index 00000000..c73d620e
--- /dev/null
+++ b/front/src/Components/Video/Peer.svelte
@@ -0,0 +1,20 @@
+
+
+
+ {#if peer instanceof VideoPeer}
+
+ {:else if peer instanceof ScreenSharingPeer}
+
+ {:else}
+
+ {/if}
+
diff --git a/front/src/Components/Video/ScreenSharingMedia.svelte b/front/src/Components/Video/ScreenSharingMedia.svelte
new file mode 100644
index 00000000..e16fac58
--- /dev/null
+++ b/front/src/Components/Video/ScreenSharingMedia.svelte
@@ -0,0 +1,57 @@
+
+
+
+ {#if $statusStore === 'connecting'}
+
+ {/if}
+ {#if $statusStore === 'error'}
+
+ {/if}
+ {#if $streamStore === null}
+
{name}
+ {/if}
+
+
+
+
diff --git a/front/src/Components/Video/VideoMedia.svelte b/front/src/Components/Video/VideoMedia.svelte
new file mode 100644
index 00000000..fbc5c6f7
--- /dev/null
+++ b/front/src/Components/Video/VideoMedia.svelte
@@ -0,0 +1,75 @@
+
+
+
+ {#if $statusStore === 'connecting'}
+
+ {/if}
+ {#if $statusStore === 'error'}
+
+ {/if}
+ {#if !$constraintStore || $constraintStore.video === false}
+
{name}
+ {/if}
+ {#if $constraintStore && $constraintStore.audio === false}
+

+ {/if}
+
+
+

+ {#if $constraintStore && $constraintStore.audio !== false}
+
+ {/if}
+
+
+
diff --git a/front/src/Components/Video/VideoOverlay.svelte b/front/src/Components/Video/VideoOverlay.svelte
new file mode 100644
index 00000000..5ba7fbc7
--- /dev/null
+++ b/front/src/Components/Video/VideoOverlay.svelte
@@ -0,0 +1,32 @@
+
+
+
+
+ {#each [...$layoutStore.get(DivImportance.Important).values()] as peer (peer.uniqueId)}
+
+ {/each}
+
+
+
+
+
+
+
+
+
diff --git a/front/src/Components/Video/images/blockSign.svg b/front/src/Components/Video/images/blockSign.svg
new file mode 100644
index 00000000..c64ba294
--- /dev/null
+++ b/front/src/Components/Video/images/blockSign.svg
@@ -0,0 +1,22 @@
+
+
+
\ No newline at end of file
diff --git a/front/src/Components/Video/images/report.svg b/front/src/Components/Video/images/report.svg
new file mode 100644
index 00000000..14753256
--- /dev/null
+++ b/front/src/Components/Video/images/report.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts
index b5876d5a..1bec39fc 100644
--- a/front/src/Phaser/Game/GameScene.ts
+++ b/front/src/Phaser/Game/GameScene.ts
@@ -30,7 +30,7 @@ import {PlayerMovement} from "./PlayerMovement";
import {PlayersPositionInterpolator} from "./PlayersPositionInterpolator";
import {RemotePlayer} from "../Entity/RemotePlayer";
import {Queue} from 'queue-typescript';
-import {SimplePeer, UserSimplePeerInterface} from "../../WebRtc/SimplePeer";
+import {SimplePeer} from "../../WebRtc/SimplePeer";
import {ReconnectingSceneName} from "../Reconnecting/ReconnectingScene";
import {lazyLoadPlayerCharacterTextures, loadCustomTexture} from "../Entity/PlayerTexturesLoadingManager";
import {
@@ -93,7 +93,7 @@ import {PinchManager} from "../UserInput/PinchManager";
import {joystickBaseImg, joystickBaseKey, joystickThumbImg, joystickThumbKey} from "../Components/MobileJoystick";
import {DEPTH_OVERLAY_INDEX} from "./DepthIndexes";
import {waScaleManager} from "../Services/WaScaleManager";
-import {peerStore} from "../../Stores/PeerStore";
+import {peerStore, screenSharingPeerStore} from "../../Stores/PeerStore";
import {EmoteManager} from "./EmoteManager";
export interface GameSceneInitInterface {
@@ -646,12 +646,13 @@ export class GameScene extends DirtyScene implements CenterListener {
// When connection is performed, let's connect SimplePeer
this.simplePeer = new SimplePeer(this.connection, !this.room.isPublic, this.playerName);
peerStore.connectToSimplePeer(this.simplePeer);
+ screenSharingPeerStore.connectToSimplePeer(this.simplePeer);
this.GlobalMessageManager = new GlobalMessageManager(this.connection);
userMessageManager.setReceiveBanListener(this.bannedUser.bind(this));
const self = this;
this.simplePeer.registerPeerConnectionListener({
- onConnect(user: UserSimplePeerInterface) {
+ onConnect(peer) {
self.presentationModeSprite.setVisible(true);
self.chatModeSprite.setVisible(true);
self.openChatIcon.setVisible(true);
diff --git a/front/src/Stores/GameOverlayStoreVisibility.ts b/front/src/Stores/GameOverlayStoreVisibility.ts
new file mode 100644
index 00000000..c58c929d
--- /dev/null
+++ b/front/src/Stores/GameOverlayStoreVisibility.ts
@@ -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();
diff --git a/front/src/Stores/LayoutStore.ts b/front/src/Stores/LayoutStore.ts
new file mode 100644
index 00000000..45e6f604
--- /dev/null
+++ b/front/src/Stores/LayoutStore.ts
@@ -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
>();
+ peers.set(DivImportance.Normal, new Map());
+ peers.set(DivImportance.Important, new Map());
+
+ 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();
diff --git a/front/src/Stores/MediaStore.ts b/front/src/Stores/MediaStore.ts
index d622511e..b2cd9f42 100644
--- a/front/src/Stores/MediaStore.ts
+++ b/front/src/Stores/MediaStore.ts
@@ -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();
/**
diff --git a/front/src/Stores/PeerStore.ts b/front/src/Stores/PeerStore.ts
index a582e692..df8b17ce 100644
--- a/front/src/Stores/PeerStore.ts
+++ b/front/src/Stores/PeerStore.ts
@@ -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();
+ let peers = new Map();
- const { subscribe, set, update } = writable(users);
+ const { subscribe, set, update } = writable(peers);
return {
subscribe,
connectToSimplePeer: (simplePeer: SimplePeer) => {
- users = new Map();
- set(users);
+ peers = new Map();
+ 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();
+
+ const { subscribe, set, update } = writable(peers);
+
+ return {
+ subscribe,
+ connectToSimplePeer: (simplePeer: SimplePeer) => {
+ peers = new Map();
+ 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();
+
+ return readable