diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index 457702da..190ad1f4 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -71,7 +71,7 @@ import { biggestAvailableAreaStore } from "../../Stores/BiggestAvailableAreaStor import { layoutManagerActionStore } from "../../Stores/LayoutManagerStore"; import { playersStore } from "../../Stores/PlayersStore"; import { emoteStore, emoteMenuStore } from "../../Stores/EmoteStore"; -import { userIsAdminStore } from "../../Stores/GameStore"; +import { userIsAdminStore, userIsJitsiDominantSpeakerStore } from "../../Stores/GameStore"; import { contactPageStore } from "../../Stores/MenuStore"; import type { WasCameraUpdatedEvent } from "../../Api/Events/WasCameraUpdatedEvent"; import { audioManagerFileStore } from "../../Stores/AudioManagerStore"; @@ -178,6 +178,7 @@ export class GameScene extends DirtyScene { private localVolumeStoreUnsubscriber: Unsubscriber | undefined; private followUsersColorStoreUnsubscribe!: Unsubscriber; private currentPlayerGroupIdStoreUnsubscribe!: Unsubscriber; + private userIsJitsiDominantSpeakerStoreUnsubscriber!: Unsubscriber; private biggestAvailableAreaStoreUnsubscribe!: () => void; MapUrlFile: string; @@ -648,16 +649,7 @@ export class GameScene extends DirtyScene { if (volume === undefined) { return; } - const aboveTreshold = volume > talkIconVolumeTreshold; - this.CurrentPlayer.showTalkIcon(aboveTreshold); - - if (this.showVoiceIndicatorChangeMessageSent && !aboveTreshold) { - this.connection?.emitPlayerShowVoiceIndicator(false); - this.showVoiceIndicatorChangeMessageSent = false; - } else if (!this.showVoiceIndicatorChangeMessageSent && aboveTreshold) { - this.connection?.emitPlayerShowVoiceIndicator(true); - this.showVoiceIndicatorChangeMessageSent = true; - } + this.tryChangeShowVoiceIndicatorState(volume > talkIconVolumeTreshold); }); } } else { @@ -673,6 +665,12 @@ export class GameScene extends DirtyScene { oldPeersNumber = peers.size; }); + this.userIsJitsiDominantSpeakerStoreUnsubscriber = userIsJitsiDominantSpeakerStore.subscribe( + (dominantSpeaker) => { + this.tryChangeShowVoiceIndicatorState(dominantSpeaker); + } + ); + this.emoteUnsubscribe = emoteStore.subscribe((emote) => { if (emote) { this.CurrentPlayer?.playEmote(emote.url); @@ -1563,6 +1561,7 @@ ${escapedMessage} this.emoteMenuUnsubscribe(); this.followUsersColorStoreUnsubscribe(); this.biggestAvailableAreaStoreUnsubscribe(); + this.userIsJitsiDominantSpeakerStoreUnsubscriber(); iframeListener.unregisterAnswerer("getState"); iframeListener.unregisterAnswerer("loadTileset"); iframeListener.unregisterAnswerer("getMapData"); @@ -1961,6 +1960,17 @@ ${escapedMessage} }); } + private tryChangeShowVoiceIndicatorState(show: boolean): void { + this.CurrentPlayer.showTalkIcon(show); + if (this.showVoiceIndicatorChangeMessageSent && !show) { + this.connection?.emitPlayerShowVoiceIndicator(false); + this.showVoiceIndicatorChangeMessageSent = false; + } else if (!this.showVoiceIndicatorChangeMessageSent && show) { + this.connection?.emitPlayerShowVoiceIndicator(true); + this.showVoiceIndicatorChangeMessageSent = true; + } + } + private doRemovePlayer(userId: number) { const player = this.MapPlayersByKey.get(userId); if (player === undefined) { diff --git a/front/src/Stores/GameStore.ts b/front/src/Stores/GameStore.ts index e5298b7c..ddab3f66 100644 --- a/front/src/Stores/GameStore.ts +++ b/front/src/Stores/GameStore.ts @@ -6,4 +6,6 @@ export const requestVisitCardsStore = writable(null); export const userIsAdminStore = writable(false); +export const userIsJitsiDominantSpeakerStore = writable(false); + export const limitMapStore = writable(false); diff --git a/front/src/WebRtc/JitsiFactory.ts b/front/src/WebRtc/JitsiFactory.ts index 3d58d9c2..002452ea 100644 --- a/front/src/WebRtc/JitsiFactory.ts +++ b/front/src/WebRtc/JitsiFactory.ts @@ -3,6 +3,8 @@ import { coWebsiteManager } from "./CoWebsiteManager"; import { requestedCameraState, requestedMicrophoneState } from "../Stores/MediaStore"; import { get } from "svelte/store"; import CancelablePromise from "cancelable-promise"; +import { gameManager } from "../Phaser/Game/GameManager"; +import { userIsJitsiDominantSpeakerStore } from "../Stores/GameStore"; interface jitsiConfigInterface { startWithAudioMuted: boolean; @@ -126,6 +128,7 @@ class JitsiFactory { private jitsiApi?: JitsiApi; private audioCallback = this.onAudioChange.bind(this); private videoCallback = this.onVideoChange.bind(this); + private dominantSpeakerChangedCallback = this.onDominantSpeakerChanged.bind(this); private jitsiScriptLoaded: boolean = false; /** @@ -204,6 +207,7 @@ class JitsiFactory { this.jitsiApi.addListener("audioMuteStatusChanged", this.audioCallback); this.jitsiApi.addListener("videoMuteStatusChanged", this.videoCallback); + this.jitsiApi.addListener("dominantSpeakerChanged", this.dominantSpeakerChangedCallback); }); cancel(() => { @@ -262,6 +266,25 @@ class JitsiFactory { } } + private onDominantSpeakerChanged(data: { id: string }): void { + userIsJitsiDominantSpeakerStore.set( + //@ts-ignore + data.id === this.getCurrentParticipantId(this.jitsiApi?.getParticipantsInfo()) + ); + } + + private getCurrentParticipantId( + participants: { displayName: string; participantId: string }[] + ): string | undefined { + const currentPlayerName = gameManager.getPlayerName(); + for (const participant of participants) { + if (participant.displayName === currentPlayerName) { + return participant.participantId; + } + } + return; + } + private loadJitsiScript(domain: string): CancelablePromise { return new CancelablePromise((resolve, reject, cancel) => { if (this.jitsiScriptLoaded) {