Fixing warnings and moving biggest area compute in store
This commit is contained in:
parent
d3544e2d97
commit
d533894a74
@ -58,7 +58,7 @@
|
|||||||
"test": "TS_NODE_PROJECT=\"tsconfig-for-jasmine.json\" ts-node node_modules/jasmine/bin/jasmine --config=jasmine.json",
|
"test": "TS_NODE_PROJECT=\"tsconfig-for-jasmine.json\" ts-node node_modules/jasmine/bin/jasmine --config=jasmine.json",
|
||||||
"lint": "node_modules/.bin/eslint src/ . --ext .ts",
|
"lint": "node_modules/.bin/eslint src/ . --ext .ts",
|
||||||
"fix": "node_modules/.bin/eslint --fix src/ . --ext .ts",
|
"fix": "node_modules/.bin/eslint --fix src/ . --ext .ts",
|
||||||
"svelte-check-watch": "svelte-check --fail-on-warnings --fail-on-hints --compiler-warnings \"a11y-no-onchange:ignore,a11y-autofocus:ignore a11y-media-has-caption:ignore\" --watch",
|
"svelte-check-watch": "svelte-check --fail-on-warnings --fail-on-hints --compiler-warnings \"a11y-no-onchange:ignore,a11y-autofocus:ignore,a11y-media-has-caption:ignore\" --watch",
|
||||||
"svelte-check": "svelte-check --fail-on-warnings --fail-on-hints --compiler-warnings \"a11y-no-onchange:ignore,a11y-autofocus:ignore a11y-media-has-caption:ignore\""
|
"svelte-check": "svelte-check --fail-on-warnings --fail-on-hints --compiler-warnings \"a11y-no-onchange:ignore,a11y-autofocus:ignore,a11y-media-has-caption:ignore\""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,6 @@
|
|||||||
export let stream: MediaStream|null;
|
export let stream: MediaStream|null;
|
||||||
let volume = 0;
|
let volume = 0;
|
||||||
|
|
||||||
const NB_BARS = 5;
|
|
||||||
|
|
||||||
let timeout: ReturnType<typeof setTimeout>;
|
let timeout: ReturnType<typeof setTimeout>;
|
||||||
const soundMeter = new SoundMeter();
|
const soundMeter = new SoundMeter();
|
||||||
let display = false;
|
let display = false;
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Peer from "./Peer.svelte";
|
import Peer from "./Peer.svelte";
|
||||||
import {layoutStore} from "../../Stores/LayoutStore";
|
import {layoutStore} from "../../Stores/LayoutStore";
|
||||||
import {onDestroy} from "svelte";
|
import {afterUpdate, onDestroy} from "svelte";
|
||||||
|
import {biggestAvailableArrayStore} from "../../Stores/BiggestAvailableArrayStore";
|
||||||
|
|
||||||
let cssClass = 'one-col';
|
let cssClass = 'one-col';
|
||||||
|
|
||||||
@ -21,6 +22,10 @@
|
|||||||
onDestroy(() => {
|
onDestroy(() => {
|
||||||
unsubscribe();
|
unsubscribe();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
afterUpdate(() => {
|
||||||
|
biggestAvailableArrayStore.recompute();
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="chat-mode {cssClass}">
|
<div class="chat-mode {cssClass}">
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
<script lang="typescript">
|
<script lang="typescript">
|
||||||
import {ScreenSharingLocalMedia} from "../../Stores/ScreenSharingStore";
|
import type {ScreenSharingLocalMedia} from "../../Stores/ScreenSharingStore";
|
||||||
import {videoFocusStore} from "../../Stores/VideoFocusStore";
|
import {videoFocusStore} from "../../Stores/VideoFocusStore";
|
||||||
|
|
||||||
function srcObject(node, stream) {
|
function srcObject(node: HTMLVideoElement, stream: MediaStream) {
|
||||||
node.srcObject = stream;
|
node.srcObject = stream;
|
||||||
return {
|
return {
|
||||||
update(newStream) {
|
update(newStream: MediaStream) {
|
||||||
if (node.srcObject != newStream) {
|
if (node.srcObject != newStream) {
|
||||||
node.srcObject = newStream
|
node.srcObject = newStream
|
||||||
}
|
}
|
||||||
@ -14,11 +14,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
export let peer : ScreenSharingLocalMedia;
|
export let peer : ScreenSharingLocalMedia;
|
||||||
let stream : MediaStream|undefined = peer.stream;
|
let stream = peer.stream;
|
||||||
export let cssClass : string|undefined;
|
export let cssClass : string|undefined;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
<div class="video-container {cssClass ? cssClass : ''}" class:hide={!stream}>
|
<div class="video-container {cssClass ? cssClass : ''}" class:hide={!stream}>
|
||||||
|
{#if stream}
|
||||||
<video use:srcObject={stream} autoplay muted playsinline on:click={() => videoFocusStore.toggleFocus(peer)}></video>
|
<video use:srcObject={stream} autoplay muted playsinline on:click={() => videoFocusStore.toggleFocus(peer)}></video>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
import ScreenSharingMedia from "./ScreenSharingMedia.svelte";
|
import ScreenSharingMedia from "./ScreenSharingMedia.svelte";
|
||||||
import {ScreenSharingPeer} from "../../WebRtc/ScreenSharingPeer";
|
import {ScreenSharingPeer} from "../../WebRtc/ScreenSharingPeer";
|
||||||
import LocalStreamMedia from "./LocalStreamMedia.svelte";
|
import LocalStreamMedia from "./LocalStreamMedia.svelte";
|
||||||
import {DisplayableMedia} from "../../Stores/LayoutStore";
|
import type {DisplayableMedia} from "../../Stores/LayoutStore";
|
||||||
|
|
||||||
export let peer: DisplayableMedia;
|
export let peer: DisplayableMedia;
|
||||||
</script>
|
</script>
|
||||||
@ -15,6 +15,6 @@
|
|||||||
{:else if peer instanceof ScreenSharingPeer}
|
{:else if peer instanceof ScreenSharingPeer}
|
||||||
<ScreenSharingMedia peer={peer}/>
|
<ScreenSharingMedia peer={peer}/>
|
||||||
{:else}
|
{:else}
|
||||||
<LocalStreamMedia peer={peer}/>
|
<LocalStreamMedia peer={peer} cssClass=""/>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
@ -2,6 +2,12 @@
|
|||||||
import Peer from "./Peer.svelte";
|
import Peer from "./Peer.svelte";
|
||||||
import {layoutStore} from "../../Stores/LayoutStore";
|
import {layoutStore} from "../../Stores/LayoutStore";
|
||||||
import {videoFocusStore} from "../../Stores/VideoFocusStore";
|
import {videoFocusStore} from "../../Stores/VideoFocusStore";
|
||||||
|
import {afterUpdate} from "svelte";
|
||||||
|
import {biggestAvailableArrayStore} from "../../Stores/BiggestAvailableArrayStore";
|
||||||
|
|
||||||
|
afterUpdate(() => {
|
||||||
|
biggestAvailableArrayStore.recompute();
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="main-section">
|
<div class="main-section">
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {ScreenSharingPeer} from "../../WebRtc/ScreenSharingPeer";
|
import type {ScreenSharingPeer} from "../../WebRtc/ScreenSharingPeer";
|
||||||
import {videoFocusStore} from "../../Stores/VideoFocusStore";
|
import {videoFocusStore} from "../../Stores/VideoFocusStore";
|
||||||
|
|
||||||
export let peer: ScreenSharingPeer;
|
export let peer: ScreenSharingPeer;
|
||||||
@ -7,10 +7,10 @@
|
|||||||
let name = peer.userName;
|
let name = peer.userName;
|
||||||
let statusStore = peer.statusStore;
|
let statusStore = peer.statusStore;
|
||||||
|
|
||||||
function srcObject(node, stream) {
|
function srcObject(node: HTMLVideoElement, stream: MediaStream) {
|
||||||
node.srcObject = stream;
|
node.srcObject = stream;
|
||||||
return {
|
return {
|
||||||
update(newStream) {
|
update(newStream: MediaStream) {
|
||||||
if (node.srcObject != newStream) {
|
if (node.srcObject != newStream) {
|
||||||
node.srcObject = newStream
|
node.srcObject = newStream
|
||||||
}
|
}
|
||||||
@ -45,8 +45,9 @@
|
|||||||
{/if}
|
{/if}
|
||||||
{#if $streamStore === null}
|
{#if $streamStore === null}
|
||||||
<i style="background-color: {getColorByString(name)};">{name}</i>
|
<i style="background-color: {getColorByString(name)};">{name}</i>
|
||||||
|
{:else}
|
||||||
|
<video use:srcObject={$streamStore} autoplay playsinline on:click={() => videoFocusStore.toggleFocus(peer)}></video>
|
||||||
{/if}
|
{/if}
|
||||||
<video use:srcObject={$streamStore} autoplay playsinline on:click={() => videoFocusStore.toggleFocus(peer)}></video>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
@ -1,13 +1,10 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {VideoPeer} from "../../WebRtc/VideoPeer";
|
import type {VideoPeer} from "../../WebRtc/VideoPeer";
|
||||||
import SoundMeterWidget from "../SoundMeterWidget.svelte";
|
import SoundMeterWidget from "../SoundMeterWidget.svelte";
|
||||||
import microphoneCloseImg from "../images/microphone-close.svg";
|
import microphoneCloseImg from "../images/microphone-close.svg";
|
||||||
import reportImg from "./images/report.svg";
|
import reportImg from "./images/report.svg";
|
||||||
import blockSignImg from "./images/blockSign.svg";
|
import blockSignImg from "./images/blockSign.svg";
|
||||||
import {DivImportance} from "../../WebRtc/LayoutManager";
|
|
||||||
import {videoFocusStore} from "../../Stores/VideoFocusStore";
|
import {videoFocusStore} from "../../Stores/VideoFocusStore";
|
||||||
import {EnableCameraScene, EnableCameraSceneName} from "../../Phaser/Login/EnableCameraScene";
|
|
||||||
import {MenuScene, MenuSceneName} from "../../Phaser/Menu/MenuScene";
|
|
||||||
import {showReportScreenStore} from "../../Stores/ShowReportScreenStore";
|
import {showReportScreenStore} from "../../Stores/ShowReportScreenStore";
|
||||||
|
|
||||||
export let peer: VideoPeer;
|
export let peer: VideoPeer;
|
||||||
@ -16,8 +13,6 @@
|
|||||||
let statusStore = peer.statusStore;
|
let statusStore = peer.statusStore;
|
||||||
let constraintStore = peer.constraintsStore;
|
let constraintStore = peer.constraintsStore;
|
||||||
|
|
||||||
constraintStore.subscribe((vl) => console.log('CONS', vl));
|
|
||||||
|
|
||||||
function getColorByString(str: string) : string|null {
|
function getColorByString(str: string) : string|null {
|
||||||
let hash = 0;
|
let hash = 0;
|
||||||
if (str.length === 0) {
|
if (str.length === 0) {
|
||||||
@ -35,10 +30,10 @@
|
|||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
function srcObject(node, stream) {
|
function srcObject(node: HTMLVideoElement, stream: MediaStream) {
|
||||||
node.srcObject = stream;
|
node.srcObject = stream;
|
||||||
return {
|
return {
|
||||||
update(newStream) {
|
update(newStream: MediaStream) {
|
||||||
if (node.srcObject != newStream) {
|
if (node.srcObject != newStream) {
|
||||||
node.srcObject = newStream
|
node.srcObject = newStream
|
||||||
}
|
}
|
||||||
@ -47,7 +42,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function openReport(peer: VideoPeer): void {
|
function openReport(peer: VideoPeer): void {
|
||||||
console.log('OPENING REPORT');
|
|
||||||
showReportScreenStore.set({ userId:peer.userId, userName: peer.userName });
|
showReportScreenStore.set({ userId:peer.userId, userName: peer.userName });
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +64,9 @@
|
|||||||
<img alt="Report this user" src={reportImg}>
|
<img alt="Report this user" src={reportImg}>
|
||||||
<span>Report/Block</span>
|
<span>Report/Block</span>
|
||||||
</button>
|
</button>
|
||||||
|
{#if $streamStore }
|
||||||
<video use:srcObject={$streamStore} autoplay playsinline on:click={() => videoFocusStore.toggleFocus(peer)}></video>
|
<video use:srcObject={$streamStore} autoplay playsinline on:click={() => videoFocusStore.toggleFocus(peer)}></video>
|
||||||
|
{/if}
|
||||||
<img src={blockSignImg} class="block-logo" alt="Block" />
|
<img src={blockSignImg} class="block-logo" alt="Block" />
|
||||||
{#if $constraintStore && $constraintStore.audio !== false}
|
{#if $constraintStore && $constraintStore.audio !== false}
|
||||||
<SoundMeterWidget stream={$streamStore}></SoundMeterWidget>
|
<SoundMeterWidget stream={$streamStore}></SoundMeterWidget>
|
||||||
|
@ -96,6 +96,7 @@ import {waScaleManager} from "../Services/WaScaleManager";
|
|||||||
import {peerStore, screenSharingPeerStore} from "../../Stores/PeerStore";
|
import {peerStore, screenSharingPeerStore} from "../../Stores/PeerStore";
|
||||||
import {EmoteManager} from "./EmoteManager";
|
import {EmoteManager} from "./EmoteManager";
|
||||||
import {videoFocusStore} from "../../Stores/VideoFocusStore";
|
import {videoFocusStore} from "../../Stores/VideoFocusStore";
|
||||||
|
import {biggestAvailableArrayStore} from "../../Stores/BiggestAvailableArrayStore";
|
||||||
|
|
||||||
export interface GameSceneInitInterface {
|
export interface GameSceneInitInterface {
|
||||||
initPosition: PointInterface|null,
|
initPosition: PointInterface|null,
|
||||||
@ -134,7 +135,7 @@ interface DeleteGroupEventInterface {
|
|||||||
|
|
||||||
const defaultStartLayerName = 'start';
|
const defaultStartLayerName = 'start';
|
||||||
|
|
||||||
export class GameScene extends DirtyScene implements CenterListener {
|
export class GameScene extends DirtyScene /*implements CenterListener*/ {
|
||||||
Terrains : Array<Phaser.Tilemaps.Tileset>;
|
Terrains : Array<Phaser.Tilemaps.Tileset>;
|
||||||
CurrentPlayer!: Player;
|
CurrentPlayer!: Player;
|
||||||
MapPlayers!: Phaser.Physics.Arcade.Group;
|
MapPlayers!: Phaser.Physics.Arcade.Group;
|
||||||
@ -516,7 +517,9 @@ export class GameScene extends DirtyScene implements CenterListener {
|
|||||||
this.reposition();
|
this.reposition();
|
||||||
|
|
||||||
// From now, this game scene will be notified of reposition events
|
// From now, this game scene will be notified of reposition events
|
||||||
layoutManager.setListener(this);
|
//layoutManager.setListener(this);
|
||||||
|
biggestAvailableArrayStore.subscribe((box) => this.updateCameraOffset());
|
||||||
|
|
||||||
this.triggerOnMapLayerPropertyChange();
|
this.triggerOnMapLayerPropertyChange();
|
||||||
this.listenToIframeEvents();
|
this.listenToIframeEvents();
|
||||||
|
|
||||||
@ -1142,7 +1145,8 @@ ${escapedMessage}
|
|||||||
initCamera() {
|
initCamera() {
|
||||||
this.cameras.main.setBounds(0,0, this.Map.widthInPixels, this.Map.heightInPixels);
|
this.cameras.main.setBounds(0,0, this.Map.widthInPixels, this.Map.heightInPixels);
|
||||||
this.cameras.main.startFollow(this.CurrentPlayer, true);
|
this.cameras.main.startFollow(this.CurrentPlayer, true);
|
||||||
this.updateCameraOffset();
|
//this.updateCameraOffset();
|
||||||
|
biggestAvailableArrayStore.recompute();
|
||||||
}
|
}
|
||||||
|
|
||||||
addLayer(Layer : Phaser.Tilemaps.TilemapLayer){
|
addLayer(Layer : Phaser.Tilemaps.TilemapLayer){
|
||||||
@ -1524,7 +1528,8 @@ ${escapedMessage}
|
|||||||
this.openChatIcon.setY(this.game.renderer.height - 2);
|
this.openChatIcon.setY(this.game.renderer.height - 2);
|
||||||
|
|
||||||
// Recompute camera offset if needed
|
// Recompute camera offset if needed
|
||||||
this.updateCameraOffset();
|
//this.updateCameraOffset();
|
||||||
|
biggestAvailableArrayStore.recompute();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1542,9 +1547,9 @@ ${escapedMessage}
|
|||||||
this.cameras.main.setFollowOffset((xCenter - game.offsetWidth/2) * window.devicePixelRatio / this.scale.zoom , (yCenter - game.offsetHeight/2) * window.devicePixelRatio / this.scale.zoom);
|
this.cameras.main.setFollowOffset((xCenter - game.offsetWidth/2) * window.devicePixelRatio / this.scale.zoom , (yCenter - game.offsetHeight/2) * window.devicePixelRatio / this.scale.zoom);
|
||||||
}
|
}
|
||||||
|
|
||||||
public onCenterChange(): void {
|
/*public onCenterChange(): void {
|
||||||
this.updateCameraOffset();
|
this.updateCameraOffset();
|
||||||
}
|
}*/
|
||||||
|
|
||||||
public startJitsi(roomName: string, jwt?: string): void {
|
public startJitsi(roomName: string, jwt?: string): void {
|
||||||
const allProps = this.gameMap.getCurrentProperties();
|
const allProps = this.gameMap.getCurrentProperties();
|
||||||
@ -1605,6 +1610,7 @@ ${escapedMessage}
|
|||||||
|
|
||||||
zoomByFactor(zoomFactor: number) {
|
zoomByFactor(zoomFactor: number) {
|
||||||
waScaleManager.zoomModifier *= zoomFactor;
|
waScaleManager.zoomModifier *= zoomFactor;
|
||||||
this.updateCameraOffset();
|
//this.updateCameraOffset();
|
||||||
|
biggestAvailableArrayStore.recompute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
132
front/src/Stores/BiggestAvailableArrayStore.ts
Normal file
132
front/src/Stores/BiggestAvailableArrayStore.ts
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
import {derived, get, Readable, writable} from "svelte/store";
|
||||||
|
import type {Box} from "../WebRtc/LayoutManager";
|
||||||
|
import {HtmlUtils} from "../WebRtc/HtmlUtils";
|
||||||
|
import {LayoutMode} from "../WebRtc/LayoutManager";
|
||||||
|
import {layoutModeStore} from "./LayoutStore";
|
||||||
|
import {VideoPeer} from "../WebRtc/VideoPeer";
|
||||||
|
import {RemotePeer, SimplePeer} from "../WebRtc/SimplePeer";
|
||||||
|
import {ScreenSharingPeer} from "../WebRtc/ScreenSharingPeer";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tries to find the biggest available box of remaining space (this is a space where we can center the character)
|
||||||
|
*/
|
||||||
|
function findBiggestAvailableArray(): Box {
|
||||||
|
const game = HtmlUtils.querySelectorOrFail<HTMLCanvasElement>('#game canvas');
|
||||||
|
if (get(layoutModeStore) === LayoutMode.VideoChat) {
|
||||||
|
const children = document.querySelectorAll<HTMLDivElement>('div.chat-mode > div');
|
||||||
|
const htmlChildren = Array.from(children.values());
|
||||||
|
|
||||||
|
// No chat? Let's go full center
|
||||||
|
if (htmlChildren.length === 0) {
|
||||||
|
return {
|
||||||
|
xStart: 0,
|
||||||
|
yStart: 0,
|
||||||
|
xEnd: game.offsetWidth,
|
||||||
|
yEnd: game.offsetHeight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const lastDiv = htmlChildren[htmlChildren.length - 1];
|
||||||
|
// Compute area between top right of the last div and bottom right of window
|
||||||
|
const area1 = (game.offsetWidth - (lastDiv.offsetLeft + lastDiv.offsetWidth))
|
||||||
|
* (game.offsetHeight - lastDiv.offsetTop);
|
||||||
|
|
||||||
|
// Compute area between bottom of last div and bottom of the screen on whole width
|
||||||
|
const area2 = game.offsetWidth
|
||||||
|
* (game.offsetHeight - (lastDiv.offsetTop + lastDiv.offsetHeight));
|
||||||
|
|
||||||
|
if (area1 < 0 && area2 < 0) {
|
||||||
|
// If screen is full, let's not attempt something foolish and simply center character in the middle.
|
||||||
|
return {
|
||||||
|
xStart: 0,
|
||||||
|
yStart: 0,
|
||||||
|
xEnd: game.offsetWidth,
|
||||||
|
yEnd: game.offsetHeight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (area1 <= area2) {
|
||||||
|
console.log('lastDiv', lastDiv.offsetTop, lastDiv.offsetHeight);
|
||||||
|
return {
|
||||||
|
xStart: 0,
|
||||||
|
yStart: lastDiv.offsetTop + lastDiv.offsetHeight,
|
||||||
|
xEnd: game.offsetWidth,
|
||||||
|
yEnd: game.offsetHeight
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log('lastDiv', lastDiv.offsetTop);
|
||||||
|
return {
|
||||||
|
xStart: lastDiv.offsetLeft + lastDiv.offsetWidth,
|
||||||
|
yStart: lastDiv.offsetTop,
|
||||||
|
xEnd: game.offsetWidth,
|
||||||
|
yEnd: game.offsetHeight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Possible destinations: at the center bottom or at the right bottom.
|
||||||
|
const mainSectionChildren = Array.from(document.querySelectorAll<HTMLDivElement>('div.main-section > div').values());
|
||||||
|
const sidebarChildren = Array.from(document.querySelectorAll<HTMLDivElement>('aside.sidebar > div').values());
|
||||||
|
|
||||||
|
// No presentation? Let's center on the screen
|
||||||
|
if (mainSectionChildren.length === 0) {
|
||||||
|
return {
|
||||||
|
xStart: 0,
|
||||||
|
yStart: 0,
|
||||||
|
xEnd: game.offsetWidth,
|
||||||
|
yEnd: game.offsetHeight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// At this point, we know we have at least one element in the main section.
|
||||||
|
const lastPresentationDiv = mainSectionChildren[mainSectionChildren.length-1];
|
||||||
|
|
||||||
|
const presentationArea = (game.offsetHeight - (lastPresentationDiv.offsetTop + lastPresentationDiv.offsetHeight))
|
||||||
|
* (lastPresentationDiv.offsetLeft + lastPresentationDiv.offsetWidth);
|
||||||
|
|
||||||
|
let leftSideBar: number;
|
||||||
|
let bottomSideBar: number;
|
||||||
|
if (sidebarChildren.length === 0) {
|
||||||
|
leftSideBar = HtmlUtils.getElementByIdOrFail<HTMLDivElement>('sidebar').offsetLeft;
|
||||||
|
bottomSideBar = 0;
|
||||||
|
} else {
|
||||||
|
const lastSideBarChildren = sidebarChildren[sidebarChildren.length - 1];
|
||||||
|
leftSideBar = lastSideBarChildren.offsetLeft;
|
||||||
|
bottomSideBar = lastSideBarChildren.offsetTop + lastSideBarChildren.offsetHeight;
|
||||||
|
}
|
||||||
|
const sideBarArea = (game.offsetWidth - leftSideBar)
|
||||||
|
* (game.offsetHeight - bottomSideBar);
|
||||||
|
|
||||||
|
if (presentationArea <= sideBarArea) {
|
||||||
|
return {
|
||||||
|
xStart: leftSideBar,
|
||||||
|
yStart: bottomSideBar,
|
||||||
|
xEnd: game.offsetWidth,
|
||||||
|
yEnd: game.offsetHeight
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
xStart: 0,
|
||||||
|
yStart: lastPresentationDiv.offsetTop + lastPresentationDiv.offsetHeight,
|
||||||
|
xEnd: /*lastPresentationDiv.offsetLeft + lastPresentationDiv.offsetWidth*/ game.offsetWidth , // To avoid flickering when a chat start, we center on the center of the screen, not the center of the main content area
|
||||||
|
yEnd: game.offsetHeight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A store that contains the list of (video) peers we are connected to.
|
||||||
|
*/
|
||||||
|
function createBiggestAvailableArrayStore() {
|
||||||
|
|
||||||
|
const { subscribe, set, update } = writable<Box>({xStart:0, yStart: 0, xEnd: 1, yEnd: 1});
|
||||||
|
|
||||||
|
return {
|
||||||
|
subscribe,
|
||||||
|
recompute: () => {
|
||||||
|
set(findBiggestAvailableArray());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export const biggestAvailableArrayStore = createBiggestAvailableArrayStore();
|
@ -34,6 +34,8 @@ export const JITSI_MESSAGE_PROPERTIES = 'jitsiTriggerMessage';
|
|||||||
export const AUDIO_VOLUME_PROPERTY = 'audioVolume';
|
export const AUDIO_VOLUME_PROPERTY = 'audioVolume';
|
||||||
export const AUDIO_LOOP_PROPERTY = 'audioLoop';
|
export const AUDIO_LOOP_PROPERTY = 'audioLoop';
|
||||||
|
|
||||||
|
export type Box = {xStart: number, yStart: number, xEnd: number, yEnd: number};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is in charge of the video-conference layout.
|
* This class is in charge of the video-conference layout.
|
||||||
* It receives positioning requests for videos and does its best to place them on the screen depending on the active layout mode.
|
* It receives positioning requests for videos and does its best to place them on the screen depending on the active layout mode.
|
||||||
@ -52,38 +54,6 @@ class LayoutManager {
|
|||||||
this.listener = centerListener;
|
this.listener = centerListener;
|
||||||
}
|
}
|
||||||
|
|
||||||
public add(importance: DivImportance, userId: string, html: string): void {
|
|
||||||
const div = document.createElement('div');
|
|
||||||
div.innerHTML = html;
|
|
||||||
div.id = "user-"+userId;
|
|
||||||
div.className = "media-container"
|
|
||||||
div.onclick = () => {
|
|
||||||
const parentId = div.parentElement?.id;
|
|
||||||
if (parentId === 'sidebar' || parentId === 'chat-mode') {
|
|
||||||
this.focusOn(userId);
|
|
||||||
} else {
|
|
||||||
this.removeFocusOn(userId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (importance === DivImportance.Important) {
|
|
||||||
this.importantDivs.set(userId, div);
|
|
||||||
|
|
||||||
// If this is the first video with high importance, let's switch mode automatically.
|
|
||||||
if (this.importantDivs.size === 1 && this.mode === LayoutMode.VideoChat) {
|
|
||||||
this.switchLayoutMode(LayoutMode.Presentation);
|
|
||||||
}
|
|
||||||
} else if (importance === DivImportance.Normal) {
|
|
||||||
this.normalDivs.set(userId, div);
|
|
||||||
} else {
|
|
||||||
throw new Error('Unexpected importance');
|
|
||||||
}
|
|
||||||
|
|
||||||
this.positionDiv(div, importance);
|
|
||||||
this.adjustVideoChatClass();
|
|
||||||
this.listener?.onCenterChange();
|
|
||||||
}
|
|
||||||
|
|
||||||
private positionDiv(elem: HTMLDivElement, importance: DivImportance): void {
|
private positionDiv(elem: HTMLDivElement, importance: DivImportance): void {
|
||||||
if (this.mode === LayoutMode.VideoChat) {
|
if (this.mode === LayoutMode.VideoChat) {
|
||||||
const chatModeDiv = HtmlUtils.getElementByIdOrFail<HTMLDivElement>('chat-mode');
|
const chatModeDiv = HtmlUtils.getElementByIdOrFail<HTMLDivElement>('chat-mode');
|
||||||
@ -99,48 +69,6 @@ class LayoutManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Put the screen in presentation mode and move elem in presentation mode (and all other videos in normal mode)
|
|
||||||
*/
|
|
||||||
private focusOn(userId: string): void {
|
|
||||||
const focusedDiv = this.getDivByUserId(userId);
|
|
||||||
for (const [importantUserId, importantDiv] of this.importantDivs.entries()) {
|
|
||||||
//this.positionDiv(importantDiv, DivImportance.Normal);
|
|
||||||
this.importantDivs.delete(importantUserId);
|
|
||||||
this.normalDivs.set(importantUserId, importantDiv);
|
|
||||||
}
|
|
||||||
this.normalDivs.delete(userId);
|
|
||||||
this.importantDivs.set(userId, focusedDiv);
|
|
||||||
//this.positionDiv(focusedDiv, DivImportance.Important);
|
|
||||||
this.switchLayoutMode(LayoutMode.Presentation);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes userId from presentation mode
|
|
||||||
*/
|
|
||||||
private removeFocusOn(userId: string): void {
|
|
||||||
const importantDiv = this.importantDivs.get(userId);
|
|
||||||
if (importantDiv === undefined) {
|
|
||||||
throw new Error('Div with user id "'+userId+'" is not in important mode');
|
|
||||||
}
|
|
||||||
this.normalDivs.set(userId, importantDiv);
|
|
||||||
this.importantDivs.delete(userId);
|
|
||||||
|
|
||||||
this.positionDiv(importantDiv, DivImportance.Normal);
|
|
||||||
}
|
|
||||||
|
|
||||||
private getDivByUserId(userId: string): HTMLDivElement {
|
|
||||||
let div = this.importantDivs.get(userId);
|
|
||||||
if (div !== undefined) {
|
|
||||||
return div;
|
|
||||||
}
|
|
||||||
div = this.normalDivs.get(userId);
|
|
||||||
if (div !== undefined) {
|
|
||||||
return div;
|
|
||||||
}
|
|
||||||
throw new Error('Could not find media with user id '+userId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the DIV matching userId.
|
* Removes the DIV matching userId.
|
||||||
*/
|
*/
|
||||||
@ -218,7 +146,7 @@ class LayoutManager {
|
|||||||
/**
|
/**
|
||||||
* Tries to find the biggest available box of remaining space (this is a space where we can center the character)
|
* Tries to find the biggest available box of remaining space (this is a space where we can center the character)
|
||||||
*/
|
*/
|
||||||
public findBiggestAvailableArray(): {xStart: number, yStart: number, xEnd: number, yEnd: number} {
|
public findBiggestAvailableArray(): Box {
|
||||||
const game = HtmlUtils.querySelectorOrFail<HTMLCanvasElement>('#game canvas');
|
const game = HtmlUtils.querySelectorOrFail<HTMLCanvasElement>('#game canvas');
|
||||||
if (this.mode === LayoutMode.VideoChat) {
|
if (this.mode === LayoutMode.VideoChat) {
|
||||||
const children = document.querySelectorAll<HTMLDivElement>('div.chat-mode > div');
|
const children = document.querySelectorAll<HTMLDivElement>('div.chat-mode > div');
|
||||||
|
Loading…
Reference in New Issue
Block a user