minor changes in plugins (#502)
* BetterAudioPlayer: fix observer cleanup * TosuRPC: fix websocket reconnect * Jumpscare: fix flux subscription leak * Animalese: fix infinite recursion * GensokyoRadioRPC: fix interval cleanup * JellyfinRichPresence: fix interval cleanup * ListenBrainzRPC: fix interval cleanup * AbsRPC: fix interval cleanup * StatsfmPresence: fix interval cleanup * AppleMusic: fix interval cleanup * LastfmRichPresence: fix interval cleanup * fix: remove pointless null checks * CleanUserArea renamed to BetterUserArea and added additional features * BetterUserArea: migrate from CleanUserArea
This commit is contained in:
parent
3bab98c7db
commit
452b7a50a0
13 changed files with 170 additions and 59 deletions
|
|
@ -72,6 +72,7 @@ const applicationId = "1381423044907503636";
|
|||
const logger = new Logger("AudioBookShelfRichPresence");
|
||||
|
||||
let authToken: string | null = null;
|
||||
let updateInterval: NodeJS.Timeout | undefined;
|
||||
|
||||
async function getApplicationAsset(key: string): Promise<string> {
|
||||
return (await ApplicationAssetUtils.fetchAssetIds(applicationId, [key]))[0];
|
||||
|
|
@ -105,11 +106,12 @@ export default definePlugin({
|
|||
|
||||
start() {
|
||||
this.updatePresence();
|
||||
this.updateInterval = setInterval(() => { this.updatePresence(); }, 10000);
|
||||
updateInterval = setInterval(() => { this.updatePresence(); }, 10000);
|
||||
},
|
||||
|
||||
stop() {
|
||||
clearInterval(this.updateInterval);
|
||||
clearInterval(updateInterval);
|
||||
updateInterval = undefined;
|
||||
},
|
||||
|
||||
async authenticate(): Promise<boolean> {
|
||||
|
|
|
|||
|
|
@ -222,16 +222,11 @@ export default definePlugin({
|
|||
}
|
||||
},
|
||||
|
||||
start() {
|
||||
// Only subscribe once!
|
||||
const init = async () => {
|
||||
if (!audioContext) {
|
||||
audioContext = new AudioContext();
|
||||
await initSoundBuffers();
|
||||
}
|
||||
init();
|
||||
};
|
||||
init();
|
||||
async start() {
|
||||
if (!audioContext) {
|
||||
audioContext = new AudioContext();
|
||||
await initSoundBuffers();
|
||||
}
|
||||
},
|
||||
|
||||
stop() {
|
||||
|
|
|
|||
|
|
@ -222,6 +222,7 @@ function createObserver(targetNode: HTMLElement) {
|
|||
childList: true,
|
||||
subtree: true,
|
||||
});
|
||||
return observer;
|
||||
}
|
||||
|
||||
function tryHexToRgb(hex) {
|
||||
|
|
@ -292,6 +293,8 @@ const settings = definePluginSettings({
|
|||
},
|
||||
});
|
||||
|
||||
let observer: MutationObserver | null = null;
|
||||
|
||||
export default definePlugin({
|
||||
name: "BetterAudioPlayer",
|
||||
description: "Adds a spectrograph and oscilloscope visualizer to audio attachment players",
|
||||
|
|
@ -302,11 +305,15 @@ export default definePlugin({
|
|||
const targetNode = document.querySelector("[class^='content_']");
|
||||
if (targetNode) {
|
||||
scanForAudioElements(targetNode as HTMLElement);
|
||||
createObserver(targetNode as HTMLElement);
|
||||
observer = createObserver(targetNode as HTMLElement);
|
||||
} else {
|
||||
requestAnimationFrame(waitForContent);
|
||||
}
|
||||
};
|
||||
waitForContent();
|
||||
},
|
||||
stop() {
|
||||
observer?.disconnect();
|
||||
observer = null;
|
||||
},
|
||||
});
|
||||
|
|
|
|||
107
src/equicordplugins/betterUserArea/index.ts
Normal file
107
src/equicordplugins/betterUserArea/index.ts
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* Vencord, a Discord client mod
|
||||
* Copyright (c) 2025 Vendicated and contributors
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { definePluginSettings, migratePluginToSetting } from "@api/Settings";
|
||||
import { EquicordDevs } from "@utils/constants";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
|
||||
const settings = definePluginSettings({
|
||||
removeNameplate: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Remove nameplate styling.",
|
||||
default: true,
|
||||
restartNeeded: true
|
||||
},
|
||||
removeAudioMenus: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Remove menus next to mute and deafen buttons.",
|
||||
default: true,
|
||||
restartNeeded: true
|
||||
},
|
||||
alwaysShowUsername: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Always show username instead of status.",
|
||||
default: true,
|
||||
restartNeeded: true
|
||||
},
|
||||
removeButtonTooltips: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Remove button tooltips.",
|
||||
default: false,
|
||||
restartNeeded: true
|
||||
},
|
||||
removeAvatarDecoration: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Remove avatar decoration.",
|
||||
default: true,
|
||||
restartNeeded: true
|
||||
},
|
||||
removeUsernameStyles: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Remove username colors and effects.",
|
||||
default: true,
|
||||
restartNeeded: true
|
||||
}
|
||||
});
|
||||
|
||||
migratePluginToSetting("BetterUserArea", "CleanUserArea", "removeNameplate");
|
||||
|
||||
export default definePlugin({
|
||||
name: "BetterUserArea",
|
||||
description: "Customize and make the user area more clean.",
|
||||
authors: [EquicordDevs.Prism],
|
||||
settings,
|
||||
patches: [
|
||||
{
|
||||
find: "#{intl::ACCOUNT_SPEAKING_WHILE_MUTED}",
|
||||
replacement: {
|
||||
match: /,nameplate:\i,selectedGuildId:(\i),avatarDecoration/,
|
||||
replace: ",nameplate:null,selectedGuildId:$1,avatarDecoration"
|
||||
},
|
||||
predicate: () => settings.store.removeNameplate
|
||||
},
|
||||
{
|
||||
find: "#{intl::ACCOUNT_SPEAKING_WHILE_MUTED}",
|
||||
replacement: {
|
||||
match: /\{showRefreshedAudioContextMenu:(\i)\}=(?=.+?location:"\w+Button")/g,
|
||||
replace: "{showRefreshedAudioContextMenu:$1}=$self.settings.store.removeAudioMenus?{showRefreshedAudioContextMenu:!1}:"
|
||||
},
|
||||
predicate: () => settings.store.removeAudioMenus
|
||||
},
|
||||
{
|
||||
find: "#{intl::ACCOUNT_SPEAKING_WHILE_MUTED}",
|
||||
replacement: {
|
||||
match: /hoverText:(\i),forceHover:\i,children:/g,
|
||||
replace: "hoverText:$1,forceHover:!0,children:"
|
||||
},
|
||||
predicate: () => settings.store.alwaysShowUsername
|
||||
},
|
||||
{
|
||||
find: "#{intl::ACCOUNT_SPEAKING_WHILE_MUTED}",
|
||||
replacement: {
|
||||
match: /tooltipText:\i,/g,
|
||||
replace: "tooltipText:void 0,"
|
||||
},
|
||||
predicate: () => settings.store.removeButtonTooltips
|
||||
},
|
||||
{
|
||||
find: "#{intl::ACCOUNT_SPEAKING_WHILE_MUTED}",
|
||||
replacement: {
|
||||
match: /avatarDecoration:(\i),size:/,
|
||||
replace: "avatarDecoration:void 0,size:"
|
||||
},
|
||||
predicate: () => settings.store.removeAvatarDecoration
|
||||
},
|
||||
{
|
||||
find: "#{intl::ACCOUNT_SPEAKING_WHILE_MUTED}",
|
||||
replacement: {
|
||||
match: /displayNameStyles:(\i),/,
|
||||
replace: "displayNameStyles:void 0,"
|
||||
},
|
||||
predicate: () => settings.store.removeUsernameStyles
|
||||
}
|
||||
],
|
||||
});
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
/*
|
||||
* Vencord, a Discord client mod
|
||||
* Copyright (c) 2025 Vendicated and contributors
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { EquicordDevs } from "@utils/constants";
|
||||
import definePlugin from "@utils/types";
|
||||
|
||||
export default definePlugin({
|
||||
name: "CleanUserArea",
|
||||
description: "Removes the nameplate styling from the user area.",
|
||||
authors: [EquicordDevs.Prism],
|
||||
patches: [
|
||||
{
|
||||
find: "#{intl::ACCOUNT_SPEAKING_WHILE_MUTED}",
|
||||
replacement: {
|
||||
match: /,nameplate:\i,selectedGuildId:(\i),avatarDecoration/,
|
||||
replace: ",nameplate:null,selectedGuildId:$1,avatarDecoration",
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
|
@ -39,6 +39,8 @@ const settings = definePluginSettings({
|
|||
}
|
||||
});
|
||||
|
||||
let updateInterval: NodeJS.Timeout | undefined;
|
||||
|
||||
export default definePlugin({
|
||||
name: "GensokyoRadioRPC",
|
||||
description: "Discord rich presence for Gensokyo Radio!",
|
||||
|
|
@ -57,11 +59,12 @@ export default definePlugin({
|
|||
|
||||
start() {
|
||||
this.updatePresence();
|
||||
this.updateInterval = setInterval(() => { this.updatePresence(); }, settings.store.refreshInterval * 1000);
|
||||
updateInterval = setInterval(() => { this.updatePresence(); }, settings.store.refreshInterval * 1000);
|
||||
},
|
||||
|
||||
stop() {
|
||||
clearInterval(this.updateInterval);
|
||||
clearInterval(updateInterval);
|
||||
updateInterval = undefined;
|
||||
FluxDispatcher.dispatch({ type: "LOCAL_ACTIVITY_UPDATE", activity: null });
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -155,6 +155,8 @@ const applicationId = "1381368130164625469";
|
|||
|
||||
const logger = new Logger("JellyfinRichPresence");
|
||||
|
||||
let updateInterval: NodeJS.Timeout | undefined;
|
||||
|
||||
async function getApplicationAsset(key: string): Promise<string> {
|
||||
return (await ApplicationAssetUtils.fetchAssetIds(applicationId, [key]))[0];
|
||||
}
|
||||
|
|
@ -200,11 +202,12 @@ export default definePlugin({
|
|||
|
||||
start() {
|
||||
this.updatePresence();
|
||||
this.updateInterval = setInterval(() => { this.updatePresence(); }, 10000);
|
||||
updateInterval = setInterval(() => { this.updatePresence(); }, 10000);
|
||||
},
|
||||
|
||||
stop() {
|
||||
clearInterval(this.updateInterval);
|
||||
clearInterval(updateInterval);
|
||||
updateInterval = undefined;
|
||||
},
|
||||
|
||||
async fetchMediaData(): Promise<MediaData | null> {
|
||||
|
|
@ -236,12 +239,11 @@ export default definePlugin({
|
|||
if (playState?.IsPaused && !settings.store.showPausedState) return null;
|
||||
|
||||
const imageUrl = item.ImageTags?.Primary
|
||||
? `${baseUrl}/Items/${
|
||||
item.Type === "Episode" &&
|
||||
? `${baseUrl}/Items/${item.Type === "Episode" &&
|
||||
item.SeriesId &&
|
||||
settings.store.coverType === "series"
|
||||
? item.SeriesId
|
||||
: item.Id
|
||||
? item.SeriesId
|
||||
: item.Id
|
||||
}/Images/Primary`
|
||||
: undefined;
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import { createAudioPlayer } from "@api/AudioPlayer";
|
|||
import { definePluginSettings } from "@api/Settings";
|
||||
import { Devs } from "@utils/constants";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { createRoot, FluxDispatcher, useEffect, useState } from "@webpack/common";
|
||||
import { createRoot, FluxDispatcher, useCallback, useEffect, useState } from "@webpack/common";
|
||||
import { Root } from "react-dom/client";
|
||||
|
||||
let jumpscareRoot: Root | undefined;
|
||||
|
|
@ -67,7 +67,7 @@ export default definePlugin({
|
|||
const [isPlaying, setIsPlaying] = useState(false);
|
||||
const jumpscareAudio = createAudioPlayer(settings.store.audioSource, { volume: 100, onEnded: () => { setIsPlaying(false); } });
|
||||
|
||||
const jumpscare = event => {
|
||||
const jumpscare = useCallback(event => {
|
||||
if (isPlaying) return;
|
||||
|
||||
const chance = 1 / settings.store.chance;
|
||||
|
|
@ -75,7 +75,7 @@ export default definePlugin({
|
|||
|
||||
setIsPlaying(true);
|
||||
jumpscareAudio.play();
|
||||
};
|
||||
}, [isPlaying]);
|
||||
|
||||
useEffect(() => {
|
||||
FluxDispatcher.subscribe("CHANNEL_SELECT", jumpscare);
|
||||
|
|
@ -83,7 +83,7 @@ export default definePlugin({
|
|||
return () => {
|
||||
FluxDispatcher.unsubscribe("CHANNEL_SELECT", jumpscare);
|
||||
};
|
||||
});
|
||||
}, [jumpscare]);
|
||||
|
||||
return <img className={`jumpscare-img ${isPlaying ? "jumpscare-animate" : ""}`} src={settings.store.imageSource} />;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,8 @@ const logger = new Logger("ListenBrainzRPC");
|
|||
|
||||
const PresenceStore = findByPropsLazy("getLocalPresence");
|
||||
|
||||
let updateInterval: NodeJS.Timeout | undefined;
|
||||
|
||||
async function getApplicationAsset(key: string): Promise<string> {
|
||||
return (await ApplicationAssetUtils.fetchAssetIds(applicationId, [key]))[0];
|
||||
}
|
||||
|
|
@ -181,13 +183,14 @@ export default definePlugin({
|
|||
|
||||
start() {
|
||||
this.updatePresence();
|
||||
this.updateInterval = setInterval(() => {
|
||||
updateInterval = setInterval(() => {
|
||||
this.updatePresence();
|
||||
}, 16000);
|
||||
},
|
||||
|
||||
stop() {
|
||||
clearInterval(this.updateInterval);
|
||||
clearInterval(updateInterval);
|
||||
updateInterval = undefined;
|
||||
},
|
||||
|
||||
async fetchTrackData(): Promise<TrackData | null> {
|
||||
|
|
|
|||
|
|
@ -114,6 +114,8 @@ const logger = new Logger("StatsfmPresence");
|
|||
|
||||
const PresenceStore = findByPropsLazy("getLocalPresence");
|
||||
|
||||
let updateInterval: NodeJS.Timeout | undefined;
|
||||
|
||||
async function getApplicationAsset(key: string): Promise<string> {
|
||||
return (await ApplicationAssetUtils.fetchAssetIds(applicationId, [key]))[0];
|
||||
}
|
||||
|
|
@ -237,11 +239,12 @@ export default definePlugin({
|
|||
|
||||
start() {
|
||||
this.updatePresence();
|
||||
this.updateInterval = setInterval(() => { this.updatePresence(); }, 16000);
|
||||
updateInterval = setInterval(() => { this.updatePresence(); }, 16000);
|
||||
},
|
||||
|
||||
stop() {
|
||||
clearInterval(this.updateInterval);
|
||||
clearInterval(updateInterval);
|
||||
updateInterval = undefined;
|
||||
},
|
||||
|
||||
async fetchTrackData(): Promise<TrackData | null> {
|
||||
|
|
|
|||
|
|
@ -24,22 +24,28 @@ const throttledOnMessage = throttle(onMessage, 3000, () => FluxDispatcher.dispat
|
|||
|
||||
let ws: WebSocket;
|
||||
let wsReconnect: NodeJS.Timeout;
|
||||
let shouldReconnect = false;
|
||||
|
||||
export default definePlugin({
|
||||
name: "TosuRPC",
|
||||
description: "osu! RPC with data from tosu",
|
||||
authors: [Devs.AutumnVN],
|
||||
start() {
|
||||
shouldReconnect = true;
|
||||
(function connect() {
|
||||
ws = new WebSocket("ws://127.0.0.1:24050/websocket/v2");
|
||||
ws.addEventListener("error", () => ws.close());
|
||||
ws.addEventListener("close", () => wsReconnect = setTimeout(connect, 5000));
|
||||
ws.addEventListener("close", () => {
|
||||
if (!shouldReconnect) return;
|
||||
wsReconnect = setTimeout(connect, 5000);
|
||||
});
|
||||
ws.addEventListener("message", ({ data }) => throttledOnMessage(data));
|
||||
})();
|
||||
},
|
||||
stop() {
|
||||
ws.close();
|
||||
clearTimeout(wsReconnect);
|
||||
shouldReconnect = false;
|
||||
if (wsReconnect) clearTimeout(wsReconnect);
|
||||
if (ws) ws.close();
|
||||
FluxDispatcher.dispatch({ type: "LOCAL_ACTIVITY_UPDATE", activity: null, socketId: "tosu" });
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@ const enum AssetImageType {
|
|||
|
||||
const applicationId = "1239490006054207550";
|
||||
|
||||
let updateInterval: NodeJS.Timeout | undefined;
|
||||
|
||||
function setActivity(activity: Activity | null) {
|
||||
FluxDispatcher.dispatch({
|
||||
type: "LOCAL_ACTIVITY_UPDATE",
|
||||
|
|
@ -172,11 +174,12 @@ export default definePlugin({
|
|||
|
||||
start() {
|
||||
this.updatePresence();
|
||||
this.updateInterval = setInterval(() => { this.updatePresence(); }, settings.store.refreshInterval * 1000);
|
||||
updateInterval = setInterval(() => { this.updatePresence(); }, settings.store.refreshInterval * 1000);
|
||||
},
|
||||
|
||||
stop() {
|
||||
clearInterval(this.updateInterval);
|
||||
clearInterval(updateInterval);
|
||||
updateInterval = undefined;
|
||||
FluxDispatcher.dispatch({ type: "LOCAL_ACTIVITY_UPDATE", activity: null });
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -48,6 +48,8 @@ const LASTFM_PLACEHOLDER_IMAGE_HASH = "2a96cbd8b46e442fc41c2b86b821562f";
|
|||
|
||||
const logger = new Logger("LastFMRichPresence");
|
||||
|
||||
let updateInterval: NodeJS.Timeout | undefined;
|
||||
|
||||
async function getApplicationAsset(key: string): Promise<string> {
|
||||
return (await ApplicationAssetUtils.fetchAssetIds(DISCORD_APP_ID, [key]))[0];
|
||||
}
|
||||
|
|
@ -185,11 +187,12 @@ export default definePlugin({
|
|||
|
||||
start() {
|
||||
this.updatePresence();
|
||||
this.updateInterval = setInterval(() => { this.updatePresence(); }, 16000);
|
||||
updateInterval = setInterval(() => { this.updatePresence(); }, 16000);
|
||||
},
|
||||
|
||||
stop() {
|
||||
clearInterval(this.updateInterval);
|
||||
clearInterval(updateInterval);
|
||||
updateInterval = undefined;
|
||||
},
|
||||
|
||||
async fetchTrackData(): Promise<TrackData | null> {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue