Merge branch 'dev' into rip-plugins
This commit is contained in:
commit
405b360c0e
11 changed files with 829 additions and 827 deletions
|
|
@ -88,7 +88,7 @@ export default tseslint.config(
|
|||
"@stylistic/no-extra-semi": "error",
|
||||
|
||||
// TS Rules
|
||||
"@/func-call-spacing": ["error", "never"],
|
||||
"@stylistic/func-call-spacing": ["error", "never"],
|
||||
|
||||
// ESLint Rules
|
||||
"yoda": "error",
|
||||
|
|
|
|||
60
package.json
60
package.json
|
|
@ -38,11 +38,11 @@
|
|||
"testTsc": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ffmpeg/ffmpeg": "^0.12.15",
|
||||
"@ffmpeg/util": "^0.12.2",
|
||||
"@ffmpeg/ffmpeg": "^0.12.10",
|
||||
"@ffmpeg/util": "^0.12.1",
|
||||
"@intrnl/xxhash64": "^0.1.2",
|
||||
"@types/less": "^3.0.8",
|
||||
"@types/stylus": "^0.48.43",
|
||||
"@types/stylus": "^0.48.42",
|
||||
"@types/tinycolor2": "^1.4.6",
|
||||
"@vap/core": "0.0.12",
|
||||
"@vap/shiki": "0.10.5",
|
||||
|
|
@ -50,50 +50,51 @@
|
|||
"gifenc": "github:mattdesl/gifenc#64842fca317b112a8590f8fef2bf3825da8f6fe3",
|
||||
"idb": "8.0.3",
|
||||
"jsqr": "1.4.0",
|
||||
"monaco-editor": "^0.53.0",
|
||||
"monaco-editor": "^0.52.2",
|
||||
"nanoid": "^5.1.5",
|
||||
"usercss-meta": "^0.12.0",
|
||||
"virtual-merge": "^1.0.2"
|
||||
"virtual-merge": "^1.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@electron/asar": "^4.0.1",
|
||||
"@stylistic/eslint-plugin": "^5.3.1",
|
||||
"@stylistic/eslint-plugin": "^4.2.0",
|
||||
"@types/adm-zip": "^0.5.7",
|
||||
"@types/chrome": "^0.1.9",
|
||||
"@types/lodash": "^4.17.20",
|
||||
"@types/node": "^24.3.1",
|
||||
"@types/react": "^19.1.12",
|
||||
"@types/react-dom": "^19.1.9",
|
||||
"@types/yazl": "^3.3.0",
|
||||
"@types/chrome": "^0.0.312",
|
||||
"@types/diff": "^7.0.2",
|
||||
"@types/lodash": "^4.17.14",
|
||||
"@types/node": "^22.13.13",
|
||||
"@types/react": "^19.0.10",
|
||||
"@types/react-dom": "^19.0.4",
|
||||
"@types/yazl": "^2.4.5",
|
||||
"@vencord/discord-types": "link:packages/discord-types",
|
||||
"adm-zip": "^0.5.16",
|
||||
"diff": "^8.0.2",
|
||||
"esbuild": "^0.25.9",
|
||||
"eslint": "9.35.0",
|
||||
"diff": "^7.0.0",
|
||||
"esbuild": "^0.25.1",
|
||||
"eslint": "9.20.1",
|
||||
"eslint-import-resolver-alias": "^1.1.2",
|
||||
"eslint-plugin-react": "^7.37.5",
|
||||
"eslint-plugin-simple-header": "^1.2.2",
|
||||
"eslint-plugin-react": "^7.37.3",
|
||||
"eslint-plugin-simple-header": "^1.2.1",
|
||||
"eslint-plugin-simple-import-sort": "^12.1.1",
|
||||
"eslint-plugin-unused-imports": "^4.2.0",
|
||||
"eslint-plugin-unused-imports": "^4.1.4",
|
||||
"highlight.js": "11.11.1",
|
||||
"html-minifier-terser": "^7.2.0",
|
||||
"moment": "^2.30.1",
|
||||
"moment": "^2.22.2",
|
||||
"puppeteer-core": "^24.19.0",
|
||||
"standalone-electron-types": "^34.2.0",
|
||||
"stylelint": "^16.24.0",
|
||||
"stylelint-config-standard": "^39.0.0",
|
||||
"stylelint": "^16.17.0",
|
||||
"stylelint-config-standard": "^37.0.0",
|
||||
"ts-patch": "^3.3.0",
|
||||
"ts-pattern": "^5.8.0",
|
||||
"tsx": "^4.20.5",
|
||||
"type-fest": "^4.41.0",
|
||||
"typescript": "^5.9.2",
|
||||
"typescript-eslint": "^8.43.0",
|
||||
"ts-pattern": "^5.6.0",
|
||||
"tsx": "^4.19.3",
|
||||
"type-fest": "^4.38.0",
|
||||
"typescript": "^5.8.2",
|
||||
"typescript-eslint": "^8.28.0",
|
||||
"typescript-transform-paths": "^3.5.5"
|
||||
},
|
||||
"packageManager": "pnpm@10.14.0",
|
||||
"pnpm": {
|
||||
"patchedDependencies": {
|
||||
"eslint@9.35.0": "patches/eslint@9.35.0.patch",
|
||||
"eslint@9.20.1": "patches/eslint@9.20.1.patch",
|
||||
"@types/less@3.0.8": "patches/@types__less@3.0.8.patch"
|
||||
},
|
||||
"peerDependencyRules": {
|
||||
|
|
@ -111,7 +112,10 @@
|
|||
},
|
||||
"onlyBuiltDependencies": [
|
||||
"esbuild"
|
||||
]
|
||||
],
|
||||
"overrides": {
|
||||
"@eslint/plugin-kit@<0.3.4": ">=0.3.4"
|
||||
}
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
|
|
|
|||
49
patches/eslint@9.20.1.patch
Normal file
49
patches/eslint@9.20.1.patch
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
diff --git a/lib/rules/no-useless-escape.js b/lib/rules/no-useless-escape.js
|
||||
index 0e0f6f09f2c35f3276173c08f832cde9f2cf56a0..7dc22851715f3574d935f513c1b5e35552985711 100644
|
||||
--- a/lib/rules/no-useless-escape.js
|
||||
+++ b/lib/rules/no-useless-escape.js
|
||||
@@ -65,13 +65,31 @@ module.exports = {
|
||||
escapeBackslash: "Replace the `\\` with `\\\\` to include the actual backslash character."
|
||||
},
|
||||
|
||||
- schema: []
|
||||
+ schema: [{
|
||||
+ type: "object",
|
||||
+ properties: {
|
||||
+ extra: {
|
||||
+ type: "string",
|
||||
+ default: ""
|
||||
+ },
|
||||
+ extraCharClass: {
|
||||
+ type: "string",
|
||||
+ default: ""
|
||||
+ },
|
||||
+ },
|
||||
+ additionalProperties: false
|
||||
+ }]
|
||||
},
|
||||
|
||||
create(context) {
|
||||
+ const options = context.options[0] || {};
|
||||
+ const { extra, extraCharClass } = options;
|
||||
const sourceCode = context.sourceCode;
|
||||
const parser = new RegExpParser();
|
||||
|
||||
+ const NON_CHARCLASS_ESCAPES = union(REGEX_NON_CHARCLASS_ESCAPES, new Set(extra));
|
||||
+ const CHARCLASS_ESCAPES = union(REGEX_GENERAL_ESCAPES, new Set(extraCharClass));
|
||||
+
|
||||
/**
|
||||
* Reports a node
|
||||
* @param {ASTNode} node The node to report
|
||||
@@ -200,9 +218,9 @@ module.exports = {
|
||||
let allowedEscapes;
|
||||
|
||||
if (characterClassStack.length) {
|
||||
- allowedEscapes = unicodeSets ? REGEX_CLASSSET_CHARACTER_ESCAPES : REGEX_GENERAL_ESCAPES;
|
||||
+ allowedEscapes = unicodeSets ? REGEX_CLASSSET_CHARACTER_ESCAPES : CHARCLASS_ESCAPES;
|
||||
} else {
|
||||
- allowedEscapes = REGEX_NON_CHARCLASS_ESCAPES;
|
||||
+ allowedEscapes = NON_CHARCLASS_ESCAPES;
|
||||
}
|
||||
if (allowedEscapes.has(escapedChar)) {
|
||||
return;
|
||||
|
|
@ -1,105 +0,0 @@
|
|||
diff --git a/lib/rules/no-useless-escape.js b/lib/rules/no-useless-escape.js
|
||||
index 480b51597..3e8cdbaf1 100644
|
||||
--- a/lib/rules/no-useless-escape.js
|
||||
+++ b/lib/rules/no-useless-escape.js
|
||||
@@ -95,6 +95,14 @@ module.exports = {
|
||||
},
|
||||
uniqueItems: true,
|
||||
},
|
||||
+ extra: {
|
||||
+ type: "string",
|
||||
+ default: ""
|
||||
+ },
|
||||
+ extraCharClass: {
|
||||
+ type: "string",
|
||||
+ default: ""
|
||||
+ }
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
@@ -102,10 +110,15 @@ module.exports = {
|
||||
},
|
||||
|
||||
create(context) {
|
||||
+ const options = context.options[0] || {};
|
||||
+ const { extra, extraCharClass } = options;
|
||||
const sourceCode = context.sourceCode;
|
||||
const [{ allowRegexCharacters }] = context.options;
|
||||
const parser = new RegExpParser();
|
||||
|
||||
+ const NON_CHARCLASS_ESCAPES = union(REGEX_NON_CHARCLASS_ESCAPES, new Set(extra));
|
||||
+ const CHARCLASS_ESCAPES = union(REGEX_GENERAL_ESCAPES, new Set(extraCharClass));
|
||||
+
|
||||
/**
|
||||
* Reports a node
|
||||
* @param {ASTNode} node The node to report
|
||||
@@ -145,16 +158,16 @@ module.exports = {
|
||||
...(disableEscapeBackslashSuggest
|
||||
? []
|
||||
: [
|
||||
- {
|
||||
- messageId: "escapeBackslash",
|
||||
- fix(fixer) {
|
||||
- return fixer.insertTextBeforeRange(
|
||||
- range,
|
||||
- "\\",
|
||||
- );
|
||||
- },
|
||||
+ {
|
||||
+ messageId: "escapeBackslash",
|
||||
+ fix(fixer) {
|
||||
+ return fixer.insertTextBeforeRange(
|
||||
+ range,
|
||||
+ "\\",
|
||||
+ );
|
||||
},
|
||||
- ]),
|
||||
+ },
|
||||
+ ]),
|
||||
],
|
||||
});
|
||||
}
|
||||
@@ -238,7 +251,7 @@ module.exports = {
|
||||
|
||||
if (
|
||||
escapedChar !==
|
||||
- String.fromCodePoint(characterNode.value) ||
|
||||
+ String.fromCodePoint(characterNode.value) ||
|
||||
allowRegexCharacters.includes(escapedChar)
|
||||
) {
|
||||
// It's a valid escape.
|
||||
@@ -247,11 +260,9 @@ module.exports = {
|
||||
let allowedEscapes;
|
||||
|
||||
if (characterClassStack.length) {
|
||||
- allowedEscapes = unicodeSets
|
||||
- ? REGEX_CLASSSET_CHARACTER_ESCAPES
|
||||
- : REGEX_GENERAL_ESCAPES;
|
||||
+ allowedEscapes = unicodeSets ? REGEX_CLASSSET_CHARACTER_ESCAPES : CHARCLASS_ESCAPES;
|
||||
} else {
|
||||
- allowedEscapes = REGEX_NON_CHARCLASS_ESCAPES;
|
||||
+ allowedEscapes = NON_CHARCLASS_ESCAPES;
|
||||
}
|
||||
if (allowedEscapes.has(escapedChar)) {
|
||||
return;
|
||||
@@ -287,9 +298,9 @@ module.exports = {
|
||||
*/
|
||||
if (
|
||||
characterClassNode.start + 1 !==
|
||||
- characterNode.start &&
|
||||
+ characterNode.start &&
|
||||
characterNode.end !==
|
||||
- characterClassNode.end - 1
|
||||
+ characterClassNode.end - 1
|
||||
) {
|
||||
return;
|
||||
}
|
||||
@@ -334,7 +345,7 @@ module.exports = {
|
||||
|
||||
if (
|
||||
characterNode.parent.type ===
|
||||
- "ClassIntersection" ||
|
||||
+ "ClassIntersection" ||
|
||||
characterNode.parent.type === "ClassSubtraction"
|
||||
) {
|
||||
disableEscapeBackslashSuggest = true;
|
||||
1146
pnpm-lock.yaml
generated
1146
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load diff
|
|
@ -212,7 +212,6 @@ if (!process.argv.includes("--skip-extension")) {
|
|||
firefoxZip.addLocalFolder("dist/browser/firefox-unpacked");
|
||||
firefoxZip.writeZip(path.resolve("dist/extension-firefox.zip"));
|
||||
console.info("Packed Firefox Extension written to dist/extension-firefox.zip");
|
||||
|
||||
} else {
|
||||
await appendCssRuntime;
|
||||
}
|
||||
|
|
|
|||
20
src/equicordplugins/newPluginsManager/NewPluginsModal.css
Normal file
20
src/equicordplugins/newPluginsManager/NewPluginsModal.css
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
.vc-newPluginsManager-restart-tooltip {
|
||||
max-width: 280px;
|
||||
}
|
||||
|
||||
.vc-newPluginsManager-restart-list {
|
||||
padding-left: 1.25em;
|
||||
}
|
||||
|
||||
.vc-newPluginsManager-restart-list li {
|
||||
list-style: disc;
|
||||
}
|
||||
|
||||
.vc-newPluginsManager-close > div {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.vc-newPluginsManager-disable-wrapper {
|
||||
display: flex;
|
||||
margin: auto 0;
|
||||
}
|
||||
|
|
@ -4,47 +4,36 @@
|
|||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { useSettings } from "@api/Settings";
|
||||
import "./NewPluginsModal.css";
|
||||
|
||||
import { Settings, useSettings } from "@api/Settings";
|
||||
import { classNameFactory } from "@api/Styles";
|
||||
import { PluginCard } from "@components/settings/tabs/plugins/PluginCard";
|
||||
import ErrorBoundary from "@components/ErrorBoundary";
|
||||
import { PluginCard } from "@components/settings/tabs/plugins";
|
||||
import { ChangeList } from "@utils/ChangeList";
|
||||
import { ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal";
|
||||
import { Alerts, Button, Flex, Forms, Parser, React, Text, Tooltip, useMemo } from "@webpack/common";
|
||||
import { classes, Margins } from "@utils/index";
|
||||
import { closeModal, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal";
|
||||
import { useForceUpdater } from "@utils/react";
|
||||
import { findComponentByCodeLazy } from "@webpack";
|
||||
import { Button, Flex, Forms, React, Text, Tooltip, useMemo } from "@webpack/common";
|
||||
import { JSX } from "react";
|
||||
|
||||
import Plugins from "~plugins";
|
||||
|
||||
import { getNewPlugins, writeKnownPlugins } from "./knownPlugins";
|
||||
import { getNewPlugins, getNewSettings, KnownPluginSettingsMap, writeKnownSettings } from "./knownSettings";
|
||||
|
||||
const cl = classNameFactory("vc-plugins-");
|
||||
|
||||
const Checkbox = findComponentByCodeLazy(".checkboxWrapperDisabled:");
|
||||
|
||||
let hasSeen = false;
|
||||
|
||||
// Most of this was stolen from PluginSettings directly.
|
||||
|
||||
export function NewPluginsModal({ modalProps, newPlugins }: { modalProps: ModalProps; newPlugins: Set<string>; }) {
|
||||
export function NewPluginsModal({ modalProps, newPlugins, newSettings }: { modalProps: ModalProps; newPlugins: Set<string>; newSettings: KnownPluginSettingsMap; }) {
|
||||
const settings = useSettings();
|
||||
const changes = React.useMemo(() => new ChangeList<string>(), []);
|
||||
|
||||
React.useEffect(() => {
|
||||
return () => void (changes.hasChanges && Alerts.show({
|
||||
title: "Restart required",
|
||||
body: (
|
||||
<>
|
||||
<p>The following plugins require a restart:</p>
|
||||
<div>{changes.map((s, i) => (
|
||||
<>
|
||||
{i > 0 && ", "}
|
||||
{Parser.parse("`" + s + "`")}
|
||||
</>
|
||||
))}</div>
|
||||
</>
|
||||
),
|
||||
confirmText: "Restart now",
|
||||
cancelText: "Later!",
|
||||
onConfirm: () => location.reload()
|
||||
}));
|
||||
}, []);
|
||||
let updateContinueButton = () => { };
|
||||
|
||||
const depMap = React.useMemo(() => {
|
||||
const o = {} as Record<string, string[]>;
|
||||
|
|
@ -60,8 +49,13 @@ export function NewPluginsModal({ modalProps, newPlugins }: { modalProps: ModalP
|
|||
return o;
|
||||
}, []);
|
||||
|
||||
const sortedPlugins = useMemo(() => [...newPlugins].map(pn => Plugins[pn])
|
||||
.sort((a, b) => a.name.localeCompare(b.name)), []);
|
||||
const mapPlugins = (array: string[]) => array.map(pn => Plugins[pn])
|
||||
.sort((a, b) => a.name.localeCompare(b.name));
|
||||
|
||||
const sortedPlugins = useMemo(() => [
|
||||
...mapPlugins([...newPlugins]),
|
||||
...mapPlugins([...newSettings.keys()].filter(p => !newPlugins.has(p)))
|
||||
], []);
|
||||
|
||||
const plugins = [] as JSX.Element[];
|
||||
const requiredPlugins = [] as JSX.Element[];
|
||||
|
|
@ -83,10 +77,14 @@ export function NewPluginsModal({ modalProps, newPlugins }: { modalProps: ModalP
|
|||
<PluginCard
|
||||
onMouseLeave={onMouseLeave}
|
||||
onMouseEnter={onMouseEnter}
|
||||
onRestartNeeded={name => changes.handleChange(name)}
|
||||
onRestartNeeded={name => {
|
||||
changes.handleChange(name);
|
||||
updateContinueButton();
|
||||
}}
|
||||
disabled={true}
|
||||
plugin={p}
|
||||
key={p.name}
|
||||
isNew={newPlugins.has(p.name)}
|
||||
/>
|
||||
)}
|
||||
</Tooltip>
|
||||
|
|
@ -94,10 +92,14 @@ export function NewPluginsModal({ modalProps, newPlugins }: { modalProps: ModalP
|
|||
} else {
|
||||
plugins.push(
|
||||
<PluginCard
|
||||
onRestartNeeded={name => changes.handleChange(name)}
|
||||
onRestartNeeded={name => {
|
||||
changes.handleChange(name);
|
||||
updateContinueButton();
|
||||
}}
|
||||
disabled={false}
|
||||
plugin={p}
|
||||
key={p.name}
|
||||
isNew={newPlugins.has(p.name)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
@ -106,7 +108,17 @@ export function NewPluginsModal({ modalProps, newPlugins }: { modalProps: ModalP
|
|||
|
||||
return <ModalRoot {...modalProps} size={ModalSize.MEDIUM} >
|
||||
<ModalHeader>
|
||||
<Text variant="heading-lg/semibold">New Plugins ({[...plugins, ...requiredPlugins].length})</Text>
|
||||
<Text variant="heading-lg/semibold" style={{ flexGrow: 1 }}>New Plugins and Settings ({[...plugins, ...requiredPlugins].length})</Text>
|
||||
<Tooltip text="Dismiss for this session">
|
||||
{tooltipProps =>
|
||||
<div {...tooltipProps}>
|
||||
<ModalCloseButton
|
||||
onClick={modalProps.onClose}
|
||||
className={classes(cl("close"), "vc-newPluginsManager-close")}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
</Tooltip>
|
||||
</ModalHeader>
|
||||
<ModalContent>
|
||||
<div className={cl("grid")}>
|
||||
|
|
@ -115,39 +127,79 @@ export function NewPluginsModal({ modalProps, newPlugins }: { modalProps: ModalP
|
|||
</ModalContent>
|
||||
<ModalFooter>
|
||||
<Flex direction={Flex.Direction.HORIZONTAL_REVERSE}>
|
||||
<Button
|
||||
color={Button.Colors.GREEN}
|
||||
onClick={async () => {
|
||||
await writeKnownPlugins();
|
||||
modalProps.onClose();
|
||||
}}
|
||||
>
|
||||
Continue
|
||||
</Button>
|
||||
<ContinueButton
|
||||
close={modalProps.onClose}
|
||||
changes={changes}
|
||||
callback={(v: () => void) => updateContinueButton = v}
|
||||
/>
|
||||
</Flex>
|
||||
<Flex direction={Flex.Direction.HORIZONTAL}>
|
||||
<div className="vc-newPluginsManager-disable-wrapper">
|
||||
<Checkbox
|
||||
type="inverted"
|
||||
value={!settings?.plugins?.NewPluginsManager?.enabled}
|
||||
onChange={() => {
|
||||
Settings.plugins.NewPluginsManager.enabled = !settings?.plugins?.NewPluginsManager?.enabled;
|
||||
}}
|
||||
>
|
||||
<Text>Don't show this again</Text>
|
||||
</Checkbox>
|
||||
</div>
|
||||
</Flex>
|
||||
</ModalFooter>
|
||||
</ModalRoot>;
|
||||
}
|
||||
|
||||
function ContinueButton(props: { callback: (update: () => void) => void; changes: ChangeList<string>; close: () => any; }) {
|
||||
const update = useForceUpdater();
|
||||
props.callback(update);
|
||||
return <Tooltip
|
||||
tooltipClassName="vc-newPluginsManager-restart-tooltip"
|
||||
text={<>
|
||||
The following plugins require a restart:
|
||||
<div className={Margins.bottom8} />
|
||||
<ul className="vc-newPluginsManager-restart-list">
|
||||
{props.changes.map(p => <li key={p}>{p}</li>)}
|
||||
</ul>
|
||||
</>}
|
||||
shouldShow={props.changes.hasChanges}
|
||||
>
|
||||
{tooltipProps =>
|
||||
<Button
|
||||
{...tooltipProps}
|
||||
color={Button.Colors.GREEN}
|
||||
onClick={async () => {
|
||||
await writeKnownSettings();
|
||||
props.changes.hasChanges ? location.reload() : props.close();
|
||||
}}
|
||||
>
|
||||
{props.changes.hasChanges ? "Restart" : "Continue"}
|
||||
</Button>
|
||||
}
|
||||
</Tooltip>;
|
||||
}
|
||||
|
||||
|
||||
function makeDependencyList(deps: string[]) {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Forms.FormText>This plugin is required by:</Forms.FormText>
|
||||
{deps.map((dep: string) => <Forms.FormText key={cl("dep-text")} className={cl("dep-text")}>{dep}</Forms.FormText>)}
|
||||
{deps.map((dep: string) => <Forms.FormText key={dep} className={cl("dep-text")}>{dep}</Forms.FormText>)}
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
export async function openNewPluginsModal() {
|
||||
const newPlugins = await getNewPlugins();
|
||||
if (newPlugins.size && !hasSeen) {
|
||||
const newSettings = await getNewSettings();
|
||||
if ((newPlugins.size || newSettings.size) && !hasSeen) {
|
||||
hasSeen = true;
|
||||
openModal(modalProps => (
|
||||
const modalKey = openModal(modalProps => <ErrorBoundary noop onError={() => { closeModal(modalKey); }}>
|
||||
<NewPluginsModal
|
||||
modalProps={modalProps}
|
||||
newPlugins={newPlugins}
|
||||
newSettings={newSettings}
|
||||
/>
|
||||
));
|
||||
</ErrorBoundary>);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,18 +7,22 @@
|
|||
import { Devs } from "@utils/constants";
|
||||
import definePlugin from "@utils/types";
|
||||
|
||||
import { KNOWN_PLUGINS_DATA_KEY } from "./knownPlugins";
|
||||
import * as KnownSettings from "./knownSettings";
|
||||
import { KNOWN_PLUGINS_LEGACY_DATA_KEY, KNOWN_SETTINGS_DATA_KEY } from "./knownSettings";
|
||||
import { openNewPluginsModal } from "./NewPluginsModal";
|
||||
|
||||
export default definePlugin({
|
||||
name: "NewPluginsManager",
|
||||
description: "Utility that notifies you when new plugins are added to Equicord",
|
||||
description: "Utility that notifies you when new plugins are added to Vencord",
|
||||
authors: [Devs.Sqaaakoi],
|
||||
enabledByDefault: true,
|
||||
flux: {
|
||||
async POST_CONNECTION_OPEN() {
|
||||
openNewPluginsModal();
|
||||
}
|
||||
},
|
||||
openNewPluginsModal,
|
||||
KNOWN_PLUGINS_DATA_KEY
|
||||
KNOWN_PLUGINS_LEGACY_DATA_KEY,
|
||||
KNOWN_SETTINGS_DATA_KEY,
|
||||
KnownSettings
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,32 +0,0 @@
|
|||
/*
|
||||
* Vencord, a Discord client mod
|
||||
* Copyright (c) 2024 Vendicated and contributors
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { DataStore } from "@api/index";
|
||||
|
||||
import plugins from "~plugins";
|
||||
|
||||
export const KNOWN_PLUGINS_DATA_KEY = "NewPluginsManager_KnownPlugins";
|
||||
|
||||
export async function getKnownPlugins(): Promise<Set<string>> {
|
||||
let knownPlugins = await DataStore.get(KNOWN_PLUGINS_DATA_KEY) as string[];
|
||||
if (knownPlugins === undefined) {
|
||||
knownPlugins = Object.keys(plugins);
|
||||
DataStore.set(KNOWN_PLUGINS_DATA_KEY, knownPlugins);
|
||||
}
|
||||
return new Set(knownPlugins);
|
||||
}
|
||||
|
||||
export async function getNewPlugins(): Promise<Set<string>> {
|
||||
const currentPlugins = Object.keys(plugins);
|
||||
const knownPlugins = await getKnownPlugins();
|
||||
return new Set(currentPlugins.filter(p => !knownPlugins.has(p)));
|
||||
}
|
||||
|
||||
export async function writeKnownPlugins(): Promise<void> {
|
||||
const currentPlugins = Object.keys(plugins);
|
||||
const knownPlugins = await getKnownPlugins();
|
||||
DataStore.set(KNOWN_PLUGINS_DATA_KEY, [...new Set([...currentPlugins, ...knownPlugins])]);
|
||||
}
|
||||
91
src/equicordplugins/newPluginsManager/knownSettings.ts
Normal file
91
src/equicordplugins/newPluginsManager/knownSettings.ts
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Vencord, a Discord client mod
|
||||
* Copyright (c) 2024 Vendicated and contributors
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { DataStore } from "@api/index";
|
||||
|
||||
import plugins from "~plugins";
|
||||
|
||||
export type KnownPluginSettingsMap = Map<string, Set<string>>;
|
||||
|
||||
export const KNOWN_PLUGINS_LEGACY_DATA_KEY = "NewPluginsManager_KnownPlugins";
|
||||
export const KNOWN_SETTINGS_DATA_KEY = "NewPluginsManager_KnownSettings";
|
||||
|
||||
function getSettingsSetForPlugin(plugin: string): Set<string> {
|
||||
const settings = plugins[plugin]?.settings?.def || {};
|
||||
return new Set(Object.keys(settings).filter(setting => setting !== "enabled"));
|
||||
}
|
||||
|
||||
function getCurrentSettings(pluginList: string[]): KnownPluginSettingsMap {
|
||||
return new Map(pluginList.map(name => [
|
||||
name,
|
||||
getSettingsSetForPlugin(name)
|
||||
]));
|
||||
}
|
||||
|
||||
export async function getKnownSettings(): Promise<KnownPluginSettingsMap> {
|
||||
let map = await DataStore.get(KNOWN_SETTINGS_DATA_KEY) as KnownPluginSettingsMap;
|
||||
if (map === undefined) {
|
||||
const knownPlugins = await DataStore.get(KNOWN_PLUGINS_LEGACY_DATA_KEY) ?? [] as string[];
|
||||
const Plugins = [...Object.keys(plugins), ...knownPlugins];
|
||||
map = getCurrentSettings(Plugins);
|
||||
DataStore.set(KNOWN_SETTINGS_DATA_KEY, map);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
export async function getNewSettings(): Promise<KnownPluginSettingsMap> {
|
||||
const map = getCurrentSettings(Object.keys(plugins));
|
||||
const knownSettings = await getKnownSettings();
|
||||
map.forEach((settings, plugin) => {
|
||||
const filteredSettings = [...settings].filter(setting => !knownSettings.get(plugin)?.has(setting));
|
||||
if (!filteredSettings.length) return map.delete(plugin);
|
||||
map.set(plugin, new Set(filteredSettings));
|
||||
});
|
||||
return map;
|
||||
}
|
||||
|
||||
export async function getKnownPlugins(): Promise<Set<string>> {
|
||||
const knownSettings = await getKnownSettings();
|
||||
return new Set(knownSettings.keys());
|
||||
}
|
||||
|
||||
export async function getNewPlugins(): Promise<Set<string>> {
|
||||
const currentPlugins = Object.keys(plugins);
|
||||
const knownPlugins = await getKnownPlugins();
|
||||
return new Set(currentPlugins.filter(p => !knownPlugins.has(p)));
|
||||
}
|
||||
|
||||
export async function writeKnownSettings() {
|
||||
const currentSettings = getCurrentSettings(Object.keys(plugins));
|
||||
const knownSettings = await getKnownSettings();
|
||||
const allSettings = new Map();
|
||||
new Set([...currentSettings.keys(), ...knownSettings.keys()]).forEach(plugin => {
|
||||
allSettings.set(plugin, new Set([
|
||||
...(currentSettings.get(plugin) || []),
|
||||
...(knownSettings.get(plugin) || [])
|
||||
]));
|
||||
});
|
||||
await DataStore.set(KNOWN_SETTINGS_DATA_KEY, allSettings);
|
||||
}
|
||||
|
||||
export async function debugWipeSomeData() {
|
||||
const settings = await getKnownSettings();
|
||||
settings.forEach((value, key) => {
|
||||
if (Math.random() > 0.8) {
|
||||
if (Math.random() > 0.5) return settings.set(key, new Set([...value].filter(() => Math.random() > 0.5)));
|
||||
return settings.delete(key);
|
||||
}
|
||||
});
|
||||
await DataStore.set(KNOWN_SETTINGS_DATA_KEY, settings);
|
||||
}
|
||||
|
||||
export async function editRawData(patcher: (data: KnownPluginSettingsMap) => (Promise<any> | any)) {
|
||||
if (!patcher) return;
|
||||
const map = await DataStore.get(KNOWN_SETTINGS_DATA_KEY) as KnownPluginSettingsMap;
|
||||
const newMap = new Map(map);
|
||||
await patcher(newMap);
|
||||
await DataStore.set(KNOWN_SETTINGS_DATA_KEY, newMap ?? map);
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue