From 75cc24ee2f34fea26ab03844add28496b777d76a Mon Sep 17 00:00:00 2001 From: Aidan <76609332+redbaron2k7@users.noreply.github.com> Date: Thu, 6 Feb 2025 16:09:03 -0600 Subject: [PATCH] fix: improve type safety and store usage --- src/plugins/webcamStartNotifier/index.ts | 54 +++++++++++++++++++----- 1 file changed, 44 insertions(+), 10 deletions(-) diff --git a/src/plugins/webcamStartNotifier/index.ts b/src/plugins/webcamStartNotifier/index.ts index 34290b8ec..357eb033b 100644 --- a/src/plugins/webcamStartNotifier/index.ts +++ b/src/plugins/webcamStartNotifier/index.ts @@ -7,14 +7,37 @@ import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; +import { findStoreLazy } from "@webpack"; import { ChannelStore, SelectedChannelStore } from "@webpack/common"; +interface VoiceState { + userId: string; + channelId: string; + selfVideo: boolean; + deaf: boolean; + mute: boolean; + selfDeaf: boolean; + selfMute: boolean; + selfStream: boolean; + sessionId: string; + suppress: boolean; + requestToSpeakTimestamp: number | null; +} + +interface VoiceStateUpdate { + voiceStates: Array<{ + userId: string; + channelId: string; + selfVideo?: boolean; + }>; +} + const startSound = "https://raw.githubusercontent.com/redbaron2k7/videoStartNotifier/117738bff76699a89531a067e321b6406bffbc88/start.mp3"; const stopSound = "https://raw.githubusercontent.com/redbaron2k7/videoStartNotifier/117738bff76699a89531a067e321b6406bffbc88/stop.mp3"; -const videoStates = new Map(); +const VoiceStateStore = findStoreLazy("VoiceStateStore"); -function playNotification(isVideoOn: boolean) { +function playNotification(isVideoOn: boolean): void { new Audio(isVideoOn ? startSound : stopSound).play(); } @@ -38,29 +61,40 @@ export default definePlugin({ settings, flux: (() => { + const lastKnownStates = new Map(); + return { - VOICE_STATE_UPDATES: ({ voiceStates }: { voiceStates: Array<{ userId: string, channelId: string, selfVideo?: boolean; }>; }) => { + VOICE_STATE_UPDATES: ({ voiceStates }: VoiceStateUpdate): void => { const currentChannelId = SelectedChannelStore.getVoiceChannelId(); if (!currentChannelId) return; const currentChannel = ChannelStore.getChannel(currentChannelId); if (!currentChannel) return; - const isPrivateChannel = currentChannel.type === 1 || currentChannel.type === 3; + const isPrivateChannel = currentChannel.isPrivate(); if ((isPrivateChannel && !settings.store.playInPrivate) || (!isPrivateChannel && !settings.store.playInServer)) { return; } - voiceStates.forEach(state => { - if (state.channelId !== currentChannelId) return; + const channelStates = VoiceStateStore.getVoiceStatesForChannel(currentChannelId) as Record; - const prevVideoState = videoStates.get(state.userId); - if (state.selfVideo !== undefined && prevVideoState !== undefined && prevVideoState !== state.selfVideo) { - playNotification(state.selfVideo); + voiceStates.forEach(state => { + if (!state?.channelId || state.channelId !== currentChannelId) return; + + const lastKnownState = lastKnownStates.get(state.userId); + const currentState = Boolean(state.selfVideo); + + if (typeof lastKnownState === "boolean" && lastKnownState !== currentState) { + playNotification(currentState); + } + + lastKnownStates.set(state.userId, currentState); + + if (!channelStates[state.userId]) { + lastKnownStates.delete(state.userId); } - videoStates.set(state.userId, state.selfVideo ?? false); }); } };