2021-06-25 18:14:40 +02:00
import { get , writable } from "svelte/store" ;
import type { Box } from "../WebRtc/LayoutManager" ;
import { HtmlUtils } from "../WebRtc/HtmlUtils" ;
import { LayoutMode } from "../WebRtc/LayoutManager" ;
import { layoutModeStore } from "./StreamableCollectionStore" ;
2021-06-17 10:07:15 +02:00
/ * *
* Tries to find the biggest available box of remaining space ( this is a space where we can center the character )
* /
2021-06-21 14:07:03 +02:00
function findBiggestAvailableArea ( ) : Box {
2021-06-25 18:14:40 +02:00
const game = HtmlUtils . querySelectorOrFail < HTMLCanvasElement > ( "#game canvas" ) ;
2021-06-17 10:07:15 +02:00
if ( get ( layoutModeStore ) === LayoutMode . VideoChat ) {
2021-06-25 18:14:40 +02:00
const children = document . querySelectorAll < HTMLDivElement > ( "div.chat-mode > div" ) ;
2021-06-17 10:07:15 +02:00
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 ,
2021-06-25 18:14:40 +02:00
yEnd : game.offsetHeight ,
} ;
2021-06-17 10:07:15 +02:00
}
const lastDiv = htmlChildren [ htmlChildren . length - 1 ] ;
// Compute area between top right of the last div and bottom right of window
2021-06-25 18:14:40 +02:00
const area1 =
( game . offsetWidth - ( lastDiv . offsetLeft + lastDiv . offsetWidth ) ) * ( game . offsetHeight - lastDiv . offsetTop ) ;
2021-06-17 10:07:15 +02:00
// Compute area between bottom of last div and bottom of the screen on whole width
2021-06-25 18:14:40 +02:00
const area2 = game . offsetWidth * ( game . offsetHeight - ( lastDiv . offsetTop + lastDiv . offsetHeight ) ) ;
2021-06-17 10:07:15 +02:00
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 ,
2021-06-25 18:14:40 +02:00
yEnd : game.offsetHeight ,
} ;
2021-06-17 10:07:15 +02:00
}
if ( area1 <= area2 ) {
return {
xStart : 0 ,
yStart : lastDiv.offsetTop + lastDiv . offsetHeight ,
xEnd : game.offsetWidth ,
2021-06-25 18:14:40 +02:00
yEnd : game.offsetHeight ,
} ;
2021-06-17 10:07:15 +02:00
} else {
return {
xStart : lastDiv.offsetLeft + lastDiv . offsetWidth ,
yStart : lastDiv.offsetTop ,
xEnd : game.offsetWidth ,
2021-06-25 18:14:40 +02:00
yEnd : game.offsetHeight ,
} ;
2021-06-17 10:07:15 +02:00
}
} else {
// Possible destinations: at the center bottom or at the right bottom.
2021-06-25 18:14:40 +02:00
const mainSectionChildren = Array . from (
document . querySelectorAll < HTMLDivElement > ( "div.main-section > div" ) . values ( )
) ;
const sidebarChildren = Array . from ( document . querySelectorAll < HTMLDivElement > ( "aside.sidebar > div" ) . values ( ) ) ;
2021-06-17 10:07:15 +02:00
// No presentation? Let's center on the screen
if ( mainSectionChildren . length === 0 ) {
return {
xStart : 0 ,
yStart : 0 ,
xEnd : game.offsetWidth ,
2021-06-25 18:14:40 +02:00
yEnd : game.offsetHeight ,
} ;
2021-06-17 10:07:15 +02:00
}
// At this point, we know we have at least one element in the main section.
2021-06-25 18:14:40 +02:00
const lastPresentationDiv = mainSectionChildren [ mainSectionChildren . length - 1 ] ;
2021-06-17 10:07:15 +02:00
2021-06-25 18:14:40 +02:00
const presentationArea =
( game . offsetHeight - ( lastPresentationDiv . offsetTop + lastPresentationDiv . offsetHeight ) ) *
( lastPresentationDiv . offsetLeft + lastPresentationDiv . offsetWidth ) ;
2021-06-17 10:07:15 +02:00
let leftSideBar : number ;
let bottomSideBar : number ;
if ( sidebarChildren . length === 0 ) {
2021-06-25 18:14:40 +02:00
leftSideBar = HtmlUtils . getElementByIdOrFail < HTMLDivElement > ( "sidebar" ) . offsetLeft ;
2021-06-17 10:07:15 +02:00
bottomSideBar = 0 ;
} else {
const lastSideBarChildren = sidebarChildren [ sidebarChildren . length - 1 ] ;
leftSideBar = lastSideBarChildren . offsetLeft ;
bottomSideBar = lastSideBarChildren . offsetTop + lastSideBarChildren . offsetHeight ;
}
2021-06-25 18:14:40 +02:00
const sideBarArea = ( game . offsetWidth - leftSideBar ) * ( game . offsetHeight - bottomSideBar ) ;
2021-06-17 10:07:15 +02:00
if ( presentationArea <= sideBarArea ) {
return {
xStart : leftSideBar ,
yStart : bottomSideBar ,
xEnd : game.offsetWidth ,
2021-06-25 18:14:40 +02:00
yEnd : game.offsetHeight ,
} ;
2021-06-17 10:07:15 +02:00
} else {
return {
xStart : 0 ,
yStart : lastPresentationDiv.offsetTop + lastPresentationDiv . offsetHeight ,
2021-06-25 18:14:40 +02:00
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 ,
} ;
2021-06-17 10:07:15 +02:00
}
}
}
/ * *
* A store that contains the list of ( video ) peers we are connected to .
* /
2021-06-21 14:07:03 +02:00
function createBiggestAvailableAreaStore() {
2021-06-25 18:14:40 +02:00
const { subscribe , set } = writable < Box > ( { xStart : 0 , yStart : 0 , xEnd : 1 , yEnd : 1 } ) ;
2021-06-17 10:07:15 +02:00
return {
subscribe ,
recompute : ( ) = > {
2021-06-21 14:07:03 +02:00
set ( findBiggestAvailableArea ( ) ) ;
2021-06-25 18:14:40 +02:00
} ,
2021-06-17 10:07:15 +02:00
} ;
}
2021-06-21 14:07:03 +02:00
export const biggestAvailableAreaStore = createBiggestAvailableAreaStore ( ) ;