/* * Vencord, a modification for Discord's desktop app * Copyright (c) 2022 Vendicated and contributors * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ import * as DataStore from "@api/DataStore"; import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import { useForceUpdater } from "@utils/react"; import definePlugin from "@utils/types"; import { findByPropsLazy, findStoreLazy } from "@webpack"; import { Tooltip } from "webpack/common"; const enum ActivitiesTypes { Game, Embedded } interface IgnoredActivity { id: string; type: ActivitiesTypes; } const RegisteredGamesClasses = findByPropsLazy("overlayToggleIconOff", "overlayToggleIconOn"); const TryItOutClasses = findByPropsLazy("tryItOutBadge", "tryItOutBadgeIcon"); const BaseShapeRoundClasses = findByPropsLazy("baseShapeRound", "baseShapeRoundLeft", "baseShapeRoundRight"); const RunningGameStore = findStoreLazy("RunningGameStore"); function ToggleIconOff() { return ( ); } function ToggleIconOn({ forceWhite }: { forceWhite?: boolean; }) { return ( ); } function ToggleActivityComponent({ activity, forceWhite, forceLeftMargin }: { activity: IgnoredActivity; forceWhite?: boolean; forceLeftMargin?: boolean; }) { const forceUpdate = useForceUpdater(); return ( {({ onMouseLeave, onMouseEnter }) => (
handleActivityToggle(e, activity, forceUpdate)} > { ignoredActivitiesCache.has(activity.id) ? : }
)}
); } function ToggleActivityComponentWithBackground({ activity }: { activity: IgnoredActivity; }) { return (
); } function handleActivityToggle(e: React.MouseEvent, activity: IgnoredActivity, forceUpdateComponent: () => void) { e.stopPropagation(); if (ignoredActivitiesCache.has(activity.id)) ignoredActivitiesCache.delete(activity.id); else ignoredActivitiesCache.set(activity.id, activity); forceUpdateComponent(); saveCacheToDatastore(); } async function saveCacheToDatastore() { await DataStore.set("IgnoreActivities_ignoredActivities", ignoredActivitiesCache); } let ignoredActivitiesCache = new Map(); export default definePlugin({ name: "IgnoreActivities", authors: [Devs.Nuckyz], description: "Ignore certain activities (like games and actual activities) from showing up on your status. You can configure which ones are ignored from the Registered Games and Activities tabs.", patches: [ { find: ".Messages.SETTINGS_GAMES_TOGGLE_OVERLAY", replacement: { match: /!(\i)(\)return null;var \i=(\i)\.overlay.+?children:)(\[.{0,70}overlayStatusText.+?\])(?=}\)}\(\))/, replace: (_, platformCheck, restWithoutPlatformCheck, props, children) => "false" + `${restWithoutPlatformCheck}` + `(${platformCheck}?${children}:[])` + `.concat(Vencord.Plugins.plugins.IgnoreActivities.renderToggleGameActivityButton(${props}))` } }, { find: ".overlayBadge", replacement: [ { match: /(?<=\(\)\.badgeContainer,children:).{0,50}?name:(\i)\.name.+?null/, replace: (m, props) => `[${m},$self.renderToggleActivityButton(${props})]` }, { match: /(?<=\(\)\.badgeContainer,children:).{0,50}?name:(\i\.application)\.name.+?null/, replace: (m, props) => `${m},$self.renderToggleActivityButton(${props})` } ] }, { find: '.displayName="LocalActivityStore"', replacement: { match: /LISTENING.+?\)\);(?<=(\i)\.push.+?)/, replace: (m, activities) => `${m}${activities}=${activities}.filter($self.isActivityNotIgnored);` } } ], async start() { const ignoredActivitiesData = await DataStore.get>("IgnoreActivities_ignoredActivities") ?? new Map(); /** Migrate old data */ if (Array.isArray(ignoredActivitiesData)) { for (const id of ignoredActivitiesData) { ignoredActivitiesCache.set(id, { id, type: ActivitiesTypes.Game }); } await saveCacheToDatastore(); } else ignoredActivitiesCache = ignoredActivitiesData; if (ignoredActivitiesCache.size !== 0) { const gamesSeen: { id?: string; exePath: string; }[] = RunningGameStore.getGamesSeen(); for (const ignoredActivity of ignoredActivitiesCache.values()) { if (ignoredActivity.type !== ActivitiesTypes.Game) continue; if (!gamesSeen.some(game => game.id === ignoredActivity.id || game.exePath === ignoredActivity.id)) { /** Custom added game which no longer exists */ ignoredActivitiesCache.delete(ignoredActivity.id); } } await saveCacheToDatastore(); } }, renderToggleGameActivityButton(props: { id?: string; exePath: string; }) { return ( ); }, renderToggleActivityButton(props: { id: string; }) { return ( ); }, isActivityNotIgnored(props: { type: number; application_id?: string; name?: string; }) { if (props.type === 0) { if (props.application_id !== undefined) return !ignoredActivitiesCache.has(props.application_id); else { const exePath = RunningGameStore.getRunningGames().find(game => game.name === props.name)?.exePath; if (exePath) return !ignoredActivitiesCache.has(exePath); } } return true; } });