EquicordHelper: add account standing button (ft. Prism) (#755)

* EquicordHelper: add account standing button (ft. Prism)

* EquicordHelper: fix all the things

* chat

* bleh

* Update index.tsx

---------

Co-authored-by: thororen1234 <78185467+thororen1234@users.noreply.github.com>
This commit is contained in:
Key 2026-02-10 17:10:35 +00:00 • committed by GitHub
parent 999136b73a
commit 3562d383c3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 97 additions and 44 deletions

View file

@ -51,3 +51,11 @@ export const enum UserFlags {
COLLABORATOR = 1125899906842624,
RESTRICTED_COLLABORATOR = 2251799813685248,
}
export const enum StandingState {
ALL_GOOD = 100,
LIMITED = 200,
VERY_LIMITED = 300,
AT_RISK = 400,
SUSPENDED = 500,
}

View file

@ -9,7 +9,7 @@ import { PlainSettings, Settings } from "@api/Settings";
import { localStorage } from "@utils/localStorage";
import { Logger } from "@utils/Logger";
import { relaunch } from "@utils/native";
import { openUserSettingsPanel } from "@webpack/common";
import { SettingsRouter } from "@webpack/common";
import { deflateSync, inflateSync } from "fflate";
import { deauthorizeCloud, getCloudAuth, getCloudUrl } from "./cloudSetup";
@ -88,7 +88,7 @@ export async function getCloudSettings(shouldNotify = true, force = false) {
title: "Cloud Settings",
body: "Cloud sync was disabled because this account isn't connected to the cloud App. You can enable it again by connecting this account in Cloud Settings. (note: it will store your preferences separately)",
color: "var(--yellow-360)",
onClick: () => openUserSettingsPanel("equicord_cloud")
onClick: () => SettingsRouter.openUserSettings("equicord_cloud_panel")
});
// Disable cloud sync globally
Settings.cloud.authenticated = false;

View file

@ -10,7 +10,7 @@ import { Devs, EquicordDevs } from "@utils/constants";
import { getIntlMessage } from "@utils/discord";
import definePlugin, { OptionType } from "@utils/types";
import { Activity } from "@vencord/discord-types";
import { openUserSettingsPanel, PresenceStore, UserStore } from "@webpack/common";
import { PresenceStore, SettingsRouter, UserStore } from "@webpack/common";
const extraTimeslots = [3, 4, 5, 6, 7, 10, 15, 20, 25, 30];
const extraFramerates = [45, 90, 120, 144, 165, 240];
@ -57,7 +57,7 @@ const settings = definePluginSettings({
<>
<Button
onClick={() => {
openUserSettingsPanel("clips");
SettingsRouter.openUserSettings("clips_panel");
}}
>
Change FPS and duration options in Clips settings!

View file

@ -14,7 +14,7 @@ import type { Plugin } from "@utils/types";
import { changes, checkForUpdates } from "@utils/updater";
import { Guild } from "@vencord/discord-types";
import { findByPropsLazy, findStoreLazy } from "@webpack";
import { ChannelActionCreators, ChannelRouter, ChannelStore, ComponentDispatch, FluxDispatcher, GuildStore, MediaEngineStore, NavigationRouter, openUserSettingsPanel, React, ReadStateUtils, RelationshipStore, SelectedChannelStore, SelectedGuildStore, StreamerModeStore, Toasts, useEffect, UserStore, VoiceActions } from "@webpack/common";
import { ChannelActionCreators, ChannelRouter, ChannelStore, ComponentDispatch, FluxDispatcher, GuildStore, MediaEngineStore, NavigationRouter, React, ReadStateUtils, RelationshipStore, SelectedChannelStore, SelectedGuildStore, SettingsRouter, StreamerModeStore, Toasts, useEffect, UserStore, VoiceActions } from "@webpack/common";
import type { FC, ReactElement, ReactNode } from "react";
import { Settings } from "Vencord";
@ -1283,7 +1283,7 @@ const BUILT_IN_COMMANDS: CommandEntry[] = [
keywords: ["settings", "equicord"],
categoryId: DEFAULT_CATEGORY_ID,
tags: [TAG_NAVIGATION, TAG_CORE],
handler: () => openUserSettingsPanel("equicord_main")
handler: () => SettingsRouter.openUserSettings("equicord_main_panel")
},
{
id: "open-plugin-settings",
@ -1291,7 +1291,7 @@ const BUILT_IN_COMMANDS: CommandEntry[] = [
keywords: ["settings", "plugins"],
categoryId: DEFAULT_CATEGORY_ID,
tags: [TAG_NAVIGATION, TAG_PLUGINS],
handler: () => openUserSettingsPanel("equicord_plugins")
handler: () => SettingsRouter.openUserSettings("equicord_plugins_panel")
},
{
id: "reload-windows",
@ -1305,15 +1305,15 @@ const BUILT_IN_COMMANDS: CommandEntry[] = [
];
const DISCORD_SETTINGS_COMMANDS: Array<{ id: string; label: string; route: string; keywords: string[]; description?: string; }> = [
{ id: "settings-account", label: "Open My Account", route: "my_account", keywords: ["account", "profile"] },
{ id: "settings-privacy", label: "Open Data & Privacy", route: "data_and_privacy", keywords: ["privacy", "safety", "data"] },
{ id: "settings-notifications", label: "Open Notifications", route: "legacy_notifications_settings", keywords: ["notifications"] },
{ id: "settings-voice", label: "Open Voice & Video", route: "voice_and_video", keywords: ["voice", "video", "audio"] },
{ id: "settings-text", label: "Open Text & Images", route: "text_and_images", keywords: ["text", "images"] },
{ id: "settings-appearance", label: "Open Appearance", route: "appearance", keywords: ["appearance", "theme"] },
{ id: "settings-accessibility", label: "Open Accessibility", route: "accessibility", keywords: ["accessibility"] },
{ id: "settings-keybinds", label: "Open Keybinds", route: "keybinds", keywords: ["keybinds", "shortcuts"] },
{ id: "settings-advanced", label: "Open Advanced", route: "advanced", keywords: ["advanced"] }
{ id: "settings-account", label: "Open My Account", route: "my_account_panel", keywords: ["account", "profile"] },
{ id: "settings-privacy", label: "Open Data & Privacy", route: "data_and_privacy_panel", keywords: ["privacy", "safety", "data"] },
{ id: "settings-notifications", label: "Open Notifications", route: "notifications_panel", keywords: ["notifications"] },
{ id: "settings-voice", label: "Open Voice & Video", route: "voice_and_video_panel", keywords: ["voice", "video", "audio"] },
{ id: "settings-text", label: "Open Text & Images", route: "text_and_images_panel", keywords: ["text", "images"] },
{ id: "settings-appearance", label: "Open Appearance", route: "appearance_panel", keywords: ["appearance", "theme"] },
{ id: "settings-accessibility", label: "Open Accessibility", route: "accessibility_panel", keywords: ["accessibility"] },
{ id: "settings-keybinds", label: "Open Keybinds", route: "keybinds_panel", keywords: ["keybinds", "shortcuts"] },
{ id: "settings-advanced", label: "Open Advanced", route: "advanced_panel", keywords: ["advanced"] }
];
const settingsCommandsById = new Map<string, typeof DISCORD_SETTINGS_COMMANDS[number]>();
@ -1692,7 +1692,7 @@ function registerUpdateCommands() {
keywords: ["updates", "changelog"],
categoryId: "updates",
tags: [TAG_DEVELOPER, TAG_NAVIGATION],
handler: () => openUserSettingsPanel("equicord_changelog")
handler: () => SettingsRouter.openUserSettings("equicord_changelog_panel")
});
}
@ -1711,13 +1711,13 @@ function registerDiscordSettingsCommands() {
categoryId: "discord-settings",
tags: [TAG_NAVIGATION],
handler: async () => {
const fallbackRoute = command.id === "settings-privacy" ? "privacy_and_safety" : null;
const fallbackRoute = command.id === "settings-privacy" ? "privacy_and_safety_panel" : null;
try {
await openUserSettingsPanel(command.route);
await SettingsRouter.openUserSettings(command.route);
} catch (error) {
if (fallbackRoute) {
await openUserSettingsPanel(fallbackRoute);
await SettingsRouter.openUserSettings(fallbackRoute);
} else {
console.error("CommandPalette", "Failed to open Discord settings", command.route, error);
showToast(`Unable to open ${command.label}.`, Toasts.Type.FAILURE);
@ -2012,7 +2012,7 @@ async function executeCustomCommand(command: CustomCommandDefinition) {
await runCommandById(action.commandId, new Set([command.id]));
break;
case "settings":
openUserSettingsPanel(action.route);
SettingsRouter.openUserSettings(action.route);
break;
case "url": {
const external = (window as any)?.DiscordNative?.app?.openExternalURL;
@ -2708,7 +2708,7 @@ function registerCustomizationCommands() {
keywords: ["theme", "library"],
categoryId: DEFAULT_CATEGORY_ID,
tags: [TAG_CUSTOMIZATION, TAG_NAVIGATION],
handler: () => openUserSettingsPanel("equicord_themes")
handler: () => SettingsRouter.openUserSettings("equicord_themes_panel")
});
}

View file

@ -9,7 +9,7 @@ import "./styles.css";
import SettingsPlugin, { settingsSectionMap } from "@plugins/_core/settings";
import { Devs } from "@utils/constants";
import definePlugin, { StartAt } from "@utils/types";
import { openUserSettingsPanel } from "@webpack/common";
import { SettingsRouter } from "@webpack/common";
import ComponentsTab from "./components/ComponentsTab";
@ -45,7 +45,7 @@ export default definePlugin({
startAt: StartAt.WebpackReady,
toolboxActions: {
"Open Components Tab"() {
openUserSettingsPanel("equicord_components");
SettingsRouter.openUserSettings("equicord_components_panel");
},
},
start() {

View file

@ -5,19 +5,59 @@
*/
import { ApplicationCommandInputType, sendBotMessage } from "@api/Commands";
import { HeaderBarButton } from "@api/HeaderBar";
import { isPluginEnabled } from "@api/PluginManager";
import { definePluginSettings } from "@api/Settings";
import customRPC from "@plugins/customRPC";
import { Devs, EquicordDevs, GUILD_ID, SUPPORT_CHANNEL_ID, SUPPORT_CHANNEL_IDS, VC_SUPPORT_CHANNEL_IDS } from "@utils/constants";
import { isAnyPluginDev } from "@utils/misc";
import definePlugin, { OptionType } from "@utils/types";
import { Alerts, ApplicationCommandIndexStore, NavigationRouter, UserStore } from "@webpack/common";
import { StandingState } from "@vencord/discord-types/enums";
import { findByCodeLazy, findExportedComponentLazy, findStoreLazy } from "@webpack";
import { Alerts, ApplicationCommandIndexStore, NavigationRouter, React, SettingsRouter, UserStore, useStateFromStores } from "@webpack/common";
import { ComponentType } from "react";
import { PluginButtons } from "./pluginButtons";
import { PluginCards } from "./pluginCards";
let clicked = false;
const SafetyHubStore = findStoreLazy("SafetyHubStore");
const fetchSafetyHub: () => Promise<void> = findByCodeLazy("SAFETY_HUB_FETCH_START");
const WarningIcon = findExportedComponentLazy("WarningIcon");
const ShieldIcon = findExportedComponentLazy("ShieldIcon");
const StandingConfig: Record<number, { label: string; hoverColor: string; Icon: ComponentType<any>; }> = {
[StandingState.ALL_GOOD]: { label: "All good!", hoverColor: "var(--status-positive)", Icon: ShieldIcon },
[StandingState.LIMITED]: { label: "Limited", hoverColor: "var(--status-warning)", Icon: WarningIcon },
[StandingState.VERY_LIMITED]: { label: "Very limited", hoverColor: "var(--orange-345)", Icon: WarningIcon },
[StandingState.AT_RISK]: { label: "At risk", hoverColor: "var(--status-danger)", Icon: WarningIcon },
[StandingState.SUSPENDED]: { label: "Suspended", hoverColor: "var(--interactive-muted)", Icon: WarningIcon },
};
function StandingButton() {
const standing = useStateFromStores([SafetyHubStore], () => SafetyHubStore.getAccountStanding());
const isInitialized = useStateFromStores([SafetyHubStore], () => SafetyHubStore.isInitialized());
const [hovered, setHovered] = React.useState(false);
React.useEffect(() => {
if (!isInitialized) fetchSafetyHub().catch(() => { });
}, [isInitialized]);
const config = StandingConfig[standing?.state] ?? StandingConfig[StandingState.ALL_GOOD];
return (
<div style={{ display: "contents" }} onMouseEnter={() => setHovered(true)} onMouseLeave={() => setHovered(false)}>
<HeaderBarButton
tooltip={config.label}
position="bottom"
icon={props => <config.Icon {...props} color={hovered ? config.hoverColor : "currentColor"} />}
onClick={() => SettingsRouter.openUserSettings("my_account_panel")}
/>
</div>
);
}
const settings = definePluginSettings({
noMirroredCamera: {
type: OptionType.BOOLEAN,
@ -53,6 +93,12 @@ const settings = definePluginSettings({
description: "Forces role icons to display next to messages in compact mode",
restartNeeded: true,
default: false
},
accountStandingButton: {
type: OptionType.BOOLEAN,
description: "Show an account standing button in the header bar",
default: false,
restartNeeded: true,
}
});
@ -62,6 +108,10 @@ export default definePlugin({
authors: [Devs.thororen, EquicordDevs.nyx, EquicordDevs.Naibuu, EquicordDevs.keircn, EquicordDevs.SerStars, EquicordDevs.mart],
required: true,
settings,
headerBarButton: {
icon: ShieldIcon,
render: () => (settings.store.accountStandingButton ? <StandingButton /> : null),
},
patches: [
// Fixes Unknown Resolution/FPS Crashing
{

View file

@ -10,7 +10,7 @@ import { MagnifyingGlassIcon } from "@components/Icons";
import SettingsPlugin, { settingsSectionMap } from "@plugins/_core/settings";
import { EquicordDevs } from "@utils/constants";
import definePlugin, { StartAt } from "@utils/types";
import { openUserSettingsPanel } from "@webpack/common";
import { SettingsRouter } from "@webpack/common";
import IconsTab from "./components/IconsTab";
import { SettingsAbout } from "./components/Modals";
@ -23,7 +23,7 @@ export default definePlugin({
startAt: StartAt.WebpackReady,
toolboxActions: {
"Open Icons Tab"() {
openUserSettingsPanel("equicord_icon_viewer");
SettingsRouter.openUserSettings("equicord_icon_viewer_panel");
},
},
settingsAboutComponent: SettingsAbout,

View file

@ -10,7 +10,7 @@ import { gitHashShort } from "@shared/vencordUserAgent";
import { copyToClipboard } from "@utils/clipboard";
import { relaunch, showItemInFolder } from "@utils/native";
import { checkForUpdates, getRepo } from "@utils/updater";
import { GuildStore, NavigationRouter, openUserSettingsPanel, Toasts } from "@webpack/common";
import { GuildStore, NavigationRouter, SettingsRouter, Toasts } from "@webpack/common";
import gitRemote from "~git-remote";
import Plugins from "~plugins";
@ -26,12 +26,12 @@ export interface ButtonAction {
}
export const actions: ButtonAction[] = [
{ id: "openEquicordSettings", label: "Open Equicord tab", callback: async () => await openUserSettingsPanel("equicord_main"), registrar: "Equicord" },
{ id: "openPluginSettings", label: "Open Plugin tab", callback: () => openUserSettingsPanel("equicord_plugins"), registrar: "Equicord" },
{ id: "openThemesSettings", label: "Open Themes tab", callback: () => openUserSettingsPanel("equicord_themes"), registrar: "Equicord" },
{ id: "openUpdaterSettings", label: "Open Updater tab", callback: () => openUserSettingsPanel("equicord_updater"), registrar: "Equicord" },
{ id: "openEquicordCloudSettings", label: "Open Cloud tab", callback: () => openUserSettingsPanel("equicord_cloud"), registrar: "Equicord" },
{ id: "openBackupSettings", label: "Open Backup & Restore tab", callback: () => openUserSettingsPanel("equicord_backup_restore"), registrar: "Equicord" },
{ id: "openEquicordSettings", label: "Open Equicord tab", callback: async () => await SettingsRouter.openUserSettings("equicord_main_panel"), registrar: "Equicord" },
{ id: "openPluginSettings", label: "Open Plugin tab", callback: () => SettingsRouter.openUserSettings("equicord_plugins_panel"), registrar: "Equicord" },
{ id: "openThemesSettings", label: "Open Themes tab", callback: () => SettingsRouter.openUserSettings("equicord_themes_panel"), registrar: "Equicord" },
{ id: "openUpdaterSettings", label: "Open Updater tab", callback: () => SettingsRouter.openUserSettings("equicord_updater_panel"), registrar: "Equicord" },
{ id: "openEquicordCloudSettings", label: "Open Cloud tab", callback: () => SettingsRouter.openUserSettings("equicord_cloud_panel"), registrar: "Equicord" },
{ id: "openBackupSettings", label: "Open Backup & Restore tab", callback: () => SettingsRouter.openUserSettings("equicord_backup_restore_panel"), registrar: "Equicord" },
{ id: "restartClient", label: "Restart Client", callback: () => relaunch(), registrar: "Equicord" },
{ id: "openQuickCSSFile", label: "Open Quick CSS File", callback: () => VencordNative.quickCss.openEditor(), registrar: "Equicord" },
{ id: "openSettingsFolder", label: "Open Settings Folder", callback: async () => showItemInFolder(await VencordNative.settings.getSettingsDir()), registrar: "Equicord" },
@ -140,7 +140,7 @@ export const actions: ButtonAction[] = [
permanent: true,
noPersist: true,
onClick() {
openUserSettingsPanel("equicord_updater");
SettingsRouter.openUserSettings("equicord_updater_panel");
}
}), 10_000);
} else {

View file

@ -9,7 +9,7 @@ import { Devs } from "@utils/constants";
import { classNameFactory } from "@utils/css";
import { closeAllModals } from "@utils/modal";
import definePlugin, { OptionType } from "@utils/types";
import { openUserSettingsPanel, useState } from "@webpack/common";
import { SettingsRouter, useState } from "@webpack/common";
import { registerAction } from "./commands";
import { openCommandPalette } from "./components/CommandPalette";
@ -97,7 +97,7 @@ export default definePlugin({
registerAction({
id: "openDevSettings",
label: "Open Dev tab",
callback: () => openUserSettingsPanel("equicord_patch_helper"),
callback: () => SettingsRouter.openUserSettings("equicord_patch_helper_panel"),
registrar: "Equicord"
});
}

View file

@ -8,7 +8,7 @@ import { ColorPaletteIcon } from "@components/Icons";
import SettingsPlugin, { settingsSectionMap } from "@plugins/_core/settings";
import { EquicordDevs } from "@utils/constants";
import definePlugin from "@utils/types";
import { openUserSettingsPanel } from "@webpack/common";
import { SettingsRouter } from "@webpack/common";
import { settings } from "./utils/settings";
@ -19,7 +19,7 @@ export default definePlugin({
settings,
toolboxActions: {
"Open Theme Library": () => {
openUserSettingsPanel("equicord_theme_library");
SettingsRouter.openUserSettings("equicord_theme_library_panel");
},
},

View file

@ -176,11 +176,6 @@ export const { zustandPersist } = mapMangledModuleLazy(".onRehydrateStorage)?",
zustandPersist: filters.byCode(/(\(\i,\i\))=>.+?\i\1/)
});
export const { openUserSettings } = findByPropsLazy("openUserSettings");
export function openUserSettingsPanel(panel: string) {
openUserSettings(panel + "_panel");
}
export const MessageActions = findByPropsLazy("editMessage", "sendMessage");
export const MessageCache = findByPropsLazy("clearCache", "_channelMessages");
export const UserProfileActions = findByPropsLazy("openUserProfileModal", "closeUserProfileModal");