Merge pull request #1676 from albanbruder/feature-admin-message-queue

Display multiple admin messages
This commit is contained in:
David Négrier 2021-12-24 13:25:13 +01:00 committed by GitHub
commit 7d796611ae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 107 additions and 45 deletions

View File

@ -1,27 +1,22 @@
import { AdminMessageEventTypes, adminMessagesService } from "../Connexion/AdminMessagesService"; import { AdminMessageEventTypes, adminMessagesService } from "../Connexion/AdminMessagesService";
import { textMessageContentStore, textMessageVisibleStore } from "../Stores/TypeMessageStore/TextMessageStore"; import { textMessageStore } from "../Stores/TypeMessageStore/TextMessageStore";
import { soundPlayingStore } from "../Stores/SoundPlayingStore"; import { soundPlayingStore } from "../Stores/SoundPlayingStore";
import { UPLOADER_URL } from "../Enum/EnvironmentVariable"; import { UPLOADER_URL } from "../Enum/EnvironmentVariable";
import { banMessageContentStore, banMessageVisibleStore } from "../Stores/TypeMessageStore/BanMessageStore"; import { banMessageStore } from "../Stores/TypeMessageStore/BanMessageStore";
class UserMessageManager { class UserMessageManager {
receiveBannedMessageListener!: Function; receiveBannedMessageListener!: Function;
constructor() { constructor() {
adminMessagesService.messageStream.subscribe((event) => { adminMessagesService.messageStream.subscribe((event) => {
textMessageVisibleStore.set(false);
banMessageVisibleStore.set(false);
if (event.type === AdminMessageEventTypes.admin) { if (event.type === AdminMessageEventTypes.admin) {
textMessageContentStore.set(event.text); textMessageStore.addMessage(event.text);
textMessageVisibleStore.set(true);
} else if (event.type === AdminMessageEventTypes.audio) { } else if (event.type === AdminMessageEventTypes.audio) {
soundPlayingStore.playSound(UPLOADER_URL + event.text); soundPlayingStore.playSound(UPLOADER_URL + event.text);
} else if (event.type === AdminMessageEventTypes.ban) { } else if (event.type === AdminMessageEventTypes.ban) {
banMessageContentStore.set(event.text); banMessageStore.addMessage(event.text);
banMessageVisibleStore.set(true);
} else if (event.type === AdminMessageEventTypes.banned) { } else if (event.type === AdminMessageEventTypes.banned) {
banMessageContentStore.set(event.text); banMessageStore.addMessage(event.text);
banMessageVisibleStore.set(true);
this.receiveBannedMessageListener(); this.receiveBannedMessageListener();
} }
}); });

View File

@ -30,10 +30,10 @@
import EmoteMenu from "./EmoteMenu/EmoteMenu.svelte"; import EmoteMenu from "./EmoteMenu/EmoteMenu.svelte";
import VideoOverlay from "./Video/VideoOverlay.svelte"; import VideoOverlay from "./Video/VideoOverlay.svelte";
import { gameOverlayVisibilityStore } from "../Stores/GameOverlayStoreVisibility"; import { gameOverlayVisibilityStore } from "../Stores/GameOverlayStoreVisibility";
import AdminMessage from "./TypeMessage/BanMessage.svelte"; import BanMessageContainer from "./TypeMessage/BanMessageContainer.svelte";
import TextMessage from "./TypeMessage/TextMessage.svelte"; import TextMessageContainer from "./TypeMessage/TextMessageContainer.svelte";
import { banMessageVisibleStore } from "../Stores/TypeMessageStore/BanMessageStore"; import { banMessageStore } from "../Stores/TypeMessageStore/BanMessageStore";
import { textMessageVisibleStore } from "../Stores/TypeMessageStore/TextMessageStore"; import { textMessageStore } from "../Stores/TypeMessageStore/TextMessageStore";
import { warningContainerStore } from "../Stores/MenuStore"; import { warningContainerStore } from "../Stores/MenuStore";
import WarningContainer from "./WarningContainer/WarningContainer.svelte"; import WarningContainer from "./WarningContainer/WarningContainer.svelte";
import { layoutManagerVisibilityStore } from "../Stores/LayoutManagerStore"; import { layoutManagerVisibilityStore } from "../Stores/LayoutManagerStore";
@ -72,14 +72,13 @@
<EnableCameraScene {game} /> <EnableCameraScene {game} />
</div> </div>
{/if} {/if}
{#if $banMessageVisibleStore} {#if $banMessageStore.length > 0}
<div> <div>
<AdminMessage /> <BanMessageContainer />
</div> </div>
{/if} {:else if $textMessageStore.length > 0}
{#if $textMessageVisibleStore}
<div> <div>
<TextMessage /> <TextMessageContainer />
</div> </div>
{/if} {/if}
{#if $soundPlayingStore} {#if $soundPlayingStore}

View File

@ -1,12 +1,11 @@
<script lang="ts"> <script lang="ts">
import { fly } from "svelte/transition"; import { fly, fade } from "svelte/transition";
import { banMessageVisibleStore, banMessageContentStore } from "../../Stores/TypeMessageStore/BanMessageStore";
import { onMount } from "svelte"; import { onMount } from "svelte";
import type { Message } from "../../Stores/TypeMessageStore/MessageStore";
import { banMessageStore } from "../../Stores/TypeMessageStore/BanMessageStore";
export let message: Message;
let text: string;
$: {
text = $banMessageContentStore;
}
const NAME_BUTTON = "Ok"; const NAME_BUTTON = "Ok";
let nbSeconds = 10; let nbSeconds = 10;
let nameButton = ""; let nameButton = "";
@ -28,17 +27,21 @@
} }
function closeBanMessage() { function closeBanMessage() {
banMessageVisibleStore.set(false); banMessageStore.clearMessageById(message.id);
} }
</script> </script>
<div class="main-ban-message nes-container is-rounded" transition:fly={{ y: -1000, duration: 500 }}> <div
class="main-ban-message nes-container is-rounded"
in:fly={{ y: -1000, duration: 500, delay: 250 }}
out:fade={{ duration: 200 }}
>
<h2 class="title-ban-message"> <h2 class="title-ban-message">
<img src="resources/logos/report.svg" alt="***" /> Important message <img src="resources/logos/report.svg" alt="***" /> Important message
<img src="resources/logos/report.svg" alt="***" /> <img src="resources/logos/report.svg" alt="***" />
</h2> </h2>
<div class="content-ban-message"> <div class="content-ban-message">
<p>{text}</p> <p>{message.text}</p>
</div> </div>
<div class="footer-ban-message"> <div class="footer-ban-message">
<button <button

View File

@ -0,0 +1,13 @@
<script lang="ts">
import { flip } from "svelte/animate";
import { banMessageStore } from "../../Stores/TypeMessageStore/BanMessageStore";
import BanMessage from "./BanMessage.svelte";
</script>
<div class="main-ban-message-container">
{#each $banMessageStore.slice(0, 1) as message (message.id)}
<div animate:flip={{ duration: 250 }}>
<BanMessage {message} />
</div>
{/each}
</div>

View File

@ -1,17 +1,17 @@
<script lang="ts"> <script lang="ts">
import { fly } from "svelte/transition"; import { fly, fade } from "svelte/transition";
import { textMessageContentStore, textMessageVisibleStore } from "../../Stores/TypeMessageStore/TextMessageStore";
import { QuillDeltaToHtmlConverter } from "quill-delta-to-html"; import { QuillDeltaToHtmlConverter } from "quill-delta-to-html";
import type { Message } from "../../Stores/TypeMessageStore/MessageStore";
import { textMessageStore } from "../../Stores/TypeMessageStore/TextMessageStore";
let converter: QuillDeltaToHtmlConverter; export let message: Message;
$: {
const content = JSON.parse($textMessageContentStore); const content = JSON.parse(message.text);
converter = new QuillDeltaToHtmlConverter(content.ops, { inlineStyles: true }); const converter = new QuillDeltaToHtmlConverter(content.ops, { inlineStyles: true });
}
const NAME_BUTTON = "Ok"; const NAME_BUTTON = "Ok";
function closeTextMessage() { function closeTextMessage() {
textMessageVisibleStore.set(false); textMessageStore.clearMessageById(message.id);
} }
function onKeyDown(e: KeyboardEvent) { function onKeyDown(e: KeyboardEvent) {
@ -23,7 +23,11 @@
<svelte:window on:keydown={onKeyDown} /> <svelte:window on:keydown={onKeyDown} />
<div class="main-text-message nes-container is-rounded" transition:fly={{ x: -1000, duration: 500 }}> <div
class="main-text-message nes-container is-rounded"
in:fly={{ x: -1000, duration: 500, delay: 250 }}
out:fade={{ duration: 250 }}
>
<div class="content-text-message"> <div class="content-text-message">
{@html converter.convert()} {@html converter.convert()}
</div> </div>
@ -43,6 +47,8 @@
width: 80vw; width: 80vw;
margin-right: auto; margin-right: auto;
margin-left: auto; margin-left: auto;
margin-bottom: 16px;
margin-top: 0;
padding-bottom: 0; padding-bottom: 0;
pointer-events: auto; pointer-events: auto;

View File

@ -0,0 +1,21 @@
<script lang="ts">
import { flip } from "svelte/animate";
import TextMessage from "./TextMessage.svelte";
import { textMessageStore } from "../../Stores/TypeMessageStore/TextMessageStore";
const MAX_MESSAGES = 3;
</script>
<div class="main-text-message-container">
{#each $textMessageStore.slice(0, MAX_MESSAGES) as message (message.id)}
<div animate:flip={{ duration: 250 }}>
<TextMessage {message} />
</div>
{/each}
</div>
<style lang="scss">
div.main-text-message-container {
padding-top: 16px;
}
</style>

View File

@ -1,5 +1,3 @@
import { writable } from "svelte/store"; import { createMessageStore } from "./MessageStore";
export const banMessageVisibleStore = writable(false); export const banMessageStore = createMessageStore();
export const banMessageContentStore = writable("");

View File

@ -0,0 +1,29 @@
import { writable } from "svelte/store";
import { v4 as uuidv4 } from "uuid";
export interface Message {
id: string;
text: string;
}
/**
* A store that contains a list of messages to be displayed.
*/
export function createMessageStore() {
const { subscribe, update } = writable<Message[]>([]);
return {
subscribe,
addMessage: (text: string): void => {
update((messages: Message[]) => {
return [...messages, { id: uuidv4(), text }];
});
},
clearMessageById: (id: string): void => {
update((messages: Message[]) => {
messages = messages.filter((message) => message.id !== id);
return messages;
});
},
};
}

View File

@ -1,5 +1,3 @@
import { writable } from "svelte/store"; import { createMessageStore } from "./MessageStore";
export const textMessageVisibleStore = writable(false); export const textMessageStore = createMessageStore();
export const textMessageContentStore = writable("");