- {#each [...$layoutStore.get(DivImportance.Important).values()] as peer (peer.uniqueId)}
-
+ {#each [...$layoutStore.values()] as peer (peer.uniqueId)}
+ {#if $videoFocusStore && peer === $videoFocusStore }
+
+ {/if}
{/each}
diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts
index 1bec39fc..2531bd4b 100644
--- a/front/src/Phaser/Game/GameScene.ts
+++ b/front/src/Phaser/Game/GameScene.ts
@@ -95,6 +95,7 @@ import {DEPTH_OVERLAY_INDEX} from "./DepthIndexes";
import {waScaleManager} from "../Services/WaScaleManager";
import {peerStore, screenSharingPeerStore} from "../../Stores/PeerStore";
import {EmoteManager} from "./EmoteManager";
+import {videoFocusStore} from "../../Stores/VideoFocusStore";
export interface GameSceneInitInterface {
initPosition: PointInterface|null,
@@ -647,6 +648,7 @@ export class GameScene extends DirtyScene implements CenterListener {
this.simplePeer = new SimplePeer(this.connection, !this.room.isPublic, this.playerName);
peerStore.connectToSimplePeer(this.simplePeer);
screenSharingPeerStore.connectToSimplePeer(this.simplePeer);
+ videoFocusStore.connectToSimplePeer(this.simplePeer);
this.GlobalMessageManager = new GlobalMessageManager(this.connection);
userMessageManager.setReceiveBanListener(this.bannedUser.bind(this));
diff --git a/front/src/Stores/ImportanceStore.ts b/front/src/Stores/ImportanceStore.ts
deleted file mode 100644
index f1c8bc3a..00000000
--- a/front/src/Stores/ImportanceStore.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import {VideoPeer} from "../WebRtc/VideoPeer";
-import {Subscriber, Unsubscriber, writable} from "svelte/store";
-import {RemotePeer, SimplePeer} from "../WebRtc/SimplePeer";
-import {DivImportance} from "../WebRtc/LayoutManager";
-
-export interface ImportanceStore {
- subscribe: (this:void, run: Subscriber
, invalidate?: ((value?: DivImportance) => void | undefined)) => Unsubscriber,
- toggle: () => void,
-}
-
-export function createImportanceStore(defaultImportance: DivImportance): ImportanceStore {
- const { subscribe, set, update } = writable(defaultImportance);
-
- return {
- subscribe,
- toggle: () => {
- update((importance) => {
- if (importance === DivImportance.Important) {
- return DivImportance.Normal;
- } else {
- return DivImportance.Important;
- }
- });
- }
- };
-}
diff --git a/front/src/Stores/LayoutStore.ts b/front/src/Stores/LayoutStore.ts
index 45e6f604..d94eea48 100644
--- a/front/src/Stores/LayoutStore.ts
+++ b/front/src/Stores/LayoutStore.ts
@@ -1,6 +1,5 @@
-import {derived, get} from "svelte/store";
+import {derived, get, writable} from "svelte/store";
import {ScreenSharingLocalMedia, screenSharingLocalMedia} from "./ScreenSharingStore";
-import {DivImportance} from "../WebRtc/LayoutManager";
import { peerStore, screenSharingStreamStore} from "./PeerStore";
import type {RemotePeer} from "../WebRtc/SimplePeer";
@@ -27,26 +26,15 @@ function createLayoutStore() {
}
unsubscribes = [];
- const peers = new Map>();
- peers.set(DivImportance.Normal, new Map());
- peers.set(DivImportance.Important, new Map());
+ const peers = 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);
- }));
+ peers.set(peer.uniqueId, peer);
};
$screenSharingStreamStore.forEach(addPeer);
$peerStore.forEach(addPeer);
+
if ($screenSharingLocalMedia?.stream) {
addPeer($screenSharingLocalMedia);
}
diff --git a/front/src/Stores/ScreenSharingStore.ts b/front/src/Stores/ScreenSharingStore.ts
index 8e185285..ccb8c02c 100644
--- a/front/src/Stores/ScreenSharingStore.ts
+++ b/front/src/Stores/ScreenSharingStore.ts
@@ -5,7 +5,6 @@ import type {
} from "./MediaStore";
import {DivImportance} from "../WebRtc/LayoutManager";
import {gameOverlayVisibilityStore} from "./GameOverlayStoreVisibility";
-import {createImportanceStore, ImportanceStore} from "./ImportanceStore";
declare const navigator:any; // eslint-disable-line @typescript-eslint/no-explicit-any
@@ -189,7 +188,6 @@ export const screenSharingAvailableStore = derived(peerStore, ($peerStore, set)
export interface ScreenSharingLocalMedia {
uniqueId: string;
- importanceStore: ImportanceStore;
stream: MediaStream|null;
//subscribe(this: void, run: Subscriber, invalidate?: (value?: ScreenSharingLocalMedia) => void): Unsubscriber;
}
@@ -201,7 +199,6 @@ export const screenSharingLocalMedia = readable(nu
const localMedia: ScreenSharingLocalMedia = {
uniqueId: "localScreenSharingStream",
- importanceStore: createImportanceStore(DivImportance.Normal),
stream: null
}
diff --git a/front/src/Stores/VideoFocusStore.ts b/front/src/Stores/VideoFocusStore.ts
new file mode 100644
index 00000000..a4298cf9
--- /dev/null
+++ b/front/src/Stores/VideoFocusStore.ts
@@ -0,0 +1,48 @@
+import {writable} from "svelte/store";
+import type {RemotePeer, SimplePeer} from "../WebRtc/SimplePeer";
+import {VideoPeer} from "../WebRtc/VideoPeer";
+import {ScreenSharingPeer} from "../WebRtc/ScreenSharingPeer";
+import type {DisplayableMedia} from "./LayoutStore";
+
+/**
+ * A store that contains the peer / media that has currently the "importance" focus.
+ */
+function createVideoFocusStore() {
+ const { subscribe, set, update } = writable(null);
+
+ let focusedMedia: DisplayableMedia | null = null;
+
+ return {
+ subscribe,
+ focus: (media: DisplayableMedia) => {
+ focusedMedia = media;
+ set(media);
+ },
+ removeFocus: () => {
+ focusedMedia = null;
+ set(null);
+ },
+ toggleFocus: (media: DisplayableMedia) => {
+ if (media !== focusedMedia) {
+ focusedMedia = media;
+ } else {
+ focusedMedia = null;
+ }
+ console.log('MEDIA', 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();
diff --git a/front/src/WebRtc/ScreenSharingPeer.ts b/front/src/WebRtc/ScreenSharingPeer.ts
index 32408da1..4f5ceaeb 100644
--- a/front/src/WebRtc/ScreenSharingPeer.ts
+++ b/front/src/WebRtc/ScreenSharingPeer.ts
@@ -5,9 +5,7 @@ import type {RoomConnection} from "../Connexion/RoomConnection";
import {MESSAGE_TYPE_CONSTRAINT} from "./VideoPeer";
import type {UserSimplePeerInterface} from "./SimplePeer";
import {Readable, readable, writable, Writable} from "svelte/store";
-import {DivImportance} from "./LayoutManager";
-import type {ImportanceStore} from "../Stores/ImportanceStore";
-import {createImportanceStore} from "../Stores/ImportanceStore";
+import {videoFocusStore} from "../Stores/VideoFocusStore";
const Peer: SimplePeerNamespace.SimplePeer = require('simple-peer');
@@ -24,7 +22,6 @@ export class ScreenSharingPeer extends Peer {
public readonly userId: number;
public readonly uniqueId: string;
public readonly streamStore: Readable;
- public readonly importanceStore: ImportanceStore;
public readonly statusStore: Readable<"connecting" | "connected" | "error" | "closed">;
constructor(user: UserSimplePeerInterface, initiator: boolean, public readonly userName: string, private connection: RoomConnection, stream: MediaStream | null) {
@@ -50,6 +47,7 @@ export class ScreenSharingPeer extends Peer {
this.streamStore = readable(null, (set) => {
const onStream = (stream: MediaStream|null) => {
+ videoFocusStore.focus(this);
set(stream);
};
const onData = (chunk: Buffer) => {
@@ -73,8 +71,6 @@ export class ScreenSharingPeer extends Peer {
};
});
- this.importanceStore = createImportanceStore(DivImportance.Important);
-
this.statusStore = readable<"connecting" | "connected" | "error" | "closed">("connecting", (set) => {
const onConnect = () => {
set('connected');
diff --git a/front/src/WebRtc/VideoPeer.ts b/front/src/WebRtc/VideoPeer.ts
index c6b14ede..3ad006ce 100644
--- a/front/src/WebRtc/VideoPeer.ts
+++ b/front/src/WebRtc/VideoPeer.ts
@@ -5,11 +5,9 @@ import type {RoomConnection} from "../Connexion/RoomConnection";
import {blackListManager} from "./BlackListManager";
import type {Subscription} from "rxjs";
import type {UserSimplePeerInterface} from "./SimplePeer";
-import {get, readable, Readable, writable, Writable} from "svelte/store";
+import {get, readable, Readable} from "svelte/store";
import {obtainedMediaConstraintStore} from "../Stores/MediaStore";
import {DivImportance} from "./LayoutManager";
-import type {ImportanceStore} from "../Stores/ImportanceStore";
-import {createImportanceStore} from "../Stores/ImportanceStore";
const Peer: SimplePeerNamespace.SimplePeer = require('simple-peer');
@@ -30,7 +28,6 @@ export class VideoPeer extends Peer {
private onBlockSubscribe: Subscription;
private onUnBlockSubscribe: Subscription;
public readonly streamStore: Readable;
- public readonly importanceStore: ImportanceStore;
public readonly statusStore: Readable<"connecting" | "connected" | "error" | "closed">;
public readonly constraintsStore: Readable;
@@ -94,8 +91,6 @@ export class VideoPeer extends Peer {
};
});
- this.importanceStore = createImportanceStore(DivImportance.Normal);
-
this.statusStore = readable<"connecting" | "connected" | "error" | "closed">("connecting", (set) => {
const onConnect = () => {
set('connected');
diff --git a/front/style/style.scss b/front/style/style.scss
index beed1db5..1de9793a 100644
--- a/front/style/style.scss
+++ b/front/style/style.scss
@@ -35,102 +35,108 @@ body .message-info.info{
body .message-info.warning{
background: #ffa500d6;
}
-.video-container{
+
+.video-container {
position: relative;
transition: all 0.2s ease;
background-color: #00000099;
cursor: url('./images/cursor_pointer.png'), pointer;
-}
-.video-container i{
- position: absolute;
- width: 100px;
- height: 100px;
- left: calc(50% - 50px);
- top: calc(50% - 50px);
- background-color: black;
- border-radius: 50%;
- text-align: center;
- padding-top: 32px;
- font-size: 28px;
- color: white;
- overflow: hidden;
-}
-.video-container img{
- position: absolute;
- display: none;
- width: 40px;
- height: 40px;
- left: 5px;
- bottom: 5px;
- padding: 10px;
- z-index: 2;
-}
-.video-container img.block-logo {
- left: 30%;
- bottom: 15%;
- width: 150px;
- height: 150px;
-}
+ video {
+ width: 100%;
+ height: 100%;
+ cursor: url('./images/cursor_pointer.png'), pointer;
+ }
-.video-container button.report{
- display: block;
- cursor: url('./images/cursor_pointer.png'), pointer;
- background: none;
- background-color: rgba(0, 0, 0, 0);
- border: none;
- background-color: black;
- border-radius: 15px;
- position: absolute;
- width: 0px;
- height: 35px;
- right: 5px;
- bottom: 5px;
- padding: 0px;
- overflow: hidden;
- z-index: 2;
- transition: all .5s ease;
-}
+ i {
+ position: absolute;
+ width: 100px;
+ height: 100px;
+ left: calc(50% - 50px);
+ top: calc(50% - 50px);
+ background-color: black;
+ border-radius: 50%;
+ text-align: center;
+ padding-top: 32px;
+ font-size: 28px;
+ color: white;
+ overflow: hidden;
+ }
-.video-container:hover button.report{
- width: 35px;
- padding: 10px;
-}
+ img {
+ position: absolute;
+ display: none;
+ width: 40px;
+ height: 40px;
+ left: 5px;
+ bottom: 5px;
+ padding: 10px;
+ z-index: 2;
+ }
-.video-container button.report:hover {
- width: 160px;
-}
+ img.block-logo {
+ left: 30%;
+ bottom: 15%;
+ width: 150px;
+ height: 150px;
+ }
-.video-container button.report img{
- position: absolute;
- display: block;
- bottom: 5px;
- left: 5px;
- margin: 0;
- padding: 0;
- cursor: url('./images/cursor_pointer.png'), pointer;
- width: 25px;
- height: 25px;
-}
-.video-container button.report span{
- position: absolute;
- bottom: 6px;
- left: 36px;
- color: white;
- font-size: 16px;
- cursor: url('./images/cursor_pointer.png'), pointer;
-}
-.video-container img.active {
- display: block !important;
-}
+ button.report{
+ display: block;
+ cursor: url('./images/cursor_pointer.png'), pointer;
+ background: none;
+ background-color: rgba(0, 0, 0, 0);
+ border: none;
+ background-color: black;
+ border-radius: 15px;
+ position: absolute;
+ width: 0px;
+ height: 35px;
+ right: 5px;
+ bottom: 5px;
+ padding: 0px;
+ overflow: hidden;
+ z-index: 2;
+ transition: all .5s ease;
-.video-container video{
- height: 100%;
- cursor: url('./images/cursor_pointer.png'), pointer;
-}
+ img{
+ position: absolute;
+ display: block;
+ bottom: 5px;
+ left: 5px;
+ margin: 0;
+ padding: 0;
+ cursor: url('./images/cursor_pointer.png'), pointer;
+ width: 25px;
+ height: 25px;
+ }
-.video-container video:focus{
- outline: none;
+ span {
+ position: absolute;
+ bottom: 6px;
+ left: 36px;
+ color: white;
+ font-size: 16px;
+ cursor: url('./images/cursor_pointer.png'), pointer;
+ }
+
+ img.active {
+ display: block !important;
+ }
+ }
+
+ &:hover button.report{
+ width: 35px;
+ padding: 10px;
+
+ &:hover {
+ width: 160px;
+ }
+ }
+
+ video:focus{
+ outline: none;
+ }
}
.video-container.div-myCamVideo{