Improve game overlay UI

This commit is contained in:
Alexis Faizeau 2022-01-05 10:27:40 +01:00
parent 5f1dd09cb9
commit 0bf1acfefb
63 changed files with 976 additions and 984 deletions

View file

@ -1,166 +1,52 @@
<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 { chatVisibilityStore } from "../Stores/ChatStore";
import { helpCameraSettingsVisibleStore } from "../Stores/HelpCameraSettingsStore";
import HelpCameraSettingsPopup from "./HelpCameraSettings/HelpCameraSettingsPopup.svelte";
import { showLimitRoomModalStore, showShareLinkMapModalStore } from "../Stores/ModalStore";
import LimitRoomModal from "./Modal/LimitRoomModal.svelte";
import ShareLinkMapModal from "./Modal/ShareLinkMapModal.svelte";
import AudioPlaying from "./UI/AudioPlaying.svelte";
import { soundPlayingStore } from "../Stores/SoundPlayingStore";
import { customCharacterSceneVisibleStore } from "../Stores/CustomCharacterStore";
import { errorStore } from "../Stores/ErrorStore";
import { loginSceneVisibleStore } from "../Stores/LoginSceneStore";
import { enableCameraSceneVisibilityStore } from "../Stores/MediaStore";
import { selectCharacterSceneVisibleStore } from "../Stores/SelectCharacterStore";
import { selectCompanionSceneVisibleStore } from "../Stores/SelectCompanionStore";
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 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;
</script>
<div>
{#if $loginSceneVisibleStore}
<div class="scrollable">
<LoginScene {game} />
</div>
{/if}
{#if $selectCharacterSceneVisibleStore}
<div>
<SelectCharacterScene {game} />
</div>
{/if}
{#if $customCharacterSceneVisibleStore}
<div>
<CustomCharacterScene {game} />
</div>
{/if}
{#if $selectCompanionSceneVisibleStore}
<div>
<SelectCompanionScene {game} />
</div>
{/if}
{#if $enableCameraSceneVisibilityStore}
<div class="scrollable">
<EnableCameraScene {game} />
</div>
{/if}
{#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 $errorStore.length > 0}
<div>
<ErrorDialog />
</div>
{:else if $loginSceneVisibleStore}
<div class="scrollable">
<LoginScene {game} />
</div>
{:else if $selectCharacterSceneVisibleStore}
<div>
<SelectCharacterScene {game} />
</div>
{:else if $customCharacterSceneVisibleStore}
<div>
<CustomCharacterScene {game} />
</div>
{:else if $selectCompanionSceneVisibleStore}
<div>
<SelectCompanionScene {game} />
</div>
{:else if $enableCameraSceneVisibilityStore}
<div class="scrollable">
<EnableCameraScene {game} />
</div>
{:else}
<MainLayout />
{#if $chatVisibilityStore}
<Chat />
{/if}
{#if $warningContainerStore}
<WarningContainer />
{/if}
</div>
{/if}

View file

@ -157,13 +157,16 @@
<style lang="scss">
div.main-audio-manager.nes-container.is-rounded {
position: relative;
top: 0.5rem;
position: absolute;
top: 1%;
max-height: clamp(150px, 10vh, 15vh); //replace @media for small screen
width: clamp(200px, 15vw, 15vw);
padding: 3px 3px;
margin-left: auto;
margin-right: auto;
left: 0;
right: 0;
z-index: 200;
background-color: rgb(0, 0, 0, 0.5);
display: grid;

View file

@ -9,10 +9,15 @@
import microphoneCloseImg from "./images/microphone-close.svg";
import layoutPresentationImg from "./images/layout-presentation.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 { peerStore } from "../Stores/PeerStore";
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 {
if (isSilent) return;
@ -42,10 +47,26 @@
}
function switchLayoutMode() {
if ($layoutModeStore === LayoutMode.Presentation) {
$layoutModeStore = LayoutMode.VideoChat;
if ($embedScreenLayout === LayoutMode.Presentation) {
$embedScreenLayout = LayoutMode.VideoChat;
} 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);
</script>
<div>
<div class="btn-cam-action">
<div class="btn-layout" on:click={switchLayoutMode} class:hide={$peerStore.size === 0}>
{#if $layoutModeStore === LayoutMode.Presentation}
<img src={layoutPresentationImg} style="padding: 2px" alt="Switch to mosaic mode" />
{:else}
<img src={layoutChatImg} style="padding: 2px" alt="Switch to presentation mode" />
{/if}
</div>
<div
class="btn-monitor"
on:click={screenSharingClick}
class:hide={!$screenSharingAvailableStore || isSilent}
class:enabled={$requestedScreenSharingState}
>
{#if $requestedScreenSharingState && !isSilent}
<img src={monitorImg} alt="Start screen sharing" />
{:else}
<img src={monitorCloseImg} alt="Stop screen sharing" />
{/if}
</div>
<div class="btn-video" on:click={cameraClick} class:disabled={!$requestedCameraState || isSilent}>
{#if $requestedCameraState && !isSilent}
<img src={cinemaImg} alt="Turn on webcam" />
{:else}
<img src={cinemaCloseImg} alt="Turn off webcam" />
{/if}
</div>
<div class="btn-micro" on:click={microphoneClick} class:disabled={!$requestedMicrophoneState || isSilent}>
{#if $requestedMicrophoneState && !isSilent}
<img src={microphoneImg} alt="Turn on microphone" />
{:else}
<img src={microphoneCloseImg} alt="Turn off microphone" />
{/if}
</div>
<div class="btn-cam-action">
<div class="btn-layout" on:click={switchLayoutMode} class:hide={$peerStore.size === 0}>
{#if $embedScreenLayout === LayoutMode.Presentation}
<img class="noselect" src={layoutPresentationImg} style="padding: 2px" alt="Switch to mosaic mode" />
{:else}
<img class="noselect" src={layoutChatImg} style="padding: 2px" alt="Switch to presentation mode" />
{/if}
</div>
<div
class="btn-follow"
class:hide={($peerStore.size === 0 && $followStateStore === "off") || isSilent}
class:disabled={$followStateStore !== "off"}
on:click={followClick}
>
<img class="noselect" src={followImg} alt="" />
</div>
<div
class="btn-monitor"
on:click={screenSharingClick}
class:hide={!$screenSharingAvailableStore || isSilent}
class:enabled={$requestedScreenSharingState}
>
{#if $requestedScreenSharingState && !isSilent}
<img class="noselect" src={monitorImg} alt="Start screen sharing" />
{:else}
<img class="noselect" src={monitorCloseImg} alt="Stop screen sharing" />
{/if}
</div>
<div class="btn-video" on:click={cameraClick} class:disabled={!$requestedCameraState || isSilent}>
{#if $requestedCameraState && !isSilent}
<img class="noselect" src={cinemaImg} alt="Turn on webcam" />
{: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>
<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>

View file

@ -43,7 +43,7 @@
<svelte:window on:keydown={onKeyDown} on:click={onClick} />
<aside class="chatWindow" transition:fly={{ x: -1000, duration: 500 }} bind:this={chatWindowElement}>
<p class="close-icon" on:click={closeChat}>&times</p>
<p class="close-icon noselect" on:click={closeChat}>&times</p>
<section class="messagesList" bind:this={listDom}>
<ul>
<li><p class="system-text">{$LL.chat.intro()}</p></li>
@ -78,7 +78,7 @@
}
aside.chatWindow {
z-index: 100;
z-index: 1000;
pointer-events: auto;
position: absolute;
top: 0;

View file

@ -83,6 +83,8 @@
</form>
<style lang="scss">
@import "../../../style/breakpoints.scss";
form.customCharacterScene {
font-family: "Press Start 2P";
pointer-events: auto;
@ -129,7 +131,7 @@
}
}
@media only screen and (max-width: 800px) {
@include media-breakpoint-up(md) {
form.customCharacterScene button.customCharacterSceneButtonLeft {
left: 5vw;
}

View file

@ -3,8 +3,8 @@
import { emoteStore, emoteMenuStore } from "../../Stores/EmoteStore";
import { onDestroy, onMount } from "svelte";
import { EmojiButton } from "@joeattardi/emoji-button";
import { isMobile } from "../../Enum/EnvironmentVariable";
import LL from "../../i18n/i18n-svelte";
import { isMediaBreakpointUp } from "../../Utils/BreakpointsUtils";
let emojiContainer: HTMLElement;
let picker: EmojiButton;
@ -20,7 +20,7 @@
"--secondary-text-color": "whitesmoke",
"--category-button-color": "whitesmoke",
},
emojisPerRow: isMobile() ? 6 : 8,
emojisPerRow: isMediaBreakpointUp("md") ? 6 : 8,
autoFocusSearch: false,
style: "twemoji",
showPreview: false,
@ -86,6 +86,8 @@
height: 100%;
justify-content: center;
align-items: center;
position: absolute;
z-index: 101;
}
.emote-menu {

View file

@ -127,6 +127,8 @@
</form>
<style lang="scss">
@import "../../../style/breakpoints.scss";
.enableCameraScene {
pointer-events: auto;
margin: 20px auto 0;
@ -214,7 +216,7 @@
}
}
@media only screen and (max-width: 800px) {
@include media-breakpoint-up(md) {
.enableCameraScene h2 {
font-size: 80%;
}

View 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>

View file

@ -1,9 +1,5 @@
<!--
vim: ft=typescript
-->
<script lang="ts">
import { gameManager } from "../../Phaser/Game/GameManager";
import followImg from "../images/follow.svg";
import { followStateStore, followRoleStore, followUsersStore } from "../../Stores/FollowStore";
import LL from "../../i18n/i18n-svelte";
@ -14,10 +10,6 @@ vim: ft=typescript
return user ? user.PlayerValue : "";
}
function sendFollowRequest() {
gameScene.CurrentPlayer.sendFollowRequest();
}
function acceptFollowRequest() {
gameScene.CurrentPlayer.startFollowing();
}
@ -83,7 +75,7 @@ vim: ft=typescript
{#if $followStateStore === "active" || $followStateStore === "ending"}
<div class="interact-status nes-container is-rounded">
<section class="interact-status">
<section>
{#if $followRoleStore === "follower"}
<p>{$LL.follow.interactStatus.following({ leader: name($followUsersStore[0]) })}</p>
{:else if $followUsersStore.length === 0}
@ -109,48 +101,27 @@ vim: ft=typescript
</div>
{/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">
@import "../../../style/breakpoints.scss";
.nes-container {
padding: 5px;
}
div.interact-status {
.interact-status {
background-color: #333333;
color: whitesmoke;
position: relative;
height: 2.7em;
position: absolute;
max-height: 2.7em;
width: 40vw;
top: 87vh;
margin: auto;
text-align: center;
left: 0;
right: 0;
margin-left: auto;
margin-right: auto;
z-index: 150;
}
div.interact-menu {
@ -158,10 +129,14 @@ vim: ft=typescript
background-color: #333333;
color: whitesmoke;
position: relative;
position: absolute;
width: 60vw;
top: 60vh;
margin: auto;
left: 0;
right: 0;
margin-left: auto;
margin-right: auto;
z-index: 150;
section.interact-menu-title {
margin-bottom: 20px;
@ -189,23 +164,16 @@ vim: ft=typescript
}
}
.follow-menu-button {
position: absolute;
bottom: 10px;
left: 10px;
pointer-events: all;
}
@media only screen and (max-width: 800px) {
div.interact-status {
width: 100vw;
@include media-breakpoint-up(md) {
.interact-status {
width: 90vw;
top: 78vh;
font-size: 0.75em;
}
div.interact-menu {
height: 21vh;
width: 100vw;
max-height: 21vh;
width: 90vw;
font-size: 0.75em;
}
}

View file

@ -22,7 +22,7 @@
<form
class="helpCameraSettings nes-container"
on:submit|preventDefault={close}
transition:fly={{ y: -900, duration: 500 }}
transition:fly={{ y: -50, duration: 500 }}
>
<section>
<h2>{$LL.camera.help.title()}</h2>
@ -55,9 +55,12 @@
background: #eceeee;
margin-left: auto;
margin-right: auto;
margin-top: 10vh;
left: 0;
right: 0;
margin-top: 4%;
max-height: 80vh;
max-width: 80vw;
z-index: 250;
overflow: auto;
text-align: center;

View file

@ -21,9 +21,11 @@
left: 0;
right: 0;
bottom: 40px;
margin: 0 auto;
margin-right: auto;
margin-left: auto;
padding: 0;
width: clamp(200px, 20vw, 20vw);
z-index: 155;
display: flex;
flex-direction: column;
@ -31,6 +33,10 @@
animation: moveMessage 0.5s;
animation-iteration-count: infinite;
animation-timing-function: ease-in-out;
div {
margin-bottom: 5%;
}
}
div.nes-container.is-rounded {

View 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>

View file

@ -100,6 +100,8 @@
</div>
<style lang="scss">
@import "../../../style/breakpoints.scss";
.string-HTML {
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 {
section.container-overflow {
height: calc(100% - 120px);

View file

@ -67,6 +67,8 @@
</div>
<style lang="scss">
@import "../../../style/breakpoints.scss";
div.global-message-main {
height: calc(100% - 50px);
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 {
height: calc(100% - 5px);
}

View file

@ -36,6 +36,8 @@
</div>
<style lang="scss">
@import "../../../style/breakpoints.scss";
div.guest-main {
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 {
section.share-url.not-mobile {
display: none;

View file

@ -125,6 +125,8 @@
</div>
<style lang="scss">
@import "../../../style/breakpoints.scss";
.nes-container {
padding: 5px;
}
@ -136,11 +138,15 @@
pointer-events: auto;
height: 80%;
width: 75%;
top: 10%;
top: 4%;
position: relative;
z-index: 80;
margin: auto;
left: 0;
right: 0;
margin-left: auto;
margin-right: auto;
position: absolute;
z-index: 900;
display: 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 {
--size-first-columns-grid: 120px;
height: 70%;
top: 55px;
width: 100%;
width: 95%;
font-size: 0.5em;
div.menu-nav-sidebar {

View file

@ -14,6 +14,7 @@
function showMenu() {
menuVisiblilityStore.set(!get(menuVisiblilityStore));
}
function showChat() {
chatVisibilityStore.set(true);
}
@ -21,72 +22,94 @@
function register() {
window.open(`${ADMIN_URL}/second-step-register`, "_self");
}
function showInvite() {
showShareLinkMapModalStore.set(true);
}
function noDrag() {
return false;
}
</script>
<svelte:window />
<main class="menuIcon">
<main class="menuIcon noselect">
{#if $limitMapStore}
<img
src={logoInvite}
alt={$LL.menu.icon.open.invite()}
class="nes-pointer"
draggable="false"
on:dragstart|preventDefault={noDrag}
on:click|preventDefault={showInvite}
/>
<img
src={logoRegister}
alt={$LL.menu.icon.open.register()}
class="nes-pointer"
draggable="false"
on:dragstart|preventDefault={noDrag}
on:click|preventDefault={register}
/>
{:else}
<img src={logoWA} alt={$LL.menu.icon.open.menu()} class="nes-pointer" on:click|preventDefault={showMenu} />
<img src={logoTalk} alt={$LL.menu.icon.open.chat()} class="nes-pointer" on:click|preventDefault={showChat} />
<img
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}
</main>
<style lang="scss">
@import "../../../style/breakpoints.scss";
.menuIcon {
display: inline-grid;
z-index: 90;
display: flex;
flex-direction: column;
align-items: center;
margin-top: 20%;
z-index: 800;
position: relative;
margin: 25px;
img {
pointer-events: auto;
width: 60px;
padding-top: 0;
margin: 3px;
image-rendering: pixelated;
margin: 5%;
}
}
.menuIcon img:hover {
transform: scale(1.2);
}
@media only screen and (max-width: 800px), only screen and (max-height: 800px) {
@include media-breakpoint-up(sm) {
.menuIcon {
display: inline-grid;
z-index: 90;
position: relative;
margin: 25px;
margin-top: 10%;
img {
pointer-events: auto;
width: 60px;
padding-top: 0;
margin: 3px;
}
}
.menuIcon img:hover {
transform: scale(1.2);
}
@media only screen and (max-width: 800px), only screen and (max-height: 800px) {
.menuIcon {
margin: 3px;
img {
width: 50px;
}
}
@include media-breakpoint-up(md) {
.menuIcon {
img {
width: 50px;
}
}
}

View file

@ -102,6 +102,8 @@
</div>
<style lang="scss">
@import "../../../style/breakpoints.scss";
div.customize-main {
width: 100%;
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 {
width: 130px;
}

View file

@ -2,11 +2,11 @@
import { localUserStore } from "../../Connexion/LocalUserStore";
import { videoConstraintStore } from "../../Stores/MediaStore";
import { HtmlUtils } from "../../WebRtc/HtmlUtils";
import { isMobile } from "../../Enum/EnvironmentVariable";
import { menuVisiblilityStore } from "../../Stores/MenuStore";
import LL, { locale } from "../../i18n/i18n-svelte";
import type { Locales } from "../../i18n/i18n-types";
import { displayableLocales, setCurrentLocale } from "../../i18n/locales";
import { isMediaBreakpointUp } from "../../Utils/BreakpointsUtils";
let fullscreen: boolean = localUserStore.getFullscreen();
let notification: boolean = localUserStore.getNotification() === "granted";
@ -85,6 +85,8 @@
function closeMenu() {
menuVisiblilityStore.set(false);
}
const isMobile = isMediaBreakpointUp("md");
</script>
<div class="settings-main" on:submit|preventDefault={saveSetting}>
@ -93,22 +95,22 @@
<div class="nes-select is-dark">
<select bind:value={valueGame}>
<option value={120}
>{isMobile()
>{isMobile
? $LL.menu.settings.gameQuality.short.high()
: $LL.menu.settings.gameQuality.long.high()}</option
>
<option value={60}
>{isMobile()
>{isMobile
? $LL.menu.settings.gameQuality.short.medium()
: $LL.menu.settings.gameQuality.long.medium()}</option
>
<option value={40}
>{isMobile()
>{isMobile
? $LL.menu.settings.gameQuality.short.small()
: $LL.menu.settings.gameQuality.long.small()}</option
>
<option value={20}
>{isMobile()
>{isMobile
? $LL.menu.settings.gameQuality.short.minimum()
: $LL.menu.settings.gameQuality.long.minimum()}</option
>
@ -120,22 +122,22 @@
<div class="nes-select is-dark">
<select bind:value={valueVideo}>
<option value={30}
>{isMobile()
>{isMobile
? $LL.menu.settings.videoQuality.short.high()
: $LL.menu.settings.videoQuality.long.high()}</option
>
<option value={20}
>{isMobile()
>{isMobile
? $LL.menu.settings.videoQuality.short.medium()
: $LL.menu.settings.videoQuality.long.medium()}</option
>
<option value={10}
>{isMobile()
>{isMobile
? $LL.menu.settings.videoQuality.short.small()
: $LL.menu.settings.videoQuality.long.small()}</option
>
<option value={5}
>{isMobile()
>{isMobile
? $LL.menu.settings.videoQuality.short.minimum()
: $LL.menu.settings.videoQuality.long.minimum()}</option
>
@ -199,6 +201,8 @@
</div>
<style lang="scss">
@import "../../../style/breakpoints.scss";
div.settings-main {
height: calc(100% - 40px);
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 {
section {
padding: 0;

View file

@ -2,7 +2,7 @@
import { obtainedMediaConstraintStore } from "../Stores/MediaStore";
import { localStreamStore, isSilentStore } from "../Stores/MediaStore";
import SoundMeterWidget from "./SoundMeterWidget.svelte";
import { onDestroy } from "svelte";
import { onDestroy, onMount } from "svelte";
import { srcObject } from "./Video/utils";
import LL from "../i18n/i18n-svelte";
@ -23,15 +23,77 @@
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);
</script>
<div>
<div class="video-container div-myCamVideo" class:hide={!$obtainedMediaConstraintStore.video || isSilent}>
{#if $localStreamStore.type === "success" && $localStreamStore.stream}
<video class="myCamVideo" use:srcObject={stream} autoplay muted playsinline />
<SoundMeterWidget {stream} />
{/if}
</div>
<div class="is-silent" class:hide={isSilent}>{$LL.camera.my.silentZone()}</div>
<div
class="nes-container is-rounded my-cam-video-container"
class:hide={($localStreamStore.type !== "success" || !$obtainedMediaConstraintStore.video) && !isSilent}
bind:this={cameraContainer}
>
{#if isSilent}
<div class="is-silent">{$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>
<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>

View file

@ -108,12 +108,16 @@
pointer-events: auto;
background-color: #333333;
color: whitesmoke;
position: relative;
z-index: 300;
position: absolute;
height: 70vh;
width: 50vw;
top: 10vh;
margin: auto;
top: 4%;
left: 0;
right: 0;
margin-left: auto;
margin-right: auto;
section.report-menu-title {
display: grid;
@ -137,13 +141,4 @@
display: none;
}
}
@media only screen and (max-width: 800px) {
div.report-menu-main {
top: 21vh;
height: 60vh;
width: 100vw;
font-size: 0.5em;
}
}
</style>

View file

@ -47,6 +47,8 @@
</form>
<style lang="scss">
@import "../../../style/breakpoints.scss";
form.selectCompanionScene {
font-family: "Press Start 2P";
pointer-events: auto;
@ -85,7 +87,7 @@
}
}
@media only screen and (max-width: 800px) {
@include media-breakpoint-up(md) {
form.selectCompanionScene button.selectCharacterButtonLeft {
left: 5vw;
}

View file

@ -1,6 +1,7 @@
<script lang="ts">
import { fly, fade } from "svelte/transition";
import { onMount } from "svelte";
import { gameManager } from "../../Phaser/Game/GameManager";
import type { Message } from "../../Stores/TypeMessageStore/MessageStore";
import { banMessageStore } from "../../Stores/TypeMessageStore/BanMessageStore";
import LL from "../../i18n/i18n-svelte";
@ -13,6 +14,8 @@
onMount(() => {
timeToRead();
const gameScene = gameManager.getCurrentGameScene();
gameScene.playSound("audio-report-message");
});
function timeToRead() {
@ -53,18 +56,19 @@
on:click|preventDefault={closeBanMessage}>{nameButton}</button
>
</div>
<!-- svelte-ignore a11y-media-has-caption -->
<audio id="report-message" autoplay>
<source src="/resources/objects/report-message.mp3" type="audio/mp3" />
</audio>
</div>
<style lang="scss">
div.main-ban-message {
display: flex;
flex-direction: column;
position: relative;
top: 15vh;
position: absolute;
top: 4%;
left: 0;
right: 0;
margin-left: auto;
margin-right: auto;
z-index: 850;
height: 70vh;
width: 60vw;

View file

@ -42,14 +42,17 @@
div.main-text-message {
display: flex;
flex-direction: column;
position: absolute;
max-height: 25vh;
width: 80vw;
max-height: 25%;
width: 60%;
margin-right: auto;
margin-left: auto;
margin-bottom: 16px;
margin-top: 0;
top: 6%;
left: 0;
right: 0;
padding-bottom: 0;
z-index: 240;
pointer-events: auto;
background-color: #333333;

View file

@ -25,11 +25,17 @@
<style lang="scss">
div.error-div {
pointer-events: auto;
margin-top: 10vh;
margin-top: 4%;
margin-right: auto;
margin-left: auto;
left: 0;
right: 0;
position: absolute;
width: max-content;
max-width: 80vw;
z-index: 230;
height: auto !important;
background-clip: padding-box;
.button-bar {
text-align: center;

View file

@ -1,15 +1,33 @@
<script lang="typescript">
import { highlightedEmbedScreen } from "../../Stores/EmbedScreensStore";
import type { EmbedScreen } from "../../Stores/EmbedScreensStore";
import type { ScreenSharingLocalMedia } from "../../Stores/ScreenSharingStore";
import { videoFocusStore } from "../../Stores/VideoFocusStore";
import type { Streamable } from "../../Stores/StreamableCollectionStore";
import { srcObject } from "./utils";
export let clickable = false;
export let peer: ScreenSharingLocalMedia;
let stream = peer.stream;
export let cssClass: string | undefined;
let embedScreen: EmbedScreen;
if (stream) {
embedScreen = {
type: "streamable",
embed: stream as unknown as Streamable,
};
}
</script>
<div class="video-container {cssClass ? cssClass : ''}" class:hide={!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}
</div>

View file

@ -7,14 +7,65 @@
import type { Streamable } from "../../Stores/StreamableCollectionStore";
export let streamable: Streamable;
export let isHightlighted = false;
export let clickable = false;
</script>
<div class="media-container">
<div class="media-container nes-container is-rounded {isHightlighted ? 'hightlighted' : ''}" class:clickable>
{#if streamable instanceof VideoPeer}
<VideoMediaBox peer={streamable} />
<VideoMediaBox peer={streamable} {clickable} />
{:else if streamable instanceof ScreenSharingPeer}
<ScreenSharingMediaBox peer={streamable} />
<ScreenSharingMediaBox peer={streamable} {clickable} />
{:else}
<LocalStreamMediaBox peer={streamable} cssClass="" />
<LocalStreamMediaBox peer={streamable} {clickable} cssClass="" />
{/if}
</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>

View file

@ -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>

View file

@ -1,12 +1,26 @@
<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 { videoFocusStore } from "../../Stores/VideoFocusStore";
import { getColorByString, srcObject } from "./utils";
export let clickable = false;
export let peer: ScreenSharingPeer;
let streamStore = peer.streamStore;
let name = peer.userName;
let statusStore = peer.statusStore;
let embedScreen: EmbedScreen;
if (peer) {
embedScreen = {
type: "streamable",
embed: peer as unknown as Streamable,
};
}
</script>
<div class="video-container">
@ -20,7 +34,12 @@
<i style="background-color: {getColorByString(name)};">{name}</i>
{:else}
<!-- 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}
</div>

View file

@ -4,11 +4,17 @@
import microphoneCloseImg from "../images/microphone-close.svg";
import reportImg from "./images/report.svg";
import blockSignImg from "./images/blockSign.svg";
import { videoFocusStore } from "../../Stores/VideoFocusStore";
import { showReportScreenStore } from "../../Stores/ShowReportScreenStore";
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 { onMount } from "svelte";
import { isMediaBreakpointOnly } from "../../Utils/BreakpointsUtils";
export let clickable = false;
export let peer: VideoPeer;
let streamStore = peer.streamStore;
@ -19,9 +25,32 @@
function openReport(peer: VideoPeer): void {
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>
<div class="video-container">
<div class="video-container" class:no-clikable={!clickable} bind:this={videoContainer}>
{#if $statusStore === "connecting"}
<div class="connecting-spinner" />
{/if}
@ -30,42 +59,60 @@
{/if}
<!-- {#if !$constraintStore || $constraintStore.video === false} -->
<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)};"
>
<span>{peer.userName}</span>
<span style="noselect">{peer.userName}</span>
<div class="woka-icon"><Woka userId={peer.userId} placeholderSrc={""} /></div>
</i>
<!-- {/if} -->
{#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}
<button class="report" on:click={() => openReport(peer)}>
<img alt="Report this user" src={reportImg} />
<span>Report/Block</span>
<img alt="Report this user" draggable="false" on:dragstart|preventDefault={noDrag} src={reportImg} />
<span class="noselect">Report/Block</span>
</button>
<!-- svelte-ignore a11y-media-has-caption -->
<video use:srcObject={$streamStore} autoplay playsinline on:click={() => videoFocusStore.toggleFocus(peer)} />
<img src={blockSignImg} class="block-logo" alt="Block" />
<video
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}
<SoundMeterWidget stream={$streamStore} />
{/if}
</div>
<style>
<style lang="scss">
.container {
display: flex;
flex-direction: column;
padding-top: 15px;
}
.minimized {
left: auto;
transform: scale(0.5);
opacity: 0.5;
}
&.has-video {
left: auto;
transform: scale(0.5);
opacity: 0.5;
}
.woka-icon {
margin-right: 3px;
&.minimized {
transform: scale(0.5);
opacity: 0.5;
}
.woka-icon {
margin-right: 3px;
}
}
</style>

View file

@ -1,16 +1,16 @@
<script lang="ts">
import { LayoutMode } from "../../WebRtc/LayoutManager";
import { layoutModeStore } from "../../Stores/StreamableCollectionStore";
import PresentationLayout from "./PresentationLayout.svelte";
import ChatLayout from "./ChatLayout.svelte";
// import {LayoutMode} from "../../WebRtc/LayoutManager";
// import {layoutModeStore} from "../../Stores/StreamableCollectionStore";
// import PresentationLayout from "./PresentationLayout.svelte";
// import ChatLayout from "./ChatLayout.svelte";
</script>
<div class="video-overlay">
{#if $layoutModeStore === LayoutMode.Presentation}
<!-- {#if $layoutModeStore === LayoutMode.Presentation }
<PresentationLayout />
{:else}
<ChatLayout />
{/if}
{/if} -->
</div>
<style lang="scss">

View file

@ -57,6 +57,7 @@
height: 120px;
margin: auto;
animation: spin 2s linear infinite;
z-index: 102;
}
@keyframes spin {

View file

@ -27,18 +27,22 @@
<style lang="scss">
main.warningMain {
pointer-events: auto;
width: 100vw;
background-color: #f9e81e;
color: #14304c;
width: 80%;
background-color: #F9E81E;
color: #14304C;
text-align: center;
position: absolute;
left: 50%;
top: 4%;
left: 0;
right: 0;
margin-left: auto;
margin-right: auto;
transform: translate(-50%, 0);
font-family: Lato;
min-width: 300px;
opacity: 0.9;
z-index: 2;
z-index: 270;
h2 {
padding: 5px;
}

View file

@ -22,10 +22,21 @@
src = source ?? placeholderSrc;
});
function noDrag() {
return false;
}
onDestroy(unsubscribe);
</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>
img {

View file

@ -49,6 +49,8 @@
</form>
<style lang="scss">
@import "../../../style/breakpoints.scss";
form.selectCharacterScene {
font-family: "Press Start 2P";
pointer-events: auto;
@ -91,7 +93,7 @@
}
}
@media only screen and (max-width: 800px) {
@include media-breakpoint-up(md) {
form.selectCharacterScene button.selectCharacterButtonLeft {
left: 5vw;
}