)` +
- `${settings.additionalInfo} - ${Intl.DateTimeFormat("en-GB", { dateStyle: "medium" }).format(BUILD_TIMESTAMP)}`,
- Client: `${RELEASE_CHANNEL} ~ ${client}`,
- Platform: window.navigator.platform
- };
-
- if (IS_DISCORD_DESKTOP) {
- info["Last Crash Reason"] = (await DiscordNative.processUtils.getLastCrash())?.rendererCrashReason ?? "N/A";
- }
-
- const debugInfo = `
->>> ${Object.entries(info).map(([k, v]) => `**${k}**: ${v}`).join("\n")}
-
-Enabled Plugins (${enabledPlugins.length}):
-${makeCodeblock(enabledPlugins.join(", "))}
-`;
-
- return {
- content: debugInfo.trim().replaceAll("```\n", "```")
- };
+ commands: [
+ {
+ name: "equicord-debug",
+ description: "Send Equicord debug info",
+ predicate: ctx => isPluginDev(UserStore.getCurrentUser()?.id) || AllowedChannelIds.includes(ctx.channel.id),
+ execute: async () => ({ content: await generateDebugInfoMessage() })
+ },
+ {
+ name: "equicord-plugins",
+ description: "Send Equicord plugin list",
+ predicate: ctx => isPluginDev(UserStore.getCurrentUser()?.id) || AllowedChannelIds.includes(ctx.channel.id),
+ execute: () => ({ content: generatePluginList() })
}
- }],
+ ],
flux: {
async CHANNEL_SELECT({ channelId }) {
@@ -132,24 +186,25 @@ ${makeCodeblock(enabledPlugins.join(", "))}
const selfId = UserStore.getCurrentUser()?.id;
if (!selfId || isPluginDev(selfId) || isEquicordPluginDev(selfId)) return;
- if (isOutdated) {
- return Alerts.show({
- title: "Hold on!",
- body:
- You are using an outdated version of Equicord! Chances are, your issue is already fixed.
-
- Please first update before asking for support!
-
-
,
- onCancel: () => openUpdaterModal!(),
- cancelText: "View Updates",
- confirmText: "Update & Restart Now",
- async onConfirm() {
- await update();
- relaunch();
- },
- secondaryConfirmText: "I know what I'm doing or I can't update"
- });
+ if (!IS_UPDATER_DISABLED) {
+ await checkForUpdatesOnce().catch(() => { });
+
+ if (isOutdated) {
+ return Alerts.show({
+ title: "Hold on!",
+ body:
+ You are using an outdated version of Equicord! Chances are, your issue is already fixed.
+
+ Please first update before asking for support!
+
+
,
+ onCancel: () => openUpdaterModal!(),
+ cancelText: "View Updates",
+ confirmText: "Update & Restart Now",
+ onConfirm: forceUpdate,
+ secondaryConfirmText: "I know what I'm doing or I can't update"
+ });
+ }
}
// @ts-ignore outdated type
@@ -187,7 +242,7 @@ ${makeCodeblock(enabledPlugins.join(", "))}
ContributorDmWarningCard: ErrorBoundary.wrap(({ userId }) => {
if (!isPluginDev(userId) || !isEquicordPluginDev(userId)) return null;
- if (RelationshipStore.isFriend(userId)) return null;
+ if (RelationshipStore.isFriend(userId) || isPluginDev(UserStore.getCurrentUser()?.id)) return null;
return (
@@ -197,5 +252,86 @@ ${makeCodeblock(enabledPlugins.join(", "))}
{!ChannelStore.getChannel(SUPPORT_CHANNEL_ID) && " (Click the link to join)"}
);
- }, { noop: true })
+ }, { noop: true }),
+
+ start() {
+ addAccessory("equicord-debug", props => {
+ const buttons = [] as JSX.Element[];
+
+ const shouldAddUpdateButton =
+ !IS_UPDATER_DISABLED
+ && (
+ (props.channel.id === KNOWN_ISSUES_CHANNEL_ID) ||
+ (props.channel.id === SUPPORT_CHANNEL_ID && props.message.author.id === VENBOT_USER_ID)
+ )
+ && props.message.content?.includes("update");
+
+ if (shouldAddUpdateButton) {
+ buttons.push(
+
+ );
+ }
+
+ if (props.channel.id === SUPPORT_CHANNEL_ID) {
+ if (props.message.content.includes("/equicord-debug") || props.message.content.includes("/equicord-plugins")) {
+ buttons.push(
+ ,
+
+ );
+ }
+
+ if (props.message.author.id === VENBOT_USER_ID) {
+ const match = CodeBlockRe.exec(props.message.content || props.message.embeds[0]?.rawDescription || "");
+ if (match) {
+ buttons.push(
+
+ );
+ }
+ }
+ }
+
+ return buttons.length
+ ? {buttons}
+ : null;
+ });
+ },
});
diff --git a/src/plugins/appleMusic.desktop/index.tsx b/src/plugins/appleMusic.desktop/index.tsx
index 0d81204e..6fa989cd 100644
--- a/src/plugins/appleMusic.desktop/index.tsx
+++ b/src/plugins/appleMusic.desktop/index.tsx
@@ -9,7 +9,7 @@ import { Devs } from "@utils/constants";
import definePlugin, { OptionType, PluginNative, ReporterTestable } from "@utils/types";
import { ApplicationAssetUtils, FluxDispatcher, Forms } from "@webpack/common";
-const Native = VencordNative.pluginHelpers.AppleMusic as PluginNative;
+const Native = VencordNative.pluginHelpers.AppleMusicRichPresence as PluginNative;
interface ActivityAssets {
large_image?: string;
diff --git a/src/plugins/betterRoleContext/index.tsx b/src/plugins/betterRoleContext/index.tsx
index 77be0e2b..bf4cf0f3 100644
--- a/src/plugins/betterRoleContext/index.tsx
+++ b/src/plugins/betterRoleContext/index.tsx
@@ -5,7 +5,7 @@
*/
import { definePluginSettings } from "@api/Settings";
-import { getUserSettingDefinitionLazy } from "@api/UserSettingDefinitions";
+import { getUserSettingLazy } from "@api/UserSettings";
import { ImageIcon } from "@components/Icons";
import { Devs } from "@utils/constants";
import { getCurrentGuild, openImageModal } from "@utils/discord";
@@ -15,7 +15,7 @@ import { Clipboard, GuildStore, Menu, PermissionStore } from "@webpack/common";
const GuildSettingsActions = findByPropsLazy("open", "selectRole", "updateGuild");
-const DeveloperMode = getUserSettingDefinitionLazy("appearance", "developerMode")!;
+const DeveloperMode = getUserSettingLazy("appearance", "developerMode")!;
function PencilIcon() {
return (
@@ -65,7 +65,7 @@ export default definePlugin({
name: "BetterRoleContext",
description: "Adds options to copy role color / edit role / view role icon when right clicking roles in the user profile",
authors: [Devs.Ven, Devs.goodbee],
- dependencies: ["UserSettingDefinitionsAPI"],
+ dependencies: ["UserSettingsAPI"],
settings,
diff --git a/src/plugins/customRPC/index.tsx b/src/plugins/customRPC/index.tsx
index ed2de9b4..eebcd4dd 100644
--- a/src/plugins/customRPC/index.tsx
+++ b/src/plugins/customRPC/index.tsx
@@ -17,7 +17,7 @@
*/
import { definePluginSettings, Settings } from "@api/Settings";
-import { getUserSettingDefinitionLazy } from "@api/UserSettingDefinitions";
+import { getUserSettingLazy } from "@api/UserSettings";
import { ErrorCard } from "@components/ErrorCard";
import { Link } from "@components/Link";
import { Devs } from "@utils/constants";
@@ -33,7 +33,7 @@ const useProfileThemeStyle = findByCodeLazy("profileThemeStyle:", "--profile-gra
const ActivityComponent = findComponentByCodeLazy("onOpenGameProfile");
const ActivityClassName = findByPropsLazy("activity", "buttonColor");
-const ShowCurrentGame = getUserSettingDefinitionLazy("status", "showCurrentGame")!;
+const ShowCurrentGame = getUserSettingLazy("status", "showCurrentGame")!;
async function getApplicationAsset(key: string): Promise {
if (/https?:\/\/(cdn|media)\.discordapp\.(com|net)\/attachments\//.test(key)) return "mp:" + key.replace(/https?:\/\/(cdn|media)\.discordapp\.(com|net)\//, "");
@@ -393,7 +393,7 @@ export default definePlugin({
name: "CustomRPC",
description: "Allows you to set a custom rich presence.",
authors: [Devs.captain, Devs.AutumnVN, Devs.nin0dev],
- dependencies: ["UserSettingDefinitionsAPI"],
+ dependencies: ["UserSettingsAPI"],
start: setRpc,
stop: () => setRpc(true),
settings,
diff --git a/src/plugins/gameActivityToggle/index.tsx b/src/plugins/gameActivityToggle/index.tsx
index e7353a5d..7aeb470d 100644
--- a/src/plugins/gameActivityToggle/index.tsx
+++ b/src/plugins/gameActivityToggle/index.tsx
@@ -18,7 +18,7 @@
import { definePluginSettings } from "@api/Settings";
import { disableStyle, enableStyle } from "@api/Styles";
-import { getUserSettingDefinitionLazy } from "@api/UserSettingDefinitions";
+import { getUserSettingLazy } from "@api/UserSettings";
import ErrorBoundary from "@components/ErrorBoundary";
import { Devs } from "@utils/constants";
import definePlugin, { OptionType } from "@utils/types";
@@ -28,7 +28,7 @@ import style from "./style.css?managed";
const Button = findComponentByCodeLazy("Button.Sizes.NONE,disabled:");
-const ShowCurrentGame = getUserSettingDefinitionLazy("status", "showCurrentGame")!;
+const ShowCurrentGame = getUserSettingLazy("status", "showCurrentGame")!;
function makeIcon(showCurrentGame?: boolean) {
const { oldIcon } = settings.use(["oldIcon"]);
@@ -87,7 +87,7 @@ export default definePlugin({
name: "GameActivityToggle",
description: "Adds a button next to the mic and deafen button to toggle game activity.",
authors: [Devs.Nuckyz, Devs.RuukuLada],
- dependencies: ["UserSettingDefinitionsAPI"],
+ dependencies: ["UserSettingsAPI"],
settings,
patches: [
diff --git a/src/plugins/ignoreActivities/index.tsx b/src/plugins/ignoreActivities/index.tsx
index 431cd3e0..78c1c5cf 100644
--- a/src/plugins/ignoreActivities/index.tsx
+++ b/src/plugins/ignoreActivities/index.tsx
@@ -6,7 +6,7 @@
import * as DataStore from "@api/DataStore";
import { definePluginSettings, Settings } from "@api/Settings";
-import { getUserSettingDefinitionLazy } from "@api/UserSettingDefinitions";
+import { getUserSettingLazy } from "@api/UserSettings";
import ErrorBoundary from "@components/ErrorBoundary";
import { Flex } from "@components/Flex";
import { Devs } from "@utils/constants";
@@ -28,7 +28,7 @@ interface IgnoredActivity {
const RunningGameStore = findStoreLazy("RunningGameStore");
-const ShowCurrentGame = getUserSettingDefinitionLazy("status", "showCurrentGame")!;
+const ShowCurrentGame = getUserSettingLazy("status", "showCurrentGame")!;
function ToggleIcon(activity: IgnoredActivity, tooltipText: string, path: string, fill: string) {
return (
@@ -208,7 +208,7 @@ export default definePlugin({
name: "IgnoreActivities",
authors: [Devs.Nuckyz],
description: "Ignore activities from showing up on your status ONLY. You can configure which ones are specifically ignored from the Registered Games and Activities tabs, or use the general settings below.",
- dependencies: ["UserSettingDefinitionsAPI"],
+ dependencies: ["UserSettingsAPI"],
settings,
diff --git a/src/plugins/messageLinkEmbeds/index.tsx b/src/plugins/messageLinkEmbeds/index.tsx
index b42992f9..062b850d 100644
--- a/src/plugins/messageLinkEmbeds/index.tsx
+++ b/src/plugins/messageLinkEmbeds/index.tsx
@@ -19,7 +19,7 @@
import { addAccessory, removeAccessory } from "@api/MessageAccessories";
import { updateMessage } from "@api/MessageUpdater";
import { definePluginSettings } from "@api/Settings";
-import { getUserSettingDefinitionLazy } from "@api/UserSettingDefinitions";
+import { getUserSettingLazy } from "@api/UserSettings";
import ErrorBoundary from "@components/ErrorBoundary";
import { Devs } from "@utils/constants.js";
import { classes } from "@utils/misc";
@@ -54,7 +54,7 @@ const ChannelMessage = findComponentByCodeLazy("childrenExecutedCommand:", ".hid
const SearchResultClasses = findByPropsLazy("message", "searchResult");
const EmbedClasses = findByPropsLazy("embedAuthorIcon", "embedAuthor", "embedAuthor");
-const MessageDisplayCompact = getUserSettingDefinitionLazy("textAndImages", "messageDisplayCompact")!;
+const MessageDisplayCompact = getUserSettingLazy("textAndImages", "messageDisplayCompact")!;
const messageLinkRegex = /(? `${m}reverseImageSearchType:${target}.getAttribute("data-role"),`
diff --git a/src/plugins/xsOverlay.desktop/index.ts b/src/plugins/xsOverlay.desktop/index.ts
index a68373a6..b42d2021 100644
--- a/src/plugins/xsOverlay.desktop/index.ts
+++ b/src/plugins/xsOverlay.desktop/index.ts
@@ -136,7 +136,7 @@ const settings = definePluginSettings({
},
});
-const Native = VencordNative.pluginHelpers.XsOverlay as PluginNative;
+const Native = VencordNative.pluginHelpers.XSOverlay as PluginNative;
export default definePlugin({
name: "XSOverlay",
diff --git a/src/utils/misc.tsx b/src/utils/misc.ts
similarity index 93%
rename from src/utils/misc.tsx
rename to src/utils/misc.ts
index 7842f79a..2738b63b 100644
--- a/src/utils/misc.tsx
+++ b/src/utils/misc.ts
@@ -100,3 +100,14 @@ export const isEquicordPluginDev = (id: string) => Object.hasOwn(EquicordDevsByI
export function pluralise(amount: number, singular: string, plural = singular + "s") {
return amount === 1 ? `${amount} ${singular}` : `${amount} ${plural}`;
}
+
+export function tryOrElse(func: () => T, fallback: T): T {
+ try {
+ const res = func();
+ return res instanceof Promise
+ ? res.catch(() => fallback) as T
+ : res;
+ } catch {
+ return fallback;
+ }
+}
diff --git a/src/utils/text.ts b/src/utils/text.ts
index 54ebe729..7f0c8c4b 100644
--- a/src/utils/text.ts
+++ b/src/utils/text.ts
@@ -164,3 +164,18 @@ export function makeCodeblock(text: string, language?: string) {
const chars = "```";
return `${chars}${language || ""}\n${text.replaceAll("```", "\\`\\`\\`")}\n${chars}`;
}
+
+export function stripIndent(strings: TemplateStringsArray, ...values: any[]) {
+ const string = String.raw({ raw: strings }, ...values);
+
+ const match = string.match(/^[ \t]*(?=\S)/gm);
+ if (!match) return string.trim();
+
+ const minIndent = match.reduce((r, a) => Math.min(r, a.length), Infinity);
+ return string.replace(new RegExp(`^[ \\t]{${minIndent}}`, "gm"), "").trim();
+}
+
+export const ZWSP = "\u200b";
+export function toInlineCode(s: string) {
+ return "``" + ZWSP + s.replaceAll("`", ZWSP + "`" + ZWSP) + ZWSP + "``";
+}
diff --git a/src/webpack/common/types/index.d.ts b/src/webpack/common/types/index.d.ts
index a6483bd0..69cc0064 100644
--- a/src/webpack/common/types/index.d.ts
+++ b/src/webpack/common/types/index.d.ts
@@ -22,7 +22,6 @@ export * from "./fluxEvents";
export * from "./i18nMessages";
export * from "./menu";
export * from "./passiveupdatestate";
-export * from "./settingsStores";
export * from "./stores";
export * from "./utils";
export * from "./voicestate";