Equicord/src/plugins/_core/settings.tsx

311 lines
9.9 KiB
TypeScript
Raw Normal View History

2022-10-22 01:17:06 +02:00
/*
* Vencord, a Discord client mod
* Copyright (c) 2025 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
2022-10-22 01:17:06 +02:00
2023-05-06 01:36:00 +02:00
import { Settings } from "@api/Settings";
import {
BackupAndRestoreTab,
ChangelogTab,
CloudTab,
PatchHelperTab,
PluginsTab,
UpdaterTab,
VencordTab,
} from "@components/settings";
2025-02-23 11:10:55 -05:00
import ThemesTab from "@components/ThemeSettings/ThemesTab";
import { Devs } from "@utils/constants";
import { getIntlMessage } from "@utils/discord";
import definePlugin, { OptionType } from "@utils/types";
2025-08-14 18:09:40 -04:00
import { shortGitHash } from "@utils/updater";
import { React } from "@webpack/common";
type SectionType = "HEADER" | "DIVIDER" | "CUSTOM";
type SectionTypes = Record<SectionType, SectionType>;
export default definePlugin({
name: "Settings",
description: "Adds Settings UI and debug info",
authors: [Devs.Ven, Devs.Megu],
2022-08-31 04:07:16 +02:00
required: true,
2023-04-15 02:27:11 +02:00
2024-05-14 18:52:35 +02:00
patches: [
{
find: ".versionHash",
replacement: [
{
match: /\.info.+?\[\(0,\i\.jsxs?\)\((.{1,10}),(\{[^{}}]+\{.{0,20}.versionHash,.+?\})\)," "/,
2024-05-14 18:52:35 +02:00
replace: (m, component, props) => {
props = props.replace(/children:\[.+\]/, "");
return `${m},$self.makeInfoElements(${component}, ${props})`;
},
},
{
match: /copyValue:\i\.join\(" "\)/,
replace: "$& + $self.getInfoString()",
},
],
2024-05-14 18:52:35 +02:00
},
{
2024-11-03 15:47:19 -03:00
find: ".SEARCH_NO_RESULTS&&0===",
replacement: [
{
match: /(?<=section:(.{0,50})\.DIVIDER\}\))([,;])(?=.{0,200}(\i)\.push.{0,100}label:(\i)\.header)/,
replace: (
_,
sectionTypes,
commaOrSemi,
elements,
element,
) =>
`${commaOrSemi} $self.addSettings(${elements}, ${element}, ${sectionTypes}) ${commaOrSemi}`,
},
{
match: /({(?=.+?function (\i).{0,160}(\i)=\i\.useMemo.{0,140}return \i\.useMemo\(\(\)=>\i\(\3).+?\(\)=>)\2/,
replace: (_, rest, settingsHook) =>
`${rest}$self.wrapSettingsHook(${settingsHook})`,
},
],
2024-05-14 18:52:35 +02:00
},
{
find: ".DEVELOPER_SECTION,",
replacement: [
{
match: /\i\.\i\.isDeveloper/,
replace: "true"
},
]
},
2024-05-14 18:52:35 +02:00
{
find: "#{intl::USER_SETTINGS_ACTIONS_MENU_LABEL}",
2024-05-14 18:52:35 +02:00
replacement: {
match: /(?<=function\((\i),\i\)\{)(?=let \i=Object.values\(\i.\i\).*?(\i\.\i)\.open\()/,
replace: "$2.open($1);return;",
},
},
2024-05-14 18:52:35 +02:00
],
2022-11-11 00:11:44 +01:00
customSections: [] as ((SectionTypes: SectionTypes) => any)[],
makeSettingsCategories(SectionTypes: SectionTypes) {
2023-04-09 04:04:02 +02:00
return [
{
2023-10-25 00:17:11 +02:00
section: SectionTypes.HEADER,
2024-04-17 14:29:47 -04:00
label: "Equicord",
className: "vc-settings-header",
2023-04-09 04:04:02 +02:00
},
{
2024-07-13 00:06:01 -04:00
section: "EquicordSettings",
2024-04-17 14:29:47 -04:00
label: "Equicord",
element: VencordTab,
className: "vc-settings",
2023-04-09 04:04:02 +02:00
},
{
2024-07-13 00:06:01 -04:00
section: "EquicordPlugins",
label: "Plugins",
2024-11-06 04:00:38 -05:00
searchableTitles: ["Plugins"],
element: PluginsTab,
className: "vc-plugins",
2023-04-09 04:04:02 +02:00
},
{
2024-07-13 00:06:01 -04:00
section: "EquicordThemes",
label: "Themes",
2024-11-06 04:00:38 -05:00
searchableTitles: ["Themes"],
2025-02-23 11:10:55 -05:00
element: ThemesTab,
className: "vc-themes",
2023-04-09 04:04:02 +02:00
},
!IS_UPDATER_DISABLED && {
2024-07-13 00:06:01 -04:00
section: "EquicordUpdater",
label: "Updater",
2024-11-06 04:00:38 -05:00
searchableTitles: ["Updater"],
element: UpdaterTab,
className: "vc-updater",
},
{
section: "EquicordChangelog",
label: "Changelog",
searchableTitles: ["Changelog"],
element: ChangelogTab,
className: "vc-changelog",
2023-04-09 04:04:02 +02:00
},
{
2024-07-13 00:06:01 -04:00
section: "EquicordCloud",
2023-04-09 04:04:02 +02:00
label: "Cloud",
2024-11-06 04:00:38 -05:00
searchableTitles: ["Cloud"],
element: CloudTab,
className: "vc-cloud",
2023-04-09 04:04:02 +02:00
},
{
section: "settings/tabsSync",
2023-04-09 04:04:02 +02:00
label: "Backup & Restore",
2024-11-06 04:00:38 -05:00
searchableTitles: ["Backup & Restore"],
element: BackupAndRestoreTab,
className: "vc-backup-restore",
2023-04-09 04:04:02 +02:00
},
2025-02-23 10:56:29 -05:00
IS_DEV && {
2024-07-13 00:06:01 -04:00
section: "EquicordPatchHelper",
label: "Patch Helper",
2024-11-06 04:00:38 -05:00
searchableTitles: ["Patch Helper"],
element: PatchHelperTab,
className: "vc-patch-helper",
2023-04-09 04:04:02 +02:00
},
2023-10-25 00:17:11 +02:00
...this.customSections.map(func => func(SectionTypes)),
2023-04-09 04:04:02 +02:00
{
section: SectionTypes.DIVIDER,
},
2023-04-09 04:04:02 +02:00
].filter(Boolean);
},
isRightSpot({
header,
settings,
}: {
header?: string;
settings?: string[];
}) {
2024-05-14 18:52:35 +02:00
const firstChild = settings?.[0];
// lowest two elements... sanity backup
if (firstChild === "LOGOUT" || firstChild === "SOCIAL_LINKS")
return true;
2024-05-14 18:52:35 +02:00
const { settingsLocation } = Settings.plugins.Settings;
if (settingsLocation === "bottom") return firstChild === "LOGOUT";
if (settingsLocation === "belowActivity")
return firstChild === "CHANGELOG";
2024-05-14 18:52:35 +02:00
if (!header) return;
2024-11-03 15:47:19 -03:00
try {
const names = {
top: getIntlMessage("USER_SETTINGS"),
aboveNitro: getIntlMessage("BILLING_SETTINGS"),
belowNitro: getIntlMessage("APP_SETTINGS"),
aboveActivity: getIntlMessage("ACTIVITY_SETTINGS"),
2024-11-03 15:47:19 -03:00
};
if (
!names[settingsLocation] ||
names[settingsLocation].endsWith("_SETTINGS")
)
return firstChild === "PREMIUM";
2024-11-03 15:47:19 -03:00
return header === names[settingsLocation];
} catch {
return firstChild === "PREMIUM";
}
2024-05-14 18:52:35 +02:00
},
patchedSettings: new WeakSet(),
addSettings(
elements: any[],
element: { header?: string; settings: string[]; },
sectionTypes: SectionTypes,
) {
if (this.patchedSettings.has(elements) || !this.isRightSpot(element))
return;
this.patchedSettings.add(elements);
2024-05-14 18:52:35 +02:00
elements.push(...this.makeSettingsCategories(sectionTypes));
},
wrapSettingsHook(
originalHook: (...args: any[]) => Record<string, unknown>[],
) {
return (...args: any[]) => {
const elements = originalHook(...args);
if (!this.patchedSettings.has(elements))
elements.unshift(
...this.makeSettingsCategories({
HEADER: "HEADER",
DIVIDER: "DIVIDER",
CUSTOM: "CUSTOM",
}),
);
return elements;
};
},
options: {
settingsLocation: {
type: OptionType.SELECT,
2024-04-17 14:29:47 -04:00
description: "Where to put the Equicord settings section",
options: [
{ label: "At the very top", value: "top" },
2024-05-14 18:52:35 +02:00
{ label: "Above the Nitro section", value: "aboveNitro", default: true },
{ label: "Below the Nitro section", value: "belowNitro" },
2024-05-14 18:52:35 +02:00
{ label: "Above Activity Settings", value: "aboveActivity" },
{ label: "Below Activity Settings", value: "belowActivity" },
{ label: "At the very bottom", value: "bottom" },
],
},
},
2022-11-17 13:49:51 +01:00
get electronVersion() {
return (
VencordNative.native.getVersions().electron ||
window.legcord?.electron ||
null
);
2022-11-17 13:49:51 +01:00
},
get chromiumVersion() {
try {
return (
VencordNative.native.getVersions().chrome ||
// @ts-expect-error Typescript will add userAgentData IMMEDIATELY
navigator.userAgentData?.brands?.find(
b =>
b.brand === "Chromium" || b.brand === "Google Chrome",
)?.version ||
null
);
2024-10-14 19:33:17 -04:00
} catch {
// inb4 some stupid browser throws unsupported error for navigator.userAgentData, it's only in chromium
2022-11-17 13:49:51 +01:00
return null;
}
},
getVersionInfo(support = true) {
2025-08-05 00:45:21 -04:00
let version = "";
if (IS_DEV) version = "Dev";
2025-08-05 14:52:51 -04:00
if (IS_WEB) version = "Web";
if (IS_VESKTOP) version = `Vesktop v${VesktopNative.app.getVersion()}`;
if (IS_EQUIBOP) version = `Equibop v${VesktopNative.app.getVersion()}`;
if (IS_STANDALONE) version = "Standalone";
2025-08-05 00:45:21 -04:00
return support && version ? ` (${version})` : version;
2022-11-17 13:49:51 +01:00
},
getInfoRows() {
2025-08-05 00:45:21 -04:00
const { electronVersion, chromiumVersion, getVersionInfo } = this;
2022-11-17 13:49:51 +01:00
2025-08-14 18:09:40 -04:00
const rows = [`Equicord ${shortGitHash()}${getVersionInfo()}`];
if (electronVersion) rows.push(`Electron ${electronVersion}`);
if (chromiumVersion) rows.push(`Chromium ${chromiumVersion}`);
return rows;
},
getInfoString() {
return "\n" + this.getInfoRows().join("\n");
},
makeInfoElements(
Component: React.ComponentType<React.PropsWithChildren>,
props: React.PropsWithChildren,
) {
return this.getInfoRows().map((text, i) => (
<Component key={i} {...props}>
{text}
</Component>
));
},
2022-09-16 22:59:34 +02:00
});