Merge branch 'develop' of github.com:thecodingmachine/workadventure into MenuSvelte
This commit is contained in:
commit
fe585297fc
167 changed files with 5730 additions and 12289 deletions
|
@ -30,6 +30,12 @@
|
|||
import {gameOverlayVisibilityStore} from "../Stores/GameOverlayStoreVisibility";
|
||||
import {consoleGlobalMessageManagerVisibleStore} from "../Stores/ConsoleGlobalMessageManagerStore";
|
||||
import ConsoleGlobalMessageManager from "./ConsoleGlobalMessageManager/ConsoleGlobalMessageManager.svelte";
|
||||
import AdminMessage from "./TypeMessage/BanMessage.svelte";
|
||||
import TextMessage from "./TypeMessage/TextMessage.svelte";
|
||||
import {banMessageVisibleStore} from "../Stores/TypeMessageStore/BanMessageStore";
|
||||
import {textMessageVisibleStore} from "../Stores/TypeMessageStore/TextMessageStore";
|
||||
import {warningContainerStore} from "../Stores/MenuStore";
|
||||
import WarningContainer from "./WarningContainer/WarningContainer.svelte";
|
||||
|
||||
export let game: Game;
|
||||
|
||||
|
@ -61,6 +67,16 @@
|
|||
<EnableCameraScene game={game}></EnableCameraScene>
|
||||
</div>
|
||||
{/if}
|
||||
{#if $banMessageVisibleStore}
|
||||
<div>
|
||||
<AdminMessage></AdminMessage>
|
||||
</div>
|
||||
{/if}
|
||||
{#if $textMessageVisibleStore}
|
||||
<div>
|
||||
<TextMessage></TextMessage>
|
||||
</div>
|
||||
{/if}
|
||||
{#if $soundPlayingStore}
|
||||
<div>
|
||||
<AudioPlaying url={$soundPlayingStore} />
|
||||
|
@ -88,7 +104,7 @@
|
|||
{/if}
|
||||
{#if $consoleGlobalMessageManagerVisibleStore}
|
||||
<div>
|
||||
<ConsoleGlobalMessageManager game={game}></ConsoleGlobalMessageManager>
|
||||
<ConsoleGlobalMessageManager></ConsoleGlobalMessageManager>
|
||||
</div>
|
||||
{/if}
|
||||
{#if $helpCameraSettingsVisibleStore}
|
||||
|
@ -107,4 +123,7 @@
|
|||
{#if $chatVisibilityStore}
|
||||
<Chat></Chat>
|
||||
{/if}
|
||||
{#if $warningContainerStore}
|
||||
<WarningContainer></WarningContainer>
|
||||
{/if}
|
||||
</div>
|
||||
|
|
|
@ -3,9 +3,12 @@
|
|||
import { chatMessagesStore, chatVisibilityStore } from "../../Stores/ChatStore";
|
||||
import ChatMessageForm from './ChatMessageForm.svelte';
|
||||
import ChatElement from './ChatElement.svelte';
|
||||
import { afterUpdate, beforeUpdate } from "svelte";
|
||||
import {afterUpdate, beforeUpdate} from "svelte";
|
||||
import {HtmlUtils} from "../../WebRtc/HtmlUtils";
|
||||
|
||||
let listDom: HTMLElement;
|
||||
let chatWindowElement: HTMLElement;
|
||||
let handleFormBlur: { blur():void };
|
||||
let autoscroll: boolean;
|
||||
|
||||
beforeUpdate(() => {
|
||||
|
@ -16,6 +19,12 @@
|
|||
if (autoscroll) listDom.scrollTo(0, listDom.scrollHeight);
|
||||
});
|
||||
|
||||
function onClick(event: MouseEvent) {
|
||||
if (HtmlUtils.isClickedOutside(event, chatWindowElement)) {
|
||||
handleFormBlur.blur();
|
||||
}
|
||||
}
|
||||
|
||||
function closeChat() {
|
||||
chatVisibilityStore.set(false);
|
||||
}
|
||||
|
@ -26,37 +35,42 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<svelte:window on:keydown={onKeyDown}/>
|
||||
<svelte:window on:keydown={onKeyDown} on:click={onClick}/>
|
||||
|
||||
|
||||
<aside class="chatWindow" transition:fly="{{ x: -1000, duration: 500 }}">
|
||||
<section class="chatWindowTitle">
|
||||
<h1>Your chat history <span class="float-right" on:click={closeChat}>×</span></h1>
|
||||
|
||||
</section>
|
||||
<aside class="chatWindow" transition:fly="{{ x: -1000, duration: 500 }}" bind:this={chatWindowElement}>
|
||||
<p class="close-icon" on:click={closeChat}>×</p>
|
||||
<section class="messagesList" bind:this={listDom}>
|
||||
<ul>
|
||||
<li><p class="system-text">Here is your chat history: </p></li>
|
||||
{#each $chatMessagesStore as message, i}
|
||||
<li><ChatElement message={message} line={i}></ChatElement></li>
|
||||
{/each}
|
||||
</ul>
|
||||
</section>
|
||||
<section class="messageForm">
|
||||
<ChatMessageForm></ChatMessageForm>
|
||||
<ChatMessageForm bind:handleForm={handleFormBlur}></ChatMessageForm>
|
||||
</section>
|
||||
</aside>
|
||||
|
||||
<style lang="scss">
|
||||
h1 {
|
||||
font-family: 'Whiteney';
|
||||
|
||||
span.float-right {
|
||||
font-size: 30px;
|
||||
line-height: 25px;
|
||||
font-weight: bold;
|
||||
float: right;
|
||||
cursor: pointer;
|
||||
}
|
||||
p.close-icon {
|
||||
position: absolute;
|
||||
padding: 4px;
|
||||
right: 12px;
|
||||
font-size: 30px;
|
||||
line-height: 25px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
p.system-text {
|
||||
border-radius: 8px;
|
||||
margin-bottom: 10px;
|
||||
padding:6px;
|
||||
overflow-wrap: break-word;
|
||||
max-width: 100%;
|
||||
background: gray;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
aside.chatWindow {
|
||||
|
@ -78,16 +92,8 @@
|
|||
border-bottom-right-radius: 16px;
|
||||
border-top-right-radius: 16px;
|
||||
|
||||
h1 {
|
||||
background-color: #5f5f5f;
|
||||
border-radius: 8px;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.chatWindowTitle {
|
||||
flex: 0 100px;
|
||||
}
|
||||
.messagesList {
|
||||
margin-top: 35px;
|
||||
overflow-y: auto;
|
||||
flex: auto;
|
||||
|
||||
|
@ -98,7 +104,7 @@
|
|||
}
|
||||
.messageForm {
|
||||
flex: 0 70px;
|
||||
padding-top: 20px;
|
||||
padding-top: 15px;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -7,13 +7,14 @@
|
|||
|
||||
export let message: ChatMessage;
|
||||
export let line: number;
|
||||
const chatStyleLink = "color: white; text-decoration: underline;";
|
||||
|
||||
$: author = message.author as PlayerInterface;
|
||||
$: targets = message.targets || [];
|
||||
$: texts = message.text || [];
|
||||
|
||||
function urlifyText(text: string): string {
|
||||
return HtmlUtils.urlify(text)
|
||||
return HtmlUtils.urlify(text, chatStyleLink);
|
||||
}
|
||||
function renderDate(date: Date) {
|
||||
return date.toLocaleTimeString(navigator.language, {
|
||||
|
@ -29,7 +30,7 @@
|
|||
<div class="chatElement">
|
||||
<div class="messagePart">
|
||||
{#if message.type === ChatMessageTypes.userIncoming}
|
||||
>> {#each targets as target, index}<ChatPlayerName player={target} line={line}></ChatPlayerName>{#if !isLastIteration(index)}, {/if}{/each} enter <span class="date">({renderDate(message.date)})</span>
|
||||
>> {#each targets as target, index}<ChatPlayerName player={target} line={line}></ChatPlayerName>{#if !isLastIteration(index)}, {/if}{/each} entered <span class="date">({renderDate(message.date)})</span>
|
||||
{:else if message.type === ChatMessageTypes.userOutcoming}
|
||||
<< {#each targets as target, index}<ChatPlayerName player={target} line={line}></ChatPlayerName>{#if !isLastIteration(index)}, {/if}{/each} left <span class="date">({renderDate(message.date)})</span>
|
||||
{:else if message.type === ChatMessageTypes.me}
|
||||
|
@ -48,7 +49,7 @@
|
|||
|
||||
<style lang="scss">
|
||||
h4, p {
|
||||
font-family: 'Whiteney';
|
||||
font-family: Lato;
|
||||
}
|
||||
div.chatElement {
|
||||
display: flex;
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
<script lang="ts">
|
||||
import {chatMessagesStore, chatInputFocusStore} from "../../Stores/ChatStore";
|
||||
|
||||
export const handleForm = {
|
||||
blur() {
|
||||
inputElement.blur();
|
||||
}
|
||||
}
|
||||
let inputElement: HTMLElement;
|
||||
let newMessageText = '';
|
||||
|
||||
function onFocus() {
|
||||
|
@ -18,7 +24,7 @@
|
|||
</script>
|
||||
|
||||
<form on:submit|preventDefault={saveMessage}>
|
||||
<input type="text" bind:value={newMessageText} placeholder="Enter your message..." on:focus={onFocus} on:blur={onBlur} >
|
||||
<input type="text" bind:value={newMessageText} placeholder="Enter your message..." on:focus={onFocus} on:blur={onBlur} bind:this={inputElement}>
|
||||
<button type="submit">
|
||||
<img src="/static/images/send.png" alt="Send" width="20">
|
||||
</button>
|
||||
|
@ -32,26 +38,25 @@
|
|||
|
||||
input {
|
||||
flex: auto;
|
||||
background-color: #42464d;
|
||||
background-color: #254560;
|
||||
color: white;
|
||||
border-bottom-left-radius: 4px;
|
||||
border-top-left-radius: 4px;
|
||||
border: none;
|
||||
font-size: 22px;
|
||||
font-family: Whiteney;
|
||||
font-family: Lato;
|
||||
padding-left: 6px;
|
||||
min-width: 0; //Needed so that the input doesn't overflow the container in firefox
|
||||
outline: none;
|
||||
}
|
||||
|
||||
button {
|
||||
background-color: #42464d;
|
||||
color: white;
|
||||
background-color: #254560;
|
||||
border-bottom-right-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
border: none;
|
||||
border-left: solid black 1px;
|
||||
border-left: solid white 1px;
|
||||
font-size: 16px;
|
||||
font-family: Whiteney;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,11 +1,25 @@
|
|||
<script lang="typescript">
|
||||
import { fly } from 'svelte/transition';
|
||||
import InputTextGlobalMessage from "./InputTextGlobalMessage.svelte";
|
||||
import UploadAudioGlobalMessage from "./UploadAudioGlobalMessage.svelte";
|
||||
import {gameManager} from "../../Phaser/Game/GameManager";
|
||||
import type {Game} from "../../Phaser/Game/Game";
|
||||
import { gameManager } from "../../Phaser/Game/GameManager";
|
||||
import { consoleGlobalMessageManagerVisibleStore } from "../../Stores/ConsoleGlobalMessageManagerStore";
|
||||
|
||||
let inputSendTextActive = true;
|
||||
let uploadMusicActive = false;
|
||||
let handleSendText: { sendTextMessage(broadcast: boolean): void };
|
||||
let handleSendAudio: { sendAudioMessage(broadcast: boolean): Promise<void> };
|
||||
let broadcastToWorld = false;
|
||||
|
||||
function closeConsoleGlobalMessage() {
|
||||
consoleGlobalMessageManagerVisibleStore.set(false)
|
||||
}
|
||||
|
||||
function onKeyDown(e:KeyboardEvent) {
|
||||
if (e.key === 'Escape') {
|
||||
closeConsoleGlobalMessage();
|
||||
}
|
||||
}
|
||||
|
||||
function inputSendTextActivate() {
|
||||
inputSendTextActive = true;
|
||||
|
@ -16,28 +30,121 @@
|
|||
uploadMusicActive = true;
|
||||
inputSendTextActive = false;
|
||||
}
|
||||
|
||||
function send() {
|
||||
if (inputSendTextActive) {
|
||||
handleSendText.sendTextMessage(broadcastToWorld);
|
||||
}
|
||||
if (uploadMusicActive) {
|
||||
handleSendAudio.sendAudioMessage(broadcastToWorld);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:window on:keydown={onKeyDown}/>
|
||||
|
||||
<div class="main-console nes-container is-rounded">
|
||||
<!-- <div class="console nes-container is-rounded">
|
||||
<img class="btn-close" src="resources/logos/send-yellow.svg" alt="Close">
|
||||
</div>-->
|
||||
<div class="main-global-message">
|
||||
<h2> Global Message </h2>
|
||||
<div class="global-message">
|
||||
<div class="menu">
|
||||
<button class="nes-btn {inputSendTextActive ? 'is-disabled' : ''}" on:click|preventDefault={inputSendTextActivate}>Message</button>
|
||||
<button class="nes-btn {uploadMusicActive ? 'is-disabled' : ''}" on:click|preventDefault={inputUploadMusicActivate}>Audio</button>
|
||||
</div>
|
||||
<div class="main-input">
|
||||
{#if inputSendTextActive}
|
||||
<InputTextGlobalMessage gameManager={gameManager}></InputTextGlobalMessage>
|
||||
{/if}
|
||||
{#if uploadMusicActive}
|
||||
<UploadAudioGlobalMessage gameManager={gameManager}></UploadAudioGlobalMessage>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="console-global-message">
|
||||
<div class="menu-console-global-message nes-container is-rounded" transition:fly="{{ x: -1000, duration: 500 }}">
|
||||
<button type="button" class="nes-btn {inputSendTextActive ? 'is-disabled' : ''}" on:click|preventDefault={inputSendTextActivate}>Message</button>
|
||||
<button type="button" class="nes-btn {uploadMusicActive ? 'is-disabled' : ''}" on:click|preventDefault={inputUploadMusicActivate}>Audio</button>
|
||||
</div>
|
||||
<div class="main-console-global-message nes-container is-rounded" transition:fly="{{ y: -1000, duration: 500 }}">
|
||||
<div class="title-console-global-message">
|
||||
<h2>Global Message</h2>
|
||||
<button type="button" class="nes-btn is-error" on:click|preventDefault={closeConsoleGlobalMessage}><i class="nes-icon close is-small"></i></button>
|
||||
</div>
|
||||
<div class="content-console-global-message">
|
||||
{#if inputSendTextActive}
|
||||
<InputTextGlobalMessage gameManager={gameManager} bind:handleSending={handleSendText}/>
|
||||
{/if}
|
||||
{#if uploadMusicActive}
|
||||
<UploadAudioGlobalMessage gameManager={gameManager} bind:handleSending={handleSendAudio}/>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="footer-console-global-message">
|
||||
<label>
|
||||
<input type="checkbox" class="nes-checkbox is-dark nes-pointer" bind:checked={broadcastToWorld}>
|
||||
<span>Broadcast to all rooms of the world</span>
|
||||
</label>
|
||||
<button class="nes-btn is-primary" on:click|preventDefault={send}>Send</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
.nes-container {
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
div.console-global-message {
|
||||
top: 20vh;
|
||||
width: 50vw;
|
||||
height: 50vh;
|
||||
position: relative;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
padding: 0;
|
||||
|
||||
pointer-events: auto;
|
||||
|
||||
div.menu-console-global-message {
|
||||
flex: 1 1 auto;
|
||||
max-width: 180px;
|
||||
|
||||
text-align: center;
|
||||
background-color: #333333;
|
||||
|
||||
button {
|
||||
width: 136px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
div.main-console-global-message {
|
||||
flex: 1 1 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
background-color: #333333;
|
||||
|
||||
div.title-console-global-message {
|
||||
flex: 0 0 auto;
|
||||
height: 50px;
|
||||
margin-bottom: 10px;
|
||||
|
||||
text-align: center;
|
||||
color: whitesmoke;
|
||||
|
||||
.nes-btn {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
div.content-console-global-message {
|
||||
flex: 1 1 auto;
|
||||
max-height: calc(100% - 120px);
|
||||
}
|
||||
|
||||
div.footer-console-global-message {
|
||||
height: 50px;
|
||||
margin-top: 10px;
|
||||
text-align: center;
|
||||
|
||||
label {
|
||||
margin: 0;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
max-width: 30%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
<script lang="ts">
|
||||
import {consoleGlobalMessageManagerFocusStore, consoleGlobalMessageManagerVisibleStore } from "../../Stores/ConsoleGlobalMessageManagerStore";
|
||||
import {onMount} from "svelte";
|
||||
import type {GameManager} from "../../Phaser/Game/GameManager";
|
||||
import type {PlayGlobalMessageInterface} from "../../Connexion/ConnexionModels";
|
||||
import {AdminMessageEventTypes} from "../../Connexion/AdminMessagesService";
|
||||
import type {Quill} from "quill";
|
||||
import { consoleGlobalMessageManagerFocusStore, consoleGlobalMessageManagerVisibleStore } from "../../Stores/ConsoleGlobalMessageManagerStore";
|
||||
import {onDestroy, onMount} from "svelte";
|
||||
import type { GameManager } from "../../Phaser/Game/GameManager";
|
||||
import { AdminMessageEventTypes } from "../../Connexion/AdminMessagesService";
|
||||
import type { Quill } from "quill";
|
||||
import type { PlayGlobalMessageInterface } from "../../Connexion/ConnexionModels";
|
||||
|
||||
//toolbar
|
||||
export const toolbarOptions = [
|
||||
const toolbarOptions = [
|
||||
['bold', 'italic', 'underline', 'strike'], // toggled buttons
|
||||
['blockquote', 'code-block'],
|
||||
|
||||
|
@ -32,12 +32,31 @@
|
|||
|
||||
export let gameManager: GameManager;
|
||||
|
||||
let gameScene = gameManager.getCurrentGameScene();
|
||||
const gameScene = gameManager.getCurrentGameScene();
|
||||
let quill: Quill;
|
||||
let INPUT_CONSOLE_MESSAGE: HTMLDivElement;
|
||||
|
||||
const MESSAGE_TYPE = AdminMessageEventTypes.admin;
|
||||
|
||||
export const handleSending = {
|
||||
sendTextMessage(broadcastToWorld: boolean) {
|
||||
if (gameScene == undefined) {
|
||||
return;
|
||||
}
|
||||
const text = JSON.stringify(quill.getContents(0, quill.getLength()));
|
||||
|
||||
const textGlobalMessage: PlayGlobalMessageInterface = {
|
||||
type: MESSAGE_TYPE,
|
||||
content: text,
|
||||
broadcastToWorld: broadcastToWorld
|
||||
};
|
||||
|
||||
quill.deleteText(0, quill.getLength());
|
||||
gameScene.connection?.emitGlobalMessage(textGlobalMessage);
|
||||
disableConsole();
|
||||
}
|
||||
}
|
||||
|
||||
//Quill
|
||||
onMount(async () => {
|
||||
|
||||
|
@ -45,49 +64,28 @@
|
|||
const {default: Quill} = await import("quill"); // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
|
||||
quill = new Quill(INPUT_CONSOLE_MESSAGE, {
|
||||
placeholder: 'Enter your message here...',
|
||||
theme: 'snow',
|
||||
modules: {
|
||||
toolbar: toolbarOptions
|
||||
},
|
||||
});
|
||||
|
||||
quill.on('selection-change', function (range, oldRange) {
|
||||
if (range === null && oldRange !== null) {
|
||||
consoleGlobalMessageManagerFocusStore.set(false);
|
||||
} else if (range !== null && oldRange === null)
|
||||
consoleGlobalMessageManagerFocusStore.set(true);
|
||||
});
|
||||
consoleGlobalMessageManagerFocusStore.set(true);
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
consoleGlobalMessageManagerFocusStore.set(false);
|
||||
})
|
||||
|
||||
function disableConsole() {
|
||||
consoleGlobalMessageManagerVisibleStore.set(false);
|
||||
consoleGlobalMessageManagerFocusStore.set(false);
|
||||
}
|
||||
|
||||
function SendTextMessage() {
|
||||
if (gameScene == undefined) {
|
||||
return;
|
||||
}
|
||||
const text = quill.getText(0, quill.getLength());
|
||||
|
||||
const GlobalMessage: PlayGlobalMessageInterface = {
|
||||
id: "1", // FIXME: use another ID?
|
||||
message: text,
|
||||
type: MESSAGE_TYPE
|
||||
};
|
||||
|
||||
quill.deleteText(0, quill.getLength());
|
||||
gameScene.connection?.emitGlobalMessage(GlobalMessage);
|
||||
disableConsole();
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<section class="section-input-send-text">
|
||||
<div class="input-send-text" bind:this={INPUT_CONSOLE_MESSAGE}></div>
|
||||
<div class="btn-action">
|
||||
<button class="nes-btn is-primary" on:click|preventDefault={SendTextMessage}>Send</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<script lang="ts">
|
||||
import {HtmlUtils} from "../../WebRtc/HtmlUtils";
|
||||
import type {GameManager} from "../../Phaser/Game/GameManager";
|
||||
import {consoleGlobalMessageManagerFocusStore, consoleGlobalMessageManagerVisibleStore} from "../../Stores/ConsoleGlobalMessageManagerStore";
|
||||
import {AdminMessageEventTypes} from "../../Connexion/AdminMessagesService";
|
||||
import type {PlayGlobalMessageInterface} from "../../Connexion/ConnexionModels";
|
||||
import { HtmlUtils } from "../../WebRtc/HtmlUtils";
|
||||
import type { GameManager } from "../../Phaser/Game/GameManager";
|
||||
import { consoleGlobalMessageManagerFocusStore, consoleGlobalMessageManagerVisibleStore } from "../../Stores/ConsoleGlobalMessageManagerStore";
|
||||
import { AdminMessageEventTypes } from "../../Connexion/AdminMessagesService";
|
||||
import uploadFile from "../images/music-file.svg";
|
||||
import type {PlayGlobalMessageInterface} from "../../Connexion/ConnexionModels";
|
||||
|
||||
interface EventTargetFiles extends EventTarget {
|
||||
files: Array<File>;
|
||||
|
@ -13,37 +13,38 @@
|
|||
export let gameManager: GameManager;
|
||||
|
||||
let gameScene = gameManager.getCurrentGameScene();
|
||||
let fileinput: HTMLInputElement;
|
||||
let filename: string;
|
||||
let filesize: string;
|
||||
let errorfile: boolean;
|
||||
let fileInput: HTMLInputElement;
|
||||
let fileName: string;
|
||||
let fileSize: string;
|
||||
let errorFile: boolean;
|
||||
|
||||
const AUDIO_TYPE = AdminMessageEventTypes.audio;
|
||||
|
||||
export const handleSending = {
|
||||
async sendAudioMessage(broadcast: boolean) {
|
||||
if (gameScene == undefined) {
|
||||
return;
|
||||
}
|
||||
const inputAudio = HtmlUtils.getElementByIdOrFail<HTMLInputElement>("input-send-audio");
|
||||
const selectedFile = inputAudio.files ? inputAudio.files[0] : null;
|
||||
if (!selectedFile) {
|
||||
errorFile = true;
|
||||
throw 'no file selected';
|
||||
}
|
||||
|
||||
async function SendAudioMessage() {
|
||||
if (gameScene == undefined) {
|
||||
return;
|
||||
}
|
||||
const inputAudio = HtmlUtils.getElementByIdOrFail<HTMLInputElement>("input-send-audio");
|
||||
const selectedFile = inputAudio.files ? inputAudio.files[0] : null;
|
||||
if (!selectedFile) {
|
||||
errorfile = true;
|
||||
throw 'no file selected';
|
||||
}
|
||||
const fd = new FormData();
|
||||
fd.append('file', selectedFile);
|
||||
const res = await gameScene.connection?.uploadAudio(fd);
|
||||
|
||||
const fd = new FormData();
|
||||
fd.append('file', selectedFile);
|
||||
const res = await gameScene.connection?.uploadAudio(fd);
|
||||
|
||||
const GlobalMessage: PlayGlobalMessageInterface = {
|
||||
id: (res as { id: string }).id,
|
||||
message: (res as { path: string }).path,
|
||||
type: AUDIO_TYPE
|
||||
const audioGlobalMessage: PlayGlobalMessageInterface = {
|
||||
content: (res as { path: string }).path,
|
||||
type: AUDIO_TYPE,
|
||||
broadcastToWorld: broadcast
|
||||
}
|
||||
inputAudio.value = '';
|
||||
gameScene.connection?.emitGlobalMessage(audioGlobalMessage);
|
||||
disableConsole();
|
||||
}
|
||||
inputAudio.value = '';
|
||||
gameScene.connection?.emitGlobalMessage(GlobalMessage);
|
||||
disableConsole();
|
||||
}
|
||||
|
||||
function inputAudioFile(event: Event) {
|
||||
|
@ -57,9 +58,9 @@
|
|||
return;
|
||||
}
|
||||
|
||||
filename = file.name;
|
||||
filesize = getFileSize(file.size);
|
||||
errorfile = false;
|
||||
fileName = file.name;
|
||||
fileSize = getFileSize(file.size);
|
||||
errorFile = false;
|
||||
}
|
||||
|
||||
function getFileSize(number: number) {
|
||||
|
@ -82,46 +83,46 @@
|
|||
|
||||
|
||||
<section class="section-input-send-audio">
|
||||
<div class="input-send-audio">
|
||||
<img src="{uploadFile}" alt="Upload a file" on:click|preventDefault={ () => {fileinput.click();}}>
|
||||
{#if filename != undefined}
|
||||
<label for="input-send-audio">{filename} : {filesize}</label>
|
||||
{/if}
|
||||
{#if errorfile}
|
||||
<p class="err">No file selected. You need to upload a file before sending it.</p>
|
||||
{/if}
|
||||
<input type="file" id="input-send-audio" bind:this={fileinput} on:change={(e) => {inputAudioFile(e)}}>
|
||||
</div>
|
||||
<div class="btn-action">
|
||||
<button class="nes-btn is-primary" on:click|preventDefault={SendAudioMessage}>Send</button>
|
||||
</div>
|
||||
<img class="nes-pointer" src="{uploadFile}" alt="Upload a file" on:click|preventDefault={ () => {fileInput.click();}}>
|
||||
{#if fileName !== undefined}
|
||||
<p>{fileName} : {fileSize}</p>
|
||||
{/if}
|
||||
{#if errorFile}
|
||||
<p class="err">No file selected. You need to upload a file before sending it.</p>
|
||||
{/if}
|
||||
<input type="file" id="input-send-audio" bind:this={fileInput} on:change={(e) => {inputAudioFile(e)}}>
|
||||
</section>
|
||||
|
||||
<style lang="scss">
|
||||
//UploadAudioGlobalMessage
|
||||
.section-input-send-audio {
|
||||
margin: 10px;
|
||||
}
|
||||
section.section-input-send-audio {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.section-input-send-audio .input-send-audio {
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.section-input-send-audio #input-send-audio{
|
||||
display: none;
|
||||
}
|
||||
img {
|
||||
flex: 1 1 auto;
|
||||
|
||||
.section-input-send-audio div.input-send-audio label{
|
||||
color: white;
|
||||
}
|
||||
max-height: 80%;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.section-input-send-audio div.input-send-audio p.err {
|
||||
color: #ce372b;
|
||||
text-align: center;
|
||||
}
|
||||
p {
|
||||
flex: 1 1 auto;
|
||||
|
||||
.section-input-send-audio div.input-send-audio img{
|
||||
height: 150px;
|
||||
cursor: url('../../../style/images/cursor_pointer.png'), pointer;
|
||||
margin-bottom: 5px;
|
||||
|
||||
color: whitesmoke;
|
||||
font-size: 1rem;
|
||||
|
||||
&.err {
|
||||
color: #ce372b;
|
||||
}
|
||||
}
|
||||
|
||||
input {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
96
front/src/Components/TypeMessage/BanMessage.svelte
Normal file
96
front/src/Components/TypeMessage/BanMessage.svelte
Normal file
|
@ -0,0 +1,96 @@
|
|||
<script lang="ts">
|
||||
import { fly } from "svelte/transition";
|
||||
import {banMessageVisibleStore, banMessageContentStore} from "../../Stores/TypeMessageStore/BanMessageStore";
|
||||
import {onMount} from "svelte";
|
||||
|
||||
const text = $banMessageContentStore;
|
||||
const NAME_BUTTON = 'Ok';
|
||||
let nbSeconds = 10;
|
||||
let nameButton = '';
|
||||
|
||||
onMount(() => {
|
||||
timeToRead()
|
||||
})
|
||||
|
||||
function timeToRead() {
|
||||
nbSeconds -= 1;
|
||||
nameButton = nbSeconds.toString();
|
||||
if ( nbSeconds > 0 ) {
|
||||
setTimeout( () => {
|
||||
timeToRead();
|
||||
}, 1000);
|
||||
} else {
|
||||
nameButton = NAME_BUTTON;
|
||||
}
|
||||
}
|
||||
|
||||
function closeBanMessage() {
|
||||
banMessageVisibleStore.set(false);
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="main-ban-message nes-container is-rounded" transition:fly="{{ y: -1000, duration: 500 }}">
|
||||
<h2 class="title-ban-message"><img src="resources/logos/report.svg" alt="***"/> Important message <img src="resources/logos/report.svg" alt="***"/></h2>
|
||||
<div class="content-ban-message">
|
||||
<p>{text}</p>
|
||||
</div>
|
||||
<div class="footer-ban-message">
|
||||
<button type="button" class="nes-btn {nameButton === NAME_BUTTON ? 'is-primary' : 'is-error'}" disabled="{!(nameButton === NAME_BUTTON)}" on:click|preventDefault={closeBanMessage}>{nameButton}</button>
|
||||
</div>
|
||||
<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;
|
||||
|
||||
height: 70vh;
|
||||
width: 60vw;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
padding-bottom: 0;
|
||||
|
||||
pointer-events: auto;
|
||||
background-color: #333333;
|
||||
color: whitesmoke;
|
||||
|
||||
h2.title-ban-message {
|
||||
flex: 1 1 auto;
|
||||
max-height: 50px;
|
||||
margin-bottom: 20px;
|
||||
|
||||
text-align: center;
|
||||
|
||||
img {
|
||||
height: 50px;
|
||||
}
|
||||
}
|
||||
|
||||
div.content-ban-message {
|
||||
flex: 1 1 auto;
|
||||
max-height: calc(100% - 50px);
|
||||
overflow: auto;
|
||||
|
||||
p {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
}
|
||||
|
||||
div.footer-ban-message {
|
||||
height: 50px;
|
||||
margin-top: 10px;
|
||||
text-align: center;
|
||||
|
||||
button {
|
||||
width: 88px;
|
||||
height: 44px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
59
front/src/Components/TypeMessage/TextMessage.svelte
Normal file
59
front/src/Components/TypeMessage/TextMessage.svelte
Normal file
|
@ -0,0 +1,59 @@
|
|||
<script lang="ts">
|
||||
import { fly } from "svelte/transition";
|
||||
import {textMessageContentStore, textMessageVisibleStore} from "../../Stores/TypeMessageStore/TextMessageStore";
|
||||
import { QuillDeltaToHtmlConverter } from "quill-delta-to-html";
|
||||
|
||||
const content = JSON.parse($textMessageContentStore);
|
||||
const converter = new QuillDeltaToHtmlConverter(content.ops, {inlineStyles: true});
|
||||
const NAME_BUTTON = 'Ok';
|
||||
|
||||
function closeTextMessage() {
|
||||
textMessageVisibleStore.set(false);
|
||||
}
|
||||
|
||||
function onKeyDown(e:KeyboardEvent) {
|
||||
if (e.key === 'Escape') {
|
||||
closeTextMessage();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:window on:keydown={onKeyDown}/>
|
||||
|
||||
<div class="main-text-message nes-container is-rounded" transition:fly="{{ x: -1000, duration: 500 }}">
|
||||
<div class="content-text-message">
|
||||
{@html converter.convert()}
|
||||
</div>
|
||||
<div class="footer-text-message">
|
||||
<button type="button" class="nes-btn is-primary" on:click|preventDefault={closeTextMessage}>{NAME_BUTTON}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
div.main-text-message {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
max-height: 25vh;
|
||||
width: 80vw;
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
padding-bottom: 0;
|
||||
|
||||
pointer-events: auto;
|
||||
background-color: #333333;
|
||||
|
||||
div.content-text-message {
|
||||
flex: 1 1 auto;
|
||||
max-height: calc(100% - 50px);
|
||||
color: whitesmoke;
|
||||
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
div.footer-text-message {
|
||||
height: 50px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -37,9 +37,7 @@
|
|||
<img alt="Report this user" src={reportImg}>
|
||||
<span>Report/Block</span>
|
||||
</button>
|
||||
{#if $streamStore }
|
||||
<video use:srcObject={$streamStore} autoplay playsinline on:click={() => videoFocusStore.toggleFocus(peer)}></video>
|
||||
{/if}
|
||||
<img src={blockSignImg} class="block-logo" alt="Block" />
|
||||
{#if $constraintStore && $constraintStore.audio !== false}
|
||||
<SoundMeterWidget stream={$streamStore}></SoundMeterWidget>
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
import type { UserSimplePeerInterface } from "../../WebRtc/SimplePeer";
|
||||
import { STUN_SERVER, TURN_PASSWORD, TURN_SERVER, TURN_USER } from "../../Enum/EnvironmentVariable";
|
||||
|
||||
export function getColorByString(str: string): string | null {
|
||||
let hash = 0;
|
||||
if (str.length === 0) {
|
||||
|
@ -15,7 +18,7 @@ export function getColorByString(str: string): string | null {
|
|||
return color;
|
||||
}
|
||||
|
||||
export function srcObject(node: HTMLVideoElement, stream: MediaStream) {
|
||||
export function srcObject(node: HTMLVideoElement, stream: MediaStream | null) {
|
||||
node.srcObject = stream;
|
||||
return {
|
||||
update(newStream: MediaStream) {
|
||||
|
@ -25,3 +28,19 @@ export function srcObject(node: HTMLVideoElement, stream: MediaStream) {
|
|||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function getIceServersConfig(user: UserSimplePeerInterface): RTCIceServer[] {
|
||||
const config: RTCIceServer[] = [
|
||||
{
|
||||
urls: STUN_SERVER.split(","),
|
||||
},
|
||||
];
|
||||
if (TURN_SERVER !== "") {
|
||||
config.push({
|
||||
urls: TURN_SERVER.split(","),
|
||||
username: user.webRtcUser || TURN_USER,
|
||||
credential: user.webRtcPassword || TURN_PASSWORD,
|
||||
});
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
|
|
@ -45,8 +45,9 @@
|
|||
|
||||
.visitCard {
|
||||
pointer-events: all;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translate(-50%, 0);
|
||||
margin-top: 200px;
|
||||
max-width: 80vw;
|
||||
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
<script lang="typescript">
|
||||
import { fly } from 'svelte/transition';
|
||||
import {userIsAdminStore} from "../../Stores/GameStore";
|
||||
import {ADMIN_URL} from "../../Enum/EnvironmentVariable";
|
||||
|
||||
const upgradeLink = ADMIN_URL+'/pricing';
|
||||
|
||||
</script>
|
||||
|
||||
<main class="warningMain" transition:fly="{{ y: -200, duration: 500 }}">
|
||||
<h2>Warning!</h2>
|
||||
{#if $userIsAdminStore}
|
||||
<p>This world is close to its limit!. You can upgrade its capacity <a href="{upgradeLink}" target="_blank">here</a></p>
|
||||
{:else}
|
||||
<p>This world is close to its limit!</p>
|
||||
{/if}
|
||||
|
||||
</main>
|
||||
|
||||
<style lang="scss">
|
||||
main.warningMain {
|
||||
pointer-events: auto;
|
||||
width: 100vw;
|
||||
background-color: red;
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translate(-50%, 0);
|
||||
font-family: Lato;
|
||||
min-width: 300px;
|
||||
opacity: 0.9;
|
||||
z-index: 2;
|
||||
h2 {
|
||||
padding: 5px;
|
||||
}
|
||||
}
|
||||
</style>
|
Loading…
Add table
Add a link
Reference in a new issue