diff --git a/src/equicordplugins/boo/Boo.tsx b/src/equicordplugins/boo/Boo.tsx index 2ccb37f00..adf8b1aee 100644 --- a/src/equicordplugins/boo/Boo.tsx +++ b/src/equicordplugins/boo/Boo.tsx @@ -12,7 +12,25 @@ import { cl } from "."; import { IconGhost } from "./IconGhost"; const countedChannels = new Set(); -export let booCount = 0; + +let _booCount = 0; +const listeners = new Set<(n: number) => void>(); + +export function getBooCount() { + return _booCount; +} + +export function setBooCount(n: number) { + _booCount = n; + for (const l of listeners) l(_booCount); +} + +export function onBooCountChange(cb: (n: number) => void) { + listeners.add(cb); + return () => { + listeners.delete(cb); + }; +} const ChannelWrapperStyles = findByPropsLazy("muted", "wrapper"); @@ -43,23 +61,28 @@ export function Boo({ channel }: { channel: Channel; }) { }); }, [lastMessage, currentUserId]); - if (countedChannels.has(id) && state.isCurrentUser) { - countedChannels.delete(id); - booCount--; - } + useEffect(() => { + if (!state.isDataProcessed) return; - if (!state.isDataProcessed || !currentUserId || !lastMessage || state.isCurrentUser) return null; + if (!state.isCurrentUser) { + if (!countedChannels.has(id)) { + countedChannels.add(id); + setBooCount(getBooCount() + 1); + } + } else { + if (countedChannels.has(id)) { + countedChannels.delete(id); + setBooCount(getBooCount() - 1); + } + } + }, [state.isCurrentUser, state.isDataProcessed]); - if (!countedChannels.has(id)) { - countedChannels.add(id); - booCount++; - } + if (!state.isDataProcessed || !currentUserId || !lastMessage || state.isCurrentUser) + return null; return (
- {state.containsQuestionMark - ? - : } +
); } diff --git a/src/equicordplugins/boo/index.tsx b/src/equicordplugins/boo/index.tsx index 5289c311c..b2ca9dffc 100644 --- a/src/equicordplugins/boo/index.tsx +++ b/src/equicordplugins/boo/index.tsx @@ -1,6 +1,6 @@ /* * Vencord, a Discord client mod - * Copyright (c) 2024 Vendicated and contributors + * Copyright (c) 2025 Vendicated and contributors * SPDX-License-Identifier: GPL-3.0-or-later */ @@ -12,17 +12,45 @@ import ErrorBoundary from "@components/ErrorBoundary"; import { Devs, EquicordDevs } from "@utils/constants"; import definePlugin from "@utils/types"; import { Channel } from "@vencord/discord-types"; -import { Tooltip } from "@webpack/common"; +import { Tooltip, useEffect, useState } from "@webpack/common"; -import { Boo, booCount } from "./Boo"; +import { Boo, getBooCount, onBooCountChange } from "./Boo"; import { IconGhost } from "./IconGhost"; export const cl = classNameFactory("vc-boo-"); + + +function BooIndicator() { + const [count, setCount] = useState(getBooCount()); + + useEffect(() => { + const unsubscribe = onBooCountChange(setCount); + return () => unsubscribe(); + }, []); + + return ( +
+ + {({ onMouseEnter, onMouseLeave }) => ( +
+ {count} +
+ )} +
+
+ ); +} + export default definePlugin({ name: "Boo", description: "A cute ghost will appear if you don't answer their DMs", authors: [EquicordDevs.vei, Devs.sadan], + patches: [ { find: "interactiveSelected]", @@ -30,7 +58,7 @@ export default definePlugin({ match: /interactiveSelected.{0,50}children:\[/, replace: "$&$self.renderBoo(arguments[0])," } - } + }, ], renderBoo(props: { channel: Channel; }) { @@ -42,20 +70,11 @@ export default definePlugin({ }, renderIndicator() { - return -
- - {({ onMouseEnter, onMouseLeave }) => ( -
- {booCount} -
- )} -
-
-
; + return ( + + + + ); }, start() { @@ -64,5 +83,5 @@ export default definePlugin({ stop() { removeServerListElement(ServerListRenderPosition.Above, this.renderIndicator); - } + }, });