diff --git a/front/dist/index.tmpl.html b/front/dist/index.tmpl.html index 279609e8..7f541145 100644 --- a/front/dist/index.tmpl.html +++ b/front/dist/index.tmpl.html @@ -87,9 +87,6 @@ -
- -
diff --git a/front/package.json b/front/package.json index 6cf0ee97..1c938195 100644 --- a/front/package.json +++ b/front/package.json @@ -46,7 +46,8 @@ "quill": "1.3.6", "rxjs": "^6.6.3", "simple-peer": "^9.6.2", - "socket.io-client": "^2.3.0" + "socket.io-client": "^2.3.0", + "standardized-audio-context": "^25.2.4" }, "scripts": { "start": "TS_NODE_PROJECT=\"tsconfig-for-webpack.json\" webpack serve --open", diff --git a/front/src/Administration/GlobalMessageManager.ts b/front/src/Administration/GlobalMessageManager.ts index 95364e4c..1500a6ec 100644 --- a/front/src/Administration/GlobalMessageManager.ts +++ b/front/src/Administration/GlobalMessageManager.ts @@ -3,6 +3,8 @@ import {AUDIO_TYPE, MESSAGE_TYPE} from "./ConsoleGlobalMessageManager"; import {PUSHER_URL, UPLOADER_URL} from "../Enum/EnvironmentVariable"; import type {RoomConnection} from "../Connexion/RoomConnection"; import type {PlayGlobalMessageInterface} from "../Connexion/ConnexionModels"; +import {soundPlayingStore} from "../Stores/SoundPlayingStore"; +import {soundManager} from "../Phaser/Game/SoundManager"; export class GlobalMessageManager { @@ -43,45 +45,8 @@ export class GlobalMessageManager { } } - private playAudioMessage(messageId : string, urlMessage: string){ - //delete previous elements - const previousDivAudio = document.getElementsByClassName('audio-playing'); - for(let i = 0; i < previousDivAudio.length; i++){ - previousDivAudio[i].remove(); - } - - //create new element - const divAudio : HTMLDivElement = document.createElement('div'); - divAudio.id = `audio-playing-${messageId}`; - divAudio.classList.add('audio-playing'); - const imgAudio : HTMLImageElement = document.createElement('img'); - imgAudio.src = '/resources/logos/megaphone.svg'; - const pAudio : HTMLParagraphElement = document.createElement('p'); - pAudio.textContent = 'Message audio' - divAudio.appendChild(imgAudio); - divAudio.appendChild(pAudio); - - const mainSectionDiv = HtmlUtils.getElementByIdOrFail('main-container'); - mainSectionDiv.appendChild(divAudio); - - const messageAudio : HTMLAudioElement = document.createElement('audio'); - messageAudio.id = this.getHtmlMessageId(messageId); - messageAudio.autoplay = true; - messageAudio.style.display = 'none'; - messageAudio.onended = () => { - divAudio.classList.remove('active'); - messageAudio.remove(); - setTimeout(() => { - divAudio.remove(); - }, 1000); - } - messageAudio.onplay = () => { - divAudio.classList.add('active'); - } - const messageAudioSource : HTMLSourceElement = document.createElement('source'); - messageAudioSource.src = `${UPLOADER_URL}${urlMessage}`; - messageAudio.appendChild(messageAudioSource); - mainSectionDiv.appendChild(messageAudio); + private playAudioMessage(messageId : string, urlMessage: string) { + soundPlayingStore.playSound(UPLOADER_URL + urlMessage); } private playTextMessage(messageId : string, htmlMessage: string){ diff --git a/front/src/Components/App.svelte b/front/src/Components/App.svelte index 5e2b88ee..97cb5071 100644 --- a/front/src/Components/App.svelte +++ b/front/src/Components/App.svelte @@ -17,6 +17,8 @@ import {Game} from "../Phaser/Game/Game"; import {helpCameraSettingsVisibleStore} from "../Stores/HelpCameraSettingsStore"; import HelpCameraSettingsPopup from "./HelpCameraSettings/HelpCameraSettingsPopup.svelte"; + import AudioPlaying from "./UI/AudioPlaying.svelte"; + import {soundPlayingStore} from "../Stores/SoundPlayingStore"; export let game: Game; @@ -47,6 +49,11 @@
{/if} + {#if $soundPlayingStore} +
+ +
+ {/if} + + + + + + + + + diff --git a/front/src/Phaser/Components/SoundMeter.ts b/front/src/Phaser/Components/SoundMeter.ts index b60fb514..53802d31 100644 --- a/front/src/Phaser/Components/SoundMeter.ts +++ b/front/src/Phaser/Components/SoundMeter.ts @@ -1,3 +1,5 @@ +import type {IAnalyserNode, IAudioContext, IMediaStreamAudioSourceNode} from 'standardized-audio-context'; + /** * Class to measure the sound volume of a media stream */ @@ -5,10 +7,10 @@ export class SoundMeter { private instant: number; private clip: number; //private script: ScriptProcessorNode; - private analyser: AnalyserNode|undefined; + private analyser: IAnalyserNode|undefined; private dataArray: Uint8Array|undefined; - private context: AudioContext|undefined; - private source: MediaStreamAudioSourceNode|undefined; + private context: IAudioContext|undefined; + private source: IMediaStreamAudioSourceNode|undefined; constructor() { this.instant = 0.0; @@ -16,7 +18,7 @@ export class SoundMeter { //this.script = context.createScriptProcessor(2048, 1, 1); } - private init(context: AudioContext) { + private init(context: IAudioContext) { this.context = context; this.analyser = this.context.createAnalyser(); @@ -25,7 +27,7 @@ export class SoundMeter { this.dataArray = new Uint8Array(bufferLength); } - public connectToSource(stream: MediaStream, context: AudioContext): void + public connectToSource(stream: MediaStream, context: IAudioContext): void { if (this.source !== undefined) { this.stop(); @@ -85,56 +87,3 @@ export class SoundMeter { } - -// Meter class that generates a number correlated to audio volume. -// The meter class itself displays nothing, but it makes the -// instantaneous and time-decaying volumes available for inspection. -// It also reports on the fraction of samples that were at or near -// the top of the measurement range. -/*function SoundMeter(context) { - this.context = context; - this.instant = 0.0; - this.slow = 0.0; - this.clip = 0.0; - this.script = context.createScriptProcessor(2048, 1, 1); - const that = this; - this.script.onaudioprocess = function(event) { - const input = event.inputBuffer.getChannelData(0); - let i; - let sum = 0.0; - let clipcount = 0; - for (i = 0; i < input.length; ++i) { - sum += input[i] * input[i]; - if (Math.abs(input[i]) > 0.99) { - clipcount += 1; - } - } - that.instant = Math.sqrt(sum / input.length); - that.slow = 0.95 * that.slow + 0.05 * that.instant; - that.clip = clipcount / input.length; - }; -} - -SoundMeter.prototype.connectToSource = function(stream, callback) { - console.log('SoundMeter connecting'); - try { - this.mic = this.context.createMediaStreamSource(stream); - this.mic.connect(this.script); - // necessary to make sample run, but should not be. - this.script.connect(this.context.destination); - if (typeof callback !== 'undefined') { - callback(null); - } - } catch (e) { - console.error(e); - if (typeof callback !== 'undefined') { - callback(e); - } - } -}; - -SoundMeter.prototype.stop = function() { - this.mic.disconnect(); - this.script.disconnect(); -}; -*/ diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index 10a038ba..fff6912c 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -280,7 +280,7 @@ export class GameScene extends DirtyScene implements CenterListener { this.load.spritesheet('layout_modes', 'resources/objects/layout_modes.png', {frameWidth: 32, frameHeight: 32}); this.load.bitmapFont('main_font', 'resources/fonts/arcade.png', 'resources/fonts/arcade.xml'); //eslint-disable-next-line @typescript-eslint/no-explicit-any - (this.load as any).rexWebFont({ + (this.load as any).rexWebFont({ custom: { families: ['Press Start 2P'], urls: ['/resources/fonts/fonts.css'], diff --git a/front/src/Phaser/Game/SoundManager.ts b/front/src/Phaser/Game/SoundManager.ts index f0210494..47614fca 100644 --- a/front/src/Phaser/Game/SoundManager.ts +++ b/front/src/Phaser/Game/SoundManager.ts @@ -17,7 +17,9 @@ class SoundManager { return res(sound); } loadPlugin.audio(soundUrl, soundUrl); - loadPlugin.once('filecomplete-audio-' + soundUrl, () => res(soundManager.add(soundUrl))); + loadPlugin.once('filecomplete-audio-' + soundUrl, () => { + res(soundManager.add(soundUrl)); + }); loadPlugin.start(); }); this.soundPromises.set(soundUrl,soundPromise); diff --git a/front/src/Stores/SoundPlayingStore.ts b/front/src/Stores/SoundPlayingStore.ts new file mode 100644 index 00000000..cf1d681c --- /dev/null +++ b/front/src/Stores/SoundPlayingStore.ts @@ -0,0 +1,22 @@ +import { writable } from "svelte/store"; + +/** + * A store that contains the URL of the sound currently playing + */ +function createSoundPlayingStore() { + const { subscribe, set, update } = writable(null); + + return { + subscribe, + playSound: (url: string) => { + set(url); + }, + soundEnded: () => { + set(null); + } + + + }; +} + +export const soundPlayingStore = createSoundPlayingStore(); diff --git a/front/style/style.scss b/front/style/style.scss index 883f63bb..f43fb240 100644 --- a/front/style/style.scss +++ b/front/style/style.scss @@ -810,35 +810,6 @@ input[type=range]:focus::-ms-fill-upper { } - -/*audio html when audio message playing*/ -.main-container .audio-playing { - position: absolute; - width: 200px; - height: 54px; - right: -210px; - top: 40px; - transition: all 0.1s ease-out; - background-color: black; - border-radius: 30px 0 0 30px; - display: inline-flex; -} - -.main-container .audio-playing.active{ - right: 0; -} -.main-container .audio-playing img{ - /*width: 30px;*/ - border-radius: 50%; - background-color: #ffda01; - padding: 10px; -} -.main-container .audio-playing p{ - color: white; - margin-left: 10px; - margin-top: 14px; -} - /* VIDEO QUALITY */ .main-console div.setting h1{ color: white; diff --git a/front/webpack.config.ts b/front/webpack.config.ts index 5ff37028..3a69b74a 100644 --- a/front/webpack.config.ts +++ b/front/webpack.config.ts @@ -94,6 +94,7 @@ module.exports = { // See https://github.com/sveltejs/svelte/issues/4946#issuecomment-662168782 if (warning.code === 'a11y-no-onchange') { return } + if (warning.code === 'a11y-autofocus') { return } // process as usual handleWarning(warning); diff --git a/front/yarn.lock b/front/yarn.lock index 180c82bf..d8ee0caa 100644 --- a/front/yarn.lock +++ b/front/yarn.lock @@ -30,6 +30,13 @@ chalk "^2.0.0" js-tokens "^4.0.0" +"@babel/runtime@^7.14.0": + version "7.14.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.0.tgz#46794bc20b612c5f75e62dd071e24dfd95f1cbe6" + integrity sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA== + dependencies: + regenerator-runtime "^0.13.4" + "@discoveryjs/json-ext@^0.5.0": version "0.5.3" resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.3.tgz#90420f9f9c6d3987f176a19a7d8e764271a2f55d" @@ -778,6 +785,14 @@ atob@^2.1.2: resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== +automation-events@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/automation-events/-/automation-events-4.0.1.tgz#93acef8a457cbea65f16fdcef8f349fd2fafe298" + integrity sha512-8bQx+PVtNDMD5F2H40cQs7oexZve3Z0xC9fWRQT4fltF65f/WsSpjM4jpulL4K4yLLB71oi4/xVJJCJ5I/Kjbw== + dependencies: + "@babel/runtime" "^7.14.0" + tslib "^2.2.0" + available-typed-arrays@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.2.tgz#6b098ca9d8039079ee3f77f7b783c4480ba513f5" @@ -4318,6 +4333,11 @@ rechoir@^0.7.0: dependencies: resolve "^1.9.0" +regenerator-runtime@^0.13.4: + version "0.13.7" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55" + integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew== + regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" @@ -4882,6 +4902,15 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= +standardized-audio-context@^25.2.4: + version "25.2.4" + resolved "https://registry.yarnpkg.com/standardized-audio-context/-/standardized-audio-context-25.2.4.tgz#d64dbdd70615171ec90d1b7151a0d945af94cf3d" + integrity sha512-uQKZXRnXrPVO1V6SwZ7PiV3RkQqRY3n7i6Q8nbTXYvoz8NftRNzfOIlwefpuC8LVLUUs9dhbKTpP+WOA82dkBw== + dependencies: + "@babel/runtime" "^7.14.0" + automation-events "^4.0.1" + tslib "^2.2.0" + static-extend@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" @@ -5212,7 +5241,7 @@ tslib@^1.8.1, tslib@^1.9.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.0.3: +tslib@^2.0.3, tslib@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.2.0.tgz#fb2c475977e35e241311ede2693cee1ec6698f5c" integrity sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==