Improve game overlay UI
This commit is contained in:
parent
5f1dd09cb9
commit
0bf1acfefb
@ -1,166 +1,52 @@
|
|||||||
<script lang="typescript">
|
<script lang="typescript">
|
||||||
import MenuIcon from "./Menu/MenuIcon.svelte";
|
|
||||||
import { menuIconVisiblilityStore, menuVisiblilityStore } from "../Stores/MenuStore";
|
|
||||||
import { emoteMenuStore } from "../Stores/EmoteStore";
|
|
||||||
import { enableCameraSceneVisibilityStore } from "../Stores/MediaStore";
|
|
||||||
import CameraControls from "./CameraControls.svelte";
|
|
||||||
import MyCamera from "./MyCamera.svelte";
|
|
||||||
import SelectCompanionScene from "./SelectCompanion/SelectCompanionScene.svelte";
|
|
||||||
import { selectCompanionSceneVisibleStore } from "../Stores/SelectCompanionStore";
|
|
||||||
import { selectCharacterSceneVisibleStore } from "../Stores/SelectCharacterStore";
|
|
||||||
import SelectCharacterScene from "./selectCharacter/SelectCharacterScene.svelte";
|
|
||||||
import { customCharacterSceneVisibleStore } from "../Stores/CustomCharacterStore";
|
|
||||||
import { errorStore } from "../Stores/ErrorStore";
|
|
||||||
import CustomCharacterScene from "./CustomCharacterScene/CustomCharacterScene.svelte";
|
|
||||||
import LoginScene from "./Login/LoginScene.svelte";
|
|
||||||
import Chat from "./Chat/Chat.svelte";
|
|
||||||
import { loginSceneVisibleStore } from "../Stores/LoginSceneStore";
|
|
||||||
import EnableCameraScene from "./EnableCamera/EnableCameraScene.svelte";
|
|
||||||
import VisitCard from "./VisitCard/VisitCard.svelte";
|
|
||||||
import { requestVisitCardsStore } from "../Stores/GameStore";
|
|
||||||
|
|
||||||
import type { Game } from "../Phaser/Game/Game";
|
import type { Game } from "../Phaser/Game/Game";
|
||||||
import { chatVisibilityStore } from "../Stores/ChatStore";
|
import { chatVisibilityStore } from "../Stores/ChatStore";
|
||||||
import { helpCameraSettingsVisibleStore } from "../Stores/HelpCameraSettingsStore";
|
import { customCharacterSceneVisibleStore } from "../Stores/CustomCharacterStore";
|
||||||
import HelpCameraSettingsPopup from "./HelpCameraSettings/HelpCameraSettingsPopup.svelte";
|
import { errorStore } from "../Stores/ErrorStore";
|
||||||
import { showLimitRoomModalStore, showShareLinkMapModalStore } from "../Stores/ModalStore";
|
import { loginSceneVisibleStore } from "../Stores/LoginSceneStore";
|
||||||
import LimitRoomModal from "./Modal/LimitRoomModal.svelte";
|
import { enableCameraSceneVisibilityStore } from "../Stores/MediaStore";
|
||||||
import ShareLinkMapModal from "./Modal/ShareLinkMapModal.svelte";
|
import { selectCharacterSceneVisibleStore } from "../Stores/SelectCharacterStore";
|
||||||
import AudioPlaying from "./UI/AudioPlaying.svelte";
|
import { selectCompanionSceneVisibleStore } from "../Stores/SelectCompanionStore";
|
||||||
import { soundPlayingStore } from "../Stores/SoundPlayingStore";
|
import Chat from "./Chat/Chat.svelte";
|
||||||
|
import CustomCharacterScene from "./CustomCharacterScene/CustomCharacterScene.svelte";
|
||||||
|
import EnableCameraScene from "./EnableCamera/EnableCameraScene.svelte";
|
||||||
|
import LoginScene from "./Login/LoginScene.svelte";
|
||||||
|
import MainLayout from "./MainLayout.svelte";
|
||||||
|
import SelectCharacterScene from "./selectCharacter/SelectCharacterScene.svelte";
|
||||||
|
import SelectCompanionScene from "./SelectCompanion/SelectCompanionScene.svelte";
|
||||||
import ErrorDialog from "./UI/ErrorDialog.svelte";
|
import ErrorDialog from "./UI/ErrorDialog.svelte";
|
||||||
import Menu from "./Menu/Menu.svelte";
|
|
||||||
import EmoteMenu from "./EmoteMenu/EmoteMenu.svelte";
|
|
||||||
import VideoOverlay from "./Video/VideoOverlay.svelte";
|
|
||||||
import { gameOverlayVisibilityStore } from "../Stores/GameOverlayStoreVisibility";
|
|
||||||
import BanMessageContainer from "./TypeMessage/BanMessageContainer.svelte";
|
|
||||||
import TextMessageContainer from "./TypeMessage/TextMessageContainer.svelte";
|
|
||||||
import { banMessageStore } from "../Stores/TypeMessageStore/BanMessageStore";
|
|
||||||
import { textMessageStore } from "../Stores/TypeMessageStore/TextMessageStore";
|
|
||||||
import { warningContainerStore } from "../Stores/MenuStore";
|
|
||||||
import WarningContainer from "./WarningContainer/WarningContainer.svelte";
|
|
||||||
import { layoutManagerVisibilityStore } from "../Stores/LayoutManagerStore";
|
|
||||||
import LayoutManager from "./LayoutManager/LayoutManager.svelte";
|
|
||||||
import { audioManagerVisibilityStore } from "../Stores/AudioManagerStore";
|
|
||||||
import AudioManager from "./AudioManager/AudioManager.svelte";
|
|
||||||
import { showReportScreenStore, userReportEmpty } from "../Stores/ShowReportScreenStore";
|
|
||||||
import ReportMenu from "./ReportMenu/ReportMenu.svelte";
|
|
||||||
import { followStateStore } from "../Stores/FollowStore";
|
|
||||||
import { peerStore } from "../Stores/PeerStore";
|
|
||||||
import FollowMenu from "./FollowMenu/FollowMenu.svelte";
|
|
||||||
|
|
||||||
export let game: Game;
|
export let game: Game;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div>
|
{#if $errorStore.length > 0}
|
||||||
{#if $loginSceneVisibleStore}
|
<div>
|
||||||
<div class="scrollable">
|
<ErrorDialog />
|
||||||
<LoginScene {game} />
|
</div>
|
||||||
</div>
|
{:else if $loginSceneVisibleStore}
|
||||||
{/if}
|
<div class="scrollable">
|
||||||
{#if $selectCharacterSceneVisibleStore}
|
<LoginScene {game} />
|
||||||
<div>
|
</div>
|
||||||
<SelectCharacterScene {game} />
|
{:else if $selectCharacterSceneVisibleStore}
|
||||||
</div>
|
<div>
|
||||||
{/if}
|
<SelectCharacterScene {game} />
|
||||||
{#if $customCharacterSceneVisibleStore}
|
</div>
|
||||||
<div>
|
{:else if $customCharacterSceneVisibleStore}
|
||||||
<CustomCharacterScene {game} />
|
<div>
|
||||||
</div>
|
<CustomCharacterScene {game} />
|
||||||
{/if}
|
</div>
|
||||||
{#if $selectCompanionSceneVisibleStore}
|
{:else if $selectCompanionSceneVisibleStore}
|
||||||
<div>
|
<div>
|
||||||
<SelectCompanionScene {game} />
|
<SelectCompanionScene {game} />
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{:else if $enableCameraSceneVisibilityStore}
|
||||||
{#if $enableCameraSceneVisibilityStore}
|
<div class="scrollable">
|
||||||
<div class="scrollable">
|
<EnableCameraScene {game} />
|
||||||
<EnableCameraScene {game} />
|
</div>
|
||||||
</div>
|
{:else}
|
||||||
{/if}
|
<MainLayout />
|
||||||
{#if $banMessageStore.length > 0}
|
|
||||||
<div>
|
|
||||||
<BanMessageContainer />
|
|
||||||
</div>
|
|
||||||
{:else if $textMessageStore.length > 0}
|
|
||||||
<div>
|
|
||||||
<TextMessageContainer />
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
{#if $soundPlayingStore}
|
|
||||||
<div>
|
|
||||||
<AudioPlaying url={$soundPlayingStore} />
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
{#if $audioManagerVisibilityStore}
|
|
||||||
<div>
|
|
||||||
<AudioManager />
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
{#if $layoutManagerVisibilityStore}
|
|
||||||
<div>
|
|
||||||
<LayoutManager />
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
{#if $showReportScreenStore !== userReportEmpty}
|
|
||||||
<div>
|
|
||||||
<ReportMenu />
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
{#if $followStateStore !== "off" || $peerStore.size > 0}
|
|
||||||
<div>
|
|
||||||
<FollowMenu />
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
{#if $menuIconVisiblilityStore}
|
|
||||||
<div>
|
|
||||||
<MenuIcon />
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
{#if $menuVisiblilityStore}
|
|
||||||
<div>
|
|
||||||
<Menu />
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
{#if $emoteMenuStore}
|
|
||||||
<div>
|
|
||||||
<EmoteMenu />
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
{#if $gameOverlayVisibilityStore}
|
|
||||||
<div>
|
|
||||||
<VideoOverlay />
|
|
||||||
<MyCamera />
|
|
||||||
<CameraControls />
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
{#if $helpCameraSettingsVisibleStore}
|
|
||||||
<div>
|
|
||||||
<HelpCameraSettingsPopup />
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
{#if $showLimitRoomModalStore}
|
|
||||||
<div>
|
|
||||||
<LimitRoomModal />
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
{#if $showShareLinkMapModalStore}
|
|
||||||
<div>
|
|
||||||
<ShareLinkMapModal />
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
{#if $requestVisitCardsStore}
|
|
||||||
<VisitCard visitCardUrl={$requestVisitCardsStore} />
|
|
||||||
{/if}
|
|
||||||
{#if $errorStore.length > 0}
|
|
||||||
<div>
|
|
||||||
<ErrorDialog />
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
{#if $chatVisibilityStore}
|
{#if $chatVisibilityStore}
|
||||||
<Chat />
|
<Chat />
|
||||||
{/if}
|
{/if}
|
||||||
{#if $warningContainerStore}
|
{/if}
|
||||||
<WarningContainer />
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
|
@ -157,13 +157,16 @@
|
|||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
div.main-audio-manager.nes-container.is-rounded {
|
div.main-audio-manager.nes-container.is-rounded {
|
||||||
position: relative;
|
position: absolute;
|
||||||
top: 0.5rem;
|
top: 1%;
|
||||||
max-height: clamp(150px, 10vh, 15vh); //replace @media for small screen
|
max-height: clamp(150px, 10vh, 15vh); //replace @media for small screen
|
||||||
width: clamp(200px, 15vw, 15vw);
|
width: clamp(200px, 15vw, 15vw);
|
||||||
padding: 3px 3px;
|
padding: 3px 3px;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 200;
|
||||||
|
|
||||||
background-color: rgb(0, 0, 0, 0.5);
|
background-color: rgb(0, 0, 0, 0.5);
|
||||||
display: grid;
|
display: grid;
|
||||||
|
@ -9,10 +9,15 @@
|
|||||||
import microphoneCloseImg from "./images/microphone-close.svg";
|
import microphoneCloseImg from "./images/microphone-close.svg";
|
||||||
import layoutPresentationImg from "./images/layout-presentation.svg";
|
import layoutPresentationImg from "./images/layout-presentation.svg";
|
||||||
import layoutChatImg from "./images/layout-chat.svg";
|
import layoutChatImg from "./images/layout-chat.svg";
|
||||||
import { layoutModeStore } from "../Stores/StreamableCollectionStore";
|
import followImg from "./images/follow.svg";
|
||||||
import { LayoutMode } from "../WebRtc/LayoutManager";
|
import { LayoutMode } from "../WebRtc/LayoutManager";
|
||||||
import { peerStore } from "../Stores/PeerStore";
|
import { peerStore } from "../Stores/PeerStore";
|
||||||
import { onDestroy } from "svelte";
|
import { onDestroy } from "svelte";
|
||||||
|
import { embedScreenLayout } from "../Stores/EmbedScreensStore";
|
||||||
|
import { followRoleStore, followStateStore, followUsersStore } from "../Stores/FollowStore";
|
||||||
|
import { gameManager } from "../Phaser/Game/GameManager";
|
||||||
|
|
||||||
|
const gameScene = gameManager.getCurrentGameScene();
|
||||||
|
|
||||||
function screenSharingClick(): void {
|
function screenSharingClick(): void {
|
||||||
if (isSilent) return;
|
if (isSilent) return;
|
||||||
@ -42,10 +47,26 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function switchLayoutMode() {
|
function switchLayoutMode() {
|
||||||
if ($layoutModeStore === LayoutMode.Presentation) {
|
if ($embedScreenLayout === LayoutMode.Presentation) {
|
||||||
$layoutModeStore = LayoutMode.VideoChat;
|
$embedScreenLayout = LayoutMode.VideoChat;
|
||||||
} else {
|
} else {
|
||||||
$layoutModeStore = LayoutMode.Presentation;
|
$embedScreenLayout = LayoutMode.Presentation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function followClick() {
|
||||||
|
switch ($followStateStore) {
|
||||||
|
case "off":
|
||||||
|
gameScene.connection?.emitFollowRequest();
|
||||||
|
followRoleStore.set("leader");
|
||||||
|
followStateStore.set("active");
|
||||||
|
break;
|
||||||
|
case "requesting":
|
||||||
|
case "active":
|
||||||
|
case "ending":
|
||||||
|
gameScene.connection?.emitFollowAbort();
|
||||||
|
followUsersStore.stopFollowing();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,40 +77,161 @@
|
|||||||
onDestroy(unsubscribeIsSilent);
|
onDestroy(unsubscribeIsSilent);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div>
|
<div class="btn-cam-action">
|
||||||
<div class="btn-cam-action">
|
<div class="btn-layout" on:click={switchLayoutMode} class:hide={$peerStore.size === 0}>
|
||||||
<div class="btn-layout" on:click={switchLayoutMode} class:hide={$peerStore.size === 0}>
|
{#if $embedScreenLayout === LayoutMode.Presentation}
|
||||||
{#if $layoutModeStore === LayoutMode.Presentation}
|
<img class="noselect" src={layoutPresentationImg} style="padding: 2px" alt="Switch to mosaic mode" />
|
||||||
<img src={layoutPresentationImg} style="padding: 2px" alt="Switch to mosaic mode" />
|
{:else}
|
||||||
{:else}
|
<img class="noselect" src={layoutChatImg} style="padding: 2px" alt="Switch to presentation mode" />
|
||||||
<img src={layoutChatImg} style="padding: 2px" alt="Switch to presentation mode" />
|
{/if}
|
||||||
{/if}
|
</div>
|
||||||
</div>
|
|
||||||
<div
|
<div
|
||||||
class="btn-monitor"
|
class="btn-follow"
|
||||||
on:click={screenSharingClick}
|
class:hide={($peerStore.size === 0 && $followStateStore === "off") || isSilent}
|
||||||
class:hide={!$screenSharingAvailableStore || isSilent}
|
class:disabled={$followStateStore !== "off"}
|
||||||
class:enabled={$requestedScreenSharingState}
|
on:click={followClick}
|
||||||
>
|
>
|
||||||
{#if $requestedScreenSharingState && !isSilent}
|
<img class="noselect" src={followImg} alt="" />
|
||||||
<img src={monitorImg} alt="Start screen sharing" />
|
</div>
|
||||||
{:else}
|
|
||||||
<img src={monitorCloseImg} alt="Stop screen sharing" />
|
<div
|
||||||
{/if}
|
class="btn-monitor"
|
||||||
</div>
|
on:click={screenSharingClick}
|
||||||
<div class="btn-video" on:click={cameraClick} class:disabled={!$requestedCameraState || isSilent}>
|
class:hide={!$screenSharingAvailableStore || isSilent}
|
||||||
{#if $requestedCameraState && !isSilent}
|
class:enabled={$requestedScreenSharingState}
|
||||||
<img src={cinemaImg} alt="Turn on webcam" />
|
>
|
||||||
{:else}
|
{#if $requestedScreenSharingState && !isSilent}
|
||||||
<img src={cinemaCloseImg} alt="Turn off webcam" />
|
<img class="noselect" src={monitorImg} alt="Start screen sharing" />
|
||||||
{/if}
|
{:else}
|
||||||
</div>
|
<img class="noselect" src={monitorCloseImg} alt="Stop screen sharing" />
|
||||||
<div class="btn-micro" on:click={microphoneClick} class:disabled={!$requestedMicrophoneState || isSilent}>
|
{/if}
|
||||||
{#if $requestedMicrophoneState && !isSilent}
|
</div>
|
||||||
<img src={microphoneImg} alt="Turn on microphone" />
|
|
||||||
{:else}
|
<div class="btn-video" on:click={cameraClick} class:disabled={!$requestedCameraState || isSilent}>
|
||||||
<img src={microphoneCloseImg} alt="Turn off microphone" />
|
{#if $requestedCameraState && !isSilent}
|
||||||
{/if}
|
<img class="noselect" src={cinemaImg} alt="Turn on webcam" />
|
||||||
</div>
|
{:else}
|
||||||
|
<img class="noselect" src={cinemaCloseImg} alt="Turn off webcam" />
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="btn-micro" on:click={microphoneClick} class:disabled={!$requestedMicrophoneState || isSilent}>
|
||||||
|
{#if $requestedMicrophoneState && !isSilent}
|
||||||
|
<img class="noselect" src={microphoneImg} alt="Turn on microphone" />
|
||||||
|
{:else}
|
||||||
|
<img class="noselect" src={microphoneCloseImg} alt="Turn off microphone" />
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@import "../../style/breakpoints.scss";
|
||||||
|
|
||||||
|
.btn-cam-action {
|
||||||
|
pointer-events: all;
|
||||||
|
position: absolute;
|
||||||
|
display: inline-flex;
|
||||||
|
bottom: 10px;
|
||||||
|
right: 15px;
|
||||||
|
width: 360px;
|
||||||
|
height: 40px;
|
||||||
|
text-align: center;
|
||||||
|
align-content: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
div.hide {
|
||||||
|
transform: translateY(60px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*btn animation*/
|
||||||
|
.btn-cam-action div {
|
||||||
|
cursor: url("../../style/images/cursor_pointer.png"), pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border: solid 0px black;
|
||||||
|
width: 44px;
|
||||||
|
height: 44px;
|
||||||
|
background: #666;
|
||||||
|
box-shadow: 2px 2px 24px #444;
|
||||||
|
border-radius: 48px;
|
||||||
|
transform: translateY(15px);
|
||||||
|
transition-timing-function: ease-in-out;
|
||||||
|
transition: all 0.3s;
|
||||||
|
margin: 0 4%;
|
||||||
|
|
||||||
|
&.hide {
|
||||||
|
transform: translateY(60px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.btn-cam-action div.disabled {
|
||||||
|
background: #d75555;
|
||||||
|
}
|
||||||
|
.btn-cam-action div.enabled {
|
||||||
|
background: #73c973;
|
||||||
|
}
|
||||||
|
.btn-cam-action:hover div {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
.btn-cam-action div:hover {
|
||||||
|
background: #407cf7;
|
||||||
|
box-shadow: 4px 4px 48px #666;
|
||||||
|
transition: 120ms;
|
||||||
|
}
|
||||||
|
.btn-micro {
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
|
.btn-video {
|
||||||
|
pointer-events: auto;
|
||||||
|
transition: all 0.25s;
|
||||||
|
}
|
||||||
|
.btn-monitor {
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
|
.btn-layout {
|
||||||
|
pointer-events: auto;
|
||||||
|
transition: all 0.15s;
|
||||||
|
}
|
||||||
|
.btn-cam-action div img {
|
||||||
|
height: 22px;
|
||||||
|
width: 30px;
|
||||||
|
position: relative;
|
||||||
|
cursor: url("../../style/images/cursor_pointer.png"), pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-follow {
|
||||||
|
pointer-events: auto;
|
||||||
|
|
||||||
|
img {
|
||||||
|
filter: brightness(0) invert(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (hover: none) {
|
||||||
|
/**
|
||||||
|
* If we cannot hover over elements, let's display camera button in full.
|
||||||
|
*/
|
||||||
|
.btn-cam-action {
|
||||||
|
div {
|
||||||
|
transform: translateY(0px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-up(sm) {
|
||||||
|
.btn-cam-action {
|
||||||
|
right: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 40%;
|
||||||
|
max-height: 40px;
|
||||||
|
|
||||||
|
div {
|
||||||
|
width: 20%;
|
||||||
|
max-height: 44px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
@ -43,7 +43,7 @@
|
|||||||
<svelte:window on:keydown={onKeyDown} on:click={onClick} />
|
<svelte:window on:keydown={onKeyDown} on:click={onClick} />
|
||||||
|
|
||||||
<aside class="chatWindow" transition:fly={{ x: -1000, duration: 500 }} bind:this={chatWindowElement}>
|
<aside class="chatWindow" transition:fly={{ x: -1000, duration: 500 }} bind:this={chatWindowElement}>
|
||||||
<p class="close-icon" on:click={closeChat}>×</p>
|
<p class="close-icon noselect" on:click={closeChat}>×</p>
|
||||||
<section class="messagesList" bind:this={listDom}>
|
<section class="messagesList" bind:this={listDom}>
|
||||||
<ul>
|
<ul>
|
||||||
<li><p class="system-text">{$LL.chat.intro()}</p></li>
|
<li><p class="system-text">{$LL.chat.intro()}</p></li>
|
||||||
@ -78,7 +78,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
aside.chatWindow {
|
aside.chatWindow {
|
||||||
z-index: 100;
|
z-index: 1000;
|
||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
@ -83,6 +83,8 @@
|
|||||||
</form>
|
</form>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
@import "../../../style/breakpoints.scss";
|
||||||
|
|
||||||
form.customCharacterScene {
|
form.customCharacterScene {
|
||||||
font-family: "Press Start 2P";
|
font-family: "Press Start 2P";
|
||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
@ -129,7 +131,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: 800px) {
|
@include media-breakpoint-up(md) {
|
||||||
form.customCharacterScene button.customCharacterSceneButtonLeft {
|
form.customCharacterScene button.customCharacterSceneButtonLeft {
|
||||||
left: 5vw;
|
left: 5vw;
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
import { emoteStore, emoteMenuStore } from "../../Stores/EmoteStore";
|
import { emoteStore, emoteMenuStore } from "../../Stores/EmoteStore";
|
||||||
import { onDestroy, onMount } from "svelte";
|
import { onDestroy, onMount } from "svelte";
|
||||||
import { EmojiButton } from "@joeattardi/emoji-button";
|
import { EmojiButton } from "@joeattardi/emoji-button";
|
||||||
import { isMobile } from "../../Enum/EnvironmentVariable";
|
|
||||||
import LL from "../../i18n/i18n-svelte";
|
import LL from "../../i18n/i18n-svelte";
|
||||||
|
import { isMediaBreakpointUp } from "../../Utils/BreakpointsUtils";
|
||||||
|
|
||||||
let emojiContainer: HTMLElement;
|
let emojiContainer: HTMLElement;
|
||||||
let picker: EmojiButton;
|
let picker: EmojiButton;
|
||||||
@ -20,7 +20,7 @@
|
|||||||
"--secondary-text-color": "whitesmoke",
|
"--secondary-text-color": "whitesmoke",
|
||||||
"--category-button-color": "whitesmoke",
|
"--category-button-color": "whitesmoke",
|
||||||
},
|
},
|
||||||
emojisPerRow: isMobile() ? 6 : 8,
|
emojisPerRow: isMediaBreakpointUp("md") ? 6 : 8,
|
||||||
autoFocusSearch: false,
|
autoFocusSearch: false,
|
||||||
style: "twemoji",
|
style: "twemoji",
|
||||||
showPreview: false,
|
showPreview: false,
|
||||||
@ -86,6 +86,8 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 101;
|
||||||
}
|
}
|
||||||
|
|
||||||
.emote-menu {
|
.emote-menu {
|
||||||
|
@ -127,6 +127,8 @@
|
|||||||
</form>
|
</form>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
@import "../../../style/breakpoints.scss";
|
||||||
|
|
||||||
.enableCameraScene {
|
.enableCameraScene {
|
||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
margin: 20px auto 0;
|
margin: 20px auto 0;
|
||||||
@ -214,7 +216,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: 800px) {
|
@include media-breakpoint-up(md) {
|
||||||
.enableCameraScene h2 {
|
.enableCameraScene h2 {
|
||||||
font-size: 80%;
|
font-size: 80%;
|
||||||
}
|
}
|
||||||
|
33
front/src/Components/FollowMenu/FollowButton.svelte
Normal file
33
front/src/Components/FollowMenu/FollowButton.svelte
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<script lang="typescript">
|
||||||
|
import followImg from "../images/follow.svg";
|
||||||
|
|
||||||
|
export let hidden: Boolean;
|
||||||
|
|
||||||
|
let cancelButton = false;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="btn-follow" class:hide={hidden} class:cancel={cancelButton}>
|
||||||
|
<img src={followImg} alt="" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.btn-follow {
|
||||||
|
cursor: url("../../../style/images/cursor_pointer.png"), pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border: solid 0px black;
|
||||||
|
width: 44px;
|
||||||
|
height: 44px;
|
||||||
|
background: #666;
|
||||||
|
box-shadow: 2px 2px 24px #444;
|
||||||
|
border-radius: 48px;
|
||||||
|
transform: translateY(15px);
|
||||||
|
transition-timing-function: ease-in-out;
|
||||||
|
margin: 0 4%;
|
||||||
|
|
||||||
|
img {
|
||||||
|
filter: brightness(0) invert(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,9 +1,5 @@
|
|||||||
<!--
|
|
||||||
vim: ft=typescript
|
|
||||||
-->
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { gameManager } from "../../Phaser/Game/GameManager";
|
import { gameManager } from "../../Phaser/Game/GameManager";
|
||||||
import followImg from "../images/follow.svg";
|
|
||||||
import { followStateStore, followRoleStore, followUsersStore } from "../../Stores/FollowStore";
|
import { followStateStore, followRoleStore, followUsersStore } from "../../Stores/FollowStore";
|
||||||
import LL from "../../i18n/i18n-svelte";
|
import LL from "../../i18n/i18n-svelte";
|
||||||
|
|
||||||
@ -14,10 +10,6 @@ vim: ft=typescript
|
|||||||
return user ? user.PlayerValue : "";
|
return user ? user.PlayerValue : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendFollowRequest() {
|
|
||||||
gameScene.CurrentPlayer.sendFollowRequest();
|
|
||||||
}
|
|
||||||
|
|
||||||
function acceptFollowRequest() {
|
function acceptFollowRequest() {
|
||||||
gameScene.CurrentPlayer.startFollowing();
|
gameScene.CurrentPlayer.startFollowing();
|
||||||
}
|
}
|
||||||
@ -83,7 +75,7 @@ vim: ft=typescript
|
|||||||
|
|
||||||
{#if $followStateStore === "active" || $followStateStore === "ending"}
|
{#if $followStateStore === "active" || $followStateStore === "ending"}
|
||||||
<div class="interact-status nes-container is-rounded">
|
<div class="interact-status nes-container is-rounded">
|
||||||
<section class="interact-status">
|
<section>
|
||||||
{#if $followRoleStore === "follower"}
|
{#if $followRoleStore === "follower"}
|
||||||
<p>{$LL.follow.interactStatus.following({ leader: name($followUsersStore[0]) })}</p>
|
<p>{$LL.follow.interactStatus.following({ leader: name($followUsersStore[0]) })}</p>
|
||||||
{:else if $followUsersStore.length === 0}
|
{:else if $followUsersStore.length === 0}
|
||||||
@ -109,48 +101,27 @@ vim: ft=typescript
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if $followStateStore === "off"}
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="nes-btn is-primary follow-menu-button"
|
|
||||||
on:click|preventDefault={sendFollowRequest}
|
|
||||||
title="Ask others to follow"><img class="background-img" src={followImg} alt="" /></button
|
|
||||||
>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{#if $followStateStore === "active" || $followStateStore === "ending"}
|
|
||||||
{#if $followRoleStore === "follower"}
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="nes-btn is-error follow-menu-button"
|
|
||||||
on:click|preventDefault={reset}
|
|
||||||
title="Stop following"><img class="background-img" src={followImg} alt="" /></button
|
|
||||||
>
|
|
||||||
{:else}
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="nes-btn is-error follow-menu-button"
|
|
||||||
on:click|preventDefault={reset}
|
|
||||||
title="Stop leading the way"><img class="background-img" src={followImg} alt="" /></button
|
|
||||||
>
|
|
||||||
{/if}
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
@import "../../../style/breakpoints.scss";
|
||||||
|
|
||||||
.nes-container {
|
.nes-container {
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.interact-status {
|
.interact-status {
|
||||||
background-color: #333333;
|
background-color: #333333;
|
||||||
color: whitesmoke;
|
color: whitesmoke;
|
||||||
|
|
||||||
position: relative;
|
position: absolute;
|
||||||
height: 2.7em;
|
max-height: 2.7em;
|
||||||
width: 40vw;
|
width: 40vw;
|
||||||
top: 87vh;
|
top: 87vh;
|
||||||
margin: auto;
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
z-index: 150;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.interact-menu {
|
div.interact-menu {
|
||||||
@ -158,10 +129,14 @@ vim: ft=typescript
|
|||||||
background-color: #333333;
|
background-color: #333333;
|
||||||
color: whitesmoke;
|
color: whitesmoke;
|
||||||
|
|
||||||
position: relative;
|
position: absolute;
|
||||||
width: 60vw;
|
width: 60vw;
|
||||||
top: 60vh;
|
top: 60vh;
|
||||||
margin: auto;
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
z-index: 150;
|
||||||
|
|
||||||
section.interact-menu-title {
|
section.interact-menu-title {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
@ -189,23 +164,16 @@ vim: ft=typescript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.follow-menu-button {
|
@include media-breakpoint-up(md) {
|
||||||
position: absolute;
|
.interact-status {
|
||||||
bottom: 10px;
|
width: 90vw;
|
||||||
left: 10px;
|
|
||||||
pointer-events: all;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (max-width: 800px) {
|
|
||||||
div.interact-status {
|
|
||||||
width: 100vw;
|
|
||||||
top: 78vh;
|
top: 78vh;
|
||||||
font-size: 0.75em;
|
font-size: 0.75em;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.interact-menu {
|
div.interact-menu {
|
||||||
height: 21vh;
|
max-height: 21vh;
|
||||||
width: 100vw;
|
width: 90vw;
|
||||||
font-size: 0.75em;
|
font-size: 0.75em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
<form
|
<form
|
||||||
class="helpCameraSettings nes-container"
|
class="helpCameraSettings nes-container"
|
||||||
on:submit|preventDefault={close}
|
on:submit|preventDefault={close}
|
||||||
transition:fly={{ y: -900, duration: 500 }}
|
transition:fly={{ y: -50, duration: 500 }}
|
||||||
>
|
>
|
||||||
<section>
|
<section>
|
||||||
<h2>{$LL.camera.help.title()}</h2>
|
<h2>{$LL.camera.help.title()}</h2>
|
||||||
@ -55,9 +55,12 @@
|
|||||||
background: #eceeee;
|
background: #eceeee;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
margin-top: 10vh;
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
margin-top: 4%;
|
||||||
max-height: 80vh;
|
max-height: 80vh;
|
||||||
max-width: 80vw;
|
max-width: 80vw;
|
||||||
|
z-index: 250;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
|
@ -21,9 +21,11 @@
|
|||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 40px;
|
bottom: 40px;
|
||||||
margin: 0 auto;
|
margin-right: auto;
|
||||||
|
margin-left: auto;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
width: clamp(200px, 20vw, 20vw);
|
width: clamp(200px, 20vw, 20vw);
|
||||||
|
z-index: 155;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@ -31,6 +33,10 @@
|
|||||||
animation: moveMessage 0.5s;
|
animation: moveMessage 0.5s;
|
||||||
animation-iteration-count: infinite;
|
animation-iteration-count: infinite;
|
||||||
animation-timing-function: ease-in-out;
|
animation-timing-function: ease-in-out;
|
||||||
|
|
||||||
|
div {
|
||||||
|
margin-bottom: 5%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
div.nes-container.is-rounded {
|
div.nes-container.is-rounded {
|
163
front/src/Components/MainLayout.svelte
Normal file
163
front/src/Components/MainLayout.svelte
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
<script lang="typescript">
|
||||||
|
import { onMount } from "svelte";
|
||||||
|
import { audioManagerVisibilityStore } from "../Stores/AudioManagerStore";
|
||||||
|
import { hasEmbedScreen } from "../Stores/EmbedScreensStore";
|
||||||
|
import { emoteMenuStore } from "../Stores/EmoteStore";
|
||||||
|
import { myCameraVisibilityStore } from "../Stores/MyCameraStoreVisibility";
|
||||||
|
import { requestVisitCardsStore } from "../Stores/GameStore";
|
||||||
|
import { helpCameraSettingsVisibleStore } from "../Stores/HelpCameraSettingsStore";
|
||||||
|
import { layoutManagerActionVisibilityStore } from "../Stores/LayoutManagerStore";
|
||||||
|
import { menuIconVisiblilityStore, menuVisiblilityStore, warningContainerStore } from "../Stores/MenuStore";
|
||||||
|
import { showReportScreenStore, userReportEmpty } from "../Stores/ShowReportScreenStore";
|
||||||
|
import AudioManager from "./AudioManager/AudioManager.svelte";
|
||||||
|
import CameraControls from "./CameraControls.svelte";
|
||||||
|
import EmbedScreensContainer from "./EmbedScreens/EmbedScreensContainer.svelte";
|
||||||
|
import EmoteMenu from "./EmoteMenu/EmoteMenu.svelte";
|
||||||
|
import HelpCameraSettingsPopup from "./HelpCameraSettings/HelpCameraSettingsPopup.svelte";
|
||||||
|
import LayoutActionManager from "./LayoutActionManager/LayoutActionManager.svelte";
|
||||||
|
import Menu from "./Menu/Menu.svelte";
|
||||||
|
import MenuIcon from "./Menu/MenuIcon.svelte";
|
||||||
|
import MyCamera from "./MyCamera.svelte";
|
||||||
|
import ReportMenu from "./ReportMenu/ReportMenu.svelte";
|
||||||
|
import VisitCard from "./VisitCard/VisitCard.svelte";
|
||||||
|
import WarningContainer from "./WarningContainer/WarningContainer.svelte";
|
||||||
|
import { isMediaBreakpointUp } from "../Utils/BreakpointsUtils";
|
||||||
|
import CoWebsitesContainer from "./EmbedScreens/CoWebsitesContainer.svelte";
|
||||||
|
import FollowMenu from "./FollowMenu/FollowMenu.svelte";
|
||||||
|
import { followStateStore } from "../Stores/FollowStore";
|
||||||
|
import { peerStore } from "../Stores/PeerStore";
|
||||||
|
import { banMessageStore } from "../Stores/TypeMessageStore/BanMessageStore";
|
||||||
|
import BanMessageContainer from "./TypeMessage/BanMessageContainer.svelte";
|
||||||
|
import { textMessageStore } from "../Stores/TypeMessageStore/TextMessageStore";
|
||||||
|
import TextMessageContainer from "./TypeMessage/TextMessageContainer.svelte";
|
||||||
|
import { soundPlayingStore } from "../Stores/SoundPlayingStore";
|
||||||
|
import AudioPlaying from "./UI/AudioPlaying.svelte";
|
||||||
|
import { showLimitRoomModalStore, showShareLinkMapModalStore } from "../Stores/ModalStore";
|
||||||
|
import LimitRoomModal from "./Modal/LimitRoomModal.svelte";
|
||||||
|
import ShareLinkMapModal from "./Modal/ShareLinkMapModal.svelte";
|
||||||
|
|
||||||
|
let mainLayout: HTMLDivElement;
|
||||||
|
|
||||||
|
let displayCoWebsiteContainer = isMediaBreakpointUp("md");
|
||||||
|
|
||||||
|
const resizeObserver = new ResizeObserver(() => {
|
||||||
|
displayCoWebsiteContainer = isMediaBreakpointUp("md");
|
||||||
|
});
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
resizeObserver.observe(mainLayout);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div id="main-layout" bind:this={mainLayout}>
|
||||||
|
<aside id="main-layout-left-aside">
|
||||||
|
{#if $menuIconVisiblilityStore}
|
||||||
|
<MenuIcon />
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if displayCoWebsiteContainer}
|
||||||
|
<CoWebsitesContainer vertical={true} />
|
||||||
|
{/if}
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
<section id="main-layout-main">
|
||||||
|
{#if $menuVisiblilityStore}
|
||||||
|
<Menu />
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if $banMessageStore.length > 0}
|
||||||
|
<BanMessageContainer />
|
||||||
|
{:else if $textMessageStore.length > 0}
|
||||||
|
<TextMessageContainer />
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if $soundPlayingStore}
|
||||||
|
<AudioPlaying url={$soundPlayingStore} />
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if $showReportScreenStore !== userReportEmpty}
|
||||||
|
<ReportMenu />
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if $warningContainerStore}
|
||||||
|
<WarningContainer />
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if $helpCameraSettingsVisibleStore}
|
||||||
|
<HelpCameraSettingsPopup />
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if $audioManagerVisibilityStore}
|
||||||
|
<AudioManager />
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if $showLimitRoomModalStore}
|
||||||
|
<LimitRoomModal />
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if $showShareLinkMapModalStore}
|
||||||
|
<ShareLinkMapModal />
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if $followStateStore !== "off" || $peerStore.size > 0}
|
||||||
|
<FollowMenu />
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if $requestVisitCardsStore}
|
||||||
|
<VisitCard visitCardUrl={$requestVisitCardsStore} />
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if $emoteMenuStore}
|
||||||
|
<EmoteMenu />
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if hasEmbedScreen}
|
||||||
|
<EmbedScreensContainer />
|
||||||
|
{/if}
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="main-layout-baseline">
|
||||||
|
{#if $layoutManagerActionVisibilityStore}
|
||||||
|
<LayoutActionManager />
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if $myCameraVisibilityStore}
|
||||||
|
<MyCamera />
|
||||||
|
<CameraControls />
|
||||||
|
{/if}
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@import "../../style/breakpoints.scss";
|
||||||
|
|
||||||
|
#main-layout {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 7% 93%;
|
||||||
|
grid-template-rows: 80% 20%;
|
||||||
|
|
||||||
|
&-left-aside {
|
||||||
|
min-width: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-baseline {
|
||||||
|
grid-column: 1/3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-up(md) {
|
||||||
|
#main-layout {
|
||||||
|
grid-template-columns: 15% 85%;
|
||||||
|
|
||||||
|
&-left-aside {
|
||||||
|
min-width: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-up(sm) {
|
||||||
|
#main-layout {
|
||||||
|
grid-template-columns: 20% 80%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -100,6 +100,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
@import "../../../style/breakpoints.scss";
|
||||||
|
|
||||||
.string-HTML {
|
.string-HTML {
|
||||||
white-space: pre-line;
|
white-space: pre-line;
|
||||||
}
|
}
|
||||||
@ -126,7 +128,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: 800px), only screen and (max-height: 800px) {
|
@include media-breakpoint-up(md) {
|
||||||
div.about-room-main {
|
div.about-room-main {
|
||||||
section.container-overflow {
|
section.container-overflow {
|
||||||
height: calc(100% - 120px);
|
height: calc(100% - 120px);
|
||||||
|
@ -67,6 +67,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
@import "../../../style/breakpoints.scss";
|
||||||
|
|
||||||
div.global-message-main {
|
div.global-message-main {
|
||||||
height: calc(100% - 50px);
|
height: calc(100% - 50px);
|
||||||
display: grid;
|
display: grid;
|
||||||
@ -109,7 +111,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: 800px), only screen and (max-height: 800px) {
|
@include media-breakpoint-up(md) {
|
||||||
.global-message-content {
|
.global-message-content {
|
||||||
height: calc(100% - 5px);
|
height: calc(100% - 5px);
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
@import "../../../style/breakpoints.scss";
|
||||||
|
|
||||||
div.guest-main {
|
div.guest-main {
|
||||||
height: calc(100% - 56px);
|
height: calc(100% - 56px);
|
||||||
|
|
||||||
@ -57,7 +59,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: 900px), only screen and (max-height: 600px) {
|
@include media-breakpoint-up(md) {
|
||||||
div.guest-main {
|
div.guest-main {
|
||||||
section.share-url.not-mobile {
|
section.share-url.not-mobile {
|
||||||
display: none;
|
display: none;
|
||||||
|
@ -125,6 +125,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
@import "../../../style/breakpoints.scss";
|
||||||
|
|
||||||
.nes-container {
|
.nes-container {
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
}
|
}
|
||||||
@ -136,11 +138,15 @@
|
|||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
height: 80%;
|
height: 80%;
|
||||||
width: 75%;
|
width: 75%;
|
||||||
top: 10%;
|
top: 4%;
|
||||||
|
|
||||||
position: relative;
|
left: 0;
|
||||||
z-index: 80;
|
right: 0;
|
||||||
margin: auto;
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
z-index: 900;
|
||||||
|
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: var(--size-first-columns-grid) calc(100% - var(--size-first-columns-grid));
|
grid-template-columns: var(--size-first-columns-grid) calc(100% - var(--size-first-columns-grid));
|
||||||
@ -173,12 +179,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: 800px) {
|
@include media-breakpoint-up(md) {
|
||||||
div.menu-container-main {
|
div.menu-container-main {
|
||||||
--size-first-columns-grid: 120px;
|
--size-first-columns-grid: 120px;
|
||||||
height: 70%;
|
height: 70%;
|
||||||
top: 55px;
|
top: 55px;
|
||||||
width: 100%;
|
width: 95%;
|
||||||
font-size: 0.5em;
|
font-size: 0.5em;
|
||||||
|
|
||||||
div.menu-nav-sidebar {
|
div.menu-nav-sidebar {
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
function showMenu() {
|
function showMenu() {
|
||||||
menuVisiblilityStore.set(!get(menuVisiblilityStore));
|
menuVisiblilityStore.set(!get(menuVisiblilityStore));
|
||||||
}
|
}
|
||||||
|
|
||||||
function showChat() {
|
function showChat() {
|
||||||
chatVisibilityStore.set(true);
|
chatVisibilityStore.set(true);
|
||||||
}
|
}
|
||||||
@ -21,72 +22,94 @@
|
|||||||
function register() {
|
function register() {
|
||||||
window.open(`${ADMIN_URL}/second-step-register`, "_self");
|
window.open(`${ADMIN_URL}/second-step-register`, "_self");
|
||||||
}
|
}
|
||||||
|
|
||||||
function showInvite() {
|
function showInvite() {
|
||||||
showShareLinkMapModalStore.set(true);
|
showShareLinkMapModalStore.set(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function noDrag() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:window />
|
<svelte:window />
|
||||||
|
|
||||||
<main class="menuIcon">
|
<main class="menuIcon noselect">
|
||||||
{#if $limitMapStore}
|
{#if $limitMapStore}
|
||||||
<img
|
<img
|
||||||
src={logoInvite}
|
src={logoInvite}
|
||||||
alt={$LL.menu.icon.open.invite()}
|
alt={$LL.menu.icon.open.invite()}
|
||||||
class="nes-pointer"
|
class="nes-pointer"
|
||||||
|
draggable="false"
|
||||||
|
on:dragstart|preventDefault={noDrag}
|
||||||
on:click|preventDefault={showInvite}
|
on:click|preventDefault={showInvite}
|
||||||
/>
|
/>
|
||||||
<img
|
<img
|
||||||
src={logoRegister}
|
src={logoRegister}
|
||||||
alt={$LL.menu.icon.open.register()}
|
alt={$LL.menu.icon.open.register()}
|
||||||
class="nes-pointer"
|
class="nes-pointer"
|
||||||
|
draggable="false"
|
||||||
|
on:dragstart|preventDefault={noDrag}
|
||||||
on:click|preventDefault={register}
|
on:click|preventDefault={register}
|
||||||
/>
|
/>
|
||||||
{:else}
|
{:else}
|
||||||
<img src={logoWA} alt={$LL.menu.icon.open.menu()} class="nes-pointer" on:click|preventDefault={showMenu} />
|
<img
|
||||||
<img src={logoTalk} alt={$LL.menu.icon.open.chat()} class="nes-pointer" on:click|preventDefault={showChat} />
|
src={logoWA}
|
||||||
|
alt={$LL.menu.icon.open.menu()}
|
||||||
|
class="nes-pointer"
|
||||||
|
draggable="false"
|
||||||
|
on:dragstart|preventDefault={noDrag}
|
||||||
|
on:click|preventDefault={showMenu}
|
||||||
|
/>
|
||||||
|
<img
|
||||||
|
src={logoTalk}
|
||||||
|
alt={$LL.menu.icon.open.chat()}
|
||||||
|
class="nes-pointer"
|
||||||
|
draggable="false"
|
||||||
|
on:dragstart|preventDefault={noDrag}
|
||||||
|
on:click|preventDefault={showChat}
|
||||||
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
@import "../../../style/breakpoints.scss";
|
||||||
.menuIcon {
|
.menuIcon {
|
||||||
display: inline-grid;
|
display: flex;
|
||||||
z-index: 90;
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 20%;
|
||||||
|
z-index: 800;
|
||||||
position: relative;
|
position: relative;
|
||||||
margin: 25px;
|
|
||||||
img {
|
img {
|
||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
width: 60px;
|
width: 60px;
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
margin: 3px;
|
margin: 5%;
|
||||||
image-rendering: pixelated;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.menuIcon img:hover {
|
.menuIcon img:hover {
|
||||||
transform: scale(1.2);
|
transform: scale(1.2);
|
||||||
}
|
}
|
||||||
@media only screen and (max-width: 800px), only screen and (max-height: 800px) {
|
@include media-breakpoint-up(sm) {
|
||||||
.menuIcon {
|
.menuIcon {
|
||||||
display: inline-grid;
|
margin-top: 10%;
|
||||||
z-index: 90;
|
|
||||||
position: relative;
|
|
||||||
margin: 25px;
|
|
||||||
img {
|
img {
|
||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
width: 60px;
|
width: 60px;
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
margin: 3px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.menuIcon img:hover {
|
.menuIcon img:hover {
|
||||||
transform: scale(1.2);
|
transform: scale(1.2);
|
||||||
}
|
}
|
||||||
@media only screen and (max-width: 800px), only screen and (max-height: 800px) {
|
}
|
||||||
.menuIcon {
|
|
||||||
margin: 3px;
|
@include media-breakpoint-up(md) {
|
||||||
img {
|
.menuIcon {
|
||||||
width: 50px;
|
img {
|
||||||
}
|
width: 50px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,6 +102,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
@import "../../../style/breakpoints.scss";
|
||||||
|
|
||||||
div.customize-main {
|
div.customize-main {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
@ -161,7 +163,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: 800px) {
|
@include media-breakpoint-up(md) {
|
||||||
div.customize-main.content section button {
|
div.customize-main.content section button {
|
||||||
width: 130px;
|
width: 130px;
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,11 @@
|
|||||||
import { localUserStore } from "../../Connexion/LocalUserStore";
|
import { localUserStore } from "../../Connexion/LocalUserStore";
|
||||||
import { videoConstraintStore } from "../../Stores/MediaStore";
|
import { videoConstraintStore } from "../../Stores/MediaStore";
|
||||||
import { HtmlUtils } from "../../WebRtc/HtmlUtils";
|
import { HtmlUtils } from "../../WebRtc/HtmlUtils";
|
||||||
import { isMobile } from "../../Enum/EnvironmentVariable";
|
|
||||||
import { menuVisiblilityStore } from "../../Stores/MenuStore";
|
import { menuVisiblilityStore } from "../../Stores/MenuStore";
|
||||||
import LL, { locale } from "../../i18n/i18n-svelte";
|
import LL, { locale } from "../../i18n/i18n-svelte";
|
||||||
import type { Locales } from "../../i18n/i18n-types";
|
import type { Locales } from "../../i18n/i18n-types";
|
||||||
import { displayableLocales, setCurrentLocale } from "../../i18n/locales";
|
import { displayableLocales, setCurrentLocale } from "../../i18n/locales";
|
||||||
|
import { isMediaBreakpointUp } from "../../Utils/BreakpointsUtils";
|
||||||
|
|
||||||
let fullscreen: boolean = localUserStore.getFullscreen();
|
let fullscreen: boolean = localUserStore.getFullscreen();
|
||||||
let notification: boolean = localUserStore.getNotification() === "granted";
|
let notification: boolean = localUserStore.getNotification() === "granted";
|
||||||
@ -85,6 +85,8 @@
|
|||||||
function closeMenu() {
|
function closeMenu() {
|
||||||
menuVisiblilityStore.set(false);
|
menuVisiblilityStore.set(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isMobile = isMediaBreakpointUp("md");
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="settings-main" on:submit|preventDefault={saveSetting}>
|
<div class="settings-main" on:submit|preventDefault={saveSetting}>
|
||||||
@ -93,22 +95,22 @@
|
|||||||
<div class="nes-select is-dark">
|
<div class="nes-select is-dark">
|
||||||
<select bind:value={valueGame}>
|
<select bind:value={valueGame}>
|
||||||
<option value={120}
|
<option value={120}
|
||||||
>{isMobile()
|
>{isMobile
|
||||||
? $LL.menu.settings.gameQuality.short.high()
|
? $LL.menu.settings.gameQuality.short.high()
|
||||||
: $LL.menu.settings.gameQuality.long.high()}</option
|
: $LL.menu.settings.gameQuality.long.high()}</option
|
||||||
>
|
>
|
||||||
<option value={60}
|
<option value={60}
|
||||||
>{isMobile()
|
>{isMobile
|
||||||
? $LL.menu.settings.gameQuality.short.medium()
|
? $LL.menu.settings.gameQuality.short.medium()
|
||||||
: $LL.menu.settings.gameQuality.long.medium()}</option
|
: $LL.menu.settings.gameQuality.long.medium()}</option
|
||||||
>
|
>
|
||||||
<option value={40}
|
<option value={40}
|
||||||
>{isMobile()
|
>{isMobile
|
||||||
? $LL.menu.settings.gameQuality.short.small()
|
? $LL.menu.settings.gameQuality.short.small()
|
||||||
: $LL.menu.settings.gameQuality.long.small()}</option
|
: $LL.menu.settings.gameQuality.long.small()}</option
|
||||||
>
|
>
|
||||||
<option value={20}
|
<option value={20}
|
||||||
>{isMobile()
|
>{isMobile
|
||||||
? $LL.menu.settings.gameQuality.short.minimum()
|
? $LL.menu.settings.gameQuality.short.minimum()
|
||||||
: $LL.menu.settings.gameQuality.long.minimum()}</option
|
: $LL.menu.settings.gameQuality.long.minimum()}</option
|
||||||
>
|
>
|
||||||
@ -120,22 +122,22 @@
|
|||||||
<div class="nes-select is-dark">
|
<div class="nes-select is-dark">
|
||||||
<select bind:value={valueVideo}>
|
<select bind:value={valueVideo}>
|
||||||
<option value={30}
|
<option value={30}
|
||||||
>{isMobile()
|
>{isMobile
|
||||||
? $LL.menu.settings.videoQuality.short.high()
|
? $LL.menu.settings.videoQuality.short.high()
|
||||||
: $LL.menu.settings.videoQuality.long.high()}</option
|
: $LL.menu.settings.videoQuality.long.high()}</option
|
||||||
>
|
>
|
||||||
<option value={20}
|
<option value={20}
|
||||||
>{isMobile()
|
>{isMobile
|
||||||
? $LL.menu.settings.videoQuality.short.medium()
|
? $LL.menu.settings.videoQuality.short.medium()
|
||||||
: $LL.menu.settings.videoQuality.long.medium()}</option
|
: $LL.menu.settings.videoQuality.long.medium()}</option
|
||||||
>
|
>
|
||||||
<option value={10}
|
<option value={10}
|
||||||
>{isMobile()
|
>{isMobile
|
||||||
? $LL.menu.settings.videoQuality.short.small()
|
? $LL.menu.settings.videoQuality.short.small()
|
||||||
: $LL.menu.settings.videoQuality.long.small()}</option
|
: $LL.menu.settings.videoQuality.long.small()}</option
|
||||||
>
|
>
|
||||||
<option value={5}
|
<option value={5}
|
||||||
>{isMobile()
|
>{isMobile
|
||||||
? $LL.menu.settings.videoQuality.short.minimum()
|
? $LL.menu.settings.videoQuality.short.minimum()
|
||||||
: $LL.menu.settings.videoQuality.long.minimum()}</option
|
: $LL.menu.settings.videoQuality.long.minimum()}</option
|
||||||
>
|
>
|
||||||
@ -199,6 +201,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
@import "../../../style/breakpoints.scss";
|
||||||
|
|
||||||
div.settings-main {
|
div.settings-main {
|
||||||
height: calc(100% - 40px);
|
height: calc(100% - 40px);
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
@ -236,7 +240,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: 800px), only screen and (max-height: 800px) {
|
@include media-breakpoint-up(md) {
|
||||||
div.settings-main {
|
div.settings-main {
|
||||||
section {
|
section {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
import { obtainedMediaConstraintStore } from "../Stores/MediaStore";
|
import { obtainedMediaConstraintStore } from "../Stores/MediaStore";
|
||||||
import { localStreamStore, isSilentStore } from "../Stores/MediaStore";
|
import { localStreamStore, isSilentStore } from "../Stores/MediaStore";
|
||||||
import SoundMeterWidget from "./SoundMeterWidget.svelte";
|
import SoundMeterWidget from "./SoundMeterWidget.svelte";
|
||||||
import { onDestroy } from "svelte";
|
import { onDestroy, onMount } from "svelte";
|
||||||
import { srcObject } from "./Video/utils";
|
import { srcObject } from "./Video/utils";
|
||||||
import LL from "../i18n/i18n-svelte";
|
import LL from "../i18n/i18n-svelte";
|
||||||
|
|
||||||
@ -23,15 +23,77 @@
|
|||||||
isSilent = value;
|
isSilent = value;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let cameraContainer: HTMLDivElement;
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
cameraContainer.addEventListener("transitionend", () => {
|
||||||
|
if (cameraContainer.classList.contains("hide")) {
|
||||||
|
cameraContainer.style.visibility = "hidden";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
cameraContainer.addEventListener("transitionstart", () => {
|
||||||
|
if (!cameraContainer.classList.contains("hide")) {
|
||||||
|
cameraContainer.style.visibility = "visible";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
onDestroy(unsubscribeIsSilent);
|
onDestroy(unsubscribeIsSilent);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div>
|
<div
|
||||||
<div class="video-container div-myCamVideo" class:hide={!$obtainedMediaConstraintStore.video || isSilent}>
|
class="nes-container is-rounded my-cam-video-container"
|
||||||
{#if $localStreamStore.type === "success" && $localStreamStore.stream}
|
class:hide={($localStreamStore.type !== "success" || !$obtainedMediaConstraintStore.video) && !isSilent}
|
||||||
<video class="myCamVideo" use:srcObject={stream} autoplay muted playsinline />
|
bind:this={cameraContainer}
|
||||||
<SoundMeterWidget {stream} />
|
>
|
||||||
{/if}
|
{#if isSilent}
|
||||||
</div>
|
<div class="is-silent">{$LL.camera.my.silentZone()}</div>
|
||||||
<div class="is-silent" class:hide={isSilent}>{$LL.camera.my.silentZone()}</div>
|
{:else if $localStreamStore.type === "success" && $localStreamStore.stream}
|
||||||
|
<video class="my-cam-video" use:srcObject={stream} autoplay muted playsinline />
|
||||||
|
<SoundMeterWidget {stream} />
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@import "../../style/breakpoints.scss";
|
||||||
|
|
||||||
|
.my-cam-video-container {
|
||||||
|
position: absolute;
|
||||||
|
right: 15px;
|
||||||
|
bottom: 30px;
|
||||||
|
max-height: 20%;
|
||||||
|
transition: transform 1000ms;
|
||||||
|
padding: 0;
|
||||||
|
background-color: #00000099;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-cam-video-container.hide {
|
||||||
|
transform: translateX(200%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-cam-video {
|
||||||
|
background-color: #00000099;
|
||||||
|
max-height: 20vh;
|
||||||
|
width: 100%;
|
||||||
|
-webkit-transform: scaleX(-1);
|
||||||
|
transform: scaleX(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-silent {
|
||||||
|
font-size: 2em;
|
||||||
|
color: white;
|
||||||
|
padding: 40px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-up(md) {
|
||||||
|
.my-cam-video {
|
||||||
|
width: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-cam-video-container.hide {
|
||||||
|
right: -160px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
@ -108,12 +108,16 @@
|
|||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
background-color: #333333;
|
background-color: #333333;
|
||||||
color: whitesmoke;
|
color: whitesmoke;
|
||||||
|
z-index: 300;
|
||||||
position: relative;
|
position: absolute;
|
||||||
height: 70vh;
|
height: 70vh;
|
||||||
width: 50vw;
|
width: 50vw;
|
||||||
top: 10vh;
|
top: 4%;
|
||||||
margin: auto;
|
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
|
||||||
section.report-menu-title {
|
section.report-menu-title {
|
||||||
display: grid;
|
display: grid;
|
||||||
@ -137,13 +141,4 @@
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: 800px) {
|
|
||||||
div.report-menu-main {
|
|
||||||
top: 21vh;
|
|
||||||
height: 60vh;
|
|
||||||
width: 100vw;
|
|
||||||
font-size: 0.5em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
@ -47,6 +47,8 @@
|
|||||||
</form>
|
</form>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
@import "../../../style/breakpoints.scss";
|
||||||
|
|
||||||
form.selectCompanionScene {
|
form.selectCompanionScene {
|
||||||
font-family: "Press Start 2P";
|
font-family: "Press Start 2P";
|
||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
@ -85,7 +87,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: 800px) {
|
@include media-breakpoint-up(md) {
|
||||||
form.selectCompanionScene button.selectCharacterButtonLeft {
|
form.selectCompanionScene button.selectCharacterButtonLeft {
|
||||||
left: 5vw;
|
left: 5vw;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { fly, fade } from "svelte/transition";
|
import { fly, fade } from "svelte/transition";
|
||||||
import { onMount } from "svelte";
|
import { onMount } from "svelte";
|
||||||
|
import { gameManager } from "../../Phaser/Game/GameManager";
|
||||||
import type { Message } from "../../Stores/TypeMessageStore/MessageStore";
|
import type { Message } from "../../Stores/TypeMessageStore/MessageStore";
|
||||||
import { banMessageStore } from "../../Stores/TypeMessageStore/BanMessageStore";
|
import { banMessageStore } from "../../Stores/TypeMessageStore/BanMessageStore";
|
||||||
import LL from "../../i18n/i18n-svelte";
|
import LL from "../../i18n/i18n-svelte";
|
||||||
@ -13,6 +14,8 @@
|
|||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
timeToRead();
|
timeToRead();
|
||||||
|
const gameScene = gameManager.getCurrentGameScene();
|
||||||
|
gameScene.playSound("audio-report-message");
|
||||||
});
|
});
|
||||||
|
|
||||||
function timeToRead() {
|
function timeToRead() {
|
||||||
@ -53,18 +56,19 @@
|
|||||||
on:click|preventDefault={closeBanMessage}>{nameButton}</button
|
on:click|preventDefault={closeBanMessage}>{nameButton}</button
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<!-- svelte-ignore a11y-media-has-caption -->
|
|
||||||
<audio id="report-message" autoplay>
|
|
||||||
<source src="/resources/objects/report-message.mp3" type="audio/mp3" />
|
|
||||||
</audio>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
div.main-ban-message {
|
div.main-ban-message {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
position: relative;
|
position: absolute;
|
||||||
top: 15vh;
|
top: 4%;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
z-index: 850;
|
||||||
|
|
||||||
height: 70vh;
|
height: 70vh;
|
||||||
width: 60vw;
|
width: 60vw;
|
||||||
|
@ -42,14 +42,17 @@
|
|||||||
div.main-text-message {
|
div.main-text-message {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
position: absolute;
|
||||||
|
|
||||||
max-height: 25vh;
|
max-height: 25%;
|
||||||
width: 80vw;
|
width: 60%;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-bottom: 16px;
|
top: 6%;
|
||||||
margin-top: 0;
|
left: 0;
|
||||||
|
right: 0;
|
||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
|
z-index: 240;
|
||||||
|
|
||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
background-color: #333333;
|
background-color: #333333;
|
||||||
|
@ -25,11 +25,17 @@
|
|||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
div.error-div {
|
div.error-div {
|
||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
margin-top: 10vh;
|
margin-top: 4%;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
position: absolute;
|
||||||
width: max-content;
|
width: max-content;
|
||||||
max-width: 80vw;
|
max-width: 80vw;
|
||||||
|
z-index: 230;
|
||||||
|
height: auto !important;
|
||||||
|
background-clip: padding-box;
|
||||||
|
|
||||||
.button-bar {
|
.button-bar {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
@ -1,15 +1,33 @@
|
|||||||
<script lang="typescript">
|
<script lang="typescript">
|
||||||
|
import { highlightedEmbedScreen } from "../../Stores/EmbedScreensStore";
|
||||||
|
import type { EmbedScreen } from "../../Stores/EmbedScreensStore";
|
||||||
import type { ScreenSharingLocalMedia } from "../../Stores/ScreenSharingStore";
|
import type { ScreenSharingLocalMedia } from "../../Stores/ScreenSharingStore";
|
||||||
import { videoFocusStore } from "../../Stores/VideoFocusStore";
|
import type { Streamable } from "../../Stores/StreamableCollectionStore";
|
||||||
import { srcObject } from "./utils";
|
import { srcObject } from "./utils";
|
||||||
|
|
||||||
|
export let clickable = false;
|
||||||
|
|
||||||
export let peer: ScreenSharingLocalMedia;
|
export let peer: ScreenSharingLocalMedia;
|
||||||
let stream = peer.stream;
|
let stream = peer.stream;
|
||||||
export let cssClass: string | undefined;
|
export let cssClass: string | undefined;
|
||||||
|
let embedScreen: EmbedScreen;
|
||||||
|
|
||||||
|
if (stream) {
|
||||||
|
embedScreen = {
|
||||||
|
type: "streamable",
|
||||||
|
embed: stream as unknown as Streamable,
|
||||||
|
};
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="video-container {cssClass ? cssClass : ''}" class:hide={!stream}>
|
<div class="video-container {cssClass ? cssClass : ''}" class:hide={!stream}>
|
||||||
{#if stream}
|
{#if stream}
|
||||||
<video use:srcObject={stream} autoplay muted playsinline on:click={() => videoFocusStore.toggleFocus(peer)} />
|
<video
|
||||||
|
use:srcObject={stream}
|
||||||
|
autoplay
|
||||||
|
muted
|
||||||
|
playsinline
|
||||||
|
on:click={() => (clickable ? highlightedEmbedScreen.toggleHighlight(embedScreen) : null)}
|
||||||
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
@ -7,14 +7,65 @@
|
|||||||
import type { Streamable } from "../../Stores/StreamableCollectionStore";
|
import type { Streamable } from "../../Stores/StreamableCollectionStore";
|
||||||
|
|
||||||
export let streamable: Streamable;
|
export let streamable: Streamable;
|
||||||
|
export let isHightlighted = false;
|
||||||
|
export let clickable = false;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="media-container">
|
<div class="media-container nes-container is-rounded {isHightlighted ? 'hightlighted' : ''}" class:clickable>
|
||||||
{#if streamable instanceof VideoPeer}
|
{#if streamable instanceof VideoPeer}
|
||||||
<VideoMediaBox peer={streamable} />
|
<VideoMediaBox peer={streamable} {clickable} />
|
||||||
{:else if streamable instanceof ScreenSharingPeer}
|
{:else if streamable instanceof ScreenSharingPeer}
|
||||||
<ScreenSharingMediaBox peer={streamable} />
|
<ScreenSharingMediaBox peer={streamable} {clickable} />
|
||||||
{:else}
|
{:else}
|
||||||
<LocalStreamMediaBox peer={streamable} cssClass="" />
|
<LocalStreamMediaBox peer={streamable} {clickable} cssClass="" />
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@import "../../../style/breakpoints.scss";
|
||||||
|
|
||||||
|
.media-container {
|
||||||
|
display: flex;
|
||||||
|
margin-top: 4%;
|
||||||
|
margin-bottom: 4%;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
transition: margin-left 0.2s, margin-right 0.2s, margin-bottom 0.2s, margin-top 0.2s, max-height 0.2s,
|
||||||
|
max-width 0.2s;
|
||||||
|
pointer-events: auto;
|
||||||
|
background-color: rgba(0, 0, 0, 0.6);
|
||||||
|
padding: 0;
|
||||||
|
max-height: 85%;
|
||||||
|
max-width: 85%;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
margin-top: 2%;
|
||||||
|
margin-bottom: 2%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.hightlighted {
|
||||||
|
margin-top: 0% !important;
|
||||||
|
margin-bottom: 0% !important;
|
||||||
|
margin-left: 0% !important;
|
||||||
|
|
||||||
|
max-height: 100% !important;
|
||||||
|
max-width: 96% !important;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
margin-top: 0% !important;
|
||||||
|
margin-bottom: 0% !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.clickable {
|
||||||
|
cursor: url("../../../style/images/cursor_pointer.png"), pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-only(md) {
|
||||||
|
.media-container {
|
||||||
|
margin-top: 10%;
|
||||||
|
margin-bottom: 10%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
<script lang="ts">
|
|
||||||
import { streamableCollectionStore } from "../../Stores/StreamableCollectionStore";
|
|
||||||
import { videoFocusStore } from "../../Stores/VideoFocusStore";
|
|
||||||
import { afterUpdate } from "svelte";
|
|
||||||
import { biggestAvailableAreaStore } from "../../Stores/BiggestAvailableAreaStore";
|
|
||||||
import MediaBox from "./MediaBox.svelte";
|
|
||||||
|
|
||||||
afterUpdate(() => {
|
|
||||||
biggestAvailableAreaStore.recompute();
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div class="main-section">
|
|
||||||
{#if $videoFocusStore}
|
|
||||||
{#key $videoFocusStore.uniqueId}
|
|
||||||
<MediaBox streamable={$videoFocusStore} />
|
|
||||||
{/key}
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
<aside class="sidebar">
|
|
||||||
{#each [...$streamableCollectionStore.values()] as peer (peer.uniqueId)}
|
|
||||||
{#if peer !== $videoFocusStore}
|
|
||||||
<MediaBox streamable={peer} />
|
|
||||||
{/if}
|
|
||||||
{/each}
|
|
||||||
</aside>
|
|
@ -1,12 +1,26 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { highlightedEmbedScreen } from "../../Stores/EmbedScreensStore";
|
||||||
|
import type { EmbedScreen } from "../../Stores/EmbedScreensStore";
|
||||||
|
import type { Streamable } from "../../Stores/StreamableCollectionStore";
|
||||||
|
|
||||||
import type { ScreenSharingPeer } from "../../WebRtc/ScreenSharingPeer";
|
import type { ScreenSharingPeer } from "../../WebRtc/ScreenSharingPeer";
|
||||||
import { videoFocusStore } from "../../Stores/VideoFocusStore";
|
|
||||||
import { getColorByString, srcObject } from "./utils";
|
import { getColorByString, srcObject } from "./utils";
|
||||||
|
|
||||||
|
export let clickable = false;
|
||||||
|
|
||||||
export let peer: ScreenSharingPeer;
|
export let peer: ScreenSharingPeer;
|
||||||
let streamStore = peer.streamStore;
|
let streamStore = peer.streamStore;
|
||||||
let name = peer.userName;
|
let name = peer.userName;
|
||||||
let statusStore = peer.statusStore;
|
let statusStore = peer.statusStore;
|
||||||
|
|
||||||
|
let embedScreen: EmbedScreen;
|
||||||
|
|
||||||
|
if (peer) {
|
||||||
|
embedScreen = {
|
||||||
|
type: "streamable",
|
||||||
|
embed: peer as unknown as Streamable,
|
||||||
|
};
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="video-container">
|
<div class="video-container">
|
||||||
@ -20,7 +34,12 @@
|
|||||||
<i style="background-color: {getColorByString(name)};">{name}</i>
|
<i style="background-color: {getColorByString(name)};">{name}</i>
|
||||||
{:else}
|
{:else}
|
||||||
<!-- svelte-ignore a11y-media-has-caption -->
|
<!-- svelte-ignore a11y-media-has-caption -->
|
||||||
<video use:srcObject={$streamStore} autoplay playsinline on:click={() => videoFocusStore.toggleFocus(peer)} />
|
<video
|
||||||
|
use:srcObject={$streamStore}
|
||||||
|
autoplay
|
||||||
|
playsinline
|
||||||
|
on:click={() => (clickable ? highlightedEmbedScreen.toggleHighlight(embedScreen) : null)}
|
||||||
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -4,11 +4,17 @@
|
|||||||
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 { videoFocusStore } from "../../Stores/VideoFocusStore";
|
|
||||||
import { showReportScreenStore } from "../../Stores/ShowReportScreenStore";
|
import { showReportScreenStore } from "../../Stores/ShowReportScreenStore";
|
||||||
import { getColorByString, srcObject } from "./utils";
|
import { getColorByString, srcObject } from "./utils";
|
||||||
|
import { highlightedEmbedScreen } from "../../Stores/EmbedScreensStore";
|
||||||
|
import type { EmbedScreen } from "../../Stores/EmbedScreensStore";
|
||||||
|
import type { Streamable } from "../../Stores/StreamableCollectionStore";
|
||||||
|
|
||||||
import Woka from "../Woka/Woka.svelte";
|
import Woka from "../Woka/Woka.svelte";
|
||||||
|
import { onMount } from "svelte";
|
||||||
|
import { isMediaBreakpointOnly } from "../../Utils/BreakpointsUtils";
|
||||||
|
|
||||||
|
export let clickable = false;
|
||||||
|
|
||||||
export let peer: VideoPeer;
|
export let peer: VideoPeer;
|
||||||
let streamStore = peer.streamStore;
|
let streamStore = peer.streamStore;
|
||||||
@ -19,9 +25,32 @@
|
|||||||
function openReport(peer: VideoPeer): void {
|
function openReport(peer: VideoPeer): void {
|
||||||
showReportScreenStore.set({ userId: peer.userId, userName: peer.userName });
|
showReportScreenStore.set({ userId: peer.userId, userName: peer.userName });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let embedScreen: EmbedScreen;
|
||||||
|
let videoContainer: HTMLDivElement;
|
||||||
|
let minimized = isMediaBreakpointOnly("md");
|
||||||
|
|
||||||
|
if (peer) {
|
||||||
|
embedScreen = {
|
||||||
|
type: "streamable",
|
||||||
|
embed: peer as unknown as Streamable,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function noDrag() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const resizeObserver = new ResizeObserver(() => {
|
||||||
|
minimized = isMediaBreakpointOnly("md");
|
||||||
|
});
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
resizeObserver.observe(videoContainer);
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="video-container">
|
<div class="video-container" class:no-clikable={!clickable} bind:this={videoContainer}>
|
||||||
{#if $statusStore === "connecting"}
|
{#if $statusStore === "connecting"}
|
||||||
<div class="connecting-spinner" />
|
<div class="connecting-spinner" />
|
||||||
{/if}
|
{/if}
|
||||||
@ -30,42 +59,60 @@
|
|||||||
{/if}
|
{/if}
|
||||||
<!-- {#if !$constraintStore || $constraintStore.video === false} -->
|
<!-- {#if !$constraintStore || $constraintStore.video === false} -->
|
||||||
<i
|
<i
|
||||||
class="container {!$constraintStore || $constraintStore.video === false ? '' : 'minimized'}"
|
class="container"
|
||||||
|
class:has-video={$constraintStore && $constraintStore.video === true}
|
||||||
|
class:minimized={(!$constraintStore || $constraintStore.video !== true) && minimized}
|
||||||
style="background-color: {getColorByString(name)};"
|
style="background-color: {getColorByString(name)};"
|
||||||
>
|
>
|
||||||
<span>{peer.userName}</span>
|
<span style="noselect">{peer.userName}</span>
|
||||||
<div class="woka-icon"><Woka userId={peer.userId} placeholderSrc={""} /></div>
|
<div class="woka-icon"><Woka userId={peer.userId} placeholderSrc={""} /></div>
|
||||||
</i>
|
</i>
|
||||||
<!-- {/if} -->
|
<!-- {/if} -->
|
||||||
{#if $constraintStore && $constraintStore.audio === false}
|
{#if $constraintStore && $constraintStore.audio === false}
|
||||||
<img src={microphoneCloseImg} class="active" alt="Muted" />
|
<img
|
||||||
|
src={microphoneCloseImg}
|
||||||
|
class="active noselect"
|
||||||
|
draggable="false"
|
||||||
|
on:dragstart|preventDefault={noDrag}
|
||||||
|
alt="Muted"
|
||||||
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
<button class="report" on:click={() => openReport(peer)}>
|
<button class="report" on:click={() => openReport(peer)}>
|
||||||
<img alt="Report this user" src={reportImg} />
|
<img alt="Report this user" draggable="false" on:dragstart|preventDefault={noDrag} src={reportImg} />
|
||||||
<span>Report/Block</span>
|
<span class="noselect">Report/Block</span>
|
||||||
</button>
|
</button>
|
||||||
<!-- svelte-ignore a11y-media-has-caption -->
|
<!-- svelte-ignore a11y-media-has-caption -->
|
||||||
<video use:srcObject={$streamStore} autoplay playsinline on:click={() => videoFocusStore.toggleFocus(peer)} />
|
<video
|
||||||
<img src={blockSignImg} class="block-logo" alt="Block" />
|
use:srcObject={$streamStore}
|
||||||
|
autoplay
|
||||||
|
playsinline
|
||||||
|
on:click={() => (clickable ? highlightedEmbedScreen.toggleHighlight(embedScreen) : null)}
|
||||||
|
/>
|
||||||
|
<img src={blockSignImg} draggable="false" on:dragstart|preventDefault={noDrag} class="block-logo" alt="Block" />
|
||||||
{#if $constraintStore && $constraintStore.audio !== false}
|
{#if $constraintStore && $constraintStore.audio !== false}
|
||||||
<SoundMeterWidget stream={$streamStore} />
|
<SoundMeterWidget stream={$streamStore} />
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style lang="scss">
|
||||||
.container {
|
.container {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding-top: 15px;
|
padding-top: 15px;
|
||||||
}
|
|
||||||
|
|
||||||
.minimized {
|
&.has-video {
|
||||||
left: auto;
|
left: auto;
|
||||||
transform: scale(0.5);
|
transform: scale(0.5);
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.woka-icon {
|
&.minimized {
|
||||||
margin-right: 3px;
|
transform: scale(0.5);
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.woka-icon {
|
||||||
|
margin-right: 3px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { LayoutMode } from "../../WebRtc/LayoutManager";
|
// import {LayoutMode} from "../../WebRtc/LayoutManager";
|
||||||
import { layoutModeStore } from "../../Stores/StreamableCollectionStore";
|
// import {layoutModeStore} from "../../Stores/StreamableCollectionStore";
|
||||||
import PresentationLayout from "./PresentationLayout.svelte";
|
// import PresentationLayout from "./PresentationLayout.svelte";
|
||||||
import ChatLayout from "./ChatLayout.svelte";
|
// import ChatLayout from "./ChatLayout.svelte";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="video-overlay">
|
<div class="video-overlay">
|
||||||
{#if $layoutModeStore === LayoutMode.Presentation}
|
<!-- {#if $layoutModeStore === LayoutMode.Presentation }
|
||||||
<PresentationLayout />
|
<PresentationLayout />
|
||||||
{:else}
|
{:else}
|
||||||
<ChatLayout />
|
<ChatLayout />
|
||||||
{/if}
|
{/if} -->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
@ -57,6 +57,7 @@
|
|||||||
height: 120px;
|
height: 120px;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
animation: spin 2s linear infinite;
|
animation: spin 2s linear infinite;
|
||||||
|
z-index: 102;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes spin {
|
@keyframes spin {
|
||||||
|
@ -27,18 +27,22 @@
|
|||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
main.warningMain {
|
main.warningMain {
|
||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
width: 100vw;
|
width: 80%;
|
||||||
background-color: #f9e81e;
|
background-color: #F9E81E;
|
||||||
color: #14304c;
|
color: #14304C;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 50%;
|
|
||||||
|
top: 4%;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
transform: translate(-50%, 0);
|
transform: translate(-50%, 0);
|
||||||
font-family: Lato;
|
font-family: Lato;
|
||||||
min-width: 300px;
|
min-width: 300px;
|
||||||
opacity: 0.9;
|
opacity: 0.9;
|
||||||
z-index: 2;
|
z-index: 270;
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
}
|
}
|
||||||
|
@ -22,10 +22,21 @@
|
|||||||
src = source ?? placeholderSrc;
|
src = source ?? placeholderSrc;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function noDrag() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
onDestroy(unsubscribe);
|
onDestroy(unsubscribe);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<img {src} alt="" class="nes-pointer" style="--theme-width: {width}; --theme-height: {height}" />
|
<img
|
||||||
|
{src}
|
||||||
|
alt=""
|
||||||
|
class="nes-pointer noselect"
|
||||||
|
style="--theme-width: {width}; --theme-height: {height}"
|
||||||
|
draggable="false"
|
||||||
|
on:dragstart|preventDefault={noDrag}
|
||||||
|
/>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
img {
|
img {
|
||||||
|
@ -49,6 +49,8 @@
|
|||||||
</form>
|
</form>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
@import "../../../style/breakpoints.scss";
|
||||||
|
|
||||||
form.selectCharacterScene {
|
form.selectCharacterScene {
|
||||||
font-family: "Press Start 2P";
|
font-family: "Press Start 2P";
|
||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
@ -91,7 +93,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: 800px) {
|
@include media-breakpoint-up(md) {
|
||||||
form.selectCharacterScene button.selectCharacterButtonLeft {
|
form.selectCharacterScene button.selectCharacterButtonLeft {
|
||||||
left: 5vw;
|
left: 5vw;
|
||||||
}
|
}
|
||||||
|
@ -42,8 +42,6 @@ export const DISABLE_ANONYMOUS: boolean = getEnv("DISABLE_ANONYMOUS") === "true"
|
|||||||
export const OPID_LOGIN_SCREEN_PROVIDER = getEnv("OPID_LOGIN_SCREEN_PROVIDER");
|
export const OPID_LOGIN_SCREEN_PROVIDER = getEnv("OPID_LOGIN_SCREEN_PROVIDER");
|
||||||
const FALLBACK_LOCALE = getEnv("FALLBACK_LOCALE") || undefined;
|
const FALLBACK_LOCALE = getEnv("FALLBACK_LOCALE") || undefined;
|
||||||
|
|
||||||
export const isMobile = (): boolean => window.innerWidth <= 800 || window.innerHeight <= 600;
|
|
||||||
|
|
||||||
export {
|
export {
|
||||||
DEBUG_MODE,
|
DEBUG_MODE,
|
||||||
START_ROOM_URL,
|
START_ROOM_URL,
|
||||||
|
@ -63,8 +63,6 @@ export class SoundMeter {
|
|||||||
//this.slow = 0.95 * that.slow + 0.05 * that.instant;
|
//this.slow = 0.95 * that.slow + 0.05 * that.instant;
|
||||||
//this.clip = clipcount / input.length;
|
//this.clip = clipcount / input.length;
|
||||||
|
|
||||||
//console.log('instant', this.instant, 'clip', this.clip);
|
|
||||||
|
|
||||||
return this.instant;
|
return this.instant;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,6 @@ export enum GameMapProperties {
|
|||||||
OPEN_WEBSITE = "openWebsite",
|
OPEN_WEBSITE = "openWebsite",
|
||||||
OPEN_WEBSITE_ALLOW_API = "openWebsiteAllowApi",
|
OPEN_WEBSITE_ALLOW_API = "openWebsiteAllowApi",
|
||||||
OPEN_WEBSITE_POLICY = "openWebsitePolicy",
|
OPEN_WEBSITE_POLICY = "openWebsitePolicy",
|
||||||
OPEN_WEBSITE_WIDTH = "openWebsiteWidth",
|
|
||||||
OPEN_WEBSITE_POSITION = "openWebsitePosition",
|
OPEN_WEBSITE_POSITION = "openWebsitePosition",
|
||||||
OPEN_WEBSITE_TRIGGER = "openWebsiteTrigger",
|
OPEN_WEBSITE_TRIGGER = "openWebsiteTrigger",
|
||||||
OPEN_WEBSITE_TRIGGER_MESSAGE = "openWebsiteTriggerMessage",
|
OPEN_WEBSITE_TRIGGER_MESSAGE = "openWebsiteTriggerMessage",
|
||||||
|
@ -252,7 +252,7 @@ export class GameScene extends DirtyScene {
|
|||||||
}
|
}
|
||||||
this.load.audio("audio-webrtc-in", "/resources/objects/webrtc-in.mp3");
|
this.load.audio("audio-webrtc-in", "/resources/objects/webrtc-in.mp3");
|
||||||
this.load.audio("audio-webrtc-out", "/resources/objects/webrtc-out.mp3");
|
this.load.audio("audio-webrtc-out", "/resources/objects/webrtc-out.mp3");
|
||||||
//this.load.audio('audio-report-message', '/resources/objects/report-message.mp3');
|
this.load.audio("audio-report-message", "/resources/objects/report-message.mp3");
|
||||||
this.sound.pauseOnBlur = false;
|
this.sound.pauseOnBlur = false;
|
||||||
|
|
||||||
this.load.on(FILE_LOAD_ERROR, (file: { src: string }) => {
|
this.load.on(FILE_LOAD_ERROR, (file: { src: string }) => {
|
||||||
@ -632,13 +632,9 @@ export class GameScene extends DirtyScene {
|
|||||||
this.peerStoreUnsubscribe = peerStore.subscribe((peers) => {
|
this.peerStoreUnsubscribe = peerStore.subscribe((peers) => {
|
||||||
const newPeerNumber = peers.size;
|
const newPeerNumber = peers.size;
|
||||||
if (newPeerNumber > oldPeerNumber) {
|
if (newPeerNumber > oldPeerNumber) {
|
||||||
this.sound.play("audio-webrtc-in", {
|
this.playSound("audio-webrtc-in");
|
||||||
volume: 0.2,
|
|
||||||
});
|
|
||||||
} else if (newPeerNumber < oldPeerNumber) {
|
} else if (newPeerNumber < oldPeerNumber) {
|
||||||
this.sound.play("audio-webrtc-out", {
|
this.playSound("audio-webrtc-out");
|
||||||
volume: 0.2,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
oldPeerNumber = newPeerNumber;
|
oldPeerNumber = newPeerNumber;
|
||||||
});
|
});
|
||||||
@ -1265,21 +1261,21 @@ ${escapedMessage}
|
|||||||
throw new Error("Unknown query source");
|
throw new Error("Unknown query source");
|
||||||
}
|
}
|
||||||
|
|
||||||
const coWebsite = await coWebsiteManager.loadCoWebsite(
|
const coWebsite = coWebsiteManager.addCoWebsite(
|
||||||
openCoWebsite.url,
|
openCoWebsite.url,
|
||||||
iframeListener.getBaseUrlFromSource(source),
|
iframeListener.getBaseUrlFromSource(source),
|
||||||
openCoWebsite.allowApi,
|
openCoWebsite.allowApi,
|
||||||
openCoWebsite.allowPolicy,
|
openCoWebsite.allowPolicy,
|
||||||
openCoWebsite.position
|
openCoWebsite.position,
|
||||||
|
openCoWebsite.closable ?? true
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!coWebsite) {
|
if (openCoWebsite.lazy !== undefined && !openCoWebsite.lazy) {
|
||||||
throw new Error("Error on opening co-website");
|
await coWebsiteManager.loadCoWebsite(coWebsite);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: coWebsite.iframe.id,
|
id: coWebsite.iframe.id,
|
||||||
position: coWebsite.position,
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1289,7 +1285,6 @@ ${escapedMessage}
|
|||||||
return coWebsites.map((coWebsite: CoWebsite) => {
|
return coWebsites.map((coWebsite: CoWebsite) => {
|
||||||
return {
|
return {
|
||||||
id: coWebsite.iframe.id,
|
id: coWebsite.iframe.id,
|
||||||
position: coWebsite.position,
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -1565,6 +1560,12 @@ ${escapedMessage}
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public playSound(sound: string) {
|
||||||
|
this.sound.play(sound, {
|
||||||
|
volume: 0.2,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public cleanupClosingScene(): void {
|
public cleanupClosingScene(): void {
|
||||||
// stop playing audio, close any open website, stop any open Jitsi
|
// stop playing audio, close any open website, stop any open Jitsi
|
||||||
coWebsiteManager.closeCoWebsites().catch((e) => console.error(e));
|
coWebsiteManager.closeCoWebsites().catch((e) => console.error(e));
|
||||||
@ -1602,7 +1603,7 @@ ${escapedMessage}
|
|||||||
this.sharedVariablesManager?.close();
|
this.sharedVariablesManager?.close();
|
||||||
this.embeddedWebsiteManager?.close();
|
this.embeddedWebsiteManager?.close();
|
||||||
|
|
||||||
mediaManager.hideGameOverlay();
|
mediaManager.hideMyCamera();
|
||||||
|
|
||||||
for (const iframeEvents of this.iframeSubscriptionList) {
|
for (const iframeEvents of this.iframeSubscriptionList) {
|
||||||
iframeEvents.unsubscribe();
|
iframeEvents.unsubscribe();
|
||||||
@ -2111,6 +2112,17 @@ ${escapedMessage}
|
|||||||
biggestAvailableAreaStore.recompute();
|
biggestAvailableAreaStore.recompute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enableMediaBehaviors() {
|
||||||
|
const silent = this.gameMap.getCurrentProperties().get(GameMapProperties.SILENT);
|
||||||
|
this.connection?.setSilent(!!silent);
|
||||||
|
mediaManager.showMyCamera();
|
||||||
|
}
|
||||||
|
|
||||||
|
public disableMediaBehaviors() {
|
||||||
|
this.connection?.setSilent(true);
|
||||||
|
mediaManager.hideMyCamera();
|
||||||
|
}
|
||||||
|
|
||||||
public startJitsi(roomName: string, jwt?: string): void {
|
public startJitsi(roomName: string, jwt?: string): void {
|
||||||
const allProps = this.gameMap.getCurrentProperties();
|
const allProps = this.gameMap.getCurrentProperties();
|
||||||
const jitsiConfig = this.safeParseJSONstring(
|
const jitsiConfig = this.safeParseJSONstring(
|
||||||
@ -2122,28 +2134,21 @@ ${escapedMessage}
|
|||||||
GameMapProperties.JITSI_INTERFACE_CONFIG
|
GameMapProperties.JITSI_INTERFACE_CONFIG
|
||||||
);
|
);
|
||||||
const jitsiUrl = allProps.get(GameMapProperties.JITSI_URL) as string | undefined;
|
const jitsiUrl = allProps.get(GameMapProperties.JITSI_URL) as string | undefined;
|
||||||
const jitsiWidth = allProps.get(GameMapProperties.JITSI_WIDTH) as number | undefined;
|
|
||||||
|
|
||||||
jitsiFactory
|
jitsiFactory.start(roomName, this.playerName, jwt, jitsiConfig, jitsiInterfaceConfig, jitsiUrl).catch(() => {
|
||||||
.start(roomName, this.playerName, jwt, jitsiConfig, jitsiInterfaceConfig, jitsiUrl, jitsiWidth)
|
console.error("Cannot start a Jitsi co-website");
|
||||||
.catch((e) => console.error(e));
|
|
||||||
this.connection?.setSilent(true);
|
|
||||||
mediaManager.hideGameOverlay();
|
|
||||||
analyticsClient.enteredJitsi(roomName, this.room.id);
|
|
||||||
|
|
||||||
//permit to stop jitsi when user close iframe
|
|
||||||
mediaManager.addTriggerCloseJitsiFrameButton("close-jitsi", () => {
|
|
||||||
this.stopJitsi();
|
|
||||||
});
|
});
|
||||||
|
this.disableMediaBehaviors();
|
||||||
|
analyticsClient.enteredJitsi(roomName, this.room.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public stopJitsi(): void {
|
public stopJitsi(): void {
|
||||||
const silent = this.gameMap.getCurrentProperties().get(GameMapProperties.SILENT);
|
const coWebsite = coWebsiteManager.searchJitsi();
|
||||||
this.connection?.setSilent(!!silent);
|
if (coWebsite) {
|
||||||
jitsiFactory.stop();
|
coWebsiteManager.closeCoWebsite(coWebsite).catch(() => {
|
||||||
mediaManager.showGameOverlay();
|
console.error("Error during Jitsi co-website closing");
|
||||||
|
});
|
||||||
mediaManager.removeTriggerCloseJitsiFrameButton("close-jitsi");
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//todo: put this into an 'orchestrator' scene (EntryScene?)
|
//todo: put this into an 'orchestrator' scene (EntryScene?)
|
||||||
|
@ -11,10 +11,10 @@ import { areCharacterLayersValid } from "../../Connexion/LocalUser";
|
|||||||
import { SelectCharacterSceneName } from "./SelectCharacterScene";
|
import { SelectCharacterSceneName } from "./SelectCharacterScene";
|
||||||
import { activeRowStore, customCharacterSceneVisibleStore } from "../../Stores/CustomCharacterStore";
|
import { activeRowStore, customCharacterSceneVisibleStore } from "../../Stores/CustomCharacterStore";
|
||||||
import { waScaleManager } from "../Services/WaScaleManager";
|
import { waScaleManager } from "../Services/WaScaleManager";
|
||||||
import { isMobile } from "../../Enum/EnvironmentVariable";
|
|
||||||
import { CustomizedCharacter } from "../Entity/CustomizedCharacter";
|
import { CustomizedCharacter } from "../Entity/CustomizedCharacter";
|
||||||
import { get } from "svelte/store";
|
import { get } from "svelte/store";
|
||||||
import { analyticsClient } from "../../Administration/AnalyticsClient";
|
import { analyticsClient } from "../../Administration/AnalyticsClient";
|
||||||
|
import { isMediaBreakpointUp } from "../../Utils/BreakpointsUtils";
|
||||||
|
|
||||||
export const CustomizeSceneName = "CustomizeScene";
|
export const CustomizeSceneName = "CustomizeScene";
|
||||||
|
|
||||||
@ -67,12 +67,12 @@ export class CustomizeScene extends AbstractCharacterScene {
|
|||||||
customCharacterSceneVisibleStore.set(true);
|
customCharacterSceneVisibleStore.set(true);
|
||||||
this.events.addListener("wake", () => {
|
this.events.addListener("wake", () => {
|
||||||
waScaleManager.saveZoom();
|
waScaleManager.saveZoom();
|
||||||
waScaleManager.zoomModifier = isMobile() ? 3 : 1;
|
waScaleManager.zoomModifier = isMediaBreakpointUp("md") ? 3 : 1;
|
||||||
customCharacterSceneVisibleStore.set(true);
|
customCharacterSceneVisibleStore.set(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
waScaleManager.saveZoom();
|
waScaleManager.saveZoom();
|
||||||
waScaleManager.zoomModifier = isMobile() ? 3 : 1;
|
waScaleManager.zoomModifier = isMediaBreakpointUp("md") ? 3 : 1;
|
||||||
|
|
||||||
this.Rectangle = this.add.rectangle(
|
this.Rectangle = this.add.rectangle(
|
||||||
this.cameras.main.worldView.x + this.cameras.main.width / 2,
|
this.cameras.main.worldView.x + this.cameras.main.width / 2,
|
||||||
|
@ -12,8 +12,8 @@ import { touchScreenManager } from "../../Touch/TouchScreenManager";
|
|||||||
import { PinchManager } from "../UserInput/PinchManager";
|
import { PinchManager } from "../UserInput/PinchManager";
|
||||||
import { selectCharacterSceneVisibleStore } from "../../Stores/SelectCharacterStore";
|
import { selectCharacterSceneVisibleStore } from "../../Stores/SelectCharacterStore";
|
||||||
import { waScaleManager } from "../Services/WaScaleManager";
|
import { waScaleManager } from "../Services/WaScaleManager";
|
||||||
import { isMobile } from "../../Enum/EnvironmentVariable";
|
|
||||||
import { analyticsClient } from "../../Administration/AnalyticsClient";
|
import { analyticsClient } from "../../Administration/AnalyticsClient";
|
||||||
|
import { isMediaBreakpointUp } from "../../Utils/BreakpointsUtils";
|
||||||
|
|
||||||
//todo: put this constants in a dedicated file
|
//todo: put this constants in a dedicated file
|
||||||
export const SelectCharacterSceneName = "SelectCharacterScene";
|
export const SelectCharacterSceneName = "SelectCharacterScene";
|
||||||
@ -60,7 +60,7 @@ export class SelectCharacterScene extends AbstractCharacterScene {
|
|||||||
selectCharacterSceneVisibleStore.set(true);
|
selectCharacterSceneVisibleStore.set(true);
|
||||||
this.events.addListener("wake", () => {
|
this.events.addListener("wake", () => {
|
||||||
waScaleManager.saveZoom();
|
waScaleManager.saveZoom();
|
||||||
waScaleManager.zoomModifier = isMobile() ? 2 : 1;
|
waScaleManager.zoomModifier = isMediaBreakpointUp("md") ? 2 : 1;
|
||||||
selectCharacterSceneVisibleStore.set(true);
|
selectCharacterSceneVisibleStore.set(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -69,7 +69,7 @@ export class SelectCharacterScene extends AbstractCharacterScene {
|
|||||||
}
|
}
|
||||||
|
|
||||||
waScaleManager.saveZoom();
|
waScaleManager.saveZoom();
|
||||||
waScaleManager.zoomModifier = isMobile() ? 2 : 1;
|
waScaleManager.zoomModifier = isMediaBreakpointUp("md") ? 2 : 1;
|
||||||
|
|
||||||
const rectangleXStart = this.game.renderer.width / 2 - (this.nbCharactersPerRow / 2) * 32 + 16;
|
const rectangleXStart = this.game.renderer.width / 2 - (this.nbCharactersPerRow / 2) * 32 + 16;
|
||||||
this.selectedRectangle = this.add.rectangle(rectangleXStart, 90, 32, 32).setStrokeStyle(2, 0xffffff);
|
this.selectedRectangle = this.add.rectangle(rectangleXStart, 90, 32, 32).setStrokeStyle(2, 0xffffff);
|
||||||
|
@ -9,7 +9,7 @@ import { touchScreenManager } from "../../Touch/TouchScreenManager";
|
|||||||
import { PinchManager } from "../UserInput/PinchManager";
|
import { PinchManager } from "../UserInput/PinchManager";
|
||||||
import { selectCompanionSceneVisibleStore } from "../../Stores/SelectCompanionStore";
|
import { selectCompanionSceneVisibleStore } from "../../Stores/SelectCompanionStore";
|
||||||
import { waScaleManager } from "../Services/WaScaleManager";
|
import { waScaleManager } from "../Services/WaScaleManager";
|
||||||
import { isMobile } from "../../Enum/EnvironmentVariable";
|
import { isMediaBreakpointUp } from "../../Utils/BreakpointsUtils";
|
||||||
|
|
||||||
export const SelectCompanionSceneName = "SelectCompanionScene";
|
export const SelectCompanionSceneName = "SelectCompanionScene";
|
||||||
|
|
||||||
@ -44,7 +44,7 @@ export class SelectCompanionScene extends ResizableScene {
|
|||||||
selectCompanionSceneVisibleStore.set(true);
|
selectCompanionSceneVisibleStore.set(true);
|
||||||
|
|
||||||
waScaleManager.saveZoom();
|
waScaleManager.saveZoom();
|
||||||
waScaleManager.zoomModifier = isMobile() ? 2 : 1;
|
waScaleManager.zoomModifier = isMediaBreakpointUp("md") ? 2 : 1;
|
||||||
|
|
||||||
if (touchScreenManager.supportTouchScreen) {
|
if (touchScreenManager.supportTouchScreen) {
|
||||||
new PinchManager(this);
|
new PinchManager(this);
|
||||||
|
@ -37,19 +37,17 @@ export class WaScaleManager {
|
|||||||
height: height * devicePixelRatio,
|
height: height * devicePixelRatio,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (gameSize.width == 0) {
|
if (realSize.width !== 0 && gameSize.width !== 0 && devicePixelRatio !== 0) {
|
||||||
return;
|
this.actualZoom = realSize.width / gameSize.width / devicePixelRatio;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.actualZoom = realSize.width / gameSize.width / devicePixelRatio;
|
this.scaleManager.setZoom(this.actualZoom);
|
||||||
|
|
||||||
this.scaleManager.setZoom(realSize.width / gameSize.width / devicePixelRatio);
|
|
||||||
this.scaleManager.resize(gameSize.width, gameSize.height);
|
this.scaleManager.resize(gameSize.width, gameSize.height);
|
||||||
|
|
||||||
// Override bug in canvas resizing in Phaser. Let's resize the canvas ourselves
|
// Override bug in canvas resizing in Phaser. Let's resize the canvas ourselves
|
||||||
const style = this.scaleManager.canvas.style;
|
const style = this.scaleManager.canvas.style;
|
||||||
style.width = Math.ceil(realSize.width / devicePixelRatio) + "px";
|
style.width = Math.ceil(realSize.width !== 0 ? realSize.width / devicePixelRatio : 0) + "px";
|
||||||
style.height = Math.ceil(realSize.height / devicePixelRatio) + "px";
|
style.height = Math.ceil(realSize.height !== 0 ? realSize.height / devicePixelRatio : 0) + "px";
|
||||||
|
|
||||||
// Resize the game element at the same size at the canvas
|
// Resize the game element at the same size at the canvas
|
||||||
const gameStyle = HtmlUtils.getElementByIdOrFail<HTMLDivElement>("game").style;
|
const gameStyle = HtmlUtils.getElementByIdOrFail<HTMLDivElement>("game").style;
|
||||||
|
@ -2,14 +2,14 @@ import { get, writable } from "svelte/store";
|
|||||||
import type { Box } from "../WebRtc/LayoutManager";
|
import type { Box } from "../WebRtc/LayoutManager";
|
||||||
import { HtmlUtils } from "../WebRtc/HtmlUtils";
|
import { HtmlUtils } from "../WebRtc/HtmlUtils";
|
||||||
import { LayoutMode } from "../WebRtc/LayoutManager";
|
import { LayoutMode } from "../WebRtc/LayoutManager";
|
||||||
import { layoutModeStore } from "./StreamableCollectionStore";
|
import { embedScreenLayout } from "./EmbedScreensStore";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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)
|
||||||
*/
|
*/
|
||||||
function findBiggestAvailableArea(): Box {
|
function findBiggestAvailableArea(): Box {
|
||||||
const game = HtmlUtils.querySelectorOrFail<HTMLCanvasElement>("#game canvas");
|
const game = HtmlUtils.querySelectorOrFail<HTMLCanvasElement>("#game canvas");
|
||||||
if (get(layoutModeStore) === LayoutMode.VideoChat) {
|
if (get(embedScreenLayout) === LayoutMode.VideoChat) {
|
||||||
const children = document.querySelectorAll<HTMLDivElement>("div.chat-mode > div");
|
const children = document.querySelectorAll<HTMLDivElement>("div.chat-mode > div");
|
||||||
const htmlChildren = Array.from(children.values());
|
const htmlChildren = Array.from(children.values());
|
||||||
|
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
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();
|
|
@ -51,6 +51,6 @@ function createLayoutManagerAction() {
|
|||||||
|
|
||||||
export const layoutManagerActionStore = createLayoutManagerAction();
|
export const layoutManagerActionStore = createLayoutManagerAction();
|
||||||
|
|
||||||
export const layoutManagerVisibilityStore = derived(layoutManagerActionStore, ($layoutManagerActionStore) => {
|
export const layoutManagerActionVisibilityStore = derived(layoutManagerActionStore, ($layoutManagerActionStore) => {
|
||||||
return !!$layoutManagerActionStore.length;
|
return !!$layoutManagerActionStore.length;
|
||||||
});
|
});
|
||||||
|
@ -6,7 +6,7 @@ import { BrowserTooOldError } from "./Errors/BrowserTooOldError";
|
|||||||
import { errorStore } from "./ErrorStore";
|
import { errorStore } from "./ErrorStore";
|
||||||
import { getNavigatorType, isIOS, NavigatorType } from "../WebRtc/DeviceUtils";
|
import { getNavigatorType, isIOS, NavigatorType } from "../WebRtc/DeviceUtils";
|
||||||
import { WebviewOnOldIOS } from "./Errors/WebviewOnOldIOS";
|
import { WebviewOnOldIOS } from "./Errors/WebviewOnOldIOS";
|
||||||
import { gameOverlayVisibilityStore } from "./GameOverlayStoreVisibility";
|
import { myCameraVisibilityStore } from "./MyCameraStoreVisibility";
|
||||||
import { peerStore } from "./PeerStore";
|
import { peerStore } from "./PeerStore";
|
||||||
import { privacyShutdownStore } from "./PrivacyShutdownStore";
|
import { privacyShutdownStore } from "./PrivacyShutdownStore";
|
||||||
import { MediaStreamConstraintsError } from "./Errors/MediaStreamConstraintsError";
|
import { MediaStreamConstraintsError } from "./Errors/MediaStreamConstraintsError";
|
||||||
@ -233,7 +233,7 @@ export const mediaStreamConstraintsStore = derived(
|
|||||||
[
|
[
|
||||||
requestedCameraState,
|
requestedCameraState,
|
||||||
requestedMicrophoneState,
|
requestedMicrophoneState,
|
||||||
gameOverlayVisibilityStore,
|
myCameraVisibilityStore,
|
||||||
enableCameraSceneVisibilityStore,
|
enableCameraSceneVisibilityStore,
|
||||||
videoConstraintStore,
|
videoConstraintStore,
|
||||||
audioConstraintStore,
|
audioConstraintStore,
|
||||||
@ -245,7 +245,7 @@ export const mediaStreamConstraintsStore = derived(
|
|||||||
[
|
[
|
||||||
$requestedCameraState,
|
$requestedCameraState,
|
||||||
$requestedMicrophoneState,
|
$requestedMicrophoneState,
|
||||||
$gameOverlayVisibilityStore,
|
$myCameraVisibilityStore,
|
||||||
$enableCameraSceneVisibilityStore,
|
$enableCameraSceneVisibilityStore,
|
||||||
$videoConstraintStore,
|
$videoConstraintStore,
|
||||||
$audioConstraintStore,
|
$audioConstraintStore,
|
||||||
@ -283,7 +283,7 @@ export const mediaStreamConstraintsStore = derived(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Disable webcam and microphone when in a Jitsi
|
// Disable webcam and microphone when in a Jitsi
|
||||||
if ($gameOverlayVisibilityStore === false) {
|
if ($myCameraVisibilityStore === false) {
|
||||||
currentVideoConstraint = false;
|
currentVideoConstraint = false;
|
||||||
currentAudioConstraint = false;
|
currentAudioConstraint = false;
|
||||||
}
|
}
|
||||||
|
8
front/src/Stores/MyCameraStoreVisibility.ts
Normal file
8
front/src/Stores/MyCameraStoreVisibility.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { writable } from "svelte/store";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A store that contains whether my camera & actions is shown or not.
|
||||||
|
* Typically, the overlay is hidden when entering Jitsi meet.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const myCameraVisibilityStore = writable(false);
|
@ -1,7 +1,7 @@
|
|||||||
import { derived, Readable, readable, writable } from "svelte/store";
|
import { derived, Readable, readable, writable } from "svelte/store";
|
||||||
import { peerStore } from "./PeerStore";
|
import { peerStore } from "./PeerStore";
|
||||||
import type { LocalStreamStoreValue } from "./MediaStore";
|
import type { LocalStreamStoreValue } from "./MediaStore";
|
||||||
import { gameOverlayVisibilityStore } from "./GameOverlayStoreVisibility";
|
import { myCameraVisibilityStore } from "./MyCameraStoreVisibility";
|
||||||
|
|
||||||
declare const navigator: any; // eslint-disable-line @typescript-eslint/no-explicit-any
|
declare const navigator: any; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||||
|
|
||||||
@ -41,8 +41,8 @@ let previousComputedAudioConstraint: boolean | MediaTrackConstraints = false;
|
|||||||
* A store containing the media constraints we want to apply.
|
* A store containing the media constraints we want to apply.
|
||||||
*/
|
*/
|
||||||
export const screenSharingConstraintsStore = derived(
|
export const screenSharingConstraintsStore = derived(
|
||||||
[requestedScreenSharingState, gameOverlayVisibilityStore, peerStore],
|
[requestedScreenSharingState, myCameraVisibilityStore, peerStore],
|
||||||
([$requestedScreenSharingState, $gameOverlayVisibilityStore, $peerStore], set) => {
|
([$requestedScreenSharingState, $myCameraVisibilityStore, $peerStore], set) => {
|
||||||
let currentVideoConstraint: boolean | MediaTrackConstraints = true;
|
let currentVideoConstraint: boolean | MediaTrackConstraints = true;
|
||||||
let currentAudioConstraint: boolean | MediaTrackConstraints = false;
|
let currentAudioConstraint: boolean | MediaTrackConstraints = false;
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ export const screenSharingConstraintsStore = derived(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Disable screen sharing when in a Jitsi
|
// Disable screen sharing when in a Jitsi
|
||||||
if (!$gameOverlayVisibilityStore) {
|
if (!$myCameraVisibilityStore) {
|
||||||
currentVideoConstraint = false;
|
currentVideoConstraint = false;
|
||||||
currentAudioConstraint = false;
|
currentAudioConstraint = false;
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,10 @@
|
|||||||
import { derived, get, Readable, writable } from "svelte/store";
|
import { derived, get, Readable } from "svelte/store";
|
||||||
import { ScreenSharingLocalMedia, screenSharingLocalMedia } from "./ScreenSharingStore";
|
import { ScreenSharingLocalMedia, screenSharingLocalMedia } from "./ScreenSharingStore";
|
||||||
import { peerStore, screenSharingStreamStore } from "./PeerStore";
|
import { peerStore, screenSharingStreamStore } from "./PeerStore";
|
||||||
import type { RemotePeer } from "../WebRtc/SimplePeer";
|
import type { RemotePeer } from "../WebRtc/SimplePeer";
|
||||||
import { LayoutMode } from "../WebRtc/LayoutManager";
|
|
||||||
|
|
||||||
export type Streamable = RemotePeer | ScreenSharingLocalMedia;
|
export type Streamable = RemotePeer | ScreenSharingLocalMedia;
|
||||||
|
|
||||||
export const layoutModeStore = writable<LayoutMode>(LayoutMode.Presentation);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A store that contains everything that can produce a stream (so the peers + the local screen sharing stream)
|
* A store that contains everything that can produce a stream (so the peers + the local screen sharing stream)
|
||||||
*/
|
*/
|
||||||
|
@ -7,6 +7,11 @@ export class HtmlUtils {
|
|||||||
throw new Error("Cannot find HTML element with id '" + id + "'");
|
throw new Error("Cannot find HTML element with id '" + id + "'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static getElementById<T extends HTMLElement>(id: string): T | undefined {
|
||||||
|
const elem = document.getElementById(id);
|
||||||
|
return HtmlUtils.isHtmlElement<T>(elem) ? elem : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
public static querySelectorOrFail<T extends HTMLElement>(selector: string): T {
|
public static querySelectorOrFail<T extends HTMLElement>(selector: string): T {
|
||||||
const elem = document.querySelector<T>(selector);
|
const elem = document.querySelector<T>(selector);
|
||||||
if (HtmlUtils.isHtmlElement<T>(elem)) {
|
if (HtmlUtils.isHtmlElement<T>(elem)) {
|
||||||
|
@ -7,8 +7,7 @@ import { helpCameraSettingsVisibleStore } from "../Stores/HelpCameraSettingsStor
|
|||||||
export type StartScreenSharingCallback = (media: MediaStream) => void;
|
export type StartScreenSharingCallback = (media: MediaStream) => void;
|
||||||
export type StopScreenSharingCallback = (media: MediaStream) => void;
|
export type StopScreenSharingCallback = (media: MediaStream) => void;
|
||||||
|
|
||||||
import { cowebsiteCloseButtonId } from "./CoWebsiteManager";
|
import { myCameraVisibilityStore } from "../Stores/MyCameraStoreVisibility";
|
||||||
import { gameOverlayVisibilityStore } from "../Stores/GameOverlayStoreVisibility";
|
|
||||||
import { layoutManagerActionStore } from "../Stores/LayoutManagerStore";
|
import { layoutManagerActionStore } from "../Stores/LayoutManagerStore";
|
||||||
import { MediaStreamConstraintsError } from "../Stores/Errors/MediaStreamConstraintsError";
|
import { MediaStreamConstraintsError } from "../Stores/Errors/MediaStreamConstraintsError";
|
||||||
import { localUserStore } from "../Connexion/LocalUserStore";
|
import { localUserStore } from "../Connexion/LocalUserStore";
|
||||||
@ -20,8 +19,6 @@ export class MediaManager {
|
|||||||
startScreenSharingCallBacks: Set<StartScreenSharingCallback> = new Set<StartScreenSharingCallback>();
|
startScreenSharingCallBacks: Set<StartScreenSharingCallback> = new Set<StartScreenSharingCallback>();
|
||||||
stopScreenSharingCallBacks: Set<StopScreenSharingCallback> = new Set<StopScreenSharingCallback>();
|
stopScreenSharingCallBacks: Set<StopScreenSharingCallback> = new Set<StopScreenSharingCallback>();
|
||||||
|
|
||||||
private triggerCloseJistiFrame: Map<String, Function> = new Map<String, Function>();
|
|
||||||
|
|
||||||
private userInputManager?: UserInputManager;
|
private userInputManager?: UserInputManager;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
@ -73,36 +70,12 @@ export class MediaManager {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public showGameOverlay(): void {
|
public showMyCamera(): void {
|
||||||
const gameOverlay = HtmlUtils.getElementByIdOrFail("game-overlay");
|
myCameraVisibilityStore.set(true);
|
||||||
gameOverlay.classList.add("active");
|
|
||||||
|
|
||||||
const buttonCloseFrame = HtmlUtils.getElementByIdOrFail(cowebsiteCloseButtonId);
|
|
||||||
const functionTrigger = () => {
|
|
||||||
this.triggerCloseJitsiFrameButton();
|
|
||||||
};
|
|
||||||
buttonCloseFrame.removeEventListener("click", () => {
|
|
||||||
buttonCloseFrame.blur();
|
|
||||||
functionTrigger();
|
|
||||||
});
|
|
||||||
|
|
||||||
gameOverlayVisibilityStore.showGameOverlay();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public hideGameOverlay(): void {
|
public hideMyCamera(): void {
|
||||||
const gameOverlay = HtmlUtils.getElementByIdOrFail("game-overlay");
|
myCameraVisibilityStore.set(false);
|
||||||
gameOverlay.classList.remove("active");
|
|
||||||
|
|
||||||
const buttonCloseFrame = HtmlUtils.getElementByIdOrFail(cowebsiteCloseButtonId);
|
|
||||||
const functionTrigger = () => {
|
|
||||||
this.triggerCloseJitsiFrameButton();
|
|
||||||
};
|
|
||||||
buttonCloseFrame.addEventListener("click", () => {
|
|
||||||
buttonCloseFrame.blur();
|
|
||||||
functionTrigger();
|
|
||||||
});
|
|
||||||
|
|
||||||
gameOverlayVisibilityStore.hideGameOverlay();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private getScreenSharingId(userId: string): string {
|
private getScreenSharingId(userId: string): string {
|
||||||
@ -179,20 +152,6 @@ export class MediaManager {
|
|||||||
return connectingSpinnerDiv;
|
return connectingSpinnerDiv;
|
||||||
}
|
}
|
||||||
|
|
||||||
public addTriggerCloseJitsiFrameButton(id: String, Function: Function) {
|
|
||||||
this.triggerCloseJistiFrame.set(id, Function);
|
|
||||||
}
|
|
||||||
|
|
||||||
public removeTriggerCloseJitsiFrameButton(id: String) {
|
|
||||||
this.triggerCloseJistiFrame.delete(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
private triggerCloseJitsiFrameButton(): void {
|
|
||||||
for (const callback of this.triggerCloseJistiFrame.values()) {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public setUserInputManager(userInputManager: UserInputManager) {
|
public setUserInputManager(userInputManager: UserInputManager) {
|
||||||
this.userInputManager = userInputManager;
|
this.userInputManager = userInputManager;
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,9 @@ import type { RoomConnection } from "../Connexion/RoomConnection";
|
|||||||
import { MESSAGE_TYPE_CONSTRAINT, PeerStatus } from "./VideoPeer";
|
import { MESSAGE_TYPE_CONSTRAINT, PeerStatus } from "./VideoPeer";
|
||||||
import type { UserSimplePeerInterface } from "./SimplePeer";
|
import type { UserSimplePeerInterface } from "./SimplePeer";
|
||||||
import { Readable, readable } from "svelte/store";
|
import { Readable, readable } from "svelte/store";
|
||||||
import { videoFocusStore } from "../Stores/VideoFocusStore";
|
|
||||||
import { getIceServersConfig } from "../Components/Video/utils";
|
import { getIceServersConfig } from "../Components/Video/utils";
|
||||||
import { isMobile } from "../Enum/EnvironmentVariable";
|
import { highlightedEmbedScreen } from "../Stores/EmbedScreensStore";
|
||||||
|
import { isMediaBreakpointUp } from "../Utils/BreakpointsUtils";
|
||||||
|
|
||||||
const Peer: SimplePeerNamespace.SimplePeer = require("simple-peer");
|
const Peer: SimplePeerNamespace.SimplePeer = require("simple-peer");
|
||||||
|
|
||||||
@ -43,7 +43,10 @@ export class ScreenSharingPeer extends Peer {
|
|||||||
|
|
||||||
this.streamStore = readable<MediaStream | null>(null, (set) => {
|
this.streamStore = readable<MediaStream | null>(null, (set) => {
|
||||||
const onStream = (stream: MediaStream | null) => {
|
const onStream = (stream: MediaStream | null) => {
|
||||||
videoFocusStore.focus(this);
|
highlightedEmbedScreen.highlight({
|
||||||
|
type: "streamable",
|
||||||
|
embed: this,
|
||||||
|
});
|
||||||
set(stream);
|
set(stream);
|
||||||
};
|
};
|
||||||
const onData = (chunk: Buffer) => {
|
const onData = (chunk: Buffer) => {
|
||||||
@ -177,7 +180,13 @@ export class ScreenSharingPeer extends Peer {
|
|||||||
public stopPushingScreenSharingToRemoteUser(stream: MediaStream) {
|
public stopPushingScreenSharingToRemoteUser(stream: MediaStream) {
|
||||||
this.removeStream(stream);
|
this.removeStream(stream);
|
||||||
this.write(
|
this.write(
|
||||||
new Buffer(JSON.stringify({ type: MESSAGE_TYPE_CONSTRAINT, streamEnded: true, isMobile: isMobile() }))
|
new Buffer(
|
||||||
|
JSON.stringify({
|
||||||
|
type: MESSAGE_TYPE_CONSTRAINT,
|
||||||
|
streamEnded: true,
|
||||||
|
isMobile: isMediaBreakpointUp("md"),
|
||||||
|
})
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@ export class SimplePeer {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
mediaManager.showGameOverlay();
|
mediaManager.showMyCamera();
|
||||||
|
|
||||||
//receive message start
|
//receive message start
|
||||||
this.Connection.webRtcStartMessageStream.subscribe((message: UserSimplePeerInterface) => {
|
this.Connection.webRtcStartMessageStream.subscribe((message: UserSimplePeerInterface) => {
|
||||||
|
@ -9,7 +9,7 @@ import { localStreamStore, obtainedMediaConstraintStore, ObtainedMediaStreamCons
|
|||||||
import { playersStore } from "../Stores/PlayersStore";
|
import { playersStore } from "../Stores/PlayersStore";
|
||||||
import { chatMessagesStore, newChatMessageSubject } from "../Stores/ChatStore";
|
import { chatMessagesStore, newChatMessageSubject } from "../Stores/ChatStore";
|
||||||
import { getIceServersConfig } from "../Components/Video/utils";
|
import { getIceServersConfig } from "../Components/Video/utils";
|
||||||
import { isMobile } from "../Enum/EnvironmentVariable";
|
import { isMediaBreakpointUp } from "../Utils/BreakpointsUtils";
|
||||||
|
|
||||||
const Peer: SimplePeerNamespace.SimplePeer = require("simple-peer");
|
const Peer: SimplePeerNamespace.SimplePeer = require("simple-peer");
|
||||||
|
|
||||||
@ -202,7 +202,7 @@ export class VideoPeer extends Peer {
|
|||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
type: MESSAGE_TYPE_CONSTRAINT,
|
type: MESSAGE_TYPE_CONSTRAINT,
|
||||||
...constraints,
|
...constraints,
|
||||||
isMobile: isMobile(),
|
isMobile: isMediaBreakpointUp("md"),
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -2,7 +2,7 @@ import "phaser";
|
|||||||
import GameConfig = Phaser.Types.Core.GameConfig;
|
import GameConfig = Phaser.Types.Core.GameConfig;
|
||||||
import "../style/index.scss";
|
import "../style/index.scss";
|
||||||
|
|
||||||
import { DEBUG_MODE, isMobile } from "./Enum/EnvironmentVariable";
|
import { DEBUG_MODE } from "./Enum/EnvironmentVariable";
|
||||||
import { LoginScene } from "./Phaser/Login/LoginScene";
|
import { LoginScene } from "./Phaser/Login/LoginScene";
|
||||||
import { ReconnectingScene } from "./Phaser/Reconnecting/ReconnectingScene";
|
import { ReconnectingScene } from "./Phaser/Reconnecting/ReconnectingScene";
|
||||||
import { SelectCharacterScene } from "./Phaser/Login/SelectCharacterScene";
|
import { SelectCharacterScene } from "./Phaser/Login/SelectCharacterScene";
|
||||||
@ -24,6 +24,7 @@ import App from "./Components/App.svelte";
|
|||||||
import { HtmlUtils } from "./WebRtc/HtmlUtils";
|
import { HtmlUtils } from "./WebRtc/HtmlUtils";
|
||||||
import WebGLRenderer = Phaser.Renderer.WebGL.WebGLRenderer;
|
import WebGLRenderer = Phaser.Renderer.WebGL.WebGLRenderer;
|
||||||
import { analyticsClient } from "./Administration/AnalyticsClient";
|
import { analyticsClient } from "./Administration/AnalyticsClient";
|
||||||
|
import { isMediaBreakpointUp } from "./Utils/BreakpointsUtils";
|
||||||
|
|
||||||
const { width, height } = coWebsiteManager.getGameSize();
|
const { width, height } = coWebsiteManager.getGameSize();
|
||||||
const valueGameQuality = localUserStore.getGameQualityValue();
|
const valueGameQuality = localUserStore.getGameQualityValue();
|
||||||
@ -90,7 +91,7 @@ const config: GameConfig = {
|
|||||||
scene: [
|
scene: [
|
||||||
EntryScene,
|
EntryScene,
|
||||||
LoginScene,
|
LoginScene,
|
||||||
isMobile() ? SelectCharacterMobileScene : SelectCharacterScene,
|
isMediaBreakpointUp("md") ? SelectCharacterMobileScene : SelectCharacterScene,
|
||||||
SelectCompanionScene,
|
SelectCompanionScene,
|
||||||
EnableCameraScene,
|
EnableCameraScene,
|
||||||
ReconnectingScene,
|
ReconnectingScene,
|
||||||
@ -136,7 +137,6 @@ const config: GameConfig = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
//const game = new Phaser.Game(config);
|
|
||||||
const game = new Game(config);
|
const game = new Game(config);
|
||||||
|
|
||||||
waScaleManager.setGame(game);
|
waScaleManager.setGame(game);
|
||||||
@ -156,7 +156,7 @@ coWebsiteManager.onResize.subscribe(() => {
|
|||||||
iframeListener.init();
|
iframeListener.init();
|
||||||
|
|
||||||
const app = new App({
|
const app = new App({
|
||||||
target: HtmlUtils.getElementByIdOrFail("svelte-overlay"),
|
target: HtmlUtils.getElementByIdOrFail("game-overlay"),
|
||||||
props: {
|
props: {
|
||||||
game: game,
|
game: game,
|
||||||
},
|
},
|
||||||
|
@ -30,7 +30,7 @@ section.section-input-send-text {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: 800px), only screen and (max-height: 800px) {
|
@include media-breakpoint-up(md) {
|
||||||
section.section-input-send-text {
|
section.section-input-send-text {
|
||||||
--height-toolbar: 30%;
|
--height-toolbar: 30%;
|
||||||
|
|
||||||
|
@ -1,136 +0,0 @@
|
|||||||
@media (max-aspect-ratio: 1/1) {
|
|
||||||
|
|
||||||
#main-container {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column-reverse;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#cowebsite {
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 50%;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column-reverse;
|
|
||||||
|
|
||||||
&.loading {
|
|
||||||
transform: translateY(-90%);
|
|
||||||
}
|
|
||||||
&.hidden {
|
|
||||||
transform: translateY(-100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
main {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
&-container {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
aside {
|
|
||||||
height: 50px;
|
|
||||||
cursor: ns-resize;
|
|
||||||
flex-direction: row-reverse;
|
|
||||||
align-items: center;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
#cowebsite-aside-holder {
|
|
||||||
pointer-events: none;
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
img {
|
|
||||||
height: 80%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#cowebsite-sub-icons {
|
|
||||||
display: inline-flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
margin-top: 0;
|
|
||||||
height: 100%;
|
|
||||||
visibility: visible;
|
|
||||||
|
|
||||||
img {
|
|
||||||
height: 30px;
|
|
||||||
width: 30px;
|
|
||||||
cursor: pointer !important;
|
|
||||||
border-radius: 50%;
|
|
||||||
background-color: whitesmoke;
|
|
||||||
}
|
|
||||||
|
|
||||||
&>div {
|
|
||||||
display: flex;
|
|
||||||
margin-left: 2px;
|
|
||||||
margin-right: 2px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#cowebsite-aside-buttons {
|
|
||||||
flex-direction: row-reverse;
|
|
||||||
margin-left: auto;
|
|
||||||
margin-bottom: 0;
|
|
||||||
justify-content: end;
|
|
||||||
}
|
|
||||||
|
|
||||||
img {
|
|
||||||
cursor: ns-resize;
|
|
||||||
}
|
|
||||||
|
|
||||||
#cowebsite-fullscreen {
|
|
||||||
padding-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.top-right-btn {
|
|
||||||
img {
|
|
||||||
width: 15px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width:960px) and (max-height:768px) {
|
|
||||||
#cowebsite {
|
|
||||||
|
|
||||||
&-container {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
aside {
|
|
||||||
#cowebsite-sub-icons {
|
|
||||||
display: inline-flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
margin-top: 0;
|
|
||||||
height: 100%;
|
|
||||||
visibility: visible;
|
|
||||||
|
|
||||||
img {
|
|
||||||
height: 28px;
|
|
||||||
width: 28px;
|
|
||||||
cursor: pointer !important;
|
|
||||||
border-radius: 50%;
|
|
||||||
background-color: whitesmoke;
|
|
||||||
}
|
|
||||||
|
|
||||||
&>div {
|
|
||||||
display: flex;
|
|
||||||
margin-top: 2px;
|
|
||||||
margin-bottom: 2px;
|
|
||||||
transform: rotate(-90deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
img {
|
|
||||||
cursor: ns-resize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,10 +1,5 @@
|
|||||||
@import "~@fontsource/press-start-2p/index.css";
|
@import "~@fontsource/press-start-2p/index.css";
|
||||||
|
|
||||||
@font-face {
|
|
||||||
font-family: "Twemoji Mozilla";
|
|
||||||
src: url("./fonts/TwemojiMozilla.ttf") format('truetype');
|
|
||||||
}
|
|
||||||
|
|
||||||
*{
|
*{
|
||||||
font-family: PixelFont-7,monospace;
|
font-family: PixelFont-7,monospace;
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
@ -1,6 +1,6 @@
|
|||||||
|
@charset 'UTF-8';
|
||||||
|
@import "breakpoints";
|
||||||
@import "cowebsite.scss";
|
@import "cowebsite.scss";
|
||||||
@import "cowebsite-mobile.scss";
|
|
||||||
@import "style";
|
|
||||||
@import "mobile-style.scss";
|
|
||||||
@import "fonts.scss";
|
@import "fonts.scss";
|
||||||
|
@import "style";
|
||||||
@import "TextGlobalMessageSvelte-Style";
|
@import "TextGlobalMessageSvelte-Style";
|
||||||
|
@ -1,48 +0,0 @@
|
|||||||
@media (hover: none) {
|
|
||||||
/**
|
|
||||||
* If we cannot hover over elements, let's display camera button in full.
|
|
||||||
*/
|
|
||||||
.btn-cam-action {
|
|
||||||
div {
|
|
||||||
transform: translateY(0px);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: 700px),
|
|
||||||
screen and (max-height: 700px){
|
|
||||||
video.myCamVideo {
|
|
||||||
width: 150px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.div-myCamVideo.hide {
|
|
||||||
right: -160px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar {
|
|
||||||
width: 20%;
|
|
||||||
min-width: 200px;
|
|
||||||
position: absolute;
|
|
||||||
display: block;
|
|
||||||
right: 0;
|
|
||||||
height: 80%;
|
|
||||||
|
|
||||||
&> div {
|
|
||||||
min-width: 200px;
|
|
||||||
max-height: 21vh;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-container{
|
|
||||||
min-width: 200px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-section {
|
|
||||||
position: absolute;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
& > div {
|
|
||||||
z-index: 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -36,15 +36,22 @@ body .message-info.warning{
|
|||||||
}
|
}
|
||||||
|
|
||||||
.video-container {
|
.video-container {
|
||||||
position: relative;
|
display: flex;
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
background-color: #00000099;
|
|
||||||
cursor: url('./images/cursor_pointer.png'), pointer;
|
cursor: url('./images/cursor_pointer.png'), pointer;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
&.no-clikable {
|
||||||
|
video {
|
||||||
|
cursor: url('./images/cursor_normal.png'), pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
video {
|
video {
|
||||||
|
height: fit-content;
|
||||||
|
max-height: 100%;
|
||||||
|
max-width: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
|
||||||
object-fit: cover;
|
|
||||||
cursor: url('./images/cursor_pointer.png'), pointer;
|
cursor: url('./images/cursor_pointer.png'), pointer;
|
||||||
|
|
||||||
&.mobile{
|
&.mobile{
|
||||||
@ -146,35 +153,6 @@ body .message-info.warning{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.video-container.div-myCamVideo{
|
|
||||||
border: none;
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.div-myCamVideo {
|
|
||||||
position: absolute;
|
|
||||||
right: 15px;
|
|
||||||
bottom: 30px;
|
|
||||||
border-radius: 15px 15px 15px 15px;
|
|
||||||
max-height: 20%;
|
|
||||||
transition: right 350ms;
|
|
||||||
}
|
|
||||||
|
|
||||||
.div-myCamVideo.hide {
|
|
||||||
right: -20vw;
|
|
||||||
}
|
|
||||||
|
|
||||||
video.myCamVideo{
|
|
||||||
background-color: #00000099;
|
|
||||||
max-height: 20vh;
|
|
||||||
width: 15vw;
|
|
||||||
-webkit-transform: scaleX(-1);
|
|
||||||
transform: scaleX(-1);
|
|
||||||
border-radius: 15px 15px 15px 15px;
|
|
||||||
/*width: 200px;*/
|
|
||||||
/*height: 113px;*/
|
|
||||||
}
|
|
||||||
|
|
||||||
.sound-progress{
|
.sound-progress{
|
||||||
display: none;
|
display: none;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@ -211,94 +189,6 @@ video.myCamVideo{
|
|||||||
top: calc(50% - 20px);
|
top: calc(50% - 20px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-cam-action {
|
|
||||||
pointer-events: all;
|
|
||||||
position: absolute;
|
|
||||||
display: inline-flex;
|
|
||||||
bottom: 10px;
|
|
||||||
right: 15px;
|
|
||||||
width: 240px;
|
|
||||||
height: 40px;
|
|
||||||
text-align: center;
|
|
||||||
align-content: center;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: flex-end;
|
|
||||||
justify-items: center;
|
|
||||||
}
|
|
||||||
/*btn animation*/
|
|
||||||
.btn-cam-action div{
|
|
||||||
cursor: url('./images/cursor_pointer.png'), pointer;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
border: solid 0px black;
|
|
||||||
width: 44px;
|
|
||||||
height: 44px;
|
|
||||||
background: #666;
|
|
||||||
box-shadow: 2px 2px 24px #444;
|
|
||||||
border-radius: 48px;
|
|
||||||
transform: translateY(15px);
|
|
||||||
transition-timing-function: ease-in-out;
|
|
||||||
margin: 0 4%;
|
|
||||||
}
|
|
||||||
.btn-cam-action div.disabled {
|
|
||||||
background: #d75555;
|
|
||||||
}
|
|
||||||
.btn-cam-action div.enabled {
|
|
||||||
background: #73c973;
|
|
||||||
}
|
|
||||||
.btn-cam-action:hover div{
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
.btn-cam-action div:hover{
|
|
||||||
background: #407cf7;
|
|
||||||
box-shadow: 4px 4px 48px #666;
|
|
||||||
transition: 120ms;
|
|
||||||
}
|
|
||||||
.btn-micro{
|
|
||||||
pointer-events: auto;
|
|
||||||
transition: all .3s;
|
|
||||||
/*right: 44px;*/
|
|
||||||
}
|
|
||||||
.btn-video{
|
|
||||||
pointer-events: auto;
|
|
||||||
transition: all .25s;
|
|
||||||
/*right: 134px;*/
|
|
||||||
}
|
|
||||||
.btn-monitor{
|
|
||||||
pointer-events: auto;
|
|
||||||
transition: all .2s;
|
|
||||||
/*right: 224px;*/
|
|
||||||
}
|
|
||||||
.btn-monitor.hide {
|
|
||||||
transform: translateY(60px);
|
|
||||||
}
|
|
||||||
.btn-cam-action:hover .btn-monitor.hide{
|
|
||||||
transform: translateY(60px);
|
|
||||||
}
|
|
||||||
.btn-layout{
|
|
||||||
pointer-events: auto;
|
|
||||||
transition: all .15s;
|
|
||||||
}
|
|
||||||
.btn-layout.hide {
|
|
||||||
transform: translateY(60px);
|
|
||||||
}
|
|
||||||
.btn-cam-action:hover .btn-layout.hide{
|
|
||||||
transform: translateY(60px);
|
|
||||||
}
|
|
||||||
.btn-copy{
|
|
||||||
pointer-events: auto;
|
|
||||||
transition: all .3s;
|
|
||||||
right: 44px;
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
.btn-cam-action div img{
|
|
||||||
height: 22px;
|
|
||||||
width: 30px;
|
|
||||||
position: relative;
|
|
||||||
cursor: url('./images/cursor_pointer.png'), pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Spinner */
|
/* Spinner */
|
||||||
.connecting-spinner {
|
.connecting-spinner {
|
||||||
/*display: inline-block;*/
|
/*display: inline-block;*/
|
||||||
@ -369,26 +259,6 @@ body {
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-aspect-ratio: 1/1) {
|
|
||||||
.game-overlay {
|
|
||||||
flex-direction: row;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar {
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar > div {
|
|
||||||
max-height: 21%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar > div:hover {
|
|
||||||
max-height: 25%;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#game {
|
#game {
|
||||||
position: relative; /* Position relative is needed for the game-overlay. */
|
position: relative; /* Position relative is needed for the game-overlay. */
|
||||||
|
|
||||||
@ -486,96 +356,6 @@ input[type=range]:focus::-ms-fill-upper {
|
|||||||
background: #FFFFFF;
|
background: #FFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.game-overlay {
|
|
||||||
display: none;
|
|
||||||
position: absolute;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
pointer-events: none;
|
|
||||||
/* TODO: DO WE NEED FLEX HERE???? WE WANT A SIDEBAR OF EXACTLY 25% (note: flex useful for direction!!!) */
|
|
||||||
}
|
|
||||||
|
|
||||||
.game-overlay + div {
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.game-overlay + div > div {
|
|
||||||
pointer-events: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.game-overlay.active {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.game-overlay video {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-section {
|
|
||||||
flex: 0 0 75%;
|
|
||||||
display: flex;
|
|
||||||
justify-content: start;
|
|
||||||
align-items: flex-start;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-section > div {
|
|
||||||
margin: 2%;
|
|
||||||
flex-basis: 96%;
|
|
||||||
transition: margin-left 0.2s, margin-right 0.2s, margin-bottom 0.2s, margin-top 0.2s, flex-basis 0.2s;
|
|
||||||
cursor: url('./images/cursor_pointer.png'), pointer;
|
|
||||||
pointer-events: auto;
|
|
||||||
/*flex-shrink: 2;*/
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-section > div:hover {
|
|
||||||
margin: 0%;
|
|
||||||
flex-basis: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar {
|
|
||||||
flex: 0 0 25%;
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar > div {
|
|
||||||
margin: 2%;
|
|
||||||
transition: margin-left 0.2s, margin-right 0.2s, margin-bottom 0.2s, margin-top 0.2s, max-height 0.2s, max-width 0.2s;
|
|
||||||
cursor: url('./images/cursor_pointer.png'), pointer;
|
|
||||||
border-radius: 15px 15px 15px 15px;
|
|
||||||
pointer-events: auto;
|
|
||||||
|
|
||||||
video {
|
|
||||||
max-height: 21vh;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar > div:hover {
|
|
||||||
margin: 0%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar > div video {
|
|
||||||
cursor: url('./images/cursor_pointer.png'), pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Let's make sure videos are vertically centered if they need to be cropped */
|
|
||||||
.media-container {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
overflow: hidden;
|
|
||||||
border-radius: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-mode {
|
|
||||||
display: grid;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
align-items: flex-start;
|
|
||||||
|
|
||||||
padding: 1%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-mode > div {
|
.chat-mode > div {
|
||||||
margin: 1%;
|
margin: 1%;
|
||||||
max-height: 96%;
|
max-height: 96%;
|
||||||
@ -1061,13 +841,22 @@ div.action.danger p.action-body{
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#svelte-overlay {
|
#game-overlay {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
|
||||||
|
& + div {
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
& + div > div {
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
|
|
||||||
& > div {
|
& > div {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -1085,22 +874,10 @@ div.action.danger p.action-body{
|
|||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
div.is-silent {
|
&.hide {
|
||||||
position: absolute;
|
visibility: hidden;
|
||||||
bottom: 40px;
|
}
|
||||||
border-radius: 15px 15px 15px 15px;
|
|
||||||
max-height: 20%;
|
|
||||||
transition: right 350ms;
|
|
||||||
right: -300px;
|
|
||||||
background-color: black;
|
|
||||||
font-size: 20px;
|
|
||||||
color: white;
|
|
||||||
padding: 30px 20px;
|
|
||||||
}
|
|
||||||
div.is-silent.hide {
|
|
||||||
right: 15px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
div.emoji-picker {
|
div.emoji-picker {
|
||||||
@ -1121,8 +898,3 @@ div.emoji-picker {
|
|||||||
user-select: none; /* Non-prefixed version, currently
|
user-select: none; /* Non-prefixed version, currently
|
||||||
supported by Chrome, Edge, Opera and Firefox */
|
supported by Chrome, Edge, Opera and Firefox */
|
||||||
}
|
}
|
||||||
|
|
||||||
.pixel {
|
|
||||||
height: 1px !important;
|
|
||||||
width: 1px !important;
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user