diff --git a/browser/VencordNativeStub.ts b/browser/VencordNativeStub.ts index ba789c666..70978f31b 100644 --- a/browser/VencordNativeStub.ts +++ b/browser/VencordNativeStub.ts @@ -19,13 +19,15 @@ /// /// +// Be very careful with imports in this file to avoid circular dependency issues. +// Only import pure modules that don't import other parts of Vencord. import monacoHtmlLocal from "file://monacoWin.html?minify"; -import * as DataStore from "../src/api/DataStore"; -import { debounce, localStorage } from "../src/utils"; -import { EXTENSION_BASE_URL } from "../src/utils/web-metadata"; -import { getTheme, Theme } from "../src/utils/discord"; -import { Settings } from "../src/Vencord"; +import * as DataStore from "@api/DataStore"; +import type { Settings } from "@api/Settings"; +import { debounce } from "@shared/debounce"; +import { localStorage } from "@utils/localStorage"; import { getStylusWebStoreUrl } from "@utils/web"; +import { EXTENSION_BASE_URL } from "@utils/web-metadata"; // listeners for ipc.on const cssListeners = new Set<(css: string) => void>(); @@ -90,6 +92,8 @@ window.VencordNative = { return; } + const { getTheme, Theme } = require("@utils/discord"); + win.baseUrl = EXTENSION_BASE_URL; win.setCss = setCssDebounced; win.getCurrentCss = () => VencordNative.quickCss.get(); diff --git a/eslint.config.mjs b/eslint.config.mjs index fabceecd1..e764a20b0 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -88,7 +88,7 @@ export default tseslint.config( "@stylistic/no-extra-semi": "error", // TS Rules - "@stylistic/func-call-spacing": ["error", "never"], + "@stylistic/function-call-spacing": ["error", "never"], // ESLint Rules "yoda": "error", @@ -113,7 +113,7 @@ export default tseslint.config( "no-useless-escape": [ "error", { - "extra": "i" + "allowRegexCharacters": ["i"] } ], "no-fallthrough": "error", diff --git a/package.json b/package.json index 059fab231..38d239ce3 100644 --- a/package.json +++ b/package.json @@ -51,51 +51,51 @@ "gifenc": "github:mattdesl/gifenc#64842fca317b112a8590f8fef2bf3825da8f6fe3", "idb": "8.0.3", "jsqr": "1.4.0", - "monaco-editor": "^0.52.2", - "nanoid": "^5.1.5", + "monaco-editor": "^0.54.0", + "nanoid": "^5.1.6", "usercss-meta": "^0.12.0", "virtual-merge": "^1.0.1" }, "devDependencies": { "@electron/asar": "^4.0.1", - "@stylistic/eslint-plugin": "^4.2.0", + "@stylistic/eslint-plugin": "^5.6.0", "@types/adm-zip": "^0.5.7", - "@types/chrome": "^0.0.312", + "@types/chrome": "^0.1.30", "@types/diff": "^7.0.2", - "@types/lodash": "^4.17.14", - "@types/node": "^22.13.13", + "@types/lodash": "^4.17.20", + "@types/node": "^24.10.1", "@types/react": "^19.0.10", "@types/react-dom": "^19.0.4", - "@types/yazl": "^2.4.5", + "@types/yazl": "^3.3.0", "@vencord/discord-types": "link:packages/discord-types", "adm-zip": "^0.5.16", - "diff": "^7.0.0", - "esbuild": "^0.25.1", - "eslint": "9.20.1", + "diff": "^8.0.2", + "esbuild": "^0.27.0", + "eslint": "9.39.1", "eslint-import-resolver-alias": "^1.1.2", - "eslint-plugin-react": "^7.37.3", + "eslint-plugin-react": "^7.37.5", "eslint-plugin-simple-header": "^1.2.1", "eslint-plugin-simple-import-sort": "^12.1.1", - "eslint-plugin-unused-imports": "^4.1.4", + "eslint-plugin-unused-imports": "^4.3.0", "highlight.js": "11.11.1", "html-minifier-terser": "^7.2.0", "moment": "^2.22.2", - "puppeteer-core": "^24.19.0", + "puppeteer-core": "^24.30.0", "standalone-electron-types": "^34.2.0", - "stylelint": "^16.17.0", - "stylelint-config-standard": "^37.0.0", + "stylelint": "^16.25.0", + "stylelint-config-standard": "^39.0.1", "ts-patch": "^3.3.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" + "tsx": "^4.20.6", + "type-fest": "^5.2.0", + "typescript": "^5.9.3", + "typescript-eslint": "^8.47.0", + "typescript-transform-paths": "^3.5.5", + "zip-local": "^0.3.5" }, - "packageManager": "pnpm@10.17.1", + "packageManager": "pnpm@10.22.0", "pnpm": { "patchedDependencies": { - "eslint@9.20.1": "patches/eslint@9.20.1.patch", "@types/less@3.0.8": "patches/@types__less@3.0.8.patch" }, "peerDependencyRules": { diff --git a/packages/discord-types/src/common/Activity.d.ts b/packages/discord-types/src/common/Activity.d.ts index ba7c647d3..06e91e7bd 100644 --- a/packages/discord-types/src/common/Activity.d.ts +++ b/packages/discord-types/src/common/Activity.d.ts @@ -47,3 +47,5 @@ export interface Activity { size?: [number, number]; }; } + +export type OnlineStatus = "online" | "idle" | "dnd" | "invisible" | "offline" | "unknown" | "streaming"; diff --git a/packages/discord-types/src/stores/PresenceStore.d.ts b/packages/discord-types/src/stores/PresenceStore.d.ts new file mode 100644 index 000000000..3f245aca9 --- /dev/null +++ b/packages/discord-types/src/stores/PresenceStore.d.ts @@ -0,0 +1,26 @@ +import { Activity, OnlineStatus } from "../common"; +import { FluxStore } from "./FluxStore"; + +export interface UserAndActivity { + userId: string; + activity: Activity; +} + +export type DiscordPlatform = "desktop" | "mobile" | "web" | "embedded"; + +export class PresenceStore extends FluxStore { + findActivity(userId: string, predicate: (activity: Activity) => boolean, guildId?: string): Activity | undefined; + getActivities(userId: string, guildId?: string): Activity[]; + getActivityMetadata(userId: string): any; + getAllApplicationActivities(applicationId: string): UserAndActivity[]; + getApplicationActivity(userId: string, applicationId: string, guildId?: string): Activity | null; + getClientStatus(userId: string): Record; + getHiddenActivities(): any; + /** literally just getActivities(...)[0] */ + getPrimaryActivity(userId: string, guildId?: string): Activity | null; + getState(): any; + getStatus(userId: string, guildId?: string | null, defaultStatus?: OnlineStatus): OnlineStatus; + getUnfilteredActivities(userId: string, guildId?: string): Activity[]; + getUserIds(): string[]; + isMobileOnline(userId: string): boolean; +} diff --git a/packages/discord-types/src/stores/index.d.ts b/packages/discord-types/src/stores/index.d.ts index 45f66142b..ecbb256ef 100644 --- a/packages/discord-types/src/stores/index.d.ts +++ b/packages/discord-types/src/stores/index.d.ts @@ -8,6 +8,7 @@ export * from "./GuildMemberStore"; export * from "./GuildRoleStore"; export * from "./GuildStore"; export * from "./MessageStore"; +export * from "./PresenceStore"; export * from "./RelationshipStore"; export * from "./MediaEngineStore"; export * from "./StreamerModeStore"; diff --git a/patches/eslint@9.20.1.patch b/patches/eslint@9.20.1.patch deleted file mode 100644 index c91e45d56..000000000 --- a/patches/eslint@9.20.1.patch +++ /dev/null @@ -1,49 +0,0 @@ -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; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index acf03949d..3e4b4ce56 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,9 +11,6 @@ patchedDependencies: '@types/less@3.0.8': hash: 641e6c93bb737bac7fc283416857bd095cd85bcbcba63becb7a8bbcc78f73076 path: patches/@types__less@3.0.8.patch - eslint@9.20.1: - hash: 4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215 - path: patches/eslint@9.20.1.patch importers: @@ -56,11 +53,11 @@ importers: specifier: 1.4.0 version: 1.4.0 monaco-editor: - specifier: ^0.52.2 - version: 0.52.2 + specifier: ^0.54.0 + version: 0.54.0 nanoid: - specifier: ^5.1.5 - version: 5.1.5 + specifier: ^5.1.6 + version: 5.1.6 usercss-meta: specifier: ^0.12.0 version: 0.12.0 @@ -72,23 +69,23 @@ importers: specifier: ^4.0.1 version: 4.0.1 '@stylistic/eslint-plugin': - specifier: ^4.2.0 - version: 4.4.1(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2) + specifier: ^5.6.0 + version: 5.6.0(eslint@9.39.1) '@types/adm-zip': specifier: ^0.5.7 version: 0.5.7 '@types/chrome': - specifier: ^0.0.312 - version: 0.0.312 + specifier: ^0.1.30 + version: 0.1.30 '@types/diff': specifier: ^7.0.2 version: 7.0.2 '@types/lodash': - specifier: ^4.17.14 - version: 4.17.15 + specifier: ^4.17.20 + version: 4.17.20 '@types/node': - specifier: ^22.13.13 - version: 22.13.13 + specifier: ^24.10.1 + version: 24.10.1 '@types/react': specifier: ^19.0.10 version: 19.0.12 @@ -96,8 +93,8 @@ importers: specifier: ^19.0.4 version: 19.0.4(@types/react@19.0.12) '@types/yazl': - specifier: ^2.4.5 - version: 2.4.6 + specifier: ^3.3.0 + version: 3.3.0 '@vencord/discord-types': specifier: link:packages/discord-types version: link:packages/discord-types @@ -105,29 +102,29 @@ importers: specifier: ^0.5.16 version: 0.5.16 diff: - specifier: ^7.0.0 - version: 7.0.0 + specifier: ^8.0.2 + version: 8.0.2 esbuild: - specifier: ^0.25.1 - version: 0.25.1 + specifier: ^0.27.0 + version: 0.27.0 eslint: - specifier: 9.20.1 - version: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215) + specifier: 9.39.1 + version: 9.39.1 eslint-import-resolver-alias: specifier: ^1.1.2 - version: 1.1.2(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))) + version: 1.1.2(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.47.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)) eslint-plugin-react: - specifier: ^7.37.3 - version: 7.37.4(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)) + specifier: ^7.37.5 + version: 7.37.5(eslint@9.39.1) eslint-plugin-simple-header: specifier: ^1.2.1 - version: 1.2.2(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)) + version: 1.2.2(eslint@9.39.1) eslint-plugin-simple-import-sort: specifier: ^12.1.1 - version: 12.1.1(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)) + version: 12.1.1(eslint@9.39.1) eslint-plugin-unused-imports: - specifier: ^4.1.4 - version: 4.1.4(@typescript-eslint/eslint-plugin@8.28.0(@typescript-eslint/parser@8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)) + specifier: ^4.3.0 + version: 4.3.0(@typescript-eslint/eslint-plugin@8.47.0(@typescript-eslint/parser@8.47.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1) highlight.js: specifier: 11.11.1 version: 11.11.1 @@ -138,17 +135,17 @@ importers: specifier: ^2.22.2 version: 2.30.1 puppeteer-core: - specifier: ^24.19.0 - version: 24.19.0 + specifier: ^24.30.0 + version: 24.30.0 standalone-electron-types: specifier: ^34.2.0 version: 34.2.0 stylelint: - specifier: ^16.17.0 - version: 16.17.0(typescript@5.8.2) + specifier: ^16.25.0 + version: 16.25.0(typescript@5.9.3) stylelint-config-standard: - specifier: ^37.0.0 - version: 37.0.0(stylelint@16.17.0(typescript@5.8.2)) + specifier: ^39.0.1 + version: 39.0.1(stylelint@16.25.0(typescript@5.9.3)) ts-patch: specifier: ^3.3.0 version: 3.3.0 @@ -156,20 +153,23 @@ importers: specifier: ^5.6.0 version: 5.6.2 tsx: - specifier: ^4.19.3 - version: 4.19.3 + specifier: ^4.20.6 + version: 4.20.6 type-fest: - specifier: ^4.38.0 - version: 4.38.0 + specifier: ^5.2.0 + version: 5.2.0 typescript: - specifier: ^5.8.2 - version: 5.8.2 + specifier: ^5.9.3 + version: 5.9.3 typescript-eslint: - specifier: ^8.28.0 - version: 8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2) + specifier: ^8.47.0 + version: 8.47.0(eslint@9.39.1)(typescript@5.9.3) typescript-transform-paths: specifier: ^3.5.5 - version: 3.5.5(typescript@5.8.2) + version: 3.5.5(typescript@5.9.3) + zip-local: + specifier: ^0.3.5 + version: 0.3.5 packages/discord-types: dependencies: @@ -237,22 +237,28 @@ packages: resolution: {integrity: sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==} engines: {node: '>=6.9.0'} - '@csstools/css-parser-algorithms@3.0.4': - resolution: {integrity: sha512-Up7rBoV77rv29d3uKHUIVubz1BTcgyUK72IvCQAbfbMv584xHcGKCKbWh7i8hPrRJ7qU4Y8IO3IY9m+iTB7P3A==} + '@cacheable/memory@2.0.5': + resolution: {integrity: sha512-fkiAxCvssEyJZ5fxX4tcdZFRmW9JehSTGvvqmXn6rTzG5cH6V/3C4ad8yb01vOjp2xBydHkHrgpW0qeGtzt6VQ==} + + '@cacheable/utils@2.3.1': + resolution: {integrity: sha512-38NJXjIr4W1Sghun8ju+uYWD8h2c61B4dKwfnQHVDFpAJ9oS28RpfqZQJ6Dgd3RceGkILDY9YT+72HJR3LoeSQ==} + + '@csstools/css-parser-algorithms@3.0.5': + resolution: {integrity: sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==} engines: {node: '>=18'} peerDependencies: - '@csstools/css-tokenizer': ^3.0.3 + '@csstools/css-tokenizer': ^3.0.4 - '@csstools/css-tokenizer@3.0.3': - resolution: {integrity: sha512-UJnjoFsmxfKUdNYdWgOB0mWUypuLvAfQPH1+pyvRJs6euowbFkFC6P13w1l8mJyi3vxYMxc9kld5jZEGRQs6bw==} + '@csstools/css-tokenizer@3.0.4': + resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==} engines: {node: '>=18'} - '@csstools/media-query-list-parser@4.0.2': - resolution: {integrity: sha512-EUos465uvVvMJehckATTlNqGj4UJWkTmdWuDMjqvSUkjGpmOyFZBVwb4knxCm/k2GMTXY+c/5RkdndzFYWeX5A==} + '@csstools/media-query-list-parser@4.0.3': + resolution: {integrity: sha512-HAYH7d3TLRHDOUQK4mZKf9k9Ph/m8Akstg66ywKR4SFAigjs3yBiUeZtFxywiTm5moZMAp/5W/ZuFnNXXYLuuQ==} engines: {node: '>=18'} peerDependencies: - '@csstools/css-parser-algorithms': ^3.0.4 - '@csstools/css-tokenizer': ^3.0.3 + '@csstools/css-parser-algorithms': ^3.0.5 + '@csstools/css-tokenizer': ^3.0.4 '@csstools/selector-specificity@5.0.0': resolution: {integrity: sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==} @@ -260,8 +266,8 @@ packages: peerDependencies: postcss-selector-parser: ^7.0.0 - '@dual-bundle/import-meta-resolve@4.1.0': - resolution: {integrity: sha512-+nxncfwHM5SgAtrVzgpzJOI1ol0PkumhVo469KCf9lUi21IGcY90G98VuHm9VRrUypmAzawAHO9bs6hqeADaVg==} + '@dual-bundle/import-meta-resolve@4.2.1': + resolution: {integrity: sha512-id+7YRUgoUX6CgV0DtuhirQWodeeA7Lf4i2x71JS/vtA5pRb/hIGWlw+G6MeXvsM+MXrz0VAydTGElX1rAfgPg==} '@electron/asar@4.0.1': resolution: {integrity: sha512-F4Ykm1jiBGY1WV/o8Q8oFW8Nq0u+S2/vPujzNJtdSJ6C4LHC4CiGLn7c17s7SolZ23gcvCebMncmZtNc+MkxPQ==} @@ -274,155 +280,305 @@ packages: cpu: [ppc64] os: [aix] + '@esbuild/aix-ppc64@0.27.0': + resolution: {integrity: sha512-KuZrd2hRjz01y5JK9mEBSD3Vj3mbCvemhT466rSuJYeE/hjuBrHfjjcjMdTm/sz7au+++sdbJZJmuBwQLuw68A==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + '@esbuild/android-arm64@0.25.1': resolution: {integrity: sha512-50tM0zCJW5kGqgG7fQ7IHvQOcAn9TKiVRuQ/lN0xR+T2lzEFvAi1ZcS8DiksFcEpf1t/GYOeOfCAgDHFpkiSmA==} engines: {node: '>=18'} cpu: [arm64] os: [android] + '@esbuild/android-arm64@0.27.0': + resolution: {integrity: sha512-CC3vt4+1xZrs97/PKDkl0yN7w8edvU2vZvAFGD16n9F0Cvniy5qvzRXjfO1l94efczkkQE6g1x0i73Qf5uthOQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + '@esbuild/android-arm@0.25.1': resolution: {integrity: sha512-dp+MshLYux6j/JjdqVLnMglQlFu+MuVeNrmT5nk6q07wNhCdSnB7QZj+7G8VMUGh1q+vj2Bq8kRsuyA00I/k+Q==} engines: {node: '>=18'} cpu: [arm] os: [android] + '@esbuild/android-arm@0.27.0': + resolution: {integrity: sha512-j67aezrPNYWJEOHUNLPj9maeJte7uSMM6gMoxfPC9hOg8N02JuQi/T7ewumf4tNvJadFkvLZMlAq73b9uwdMyQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + '@esbuild/android-x64@0.25.1': resolution: {integrity: sha512-GCj6WfUtNldqUzYkN/ITtlhwQqGWu9S45vUXs7EIYf+7rCiiqH9bCloatO9VhxsL0Pji+PF4Lz2XXCES+Q8hDw==} engines: {node: '>=18'} cpu: [x64] os: [android] + '@esbuild/android-x64@0.27.0': + resolution: {integrity: sha512-wurMkF1nmQajBO1+0CJmcN17U4BP6GqNSROP8t0X/Jiw2ltYGLHpEksp9MpoBqkrFR3kv2/te6Sha26k3+yZ9Q==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + '@esbuild/darwin-arm64@0.25.1': resolution: {integrity: sha512-5hEZKPf+nQjYoSr/elb62U19/l1mZDdqidGfmFutVUjjUZrOazAtwK+Kr+3y0C/oeJfLlxo9fXb1w7L+P7E4FQ==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] + '@esbuild/darwin-arm64@0.27.0': + resolution: {integrity: sha512-uJOQKYCcHhg07DL7i8MzjvS2LaP7W7Pn/7uA0B5S1EnqAirJtbyw4yC5jQ5qcFjHK9l6o/MX9QisBg12kNkdHg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + '@esbuild/darwin-x64@0.25.1': resolution: {integrity: sha512-hxVnwL2Dqs3fM1IWq8Iezh0cX7ZGdVhbTfnOy5uURtao5OIVCEyj9xIzemDi7sRvKsuSdtCAhMKarxqtlyVyfA==} engines: {node: '>=18'} cpu: [x64] os: [darwin] + '@esbuild/darwin-x64@0.27.0': + resolution: {integrity: sha512-8mG6arH3yB/4ZXiEnXof5MK72dE6zM9cDvUcPtxhUZsDjESl9JipZYW60C3JGreKCEP+p8P/72r69m4AZGJd5g==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + '@esbuild/freebsd-arm64@0.25.1': resolution: {integrity: sha512-1MrCZs0fZa2g8E+FUo2ipw6jw5qqQiH+tERoS5fAfKnRx6NXH31tXBKI3VpmLijLH6yriMZsxJtaXUyFt/8Y4A==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] + '@esbuild/freebsd-arm64@0.27.0': + resolution: {integrity: sha512-9FHtyO988CwNMMOE3YIeci+UV+x5Zy8fI2qHNpsEtSF83YPBmE8UWmfYAQg6Ux7Gsmd4FejZqnEUZCMGaNQHQw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + '@esbuild/freebsd-x64@0.25.1': resolution: {integrity: sha512-0IZWLiTyz7nm0xuIs0q1Y3QWJC52R8aSXxe40VUxm6BB1RNmkODtW6LHvWRrGiICulcX7ZvyH6h5fqdLu4gkww==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] + '@esbuild/freebsd-x64@0.27.0': + resolution: {integrity: sha512-zCMeMXI4HS/tXvJz8vWGexpZj2YVtRAihHLk1imZj4efx1BQzN76YFeKqlDr3bUWI26wHwLWPd3rwh6pe4EV7g==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + '@esbuild/linux-arm64@0.25.1': resolution: {integrity: sha512-jaN3dHi0/DDPelk0nLcXRm1q7DNJpjXy7yWaWvbfkPvI+7XNSc/lDOnCLN7gzsyzgu6qSAmgSvP9oXAhP973uQ==} engines: {node: '>=18'} cpu: [arm64] os: [linux] + '@esbuild/linux-arm64@0.27.0': + resolution: {integrity: sha512-AS18v0V+vZiLJyi/4LphvBE+OIX682Pu7ZYNsdUHyUKSoRwdnOsMf6FDekwoAFKej14WAkOef3zAORJgAtXnlQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + '@esbuild/linux-arm@0.25.1': resolution: {integrity: sha512-NdKOhS4u7JhDKw9G3cY6sWqFcnLITn6SqivVArbzIaf3cemShqfLGHYMx8Xlm/lBit3/5d7kXvriTUGa5YViuQ==} engines: {node: '>=18'} cpu: [arm] os: [linux] + '@esbuild/linux-arm@0.27.0': + resolution: {integrity: sha512-t76XLQDpxgmq2cNXKTVEB7O7YMb42atj2Re2Haf45HkaUpjM2J0UuJZDuaGbPbamzZ7bawyGFUkodL+zcE+jvQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + '@esbuild/linux-ia32@0.25.1': resolution: {integrity: sha512-OJykPaF4v8JidKNGz8c/q1lBO44sQNUQtq1KktJXdBLn1hPod5rE/Hko5ugKKZd+D2+o1a9MFGUEIUwO2YfgkQ==} engines: {node: '>=18'} cpu: [ia32] os: [linux] + '@esbuild/linux-ia32@0.27.0': + resolution: {integrity: sha512-Mz1jxqm/kfgKkc/KLHC5qIujMvnnarD9ra1cEcrs7qshTUSksPihGrWHVG5+osAIQ68577Zpww7SGapmzSt4Nw==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + '@esbuild/linux-loong64@0.25.1': resolution: {integrity: sha512-nGfornQj4dzcq5Vp835oM/o21UMlXzn79KobKlcs3Wz9smwiifknLy4xDCLUU0BWp7b/houtdrgUz7nOGnfIYg==} engines: {node: '>=18'} cpu: [loong64] os: [linux] + '@esbuild/linux-loong64@0.27.0': + resolution: {integrity: sha512-QbEREjdJeIreIAbdG2hLU1yXm1uu+LTdzoq1KCo4G4pFOLlvIspBm36QrQOar9LFduavoWX2msNFAAAY9j4BDg==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + '@esbuild/linux-mips64el@0.25.1': resolution: {integrity: sha512-1osBbPEFYwIE5IVB/0g2X6i1qInZa1aIoj1TdL4AaAb55xIIgbg8Doq6a5BzYWgr+tEcDzYH67XVnTmUzL+nXg==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] + '@esbuild/linux-mips64el@0.27.0': + resolution: {integrity: sha512-sJz3zRNe4tO2wxvDpH/HYJilb6+2YJxo/ZNbVdtFiKDufzWq4JmKAiHy9iGoLjAV7r/W32VgaHGkk35cUXlNOg==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + '@esbuild/linux-ppc64@0.25.1': resolution: {integrity: sha512-/6VBJOwUf3TdTvJZ82qF3tbLuWsscd7/1w+D9LH0W/SqUgM5/JJD0lrJ1fVIfZsqB6RFmLCe0Xz3fmZc3WtyVg==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] + '@esbuild/linux-ppc64@0.27.0': + resolution: {integrity: sha512-z9N10FBD0DCS2dmSABDBb5TLAyF1/ydVb+N4pi88T45efQ/w4ohr/F/QYCkxDPnkhkp6AIpIcQKQ8F0ANoA2JA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + '@esbuild/linux-riscv64@0.25.1': resolution: {integrity: sha512-nSut/Mx5gnilhcq2yIMLMe3Wl4FK5wx/o0QuuCLMtmJn+WeWYoEGDN1ipcN72g1WHsnIbxGXd4i/MF0gTcuAjQ==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] + '@esbuild/linux-riscv64@0.27.0': + resolution: {integrity: sha512-pQdyAIZ0BWIC5GyvVFn5awDiO14TkT/19FTmFcPdDec94KJ1uZcmFs21Fo8auMXzD4Tt+diXu1LW1gHus9fhFQ==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + '@esbuild/linux-s390x@0.25.1': resolution: {integrity: sha512-cEECeLlJNfT8kZHqLarDBQso9a27o2Zd2AQ8USAEoGtejOrCYHNtKP8XQhMDJMtthdF4GBmjR2au3x1udADQQQ==} engines: {node: '>=18'} cpu: [s390x] os: [linux] + '@esbuild/linux-s390x@0.27.0': + resolution: {integrity: sha512-hPlRWR4eIDDEci953RI1BLZitgi5uqcsjKMxwYfmi4LcwyWo2IcRP+lThVnKjNtk90pLS8nKdroXYOqW+QQH+w==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + '@esbuild/linux-x64@0.25.1': resolution: {integrity: sha512-xbfUhu/gnvSEg+EGovRc+kjBAkrvtk38RlerAzQxvMzlB4fXpCFCeUAYzJvrnhFtdeyVCDANSjJvOvGYoeKzFA==} engines: {node: '>=18'} cpu: [x64] os: [linux] + '@esbuild/linux-x64@0.27.0': + resolution: {integrity: sha512-1hBWx4OUJE2cab++aVZ7pObD6s+DK4mPGpemtnAORBvb5l/g5xFGk0vc0PjSkrDs0XaXj9yyob3d14XqvnQ4gw==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + '@esbuild/netbsd-arm64@0.25.1': resolution: {integrity: sha512-O96poM2XGhLtpTh+s4+nP7YCCAfb4tJNRVZHfIE7dgmax+yMP2WgMd2OecBuaATHKTHsLWHQeuaxMRnCsH8+5g==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] + '@esbuild/netbsd-arm64@0.27.0': + resolution: {integrity: sha512-6m0sfQfxfQfy1qRuecMkJlf1cIzTOgyaeXaiVaaki8/v+WB+U4hc6ik15ZW6TAllRlg/WuQXxWj1jx6C+dfy3w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + '@esbuild/netbsd-x64@0.25.1': resolution: {integrity: sha512-X53z6uXip6KFXBQ+Krbx25XHV/NCbzryM6ehOAeAil7X7oa4XIq+394PWGnwaSQ2WRA0KI6PUO6hTO5zeF5ijA==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] + '@esbuild/netbsd-x64@0.27.0': + resolution: {integrity: sha512-xbbOdfn06FtcJ9d0ShxxvSn2iUsGd/lgPIO2V3VZIPDbEaIj1/3nBBe1AwuEZKXVXkMmpr6LUAgMkLD/4D2PPA==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + '@esbuild/openbsd-arm64@0.25.1': resolution: {integrity: sha512-Na9T3szbXezdzM/Kfs3GcRQNjHzM6GzFBeU1/6IV/npKP5ORtp9zbQjvkDJ47s6BCgaAZnnnu/cY1x342+MvZg==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] + '@esbuild/openbsd-arm64@0.27.0': + resolution: {integrity: sha512-fWgqR8uNbCQ/GGv0yhzttj6sU/9Z5/Sv/VGU3F5OuXK6J6SlriONKrQ7tNlwBrJZXRYk5jUhuWvF7GYzGguBZQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + '@esbuild/openbsd-x64@0.25.1': resolution: {integrity: sha512-T3H78X2h1tszfRSf+txbt5aOp/e7TAz3ptVKu9Oyir3IAOFPGV6O9c2naym5TOriy1l0nNf6a4X5UXRZSGX/dw==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] + '@esbuild/openbsd-x64@0.27.0': + resolution: {integrity: sha512-aCwlRdSNMNxkGGqQajMUza6uXzR/U0dIl1QmLjPtRbLOx3Gy3otfFu/VjATy4yQzo9yFDGTxYDo1FfAD9oRD2A==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.27.0': + resolution: {integrity: sha512-nyvsBccxNAsNYz2jVFYwEGuRRomqZ149A39SHWk4hV0jWxKM0hjBPm3AmdxcbHiFLbBSwG6SbpIcUbXjgyECfA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + '@esbuild/sunos-x64@0.25.1': resolution: {integrity: sha512-2H3RUvcmULO7dIE5EWJH8eubZAI4xw54H1ilJnRNZdeo8dTADEZ21w6J22XBkXqGJbe0+wnNJtw3UXRoLJnFEg==} engines: {node: '>=18'} cpu: [x64] os: [sunos] + '@esbuild/sunos-x64@0.27.0': + resolution: {integrity: sha512-Q1KY1iJafM+UX6CFEL+F4HRTgygmEW568YMqDA5UV97AuZSm21b7SXIrRJDwXWPzr8MGr75fUZPV67FdtMHlHA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + '@esbuild/win32-arm64@0.25.1': resolution: {integrity: sha512-GE7XvrdOzrb+yVKB9KsRMq+7a2U/K5Cf/8grVFRAGJmfADr/e/ODQ134RK2/eeHqYV5eQRFxb1hY7Nr15fv1NQ==} engines: {node: '>=18'} cpu: [arm64] os: [win32] + '@esbuild/win32-arm64@0.27.0': + resolution: {integrity: sha512-W1eyGNi6d+8kOmZIwi/EDjrL9nxQIQ0MiGqe/AWc6+IaHloxHSGoeRgDRKHFISThLmsewZ5nHFvGFWdBYlgKPg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + '@esbuild/win32-ia32@0.25.1': resolution: {integrity: sha512-uOxSJCIcavSiT6UnBhBzE8wy3n0hOkJsBOzy7HDAuTDE++1DJMRRVCPGisULScHL+a/ZwdXPpXD3IyFKjA7K8A==} engines: {node: '>=18'} cpu: [ia32] os: [win32] + '@esbuild/win32-ia32@0.27.0': + resolution: {integrity: sha512-30z1aKL9h22kQhilnYkORFYt+3wp7yZsHWus+wSKAJR8JtdfI76LJ4SBdMsCopTR3z/ORqVu5L1vtnHZWVj4cQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + '@esbuild/win32-x64@0.25.1': resolution: {integrity: sha512-Y1EQdcfwMSeQN/ujR5VayLOJ1BHaK+ssyk0AEzPjC+t1lITgsnccPqFjb6V+LsTp/9Iov4ysfjxLaGJ9RPtkVg==} engines: {node: '>=18'} cpu: [x64] os: [win32] - '@eslint-community/eslint-utils@4.5.1': - resolution: {integrity: sha512-soEIOALTfTK6EjmKMMoLugwaP0rzkad90iIWd1hMO9ARkSAyjfMfkRRhLvD5qH7vvM0Cg72pieUfR6yh6XxC4w==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + '@esbuild/win32-x64@0.27.0': + resolution: {integrity: sha512-aIitBcjQeyOhMTImhLZmtxfdOcuNRpwlPNmlFKPcHQYPhEssw75Cl1TSXJXpMkzaua9FUetx/4OQKq7eJul5Cg==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] '@eslint-community/eslint-utils@4.9.0': resolution: {integrity: sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==} @@ -434,32 +590,32 @@ packages: resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@eslint/config-array@0.19.2': - resolution: {integrity: sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==} + '@eslint/config-array@0.21.1': + resolution: {integrity: sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/core@0.11.0': - resolution: {integrity: sha512-DWUB2pksgNEb6Bz2fggIy1wh6fGgZP4Xyy/Mt0QZPiloKKXerbqq9D3SBQTlCRYOrcRPu4vuz+CGjwdfqxnoWA==} + '@eslint/config-helpers@0.4.2': + resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/core@0.15.2': - resolution: {integrity: sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==} + '@eslint/core@0.17.0': + resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/eslintrc@3.3.1': resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@9.20.0': - resolution: {integrity: sha512-iZA07H9io9Wn836aVTytRaNqh00Sad+EamwOVJT12GTLw1VGMFV/4JaME+JjLtr9fiGaoWgYnS54wrfWsSs4oQ==} + '@eslint/js@9.39.1': + resolution: {integrity: sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/object-schema@2.1.6': - resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} + '@eslint/object-schema@2.1.7': + resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/plugin-kit@0.3.5': - resolution: {integrity: sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==} + '@eslint/plugin-kit@0.4.1': + resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@ffmpeg/ffmpeg@0.12.10': @@ -530,8 +686,14 @@ packages: '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} - '@keyv/serialize@1.0.3': - resolution: {integrity: sha512-qnEovoOp5Np2JDGonIDL6Ayihw0RhnRh6vxPuHo4RDn1UOzwEo4AeIfpL6UGIrsceWrCMiVPgwRjbHu4vYFc3g==} + '@keyv/bigmap@1.3.0': + resolution: {integrity: sha512-KT01GjzV6AQD5+IYrcpoYLkCu1Jod3nau1Z7EsEuViO3TZGRacSbO9MfHmbJ1WaOXFtWLxPVj169cn2WNKPkIg==} + engines: {node: '>= 18'} + peerDependencies: + keyv: ^5.5.4 + + '@keyv/serialize@1.1.1': + resolution: {integrity: sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==} '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} @@ -545,16 +707,16 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} - '@puppeteer/browsers@2.10.8': - resolution: {integrity: sha512-f02QYEnBDE0p8cteNoPYHHjbDuwyfbe4cCIVlNi8/MRicIxFW4w4CfgU0LNgWEID6s06P+hRJ1qjpBLMhPRCiQ==} + '@puppeteer/browsers@2.10.13': + resolution: {integrity: sha512-a9Ruw3j3qlnB5a/zHRTkruppynxqaeE4H9WNj5eYGRWqw0ZauZ23f4W2ARf3hghF5doozyD+CRtt7XSYuYRI/Q==} engines: {node: '>=18'} hasBin: true '@rtsao/scc@1.1.0': resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} - '@stylistic/eslint-plugin@4.4.1': - resolution: {integrity: sha512-CEigAk7eOLyHvdgmpZsKFwtiqS2wFwI1fn4j09IU9GmD4euFM4jEBAViWeCqaNLlbX2k2+A/Fq9cje4HQBXuJQ==} + '@stylistic/eslint-plugin@5.6.0': + resolution: {integrity: sha512-owEc4B8ME+O/xyZOkLVyLqPMsUgJXIM4XzCm5Vt3WvRXpyoOfYxgA+JkEiFqXPCI8+Nc2BzAT+KGAK7QleGs8Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: '>=9.0.0' @@ -565,8 +727,8 @@ packages: '@types/adm-zip@0.5.7': resolution: {integrity: sha512-DNEs/QvmyRLurdQPChqq0Md4zGvPwHerAJYWk9l2jCbD1VPpnzRJorOdiq4zsw09NFbYnhfsoEhWtxIzXpn2yw==} - '@types/chrome@0.0.312': - resolution: {integrity: sha512-m204djOoU/YqF1dRw3YLk2L3tcDTYREUERDQDUAmROK3Rv94nLbMJ4uvjzr/Yj/A7SyEpTrpoCuXBKTuerEdqg==} + '@types/chrome@0.1.30': + resolution: {integrity: sha512-rcP14i+ip4s3SLG6JzNOWIDd+0i8Bg+kBslHl8d4g6m/e2kEbWnR90AtlOPUZj9ONVRbKxnQUqsInxFzXyqLdA==} '@types/diff@7.0.2': resolution: {integrity: sha512-JSWRMozjFKsGlEjiiKajUjIJVKuKdE3oVy2DNtK+fUo8q82nhFZ2CPQwicAIkXrofahDXrWJ7mjelvZphMS98Q==} @@ -601,12 +763,15 @@ packages: '@types/lodash@4.17.15': resolution: {integrity: sha512-w/P33JFeySuhN6JLkysYUK2gEmy9kHHFN7E8ro0tkfmlDOgxBDzWEZ/J8cWA+fHqFevpswDTFZnDx+R9lbL6xw==} - '@types/node@22.10.5': - resolution: {integrity: sha512-F8Q+SeGimwOo86fiovQh8qiXfFEh2/ocYv7tU5pJ3EXMSSxk1Joj5wefpFK2fHTf/N6HKGSxIDBT9f3gCxXPkQ==} + '@types/lodash@4.17.20': + resolution: {integrity: sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA==} '@types/node@22.13.13': resolution: {integrity: sha512-ClsL5nMwKaBRwPcCvH8E7+nU4GxHVx1axNvMZTFHMEfNI7oahimt26P5zjVCRrjiIWj6YFXfE1v3dEp94wLcGQ==} + '@types/node@24.10.1': + resolution: {integrity: sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==} + '@types/prop-types@15.7.15': resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==} @@ -633,91 +798,66 @@ packages: '@types/yauzl@2.10.3': resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} - '@types/yazl@2.4.6': - resolution: {integrity: sha512-/ifFjQtcKaoZOjl5NNCQRR0fAKafB3Foxd7J/WvFPTMea46zekapcR30uzkwIkKAAuq5T6d0dkwz754RFH27hg==} + '@types/yazl@3.3.0': + resolution: {integrity: sha512-mFL6lGkk2N5u5nIxpNV/K5LW3qVSbxhJrMxYGOOxZndWxMgCamr/iCsq/1t9kd8pEwhuNP91LC5qZm/qS9pOEw==} - '@typescript-eslint/eslint-plugin@8.28.0': - resolution: {integrity: sha512-lvFK3TCGAHsItNdWZ/1FkvpzCxTHUVuFrdnOGLMa0GGCFIbCgQWVk3CzCGdA7kM3qGVc+dfW9tr0Z/sHnGDFyg==} + '@typescript-eslint/eslint-plugin@8.47.0': + resolution: {integrity: sha512-fe0rz9WJQ5t2iaLfdbDc9T80GJy0AeO453q8C3YCilnGozvOyCG5t+EZtg7j7D88+c3FipfP/x+wzGnh1xp8ZA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 + '@typescript-eslint/parser': ^8.47.0 eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.9.0' - - '@typescript-eslint/parser@8.28.0': - resolution: {integrity: sha512-LPcw1yHD3ToaDEoljFEfQ9j2xShY367h7FZ1sq5NJT9I3yj4LHer1Xd1yRSOdYy9BpsrxU7R+eoDokChYM53lQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.9.0' - - '@typescript-eslint/project-service@8.43.0': - resolution: {integrity: sha512-htB/+D/BIGoNTQYffZw4uM4NzzuolCoaA/BusuSIcC8YjmBYQioew5VUZAYdAETPjeed0hqCaW7EHg+Robq8uw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/scope-manager@8.28.0': - resolution: {integrity: sha512-u2oITX3BJwzWCapoZ/pXw6BCOl8rJP4Ij/3wPoGvY8XwvXflOzd1kLrDUUUAIEdJSFh+ASwdTHqtan9xSg8buw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@typescript-eslint/scope-manager@8.43.0': - resolution: {integrity: sha512-daSWlQ87ZhsjrbMLvpuuMAt3y4ba57AuvadcR7f3nl8eS3BjRc8L9VLxFLk92RL5xdXOg6IQ+qKjjqNEimGuAg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@typescript-eslint/tsconfig-utils@8.43.0': - resolution: {integrity: sha512-ALC2prjZcj2YqqL5X/bwWQmHA2em6/94GcbB/KKu5SX3EBDOsqztmmX1kMkvAJHzxk7TazKzJfFiEIagNV3qEA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <6.0.0' - - '@typescript-eslint/type-utils@8.28.0': - resolution: {integrity: sha512-oRoXu2v0Rsy/VoOGhtWrOKDiIehvI+YNrDk5Oqj40Mwm0Yt01FC/Q7nFqg088d3yAsR1ZcZFVfPCTTFCe/KPwg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.9.0' - - '@typescript-eslint/types@8.28.0': - resolution: {integrity: sha512-bn4WS1bkKEjx7HqiwG2JNB3YJdC1q6Ue7GyGlwPHyt0TnVq6TtD/hiOdTZt71sq0s7UzqBFXD8t8o2e63tXgwA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@typescript-eslint/types@8.43.0': - resolution: {integrity: sha512-vQ2FZaxJpydjSZJKiSW/LJsabFFvV7KgLC5DiLhkBcykhQj8iK9BOaDmQt74nnKdLvceM5xmhaTF+pLekrxEkw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@typescript-eslint/typescript-estree@8.28.0': - resolution: {integrity: sha512-H74nHEeBGeklctAVUvmDkxB1mk+PAZ9FiOMPFncdqeRBXxk1lWSYraHw8V12b7aa6Sg9HOBNbGdSHobBPuQSuA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <5.9.0' - - '@typescript-eslint/typescript-estree@8.43.0': - resolution: {integrity: sha512-7Vv6zlAhPb+cvEpP06WXXy/ZByph9iL6BQRBDj4kmBsW98AqEeQHlj/13X+sZOrKSo9/rNKH4Ul4f6EICREFdw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <6.0.0' - - '@typescript-eslint/utils@8.28.0': - resolution: {integrity: sha512-OELa9hbTYciYITqgurT1u/SzpQVtDLmQMFzy/N8pQE+tefOyCWT79jHsav294aTqV1q1u+VzqDGbuujvRYaeSQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.9.0' - - '@typescript-eslint/utils@8.43.0': - resolution: {integrity: sha512-S1/tEmkUeeswxd0GGcnwuVQPFWo8NzZTOMxCvw8BX7OMxnNae+i8Tm7REQen/SwUIPoPqfKn7EaZ+YLpiB3k9g==} + '@typescript-eslint/parser@8.47.0': + resolution: {integrity: sha512-lJi3PfxVmo0AkEY93ecfN+r8SofEqZNGByvHAI3GBLrvt1Cw6H5k1IM02nSzu0RfUafr2EvFSw0wAsZgubNplQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/visitor-keys@8.28.0': - resolution: {integrity: sha512-hbn8SZ8w4u2pRwgQ1GlUrPKE+t2XvcCW5tTRF7j6SMYIuYG37XuzIW44JCZPa36evi0Oy2SnM664BlIaAuQcvg==} + '@typescript-eslint/project-service@8.47.0': + resolution: {integrity: sha512-2X4BX8hUeB5JcA1TQJ7GjcgulXQ+5UkNb0DL8gHsHUHdFoiCTJoYLTpib3LtSDPZsRET5ygN4qqIWrHyYIKERA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/scope-manager@8.47.0': + resolution: {integrity: sha512-a0TTJk4HXMkfpFkL9/WaGTNuv7JWfFTQFJd6zS9dVAjKsojmv9HT55xzbEpnZoY+VUb+YXLMp+ihMLz/UlZfDg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/visitor-keys@8.43.0': - resolution: {integrity: sha512-T+S1KqRD4sg/bHfLwrpF/K3gQLBM1n7Rp7OjjikjTEssI2YJzQpi5WXoynOaQ93ERIuq3O8RBTOUYDKszUCEHw==} + '@typescript-eslint/tsconfig-utils@8.47.0': + resolution: {integrity: sha512-ybUAvjy4ZCL11uryalkKxuT3w3sXJAuWhOoGS3T/Wu+iUu1tGJmk5ytSY8gbdACNARmcYEB0COksD2j6hfGK2g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/type-utils@8.47.0': + resolution: {integrity: sha512-QC9RiCmZ2HmIdCEvhd1aJELBlD93ErziOXXlHEZyuBo3tBiAZieya0HLIxp+DoDWlsQqDawyKuNEhORyku+P8A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/types@8.47.0': + resolution: {integrity: sha512-nHAE6bMKsizhA2uuYZbEbmp5z2UpffNrPEqiKIeN7VsV6UY/roxanWfoRrf6x/k9+Obf+GQdkm0nPU+vnMXo9A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@8.47.0': + resolution: {integrity: sha512-k6ti9UepJf5NpzCjH31hQNLHQWupTRPhZ+KFF8WtTuTpy7uHPfeg2NM7cP27aCGajoEplxJDFVCEm9TGPYyiVg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/utils@8.47.0': + resolution: {integrity: sha512-g7XrNf25iL4TJOiPqatNuaChyqt49a/onq5YsJ9+hXeugK+41LVg7AxikMfM02PC6jbNtZLCJj6AUcQXJS/jGQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/visitor-keys@8.47.0': + resolution: {integrity: sha512-SIV3/6eftCy1bNzCQoPmbWsRLujS8t5iDIZ4spZOBHqrM+yfX2ogg8Tt3PDTAVKw3sSCiUgg30uOAvK2r9zGjQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@vap/core@0.0.12': @@ -831,6 +971,9 @@ packages: resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} engines: {node: '>= 0.4'} + async@1.5.2: + resolution: {integrity: sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==} + available-typed-arrays@1.0.7: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} @@ -874,9 +1017,6 @@ packages: bare-events: optional: true - base64-js@1.5.1: - resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - basic-ftp@5.0.5: resolution: {integrity: sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==} engines: {node: '>=10.0.0'} @@ -897,20 +1037,13 @@ packages: buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - buffer@6.0.3: - resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} - - cacheable@1.8.9: - resolution: {integrity: sha512-FicwAUyWnrtnd4QqYAoRlNs44/a1jTL7XDKqm5gJ90wz1DQPlC7U2Rd1Tydpv+E7WAr4sQHuw8Q8M3nZMAyecQ==} + cacheable@2.2.0: + resolution: {integrity: sha512-LEJxRqfeomiiRd2t0uON6hxAtgOoWDfY3fugebbz+J3vDLO+SkdfFChQcOHTZhj9SYa9iwE9MGYNX72dKiOE4w==} call-bind-apply-helpers@1.0.2: resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} engines: {node: '>= 0.4'} - call-bind@1.0.7: - resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} - engines: {node: '>= 0.4'} - call-bind@1.0.8: resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} engines: {node: '>= 0.4'} @@ -934,8 +1067,8 @@ packages: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} - chromium-bidi@8.0.0: - resolution: {integrity: sha512-d1VmE0FD7lxZQHzcDUCKZSNRtRwISXDsdg4HjdTR5+Ll5nQ/vzU12JeNmupD6VWffrPSlrnGhEWlLESKH3VO+g==} + chromium-bidi@11.0.0: + resolution: {integrity: sha512-cM3DI+OOb89T3wO8cpPSro80Q9eKYJ7hGVXoGS3GkDPxnYSqiv+6xwpIf6XERyJ9Tdsl09hmNmY94BkgZdVekw==} peerDependencies: devtools-protocol: '*' @@ -1030,8 +1163,8 @@ packages: supports-color: optional: true - debug@4.4.0: - resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} + debug@4.4.1: + resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} engines: {node: '>=6.0'} peerDependencies: supports-color: '*' @@ -1039,8 +1172,8 @@ packages: supports-color: optional: true - debug@4.4.1: - resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} engines: {node: '>=6.0'} peerDependencies: supports-color: '*' @@ -1063,11 +1196,11 @@ packages: resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==} engines: {node: '>= 14'} - devtools-protocol@0.0.1495869: - resolution: {integrity: sha512-i+bkd9UYFis40RcnkW7XrOprCujXRAHg62IVh/Ah3G8MmNXpCGt1m0dTFhSdx/AVs8XEMbdOGRwdkR1Bcta8AA==} + devtools-protocol@0.0.1521046: + resolution: {integrity: sha512-vhE6eymDQSKWUXwwA37NtTTVEzjtGVfDr3pRbsWEQ5onH/Snp2c+2xZHWJJawG/0hCCJLRGt4xVtEVUVILol4w==} - diff@7.0.0: - resolution: {integrity: sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==} + diff@8.0.2: + resolution: {integrity: sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg==} engines: {node: '>=0.3.1'} dir-glob@3.0.1: @@ -1078,6 +1211,9 @@ packages: resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} engines: {node: '>=0.10.0'} + dompurify@3.1.7: + resolution: {integrity: sha512-VaTstWtsneJY8xzy7DekmYWEOZcmzIe3Qb3zPd4STve1OBTa+e+WmS1ITQec1fZYXI3HCsOZZiSMpG6oxoWMWQ==} + dot-case@3.0.4: resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} @@ -1112,10 +1248,6 @@ packages: resolution: {integrity: sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==} engines: {node: '>= 0.4'} - es-define-property@1.0.0: - resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} - engines: {node: '>= 0.4'} - es-define-property@1.0.1: resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} engines: {node: '>= 0.4'} @@ -1132,10 +1264,6 @@ packages: resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} engines: {node: '>= 0.4'} - es-set-tostringtag@2.0.3: - resolution: {integrity: sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==} - engines: {node: '>= 0.4'} - es-set-tostringtag@2.1.0: resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} engines: {node: '>= 0.4'} @@ -1153,6 +1281,11 @@ packages: engines: {node: '>=18'} hasBin: true + esbuild@0.27.0: + resolution: {integrity: sha512-jd0f4NHbD6cALCyGElNpGAOtWxSq46l9X/sWB0Nzd5er4Kz2YTm+Vl0qKFT9KUJvD8+fiO8AvoHhFvEatfVixA==} + engines: {node: '>=18'} + hasBin: true + escalade@3.1.2: resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} engines: {node: '>=6'} @@ -1210,8 +1343,8 @@ packages: '@typescript-eslint/parser': optional: true - eslint-plugin-react@7.37.4: - resolution: {integrity: sha512-BGP0jRmfYyvOyvMoRX/uoUeW+GqNj9y16bPQzqAHf3AYII/tDs+jMN0dBVkl88/OZwNGwrVFxE7riHsXVfy/LQ==} + eslint-plugin-react@7.37.5: + resolution: {integrity: sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==} engines: {node: '>=4'} peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 @@ -1226,8 +1359,8 @@ packages: peerDependencies: eslint: '>=5.0.0' - eslint-plugin-unused-imports@4.1.4: - resolution: {integrity: sha512-YptD6IzQjDardkl0POxnnRBhU1OEePMV0nd6siHaRBbd+lyh6NAhFEobiznKU7kTsSsDeSD62Pe7kAM1b7dAZQ==} + eslint-plugin-unused-imports@4.3.0: + resolution: {integrity: sha512-ZFBmXMGBYfHttdRtOG9nFFpmUvMtbHSjsKrS20vdWdbfiVYsO3yA2SGYy9i9XmZJDfMGBflZGBCm70SEnFQtOA==} peerDependencies: '@typescript-eslint/eslint-plugin': ^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0 eslint: ^9.0.0 || ^8.0.0 @@ -1243,16 +1376,12 @@ packages: resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - eslint-visitor-keys@4.2.0: - resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint-visitor-keys@4.2.1: resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@9.20.1: - resolution: {integrity: sha512-m1mM33o6dBUjxl2qb6wv6nGNwCAsns1eKtaQ4l/NPHeTvhiUPbtdfMyktxN4B3fgHIgsYh1VT3V9txblpQHq+g==} + eslint@9.39.1: + resolution: {integrity: sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true peerDependencies: @@ -1326,8 +1455,8 @@ packages: fflate@0.8.2: resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==} - file-entry-cache@10.0.7: - resolution: {integrity: sha512-txsf5fu3anp2ff3+gOJJzRImtrtm/oa9tYLN0iTuINZ++EyVR/nRrg2fKYwvG/pXDofcrvvb0scEbX3NyW/COw==} + file-entry-cache@10.1.4: + resolution: {integrity: sha512-5XRUFc0WTtUbjfGzEwXc42tiGxQHBmtbUG1h9L2apu4SulCGN3Hqm//9D6FAolf8MYNL7f/YlJl9vy08pj5JuA==} file-entry-cache@8.0.0: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} @@ -1345,8 +1474,8 @@ packages: resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} engines: {node: '>=16'} - flat-cache@6.1.7: - resolution: {integrity: sha512-qwZ4xf1v1m7Rc9XiORly31YaChvKt6oNVHuqqZcoED/7O+ToyNVGobKsIAopY9ODcWpEDKEBAbrSOCBHtNQvew==} + flat-cache@6.1.19: + resolution: {integrity: sha512-l/K33newPTZMTGAnnzaiqSl6NnH7Namh8jBNjrgjprWxGmZUuxx/sJNIRaijOh3n7q7ESbhNZC+pvVZMFdeU4A==} flatted@3.3.3: resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} @@ -1382,14 +1511,6 @@ packages: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} - get-intrinsic@1.2.4: - resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} - engines: {node: '>= 0.4'} - - get-intrinsic@1.2.7: - resolution: {integrity: sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==} - engines: {node: '>= 0.4'} - get-intrinsic@1.3.0: resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} engines: {node: '>= 0.4'} @@ -1457,9 +1578,6 @@ packages: globjoin@0.1.4: resolution: {integrity: sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==} - gopd@1.0.1: - resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} - gopd@1.2.0: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} engines: {node: '>= 0.4'} @@ -1484,18 +1602,10 @@ packages: has-property-descriptors@1.0.2: resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} - has-proto@1.0.3: - resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} - engines: {node: '>= 0.4'} - has-proto@1.2.0: resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==} engines: {node: '>= 0.4'} - has-symbols@1.0.3: - resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} - engines: {node: '>= 0.4'} - has-symbols@1.1.0: resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} engines: {node: '>= 0.4'} @@ -1504,6 +1614,10 @@ packages: resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} engines: {node: '>= 0.4'} + hashery@1.2.0: + resolution: {integrity: sha512-43XJKpwle72Ik5Zpam7MuzRWyNdwwdf6XHlh8wCj2PggvWf+v/Dm5B0dxGZOmddidgeO6Ofu9As/o231Ti/9PA==} + engines: {node: '>=20'} + hasown@2.0.2: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} @@ -1512,8 +1626,8 @@ packages: resolution: {integrity: sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==} engines: {node: '>=12.0.0'} - hookified@1.8.1: - resolution: {integrity: sha512-GrO2l93P8xCWBSTBX9l2BxI78VU/MAAYag+pG8curS3aBGy0++ZlxrQ7PdUOUVMbn5BwkGb6+eRrnf43ipnFEA==} + hookified@1.13.0: + resolution: {integrity: sha512-6sPYUY8olshgM/1LDNW4QZQN0IqgKhtl/1C8koNZBJrKLBk3AZl6chQtNwpNztvfiApHMEwMHek5rv993PRbWw==} html-minifier-terser@7.2.0: resolution: {integrity: sha512-tXgn3QfqPIpGl9o+K5tpcj3/MN4SfLtsx2GWwBC3SSd0tXQGyF3gsSqad8loJgKZGM3ZxbYDd5yhiBIdWpmvLA==} @@ -1535,9 +1649,6 @@ packages: idb@8.0.3: resolution: {integrity: sha512-LtwtVyVYO5BqRvcsKuB2iUMnHwPVByPCXFXOpuU96IZPPoPN6xjOGxZQ74pgSVVLQWtUOYgyeL4GE98BY5D3wg==} - ieee754@1.2.1: - resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - ignore@5.3.1: resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} engines: {node: '>= 4'} @@ -1546,6 +1657,10 @@ packages: resolution: {integrity: sha512-bAH5jbK/F3T3Jls4I0SO1hmPR0dKU0a7+SY6n1yzRtG54FLO8d6w/nxLFX2Nb7dBu6cCWXPaAME6cYqFUMmuCA==} engines: {node: '>= 4'} + ignore@7.0.5: + resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} + engines: {node: '>= 4'} + import-fresh@3.3.1: resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} engines: {node: '>=6'} @@ -1592,10 +1707,6 @@ packages: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} - is-core-module@2.15.0: - resolution: {integrity: sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA==} - engines: {node: '>= 0.4'} - is-core-module@2.16.1: resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} engines: {node: '>= 0.4'} @@ -1604,10 +1715,6 @@ packages: resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==} engines: {node: '>= 0.4'} - is-date-object@1.0.5: - resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} - engines: {node: '>= 0.4'} - is-date-object@1.1.0: resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} engines: {node: '>= 0.4'} @@ -1664,10 +1771,6 @@ packages: resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} engines: {node: '>= 0.4'} - is-symbol@1.0.4: - resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} - engines: {node: '>= 0.4'} - is-symbol@1.1.1: resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} engines: {node: '>= 0.4'} @@ -1748,18 +1851,21 @@ packages: resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} engines: {node: '>=4.0'} + jszip@2.7.0: + resolution: {integrity: sha512-JIsRKRVC3gTRo2vM4Wy9WBC3TRcfnIZU8k65Phi3izkvPH975FowRYtKGT6PxevA0XnJ/yO8b0QwV0ydVyQwfw==} + keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - keyv@5.3.2: - resolution: {integrity: sha512-Lji2XRxqqa5Wg+CHLVfFKBImfJZ4pCSccu9eVWK6w4c2SDFLd8JAn1zqTuSFnsxb7ope6rMsnIHfp+eBbRBRZQ==} + keyv@5.5.4: + resolution: {integrity: sha512-eohl3hKTiVyD1ilYdw9T0OiB4hnjef89e3dMYKz+mVKDzj+5IteTseASUsOB+EU9Tf6VNTCjDePcP6wkDGmLKQ==} kind-of@6.0.3: resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} engines: {node: '>=0.10.0'} - known-css-properties@0.35.0: - resolution: {integrity: sha512-a/RAk2BfKk+WFGhhOCAYqSiFLc34k8Mt/6NWRI4joER0EYUzXIcFivjjnoD3+XU1DggLn/tZc3DOAgke7l8a4A==} + known-css-properties@0.37.0: + resolution: {integrity: sha512-JCDrsP4Z1Sb9JwG0aJ8Eo2r7k4Ou5MwmThS/6lcIe1ICyb7UBJKGRIUUdqc2ASdE/42lgz6zFUnzAIhtXnBVrQ==} levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} @@ -1793,6 +1899,11 @@ packages: resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} engines: {node: '>=12'} + marked@14.0.0: + resolution: {integrity: sha512-uIj4+faQ+MgHgwUW1l2PsPglZLOLOT1uErt06dAPtx2kjteLAkbsd/0FiYg/MGS+i7ZKLb7w2WClxHkzOOuryQ==} + engines: {node: '>= 18'} + hasBin: true + math-intrinsics@1.1.0: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} @@ -1839,8 +1950,8 @@ packages: moment@2.30.1: resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==} - monaco-editor@0.52.2: - resolution: {integrity: sha512-GEQWEZmfkOGLdd3XK8ryrfWz3AIP8YymVXiPHEdewrUq7mh0qrKrfHLNCXcbB6sTnMLnOZ3ztSiKcciFUkIJwQ==} + monaco-editor@0.54.0: + resolution: {integrity: sha512-hx45SEUoLatgWxHKCmlLJH81xBo0uXP4sRkESUpmDQevfi+e7K1VuiSprK6UpQ8u4zOcKNiH0pMvHvlMWA/4cw==} ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -1850,8 +1961,8 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - nanoid@5.1.5: - resolution: {integrity: sha512-Ir/+ZpE9fDsNH0hQ3C68uyThDXzYcim2EqcZ8zn8Chtt1iylPT9xXJB0kPCnqzgcEGikO9RxSrh63MsmVCU7Fw==} + nanoid@5.1.6: + resolution: {integrity: sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg==} engines: {node: ^18 || >=20} hasBin: true @@ -1881,10 +1992,6 @@ packages: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} engines: {node: '>= 0.4'} - object.assign@4.1.5: - resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} - engines: {node: '>= 0.4'} - object.assign@4.1.7: resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} engines: {node: '>= 0.4'} @@ -1935,6 +2042,9 @@ packages: package-json-from-dist@1.0.1: resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + pako@1.0.11: + resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} + param-case@3.0.4: resolution: {integrity: sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==} @@ -2002,8 +2112,8 @@ packages: postcss-value-parser@4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - postcss@8.5.3: - resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} + postcss@8.5.6: + resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} engines: {node: ^10 || ^12 || >=14} prelude-ls@1.2.1: @@ -2031,10 +2141,22 @@ packages: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} - puppeteer-core@24.19.0: - resolution: {integrity: sha512-qsEys4OIb2VGC2tNWKAs4U0mnjkIAxueMOOzk2nEFM9g4Y8QuvYkEMtmwsEdvzNGsUFd7DprOQfABmlN7WBOlg==} + puppeteer-core@24.30.0: + resolution: {integrity: sha512-2S3Smy0t0W4wJnNvDe7W0bE7wDmZjfZ3ljfMgJd6hn2Hq/f0jgN+x9PULZo2U3fu5UUIJ+JP8cNUGllu8P91Pg==} engines: {node: '>=18'} + q@1.5.1: + resolution: {integrity: sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==} + engines: {node: '>=0.6.0', teleport: '>=0.2.0'} + deprecated: |- + You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other. + + (For a CapTP with native promises, see @endo/eventual-send and @endo/captp) + + qified@0.5.2: + resolution: {integrity: sha512-7gJ6mxcQb9vUBOtbKm5mDevbe2uRcOEVp1g4gb/Q+oLntB3HY8eBhOYRxFI2mlDFlY1e4DOSCptzxarXRvzxCA==} + engines: {node: '>=20'} + queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -2113,6 +2235,11 @@ packages: engines: {node: '>=10'} hasBin: true + semver@7.7.3: + resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} + engines: {node: '>=10'} + hasBin: true + set-function-length@1.2.2: resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} engines: {node: '>= 0.4'} @@ -2173,10 +2300,6 @@ packages: resolution: {integrity: sha512-D3YaD0aRxR3mEcqnidIs7ReYJFVzWdd6fXJYUM8ixcQcJRGTka/b3saV0KflYhyVJXKhb947GndU35SxYNResQ==} engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} - source-map-js@1.2.0: - resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} - engines: {node: '>=0.10.0'} - source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} @@ -2240,20 +2363,20 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} - stylelint-config-recommended@15.0.0: - resolution: {integrity: sha512-9LejMFsat7L+NXttdHdTq94byn25TD+82bzGRiV1Pgasl99pWnwipXS5DguTpp3nP1XjvLXVnEJIuYBfsRjRkA==} + stylelint-config-recommended@17.0.0: + resolution: {integrity: sha512-WaMSdEiPfZTSFVoYmJbxorJfA610O0tlYuU2aEwY33UQhSPgFbClrVJYWvy3jGJx+XW37O+LyNLiZOEXhKhJmA==} engines: {node: '>=18.12.0'} peerDependencies: - stylelint: ^16.13.0 + stylelint: ^16.23.0 - stylelint-config-standard@37.0.0: - resolution: {integrity: sha512-+6eBlbSTrOn/il2RlV0zYGQwRTkr+WtzuVSs1reaWGObxnxLpbcspCUYajVQHonVfxVw2U+h42azGhrBvcg8OA==} + stylelint-config-standard@39.0.1: + resolution: {integrity: sha512-b7Fja59EYHRNOTa3aXiuWnhUWXFU2Nfg6h61bLfAb5GS5fX3LMUD0U5t4S8N/4tpHQg3Acs2UVPR9jy2l1g/3A==} engines: {node: '>=18.12.0'} peerDependencies: - stylelint: ^16.13.0 + stylelint: ^16.23.0 - stylelint@16.17.0: - resolution: {integrity: sha512-I9OwVIWRMqVm2Br5iTbrfSqGRPWQUlvm6oXO1xZuYYu0Gpduy67N8wXOZv15p6E/JdlZiAtQaIoLKZEWk5hrjw==} + stylelint@16.25.0: + resolution: {integrity: sha512-Li0avYWV4nfv1zPbdnxLYBGq4z8DVZxbRgx4Kn6V+Uftz1rMoF1qiEI3oL4kgWqyYgCgs7gT5maHNZ82Gk03vQ==} engines: {node: '>=18.12.0'} hasBin: true @@ -2280,8 +2403,12 @@ packages: resolution: {integrity: sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==} engines: {node: '>=10.0.0'} - tar-fs@3.1.0: - resolution: {integrity: sha512-5Mty5y/sOF1YWj1J6GiBodjlDc05CUR8PKXrsnFAiSG0xA+GHeWLovaZPYUDXkH/1iKRf2+M5+OrRgzC7O9b7w==} + tagged-tag@1.0.0: + resolution: {integrity: sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==} + engines: {node: '>=20'} + + tar-fs@3.1.1: + resolution: {integrity: sha512-LZA0oaPOc2fVo82Txf3gw+AkEd38szODlptMYejQUhndHMLQ9M059uXR+AfS7DNo0NpINvSqDsvyaCrBVkptWg==} tar-stream@3.1.7: resolution: {integrity: sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==} @@ -2325,6 +2452,11 @@ packages: engines: {node: '>=18.0.0'} hasBin: true + tsx@4.20.6: + resolution: {integrity: sha512-ytQKuwgmrrkDTFP4LjR0ToE2nqgy886GpvRSpU0JAnrdBYppuY5rLkRUYPU1yCryb24SsKBTL/hlDQAEFVwtZg==} + engines: {node: '>=18.0.0'} + hasBin: true + type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -2337,6 +2469,10 @@ packages: resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} engines: {node: '>=16'} + type-fest@5.2.0: + resolution: {integrity: sha512-xxCJm+Bckc6kQBknN7i9fnP/xobQRsRQxR01CztFkp/h++yfVxUUcmMgfR2HttJx/dpWjS9ubVuyspJv24Q9DA==} + engines: {node: '>=20'} + typed-array-buffer@1.0.3: resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} engines: {node: '>= 0.4'} @@ -2356,20 +2492,20 @@ packages: typed-query-selector@2.12.0: resolution: {integrity: sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg==} - typescript-eslint@8.28.0: - resolution: {integrity: sha512-jfZtxJoHm59bvoCMYCe2BM0/baMswRhMmYhy+w6VfcyHrjxZ0OJe0tGasydCpIpA+A/WIJhTyZfb3EtwNC/kHQ==} + typescript-eslint@8.47.0: + resolution: {integrity: sha512-Lwe8i2XQ3WoMjua/r1PHrCTpkubPYJCAfOurtn+mtTzqB6jNd+14n9UN1bJ4s3F49x9ixAm0FLflB/JzQ57M8Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.9.0' + typescript: '>=4.8.4 <6.0.0' typescript-transform-paths@3.5.5: resolution: {integrity: sha512-RMK86wKe/4+ad+3kMT9SKAs3K0tUHLe7hF+MLbD6VpC9VUmFuKorhf3pHz+qO5GdS4mUp2ncNUo14j6ws9UvBQ==} peerDependencies: typescript: '>=3.6.5' - typescript@5.8.2: - resolution: {integrity: sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==} + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} engines: {node: '>=14.17'} hasBin: true @@ -2380,6 +2516,9 @@ packages: undici-types@6.20.0: resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} + undici-types@7.16.0: + resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} + universalify@2.0.1: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} engines: {node: '>= 10.0.0'} @@ -2403,6 +2542,9 @@ packages: vscode-textmate@5.2.0: resolution: {integrity: sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ==} + webdriver-bidi-protocol@0.3.8: + resolution: {integrity: sha512-21Yi2GhGntMc671vNBCjiAeEVknXjVRoyu+k+9xOMShu+ZQfpGQwnBqbNz/Sv4GXZ6JmutlPAi2nIJcrymAWuQ==} + which-boxed-primitive@1.1.1: resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} engines: {node: '>= 0.4'} @@ -2483,6 +2625,9 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} + zip-local@0.3.5: + resolution: {integrity: sha512-GRV3D5TJY+/PqyeRm5CYBs7xVrKTKzljBoEXvocZu0HJ7tPEcgpSOYa2zFIsCZWgKWMuc4U3yMFgFkERGFIB9w==} + zod@3.24.2: resolution: {integrity: sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==} @@ -2502,22 +2647,34 @@ snapshots: js-tokens: 4.0.0 picocolors: 1.1.1 - '@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3)': + '@cacheable/memory@2.0.5': dependencies: - '@csstools/css-tokenizer': 3.0.3 + '@cacheable/utils': 2.3.1 + '@keyv/bigmap': 1.3.0(keyv@5.5.4) + hookified: 1.13.0 + keyv: 5.5.4 - '@csstools/css-tokenizer@3.0.3': {} - - '@csstools/media-query-list-parser@4.0.2(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3)': + '@cacheable/utils@2.3.1': dependencies: - '@csstools/css-parser-algorithms': 3.0.4(@csstools/css-tokenizer@3.0.3) - '@csstools/css-tokenizer': 3.0.3 + hashery: 1.2.0 + keyv: 5.5.4 + + '@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/css-tokenizer': 3.0.4 + + '@csstools/css-tokenizer@3.0.4': {} + + '@csstools/media-query-list-parser@4.0.3(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 '@csstools/selector-specificity@5.0.0(postcss-selector-parser@7.1.0)': dependencies: postcss-selector-parser: 7.1.0 - '@dual-bundle/import-meta-resolve@4.1.0': {} + '@dual-bundle/import-meta-resolve@4.2.1': {} '@electron/asar@4.0.1': dependencies: @@ -2528,103 +2685,176 @@ snapshots: '@esbuild/aix-ppc64@0.25.1': optional: true + '@esbuild/aix-ppc64@0.27.0': + optional: true + '@esbuild/android-arm64@0.25.1': optional: true + '@esbuild/android-arm64@0.27.0': + optional: true + '@esbuild/android-arm@0.25.1': optional: true + '@esbuild/android-arm@0.27.0': + optional: true + '@esbuild/android-x64@0.25.1': optional: true + '@esbuild/android-x64@0.27.0': + optional: true + '@esbuild/darwin-arm64@0.25.1': optional: true + '@esbuild/darwin-arm64@0.27.0': + optional: true + '@esbuild/darwin-x64@0.25.1': optional: true + '@esbuild/darwin-x64@0.27.0': + optional: true + '@esbuild/freebsd-arm64@0.25.1': optional: true + '@esbuild/freebsd-arm64@0.27.0': + optional: true + '@esbuild/freebsd-x64@0.25.1': optional: true + '@esbuild/freebsd-x64@0.27.0': + optional: true + '@esbuild/linux-arm64@0.25.1': optional: true + '@esbuild/linux-arm64@0.27.0': + optional: true + '@esbuild/linux-arm@0.25.1': optional: true + '@esbuild/linux-arm@0.27.0': + optional: true + '@esbuild/linux-ia32@0.25.1': optional: true + '@esbuild/linux-ia32@0.27.0': + optional: true + '@esbuild/linux-loong64@0.25.1': optional: true + '@esbuild/linux-loong64@0.27.0': + optional: true + '@esbuild/linux-mips64el@0.25.1': optional: true + '@esbuild/linux-mips64el@0.27.0': + optional: true + '@esbuild/linux-ppc64@0.25.1': optional: true + '@esbuild/linux-ppc64@0.27.0': + optional: true + '@esbuild/linux-riscv64@0.25.1': optional: true + '@esbuild/linux-riscv64@0.27.0': + optional: true + '@esbuild/linux-s390x@0.25.1': optional: true + '@esbuild/linux-s390x@0.27.0': + optional: true + '@esbuild/linux-x64@0.25.1': optional: true + '@esbuild/linux-x64@0.27.0': + optional: true + '@esbuild/netbsd-arm64@0.25.1': optional: true + '@esbuild/netbsd-arm64@0.27.0': + optional: true + '@esbuild/netbsd-x64@0.25.1': optional: true + '@esbuild/netbsd-x64@0.27.0': + optional: true + '@esbuild/openbsd-arm64@0.25.1': optional: true + '@esbuild/openbsd-arm64@0.27.0': + optional: true + '@esbuild/openbsd-x64@0.25.1': optional: true + '@esbuild/openbsd-x64@0.27.0': + optional: true + + '@esbuild/openharmony-arm64@0.27.0': + optional: true + '@esbuild/sunos-x64@0.25.1': optional: true + '@esbuild/sunos-x64@0.27.0': + optional: true + '@esbuild/win32-arm64@0.25.1': optional: true + '@esbuild/win32-arm64@0.27.0': + optional: true + '@esbuild/win32-ia32@0.25.1': optional: true + '@esbuild/win32-ia32@0.27.0': + optional: true + '@esbuild/win32-x64@0.25.1': optional: true - '@eslint-community/eslint-utils@4.5.1(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))': - dependencies: - eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215) - eslint-visitor-keys: 3.4.3 + '@esbuild/win32-x64@0.27.0': + optional: true - '@eslint-community/eslint-utils@4.9.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))': + '@eslint-community/eslint-utils@4.9.0(eslint@9.39.1)': dependencies: - eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215) + eslint: 9.39.1 eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.1': {} - '@eslint/config-array@0.19.2': + '@eslint/config-array@0.21.1': dependencies: - '@eslint/object-schema': 2.1.6 + '@eslint/object-schema': 2.1.7 debug: 4.4.1 minimatch: 3.1.2 transitivePeerDependencies: - supports-color - '@eslint/core@0.11.0': + '@eslint/config-helpers@0.4.2': dependencies: - '@types/json-schema': 7.0.15 + '@eslint/core': 0.17.0 - '@eslint/core@0.15.2': + '@eslint/core@0.17.0': dependencies: '@types/json-schema': 7.0.15 @@ -2642,13 +2872,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@9.20.0': {} + '@eslint/js@9.39.1': {} - '@eslint/object-schema@2.1.6': {} + '@eslint/object-schema@2.1.7': {} - '@eslint/plugin-kit@0.3.5': + '@eslint/plugin-kit@0.4.1': dependencies: - '@eslint/core': 0.15.2 + '@eslint/core': 0.17.0 levn: 0.4.1 '@ffmpeg/ffmpeg@0.12.10': @@ -2711,9 +2941,13 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.4.15 - '@keyv/serialize@1.0.3': + '@keyv/bigmap@1.3.0(keyv@5.5.4)': dependencies: - buffer: 6.0.3 + hashery: 1.2.0 + hookified: 1.13.0 + keyv: 5.5.4 + + '@keyv/serialize@1.1.1': {} '@nodelib/fs.scandir@2.1.5': dependencies: @@ -2727,14 +2961,14 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.19.1 - '@puppeteer/browsers@2.10.8': + '@puppeteer/browsers@2.10.13': dependencies: - debug: 4.4.1 + debug: 4.4.3 extract-zip: 2.0.1 progress: 2.0.3 proxy-agent: 6.5.0 - semver: 7.7.2 - tar-fs: 3.1.0 + semver: 7.7.3 + tar-fs: 3.1.1 yargs: 17.7.2 transitivePeerDependencies: - bare-buffer @@ -2742,25 +2976,23 @@ snapshots: '@rtsao/scc@1.1.0': {} - '@stylistic/eslint-plugin@4.4.1(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2)': + '@stylistic/eslint-plugin@5.6.0(eslint@9.39.1)': dependencies: - '@typescript-eslint/utils': 8.43.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2) - eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1) + '@typescript-eslint/types': 8.47.0 + eslint: 9.39.1 eslint-visitor-keys: 4.2.1 espree: 10.4.0 estraverse: 5.3.0 picomatch: 4.0.3 - transitivePeerDependencies: - - supports-color - - typescript '@tootallnate/quickjs-emscripten@0.23.0': {} '@types/adm-zip@0.5.7': dependencies: - '@types/node': 22.13.13 + '@types/node': 24.10.1 - '@types/chrome@0.0.312': + '@types/chrome@0.1.30': dependencies: '@types/filesystem': 0.0.36 '@types/har-format': 1.2.15 @@ -2794,14 +3026,16 @@ snapshots: '@types/lodash@4.17.15': {} - '@types/node@22.10.5': - dependencies: - undici-types: 6.20.0 + '@types/lodash@4.17.20': {} '@types/node@22.13.13': dependencies: undici-types: 6.20.0 + '@types/node@24.10.1': + dependencies: + undici-types: 7.16.0 + '@types/prop-types@15.7.15': {} '@types/react-dom@18.3.1': @@ -2823,146 +3057,110 @@ snapshots: '@types/stylus@0.48.42': dependencies: - '@types/node': 22.10.5 + '@types/node': 24.10.1 '@types/tinycolor2@1.4.6': {} '@types/yauzl@2.10.3': dependencies: - '@types/node': 22.13.13 + '@types/node': 24.10.1 optional: true - '@types/yazl@2.4.6': + '@types/yazl@3.3.0': dependencies: - '@types/node': 22.13.13 + '@types/node': 24.10.1 - '@typescript-eslint/eslint-plugin@8.28.0(@typescript-eslint/parser@8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2)': + '@typescript-eslint/eslint-plugin@8.47.0(@typescript-eslint/parser@8.47.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2) - '@typescript-eslint/scope-manager': 8.28.0 - '@typescript-eslint/type-utils': 8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2) - '@typescript-eslint/utils': 8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2) - '@typescript-eslint/visitor-keys': 8.28.0 - eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215) + '@typescript-eslint/parser': 8.47.0(eslint@9.39.1)(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.47.0 + '@typescript-eslint/type-utils': 8.47.0(eslint@9.39.1)(typescript@5.9.3) + '@typescript-eslint/utils': 8.47.0(eslint@9.39.1)(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.47.0 + eslint: 9.39.1 graphemer: 1.4.0 - ignore: 5.3.1 + ignore: 7.0.3 natural-compare: 1.4.0 - ts-api-utils: 2.1.0(typescript@5.8.2) - typescript: 5.8.2 + ts-api-utils: 2.1.0(typescript@5.9.3) + typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2)': + '@typescript-eslint/parser@8.47.0(eslint@9.39.1)(typescript@5.9.3)': dependencies: - '@typescript-eslint/scope-manager': 8.28.0 - '@typescript-eslint/types': 8.28.0 - '@typescript-eslint/typescript-estree': 8.28.0(typescript@5.8.2) - '@typescript-eslint/visitor-keys': 8.28.0 - debug: 4.4.0 - eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215) - typescript: 5.8.2 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/project-service@8.43.0(typescript@5.8.2)': - dependencies: - '@typescript-eslint/tsconfig-utils': 8.43.0(typescript@5.8.2) - '@typescript-eslint/types': 8.43.0 + '@typescript-eslint/scope-manager': 8.47.0 + '@typescript-eslint/types': 8.47.0 + '@typescript-eslint/typescript-estree': 8.47.0(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.47.0 debug: 4.4.1 - typescript: 5.8.2 + eslint: 9.39.1 + typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.28.0': + '@typescript-eslint/project-service@8.47.0(typescript@5.9.3)': dependencies: - '@typescript-eslint/types': 8.28.0 - '@typescript-eslint/visitor-keys': 8.28.0 - - '@typescript-eslint/scope-manager@8.43.0': - dependencies: - '@typescript-eslint/types': 8.43.0 - '@typescript-eslint/visitor-keys': 8.43.0 - - '@typescript-eslint/tsconfig-utils@8.43.0(typescript@5.8.2)': - dependencies: - typescript: 5.8.2 - - '@typescript-eslint/type-utils@8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2)': - dependencies: - '@typescript-eslint/typescript-estree': 8.28.0(typescript@5.8.2) - '@typescript-eslint/utils': 8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2) - debug: 4.4.0 - eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215) - ts-api-utils: 2.1.0(typescript@5.8.2) - typescript: 5.8.2 + '@typescript-eslint/tsconfig-utils': 8.47.0(typescript@5.9.3) + '@typescript-eslint/types': 8.47.0 + debug: 4.4.1 + typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.28.0': {} - - '@typescript-eslint/types@8.43.0': {} - - '@typescript-eslint/typescript-estree@8.28.0(typescript@5.8.2)': + '@typescript-eslint/scope-manager@8.47.0': dependencies: - '@typescript-eslint/types': 8.28.0 - '@typescript-eslint/visitor-keys': 8.28.0 - debug: 4.4.0 - fast-glob: 3.3.3 - is-glob: 4.0.3 - minimatch: 9.0.5 - semver: 7.7.1 - ts-api-utils: 2.1.0(typescript@5.8.2) - typescript: 5.8.2 + '@typescript-eslint/types': 8.47.0 + '@typescript-eslint/visitor-keys': 8.47.0 + + '@typescript-eslint/tsconfig-utils@8.47.0(typescript@5.9.3)': + dependencies: + typescript: 5.9.3 + + '@typescript-eslint/type-utils@8.47.0(eslint@9.39.1)(typescript@5.9.3)': + dependencies: + '@typescript-eslint/types': 8.47.0 + '@typescript-eslint/typescript-estree': 8.47.0(typescript@5.9.3) + '@typescript-eslint/utils': 8.47.0(eslint@9.39.1)(typescript@5.9.3) + debug: 4.4.1 + eslint: 9.39.1 + ts-api-utils: 2.1.0(typescript@5.9.3) + typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/typescript-estree@8.43.0(typescript@5.8.2)': + '@typescript-eslint/types@8.47.0': {} + + '@typescript-eslint/typescript-estree@8.47.0(typescript@5.9.3)': dependencies: - '@typescript-eslint/project-service': 8.43.0(typescript@5.8.2) - '@typescript-eslint/tsconfig-utils': 8.43.0(typescript@5.8.2) - '@typescript-eslint/types': 8.43.0 - '@typescript-eslint/visitor-keys': 8.43.0 + '@typescript-eslint/project-service': 8.47.0(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.47.0(typescript@5.9.3) + '@typescript-eslint/types': 8.47.0 + '@typescript-eslint/visitor-keys': 8.47.0 debug: 4.4.1 fast-glob: 3.3.3 is-glob: 4.0.3 minimatch: 9.0.5 semver: 7.7.2 - ts-api-utils: 2.1.0(typescript@5.8.2) - typescript: 5.8.2 + ts-api-utils: 2.1.0(typescript@5.9.3) + typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2)': + '@typescript-eslint/utils@8.47.0(eslint@9.39.1)(typescript@5.9.3)': dependencies: - '@eslint-community/eslint-utils': 4.5.1(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)) - '@typescript-eslint/scope-manager': 8.28.0 - '@typescript-eslint/types': 8.28.0 - '@typescript-eslint/typescript-estree': 8.28.0(typescript@5.8.2) - eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215) - typescript: 5.8.2 + '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1) + '@typescript-eslint/scope-manager': 8.47.0 + '@typescript-eslint/types': 8.47.0 + '@typescript-eslint/typescript-estree': 8.47.0(typescript@5.9.3) + eslint: 9.39.1 + typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.43.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2)': + '@typescript-eslint/visitor-keys@8.47.0': dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)) - '@typescript-eslint/scope-manager': 8.43.0 - '@typescript-eslint/types': 8.43.0 - '@typescript-eslint/typescript-estree': 8.43.0(typescript@5.8.2) - eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215) - typescript: 5.8.2 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/visitor-keys@8.28.0': - dependencies: - '@typescript-eslint/types': 8.28.0 - eslint-visitor-keys: 4.2.0 - - '@typescript-eslint/visitor-keys@8.43.0': - dependencies: - '@typescript-eslint/types': 8.43.0 + '@typescript-eslint/types': 8.47.0 eslint-visitor-keys: 4.2.1 '@vap/core@0.0.12': @@ -3030,7 +3228,7 @@ snapshots: array-includes@3.1.8: dependencies: - call-bind: 1.0.7 + call-bind: 1.0.8 define-properties: 1.2.1 es-abstract: 1.23.9 es-object-atoms: 1.1.1 @@ -3041,7 +3239,7 @@ snapshots: array.prototype.findlast@1.2.5: dependencies: - call-bind: 1.0.7 + call-bind: 1.0.8 define-properties: 1.2.1 es-abstract: 1.23.9 es-errors: 1.3.0 @@ -3060,7 +3258,7 @@ snapshots: array.prototype.flat@1.3.2: dependencies: - call-bind: 1.0.7 + call-bind: 1.0.8 define-properties: 1.2.1 es-abstract: 1.23.9 es-shim-unscopables: 1.1.0 @@ -3074,7 +3272,7 @@ snapshots: array.prototype.tosorted@1.1.4: dependencies: - call-bind: 1.0.7 + call-bind: 1.0.8 define-properties: 1.2.1 es-abstract: 1.23.9 es-errors: 1.3.0 @@ -3098,6 +3296,8 @@ snapshots: async-function@1.0.0: {} + async@1.5.2: {} + available-typed-arrays@1.0.7: dependencies: possible-typed-array-names: 1.1.0 @@ -3133,8 +3333,6 @@ snapshots: bare-events: 2.5.4 optional: true - base64-js@1.5.1: {} - basic-ftp@5.0.5: {} brace-expansion@1.1.12: @@ -3154,29 +3352,19 @@ snapshots: buffer-from@1.1.2: {} - buffer@6.0.3: + cacheable@2.2.0: dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - - cacheable@1.8.9: - dependencies: - hookified: 1.8.1 - keyv: 5.3.2 + '@cacheable/memory': 2.0.5 + '@cacheable/utils': 2.3.1 + hookified: 1.13.0 + keyv: 5.5.4 + qified: 0.5.2 call-bind-apply-helpers@1.0.2: dependencies: es-errors: 1.3.0 function-bind: 1.1.2 - call-bind@1.0.7: - dependencies: - es-define-property: 1.0.0 - es-errors: 1.3.0 - function-bind: 1.1.2 - get-intrinsic: 1.2.4 - set-function-length: 1.2.2 - call-bind@1.0.8: dependencies: call-bind-apply-helpers: 1.0.2 @@ -3207,9 +3395,9 @@ snapshots: ansi-styles: 4.3.0 supports-color: 7.2.0 - chromium-bidi@8.0.0(devtools-protocol@0.0.1495869): + chromium-bidi@11.0.0(devtools-protocol@0.0.1521046): dependencies: - devtools-protocol: 0.0.1495869 + devtools-protocol: 0.0.1521046 mitt: 3.0.1 zod: 3.24.2 @@ -3245,14 +3433,14 @@ snapshots: concat-map@0.0.1: {} - cosmiconfig@9.0.0(typescript@5.8.2): + cosmiconfig@9.0.0(typescript@5.9.3): dependencies: env-paths: 2.2.1 import-fresh: 3.3.1 js-yaml: 4.1.0 parse-json: 5.2.0 optionalDependencies: - typescript: 5.8.2 + typescript: 5.9.3 cross-spawn@7.0.6: dependencies: @@ -3265,7 +3453,7 @@ snapshots: css-tree@3.1.0: dependencies: mdn-data: 2.12.2 - source-map-js: 1.2.0 + source-map-js: 1.2.1 cssesc@3.0.0: {} @@ -3295,11 +3483,11 @@ snapshots: dependencies: ms: 2.1.3 - debug@4.4.0: + debug@4.4.1: dependencies: ms: 2.1.3 - debug@4.4.1: + debug@4.4.3: dependencies: ms: 2.1.3 @@ -3307,9 +3495,9 @@ snapshots: define-data-property@1.1.4: dependencies: - es-define-property: 1.0.0 + es-define-property: 1.0.1 es-errors: 1.3.0 - gopd: 1.0.1 + gopd: 1.2.0 define-properties@1.2.1: dependencies: @@ -3323,9 +3511,9 @@ snapshots: escodegen: 2.1.0 esprima: 4.0.1 - devtools-protocol@0.0.1495869: {} + devtools-protocol@0.0.1521046: {} - diff@7.0.0: {} + diff@8.0.2: {} dir-glob@3.0.1: dependencies: @@ -3335,6 +3523,8 @@ snapshots: dependencies: esutils: 2.0.3 + dompurify@3.1.7: {} + dot-case@3.0.4: dependencies: no-case: 3.0.4 @@ -3418,10 +3608,6 @@ snapshots: unbox-primitive: 1.1.0 which-typed-array: 1.1.19 - es-define-property@1.0.0: - dependencies: - get-intrinsic: 1.2.4 - es-define-property@1.0.1: {} es-errors@1.3.0: {} @@ -3433,7 +3619,7 @@ snapshots: define-properties: 1.2.1 es-abstract: 1.23.9 es-errors: 1.3.0 - es-set-tostringtag: 2.0.3 + es-set-tostringtag: 2.1.0 function-bind: 1.1.2 get-intrinsic: 1.3.0 globalthis: 1.0.4 @@ -3449,12 +3635,6 @@ snapshots: dependencies: es-errors: 1.3.0 - es-set-tostringtag@2.0.3: - dependencies: - get-intrinsic: 1.2.7 - has-tostringtag: 1.0.2 - hasown: 2.0.2 - es-set-tostringtag@2.1.0: dependencies: es-errors: 1.3.0 @@ -3469,8 +3649,8 @@ snapshots: es-to-primitive@1.3.0: dependencies: is-callable: 1.2.7 - is-date-object: 1.0.5 - is-symbol: 1.0.4 + is-date-object: 1.1.0 + is-symbol: 1.1.1 esbuild@0.25.1: optionalDependencies: @@ -3500,6 +3680,35 @@ snapshots: '@esbuild/win32-ia32': 0.25.1 '@esbuild/win32-x64': 0.25.1 + esbuild@0.27.0: + optionalDependencies: + '@esbuild/aix-ppc64': 0.27.0 + '@esbuild/android-arm': 0.27.0 + '@esbuild/android-arm64': 0.27.0 + '@esbuild/android-x64': 0.27.0 + '@esbuild/darwin-arm64': 0.27.0 + '@esbuild/darwin-x64': 0.27.0 + '@esbuild/freebsd-arm64': 0.27.0 + '@esbuild/freebsd-x64': 0.27.0 + '@esbuild/linux-arm': 0.27.0 + '@esbuild/linux-arm64': 0.27.0 + '@esbuild/linux-ia32': 0.27.0 + '@esbuild/linux-loong64': 0.27.0 + '@esbuild/linux-mips64el': 0.27.0 + '@esbuild/linux-ppc64': 0.27.0 + '@esbuild/linux-riscv64': 0.27.0 + '@esbuild/linux-s390x': 0.27.0 + '@esbuild/linux-x64': 0.27.0 + '@esbuild/netbsd-arm64': 0.27.0 + '@esbuild/netbsd-x64': 0.27.0 + '@esbuild/openbsd-arm64': 0.27.0 + '@esbuild/openbsd-x64': 0.27.0 + '@esbuild/openharmony-arm64': 0.27.0 + '@esbuild/sunos-x64': 0.27.0 + '@esbuild/win32-arm64': 0.27.0 + '@esbuild/win32-ia32': 0.27.0 + '@esbuild/win32-x64': 0.27.0 + escalade@3.1.2: {} escape-string-regexp@1.0.5: {} @@ -3514,9 +3723,9 @@ snapshots: optionalDependencies: source-map: 0.6.1 - eslint-import-resolver-alias@1.1.2(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))): + eslint-import-resolver-alias@1.1.2(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.47.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)): dependencies: - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.47.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1) eslint-import-resolver-node@0.3.9: dependencies: @@ -3526,17 +3735,17 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.0(@typescript-eslint/parser@8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)): + eslint-module-utils@2.12.0(@typescript-eslint/parser@8.47.0(eslint@9.39.1)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.39.1): dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2) - eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215) + '@typescript-eslint/parser': 8.47.0(eslint@9.39.1)(typescript@5.9.3) + eslint: 9.39.1 eslint-import-resolver-node: 0.3.9 transitivePeerDependencies: - supports-color - eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)): + eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.47.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.8 @@ -3545,9 +3754,9 @@ snapshots: array.prototype.flatmap: 1.3.3 debug: 3.2.7 doctrine: 2.1.0 - eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215) + eslint: 9.39.1 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.47.0(eslint@9.39.1)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.39.1) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -3559,13 +3768,13 @@ snapshots: string.prototype.trimend: 1.0.9 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2) + '@typescript-eslint/parser': 8.47.0(eslint@9.39.1)(typescript@5.9.3) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack - supports-color - eslint-plugin-react@7.37.4(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)): + eslint-plugin-react@7.37.5(eslint@9.39.1): dependencies: array-includes: 3.1.8 array.prototype.findlast: 1.2.5 @@ -3573,7 +3782,7 @@ snapshots: array.prototype.tosorted: 1.1.4 doctrine: 2.1.0 es-iterator-helpers: 1.2.1 - eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215) + eslint: 9.39.1 estraverse: 5.3.0 hasown: 2.0.2 jsx-ast-utils: 3.3.5 @@ -3587,19 +3796,19 @@ snapshots: string.prototype.matchall: 4.0.12 string.prototype.repeat: 1.0.0 - eslint-plugin-simple-header@1.2.2(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)): + eslint-plugin-simple-header@1.2.2(eslint@9.39.1): dependencies: - eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215) + eslint: 9.39.1 - eslint-plugin-simple-import-sort@12.1.1(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)): + eslint-plugin-simple-import-sort@12.1.1(eslint@9.39.1): dependencies: - eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215) + eslint: 9.39.1 - eslint-plugin-unused-imports@4.1.4(@typescript-eslint/eslint-plugin@8.28.0(@typescript-eslint/parser@8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)): + eslint-plugin-unused-imports@4.3.0(@typescript-eslint/eslint-plugin@8.47.0(@typescript-eslint/parser@8.47.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1): dependencies: - eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215) + eslint: 9.39.1 optionalDependencies: - '@typescript-eslint/eslint-plugin': 8.28.0(@typescript-eslint/parser@8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2) + '@typescript-eslint/eslint-plugin': 8.47.0(@typescript-eslint/parser@8.47.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3) eslint-scope@8.4.0: dependencies: @@ -3608,24 +3817,22 @@ snapshots: eslint-visitor-keys@3.4.3: {} - eslint-visitor-keys@4.2.0: {} - eslint-visitor-keys@4.2.1: {} - eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215): + eslint@9.39.1: dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1) '@eslint-community/regexpp': 4.12.1 - '@eslint/config-array': 0.19.2 - '@eslint/core': 0.11.0 + '@eslint/config-array': 0.21.1 + '@eslint/config-helpers': 0.4.2 + '@eslint/core': 0.17.0 '@eslint/eslintrc': 3.3.1 - '@eslint/js': 9.20.0 - '@eslint/plugin-kit': 0.3.5 + '@eslint/js': 9.39.1 + '@eslint/plugin-kit': 0.4.1 '@humanfs/node': 0.16.6 '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.4.2 '@types/estree': 1.0.7 - '@types/json-schema': 7.0.15 ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.6 @@ -3675,7 +3882,7 @@ snapshots: extract-zip@2.0.1: dependencies: - debug: 4.4.1 + debug: 4.4.3 get-stream: 5.2.0 yauzl: 2.10.0 optionalDependencies: @@ -3713,9 +3920,9 @@ snapshots: fflate@0.8.2: {} - file-entry-cache@10.0.7: + file-entry-cache@10.1.4: dependencies: - flat-cache: 6.1.7 + flat-cache: 6.1.19 file-entry-cache@8.0.0: dependencies: @@ -3735,11 +3942,11 @@ snapshots: flatted: 3.3.3 keyv: 4.5.4 - flat-cache@6.1.7: + flat-cache@6.1.19: dependencies: - cacheable: 1.8.9 + cacheable: 2.2.0 flatted: 3.3.3 - hookified: 1.8.1 + hookified: 1.13.0 flatted@3.3.3: {} @@ -3776,27 +3983,6 @@ snapshots: get-caller-file@2.0.5: {} - get-intrinsic@1.2.4: - dependencies: - es-errors: 1.3.0 - function-bind: 1.1.2 - has-proto: 1.0.3 - has-symbols: 1.0.3 - hasown: 2.0.2 - - get-intrinsic@1.2.7: - dependencies: - call-bind-apply-helpers: 1.0.2 - es-define-property: 1.0.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - function-bind: 1.1.2 - get-proto: 1.0.1 - gopd: 1.2.0 - has-symbols: 1.1.0 - hasown: 2.0.2 - math-intrinsics: 1.1.0 - get-intrinsic@1.3.0: dependencies: call-bind-apply-helpers: 1.0.2 @@ -3833,7 +4019,7 @@ snapshots: dependencies: basic-ftp: 5.0.5 data-uri-to-buffer: 6.0.2 - debug: 4.4.1 + debug: 4.4.3 fs-extra: 11.3.0 transitivePeerDependencies: - supports-color @@ -3891,10 +4077,6 @@ snapshots: globjoin@0.1.4: {} - gopd@1.0.1: - dependencies: - get-intrinsic: 1.2.4 - gopd@1.2.0: {} graceful-fs@4.2.11: {} @@ -3909,21 +4091,21 @@ snapshots: has-property-descriptors@1.0.2: dependencies: - es-define-property: 1.0.0 - - has-proto@1.0.3: {} + es-define-property: 1.0.1 has-proto@1.2.0: dependencies: dunder-proto: 1.0.1 - has-symbols@1.0.3: {} - has-symbols@1.1.0: {} has-tostringtag@1.0.2: dependencies: - has-symbols: 1.0.3 + has-symbols: 1.1.0 + + hashery@1.2.0: + dependencies: + hookified: 1.13.0 hasown@2.0.2: dependencies: @@ -3931,7 +4113,7 @@ snapshots: highlight.js@11.11.1: {} - hookified@1.8.1: {} + hookified@1.13.0: {} html-minifier-terser@7.2.0: dependencies: @@ -3948,25 +4130,25 @@ snapshots: http-proxy-agent@7.0.2: dependencies: agent-base: 7.1.3 - debug: 4.4.1 + debug: 4.4.3 transitivePeerDependencies: - supports-color https-proxy-agent@7.0.6: dependencies: agent-base: 7.1.3 - debug: 4.4.1 + debug: 4.4.3 transitivePeerDependencies: - supports-color idb@8.0.3: {} - ieee754@1.2.1: {} - ignore@5.3.1: {} ignore@7.0.3: {} + ignore@7.0.5: {} + import-fresh@3.3.1: dependencies: parent-module: 1.0.1 @@ -4016,10 +4198,6 @@ snapshots: is-callable@1.2.7: {} - is-core-module@2.15.0: - dependencies: - hasown: 2.0.2 - is-core-module@2.16.1: dependencies: hasown: 2.0.2 @@ -4030,10 +4208,6 @@ snapshots: get-intrinsic: 1.3.0 is-typed-array: 1.1.15 - is-date-object@1.0.5: - dependencies: - has-tostringtag: 1.0.2 - is-date-object@1.1.0: dependencies: call-bound: 1.0.4 @@ -4087,10 +4261,6 @@ snapshots: call-bound: 1.0.4 has-tostringtag: 1.0.2 - is-symbol@1.0.4: - dependencies: - has-symbols: 1.0.3 - is-symbol@1.1.1: dependencies: call-bound: 1.0.4 @@ -4167,20 +4337,24 @@ snapshots: dependencies: array-includes: 3.1.8 array.prototype.flat: 1.3.2 - object.assign: 4.1.5 + object.assign: 4.1.7 object.values: 1.2.1 + jszip@2.7.0: + dependencies: + pako: 1.0.11 + keyv@4.5.4: dependencies: json-buffer: 3.0.1 - keyv@5.3.2: + keyv@5.5.4: dependencies: - '@keyv/serialize': 1.0.3 + '@keyv/serialize': 1.1.1 kind-of@6.0.3: {} - known-css-properties@0.35.0: {} + known-css-properties@0.37.0: {} levn@0.4.1: dependencies: @@ -4209,6 +4383,8 @@ snapshots: lru-cache@7.18.3: {} + marked@14.0.0: {} + math-intrinsics@1.1.0: {} mathml-tag-names@2.1.3: {} @@ -4244,13 +4420,16 @@ snapshots: moment@2.30.1: {} - monaco-editor@0.52.2: {} + monaco-editor@0.54.0: + dependencies: + dompurify: 3.1.7 + marked: 14.0.0 ms@2.1.3: {} nanoid@3.3.11: {} - nanoid@5.1.5: {} + nanoid@5.1.6: {} natural-compare@1.4.0: {} @@ -4269,13 +4448,6 @@ snapshots: object-keys@1.1.1: {} - object.assign@4.1.5: - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - has-symbols: 1.0.3 - object-keys: 1.1.1 - object.assign@4.1.7: dependencies: call-bind: 1.0.8 @@ -4294,7 +4466,7 @@ snapshots: object.fromentries@2.0.8: dependencies: - call-bind: 1.0.7 + call-bind: 1.0.8 define-properties: 1.2.1 es-abstract: 1.23.9 es-object-atoms: 1.1.1 @@ -4343,7 +4515,7 @@ snapshots: dependencies: '@tootallnate/quickjs-emscripten': 0.23.0 agent-base: 7.1.3 - debug: 4.4.1 + debug: 4.4.3 get-uri: 6.0.3 http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.6 @@ -4359,6 +4531,8 @@ snapshots: package-json-from-dist@1.0.1: {} + pako@1.0.11: {} + param-case@3.0.4: dependencies: dot-case: 3.0.4 @@ -4405,9 +4579,9 @@ snapshots: postcss-resolve-nested-selector@0.1.6: {} - postcss-safe-parser@7.0.1(postcss@8.5.3): + postcss-safe-parser@7.0.1(postcss@8.5.6): dependencies: - postcss: 8.5.3 + postcss: 8.5.6 postcss-selector-parser@7.1.0: dependencies: @@ -4416,7 +4590,7 @@ snapshots: postcss-value-parser@4.2.0: {} - postcss@8.5.3: + postcss@8.5.6: dependencies: nanoid: 3.3.11 picocolors: 1.1.1 @@ -4435,7 +4609,7 @@ snapshots: proxy-agent@6.5.0: dependencies: agent-base: 7.1.3 - debug: 4.4.1 + debug: 4.4.3 http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.6 lru-cache: 7.18.3 @@ -4454,13 +4628,14 @@ snapshots: punycode@2.3.1: {} - puppeteer-core@24.19.0: + puppeteer-core@24.30.0: dependencies: - '@puppeteer/browsers': 2.10.8 - chromium-bidi: 8.0.0(devtools-protocol@0.0.1495869) - debug: 4.4.1 - devtools-protocol: 0.0.1495869 + '@puppeteer/browsers': 2.10.13 + chromium-bidi: 11.0.0(devtools-protocol@0.0.1521046) + debug: 4.4.3 + devtools-protocol: 0.0.1521046 typed-query-selector: 2.12.0 + webdriver-bidi-protocol: 0.3.8 ws: 8.18.3 transitivePeerDependencies: - bare-buffer @@ -4468,6 +4643,12 @@ snapshots: - supports-color - utf-8-validate + q@1.5.1: {} + + qified@0.5.2: + dependencies: + hookified: 1.13.0 + queue-microtask@1.2.3: {} react-is@16.13.1: {} @@ -4512,7 +4693,7 @@ snapshots: resolve@2.0.0-next.5: dependencies: - is-core-module: 2.15.0 + is-core-module: 2.16.1 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 @@ -4547,6 +4728,8 @@ snapshots: semver@7.7.2: {} + semver@7.7.3: {} + set-function-length@1.2.2: dependencies: define-data-property: 1.1.4 @@ -4618,7 +4801,7 @@ snapshots: socks-proxy-agent@8.0.5: dependencies: agent-base: 7.1.3 - debug: 4.4.1 + debug: 4.4.3 socks: 2.8.4 transitivePeerDependencies: - supports-color @@ -4628,8 +4811,6 @@ snapshots: ip-address: 9.0.5 smart-buffer: 4.2.0 - source-map-js@1.2.0: {} - source-map-js@1.2.1: {} source-map-support@0.5.21: @@ -4704,7 +4885,7 @@ snapshots: string.prototype.trimstart@1.0.8: dependencies: - call-bind: 1.0.7 + call-bind: 1.0.8 define-properties: 1.2.1 es-object-atoms: 1.1.1 @@ -4720,47 +4901,47 @@ snapshots: strip-json-comments@3.1.1: {} - stylelint-config-recommended@15.0.0(stylelint@16.17.0(typescript@5.8.2)): + stylelint-config-recommended@17.0.0(stylelint@16.25.0(typescript@5.9.3)): dependencies: - stylelint: 16.17.0(typescript@5.8.2) + stylelint: 16.25.0(typescript@5.9.3) - stylelint-config-standard@37.0.0(stylelint@16.17.0(typescript@5.8.2)): + stylelint-config-standard@39.0.1(stylelint@16.25.0(typescript@5.9.3)): dependencies: - stylelint: 16.17.0(typescript@5.8.2) - stylelint-config-recommended: 15.0.0(stylelint@16.17.0(typescript@5.8.2)) + stylelint: 16.25.0(typescript@5.9.3) + stylelint-config-recommended: 17.0.0(stylelint@16.25.0(typescript@5.9.3)) - stylelint@16.17.0(typescript@5.8.2): + stylelint@16.25.0(typescript@5.9.3): dependencies: - '@csstools/css-parser-algorithms': 3.0.4(@csstools/css-tokenizer@3.0.3) - '@csstools/css-tokenizer': 3.0.3 - '@csstools/media-query-list-parser': 4.0.2(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + '@csstools/media-query-list-parser': 4.0.3(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) '@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.1.0) - '@dual-bundle/import-meta-resolve': 4.1.0 + '@dual-bundle/import-meta-resolve': 4.2.1 balanced-match: 2.0.0 colord: 2.9.3 - cosmiconfig: 9.0.0(typescript@5.8.2) + cosmiconfig: 9.0.0(typescript@5.9.3) css-functions-list: 3.2.3 css-tree: 3.1.0 - debug: 4.4.0 + debug: 4.4.3 fast-glob: 3.3.3 fastest-levenshtein: 1.0.16 - file-entry-cache: 10.0.7 + file-entry-cache: 10.1.4 global-modules: 2.0.0 globby: 11.1.0 globjoin: 0.1.4 html-tags: 3.3.1 - ignore: 7.0.3 + ignore: 7.0.5 imurmurhash: 0.1.4 is-plain-object: 5.0.0 - known-css-properties: 0.35.0 + known-css-properties: 0.37.0 mathml-tag-names: 2.1.3 meow: 13.2.0 micromatch: 4.0.8 normalize-path: 3.0.0 picocolors: 1.1.1 - postcss: 8.5.3 + postcss: 8.5.6 postcss-resolve-nested-selector: 0.1.6 - postcss-safe-parser: 7.0.1(postcss@8.5.3) + postcss-safe-parser: 7.0.1(postcss@8.5.6) postcss-selector-parser: 7.1.0 postcss-value-parser: 4.2.0 resolve-from: 5.0.0 @@ -4798,7 +4979,9 @@ snapshots: string-width: 4.2.3 strip-ansi: 6.0.1 - tar-fs@3.1.0: + tagged-tag@1.0.0: {} + + tar-fs@3.1.1: dependencies: pump: 3.0.0 tar-stream: 3.1.7 @@ -4829,9 +5012,9 @@ snapshots: dependencies: is-number: 7.0.0 - ts-api-utils@2.1.0(typescript@5.8.2): + ts-api-utils@2.1.0(typescript@5.9.3): dependencies: - typescript: 5.8.2 + typescript: 5.9.3 ts-patch@3.3.0: dependencies: @@ -4862,6 +5045,13 @@ snapshots: optionalDependencies: fsevents: 2.3.3 + tsx@4.20.6: + dependencies: + esbuild: 0.25.1 + get-tsconfig: 4.10.0 + optionalDependencies: + fsevents: 2.3.3 + type-check@0.4.0: dependencies: prelude-ls: 1.2.1 @@ -4870,6 +5060,10 @@ snapshots: type-fest@4.41.0: {} + type-fest@5.2.0: + dependencies: + tagged-tag: 1.0.0 + typed-array-buffer@1.0.3: dependencies: call-bound: 1.0.4 @@ -4905,22 +5099,23 @@ snapshots: typed-query-selector@2.12.0: {} - typescript-eslint@8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2): + typescript-eslint@8.47.0(eslint@9.39.1)(typescript@5.9.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.28.0(@typescript-eslint/parser@8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2) - '@typescript-eslint/parser': 8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2) - '@typescript-eslint/utils': 8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2) - eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215) - typescript: 5.8.2 + '@typescript-eslint/eslint-plugin': 8.47.0(@typescript-eslint/parser@8.47.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3) + '@typescript-eslint/parser': 8.47.0(eslint@9.39.1)(typescript@5.9.3) + '@typescript-eslint/typescript-estree': 8.47.0(typescript@5.9.3) + '@typescript-eslint/utils': 8.47.0(eslint@9.39.1)(typescript@5.9.3) + eslint: 9.39.1 + typescript: 5.9.3 transitivePeerDependencies: - supports-color - typescript-transform-paths@3.5.5(typescript@5.8.2): + typescript-transform-paths@3.5.5(typescript@5.9.3): dependencies: minimatch: 9.0.5 - typescript: 5.8.2 + typescript: 5.9.3 - typescript@5.8.2: {} + typescript@5.9.3: {} unbox-primitive@1.1.0: dependencies: @@ -4931,6 +5126,8 @@ snapshots: undici-types@6.20.0: {} + undici-types@7.16.0: {} + universalify@2.0.1: {} uri-js@4.4.1: @@ -4947,6 +5144,8 @@ snapshots: vscode-textmate@5.2.0: {} + webdriver-bidi-protocol@0.3.8: {} + which-boxed-primitive@1.1.1: dependencies: is-bigint: 1.1.0 @@ -5044,4 +5243,11 @@ snapshots: yocto-queue@0.1.0: {} + zip-local@0.3.5: + dependencies: + async: 1.5.2 + graceful-fs: 4.2.11 + jszip: 2.7.0 + q: 1.5.1 + zod@3.24.2: {} diff --git a/scripts/generateReport.ts b/scripts/generateReport.ts index 5a1c42585..07cd2db8b 100644 --- a/scripts/generateReport.ts +++ b/scripts/generateReport.ts @@ -340,7 +340,7 @@ page.on("console", async e => { }); page.on("error", e => logStderr("[Error]", e.message)); -page.on("pageerror", e => { +page.on("pageerror", (e: any) => { if (e.message.includes("Sentry successfully disabled")) return; if (!e.message.startsWith("Object") && !e.message.includes("Cannot find module") && !/^.{1,2}$/.test(e.message)) { diff --git a/src/Vencord.ts b/src/Vencord.ts index bca2e046f..9fede6591 100644 --- a/src/Vencord.ts +++ b/src/Vencord.ts @@ -20,34 +20,32 @@ import "~plugins"; export * as Api from "./api"; +export * as Plugins from "./api/PluginManager"; export * as Components from "./components"; -export * as Plugins from "./plugins"; export * as Util from "./utils"; -export * as QuickCss from "./utils/quickCss"; export * as Updater from "./utils/updater"; export * as Webpack from "./webpack"; export * as WebpackPatcher from "./webpack/patchWebpack"; export { PlainSettings, Settings }; -import "./utils/quickCss"; -import "./webpack/patchWebpack"; - import { addVencordUiStyles } from "@components/css"; import { openUpdaterModal } from "@components/settings/tabs/updater"; +import { debounce } from "@shared/debounce"; import { IS_WINDOWS } from "@utils/constants"; import { createAndAppendStyle } from "@utils/css"; import { StartAt } from "@utils/types"; import { get as dsGet } from "./api/DataStore"; import { NotificationData, showNotification } from "./api/Notifications"; -import { PlainSettings, Settings } from "./api/Settings"; -import { patches, PMLogger, startAllPlugins } from "./plugins"; +import { initPluginManager, PMLogger, startAllPlugins } from "./api/PluginManager"; +import { PlainSettings, Settings, SettingsStore } from "./api/Settings"; +import { getCloudSettings, putCloudSettings } from "./api/SettingsSync/cloudSync"; import { localStorage } from "./utils/localStorage"; import { relaunch } from "./utils/native"; -import { getCloudSettings, putCloudSettings } from "./utils/settingsSync"; import { checkForUpdates, update, UpdateLogger } from "./utils/updater"; import { onceReady } from "./webpack"; import { SettingsRouter } from "./webpack/common"; +import { patches } from "./webpack/patchWebpack"; if (IS_REPORTER) { require("./debug/runReporter"); @@ -108,6 +106,18 @@ async function syncSettings() { }); } } + + const saveSettingsOnFrequentAction = debounce(async () => { + if (Settings.cloud.settingsSync && Settings.cloud.authenticated) { + await putCloudSettings(); + delete localStorage.Vencord_settingsDirty; + } + }, 60_000); + + SettingsStore.addGlobalChangeListener(() => { + localStorage.Vencord_settingsDirty = true; + saveSettingsOnFrequentAction(); + }); } let notifiedForUpdatesThisSession = false; @@ -179,6 +189,7 @@ async function init() { } } +initPluginManager(); startAllPlugins(StartAt.Init); init(); diff --git a/src/api/Badges.ts b/src/api/Badges.ts index 2014aa5a6..82b6a63d4 100644 --- a/src/api/Badges.ts +++ b/src/api/Badges.ts @@ -17,7 +17,7 @@ */ import ErrorBoundary from "@components/ErrorBoundary"; -import BadgeAPIPlugin from "plugins/_api/badges"; +import BadgeAPIPlugin from "@plugins/_api/badges"; import { ComponentType, HTMLProps } from "react"; export const enum BadgePosition { diff --git a/src/plugins/index.ts b/src/api/PluginManager.ts similarity index 74% rename from src/plugins/index.ts rename to src/api/PluginManager.ts index 7b111d630..218aef23a 100644 --- a/src/plugins/index.ts +++ b/src/api/PluginManager.ts @@ -28,8 +28,8 @@ import { addMessagePopoverButton, removeMessagePopoverButton } from "@api/Messag import { addNicknameIcon, removeNicknameIcon } from "@api/NicknameIcons"; import { Settings, SettingsStore } from "@api/Settings"; import { disableStyle, enableStyle } from "@api/Styles"; -import { makeLazy } from "@utils/lazy"; import { Logger } from "@utils/Logger"; +import { onlyOnce } from "@utils/onlyOnce"; import { canonicalizeFind, canonicalizeReplacement } from "@utils/patches"; import { Patch, Plugin, PluginDef, ReporterTestable, StartAt } from "@utils/types"; import { FluxEvents } from "@vencord/discord-types"; @@ -37,53 +37,29 @@ import { FluxDispatcher } from "@webpack/common"; import { patches } from "@webpack/patcher"; import Plugins from "~plugins"; +export { Plugins as plugins }; import { traceFunction } from "../debug/Tracer"; const logger = new Logger("PluginManager", "#a6d189"); export const PMLogger = logger; -export const plugins = Plugins; -export { patches }; /** Whether we have subscribed to flux events of all the enabled plugins when FluxDispatcher was ready */ let enabledPluginsSubscribedFlux = false; const subscribedFluxEventsPlugins = new Set(); -const pluginsValues = Object.values(Plugins); -const settings = Settings.plugins; - -/** - * Whether a plugin is required (or dependency of another enabled plugin) - */ -export function isPluginRequired(name: string) { - const p = Plugins[name]; - if (!p) return false; - return p.required || p.isDependency; -} - -/** - * A map of plugin names to the plugins that depend on them - */ -export const calculatePluginDependencyMap = makeLazy(() => { - const dependencies: Record = {}; - for (const plugin in Plugins) { - const deps = Plugins[plugin].dependencies; - if (deps) { - for (const dep of deps) { - dependencies[dep] ??= []; - dependencies[dep].push(plugin); - } - } - } - - return dependencies; -}); - export function isPluginEnabled(p: string) { return ( - isPluginRequired(p) || - settings[p]?.enabled + Plugins[p]?.required || + Plugins[p]?.isDependency || + Settings.plugins[p]?.enabled + ) ?? false; +} + +export function isPluginRequired(p: string) { + return ( + Plugins[p]?.required ) ?? false; } @@ -122,94 +98,6 @@ function isReporterTestable(p: Plugin, part: ReporterTestable) { : (p.reporterTestable & part) === part; } -const pluginKeysToBind: Array = [ - "onBeforeMessageEdit", "onBeforeMessageSend", "onMessageClick", - "renderChatBarButton", "renderMemberListDecorator", "renderNicknameIcon", "renderMessageAccessory", "renderMessageDecoration", "renderMessagePopoverButton" -]; - -const neededApiPlugins = new Set(); - -// First round-trip to mark and force enable dependencies -// -// FIXME: might need to revisit this if there's ever nested (dependencies of dependencies) dependencies since this only -// goes for the top level and their children, but for now this works okay with the current API plugins -for (const p of pluginsValues) if (isPluginEnabled(p.name)) { - p.dependencies?.forEach(d => { - const dep = Plugins[d]; - - if (!dep) { - const error = new Error(`Plugin ${p.name} has unresolved dependency ${d}`); - - if (IS_DEV) { - throw error; - } - - logger.warn(error); - return; - } - - settings[d].enabled = true; - dep.isDependency = true; - }); - - if (p.userProfileBadge) { - if (!p.userProfileBadges) { - p.userProfileBadges = [p.userProfileBadge]; - } else { - p.userProfileBadges = [p.userProfileBadge, ...p.userProfileBadges]; - } - } - - if (p.commands?.length) neededApiPlugins.add("CommandsAPI"); - if (p.onBeforeMessageEdit || p.onBeforeMessageSend || p.onMessageClick) neededApiPlugins.add("MessageEventsAPI"); - if (p.renderChatBarButton) neededApiPlugins.add("ChatInputButtonAPI"); - if (p.renderMemberListDecorator) neededApiPlugins.add("MemberListDecoratorsAPI"); - if (p.renderNicknameIcon) neededApiPlugins.add("NicknameIconsAPI"); - if (p.renderMessageAccessory) neededApiPlugins.add("MessageAccessoriesAPI"); - if (p.renderMessageDecoration) neededApiPlugins.add("MessageDecorationsAPI"); - if (p.renderMessagePopoverButton) neededApiPlugins.add("MessagePopoverAPI"); - if (p.userProfileBadges) neededApiPlugins.add("BadgeAPI"); - - for (const key of pluginKeysToBind) { - p[key] &&= p[key].bind(p) as any; - } -} - -for (const p of neededApiPlugins) { - Plugins[p].isDependency = true; - settings[p].enabled = true; -} - -for (const p of pluginsValues) { - if (p.settings) { - p.options ??= {}; - - p.settings.pluginName = p.name; - for (const name in p.settings.def) { - const def = p.settings.def[name]; - const checks = p.settings.checks?.[name]; - p.options[name] = { ...def, ...checks }; - } - } - - if (p.options) { - for (const name in p.options) { - const opt = p.options[name]; - if (opt.onChange != null) { - SettingsStore.addChangeListener(`plugins.${p.name}.${name}`, opt.onChange); - } - } - } - - if (p.patches && isPluginEnabled(p.name)) { - if (!IS_REPORTER || isReporterTestable(p, ReporterTestable.Patches)) { - for (const patch of p.patches) { - addPatch(patch, p.name); - } - } - } -} - export const startAllPlugins = traceFunction("startAllPlugins", function startAllPlugins(target: StartAt) { logger.info(`Starting plugins (stage ${target})`); for (const name in Plugins) { @@ -225,6 +113,7 @@ export const startAllPlugins = traceFunction("startAllPlugins", function startAl }); export function startDependenciesRecursive(p: Plugin) { + const settings = Settings.plugins; let restartNeeded = false; const failures: string[] = []; @@ -419,3 +308,88 @@ export const stopPlugin = traceFunction("stopPlugin", function stopPlugin(p: Plu return true; }, p => `stopPlugin ${p.name}`); + +export const initPluginManager = onlyOnce(function init() { + const pluginsValues = Object.values(Plugins); + const settings = Settings.plugins; + + const pluginKeysToBind: Array = [ + "onBeforeMessageEdit", "onBeforeMessageSend", "onMessageClick", + "renderChatBarButton", "renderMemberListDecorator", "renderMessageAccessory", "renderMessageDecoration", "renderMessagePopoverButton" + ]; + + const neededApiPlugins = new Set(); + + // First round-trip to mark and force enable dependencies + // + // FIXME: might need to revisit this if there's ever nested (dependencies of dependencies) dependencies since this only + // goes for the top level and their children, but for now this works okay with the current API plugins + for (const p of pluginsValues) if (isPluginEnabled(p.name)) { + p.dependencies?.forEach(d => { + const dep = Plugins[d]; + + if (!dep) { + const error = new Error(`Plugin ${p.name} has unresolved dependency ${d}`); + + if (IS_DEV) { + throw error; + } + + logger.warn(error); + return; + } + + settings[d].enabled = true; + dep.isDependency = true; + }); + + if (p.commands?.length) neededApiPlugins.add("CommandsAPI"); + if (p.onBeforeMessageEdit || p.onBeforeMessageSend || p.onMessageClick) neededApiPlugins.add("MessageEventsAPI"); + if (p.renderChatBarButton) neededApiPlugins.add("ChatInputButtonAPI"); + if (p.renderMemberListDecorator) neededApiPlugins.add("MemberListDecoratorsAPI"); + if (p.renderNicknameIcon) neededApiPlugins.add("NicknameIconsAPI"); + if (p.renderMessageAccessory) neededApiPlugins.add("MessageAccessoriesAPI"); + if (p.renderMessageDecoration) neededApiPlugins.add("MessageDecorationsAPI"); + if (p.renderMessagePopoverButton) neededApiPlugins.add("MessagePopoverAPI"); + if (p.userProfileBadge) neededApiPlugins.add("BadgeAPI"); + + for (const key of pluginKeysToBind) { + p[key] &&= p[key].bind(p) as any; + } + } + + for (const p of neededApiPlugins) { + Plugins[p].isDependency = true; + settings[p].enabled = true; + } + + for (const p of pluginsValues) { + if (p.settings) { + p.options ??= {}; + + p.settings.pluginName = p.name; + for (const name in p.settings.def) { + const def = p.settings.def[name]; + const checks = p.settings.checks?.[name]; + p.options[name] = { ...def, ...checks }; + } + } + + if (p.options) { + for (const name in p.options) { + const opt = p.options[name]; + if (opt.onChange != null) { + SettingsStore.addChangeListener(`plugins.${p.name}.${name}`, opt.onChange); + } + } + } + + if (p.patches && isPluginEnabled(p.name)) { + if (!IS_REPORTER || isReporterTestable(p, ReporterTestable.Patches)) { + for (const patch of p.patches) { + addPatch(patch, p.name); + } + } + } + } +}); diff --git a/src/api/Settings.ts b/src/api/Settings.ts index dca21bd1f..f8cb4ce0c 100644 --- a/src/api/Settings.ts +++ b/src/api/Settings.ts @@ -16,12 +16,9 @@ * along with this program. If not, see . */ -import { debounce } from "@shared/debounce"; import { SettingsStore as SettingsStoreClass } from "@shared/SettingsStore"; -import { localStorage } from "@utils/localStorage"; import { Logger } from "@utils/Logger"; import { mergeDefaults } from "@utils/mergeDefaults"; -import { putCloudSettings } from "@utils/settingsSync"; import { DefinedSettings, OptionType, SettingsChecks, SettingsDefinition } from "@utils/types"; import { React, useEffect } from "@webpack/common"; @@ -129,14 +126,6 @@ const DefaultSettings: Settings = { const settings = !IS_REPORTER ? VencordNative.settings.get() : {} as Settings; mergeDefaults(settings, DefaultSettings); -const saveSettingsOnFrequentAction = debounce(async () => { - if (Settings.cloud.settingsSync && Settings.cloud.authenticated) { - await putCloudSettings(); - delete localStorage.Vencord_settingsDirty; - } -}, 60_000); - - export const SettingsStore = new SettingsStoreClass(settings, { readOnly: true, getDefaultValue({ @@ -179,8 +168,6 @@ export const SettingsStore = new SettingsStoreClass(settings, { if (!IS_REPORTER) { SettingsStore.addGlobalChangeListener((_, path) => { SettingsStore.plain.cloud.settingsSyncVersion = Date.now(); - localStorage.Vencord_settingsDirty = true; - saveSettingsOnFrequentAction(); VencordNative.settings.set(SettingsStore.plain, path); }); } diff --git a/src/utils/cloud.tsx b/src/api/SettingsSync/cloudSetup.tsx similarity index 79% rename from src/utils/cloud.tsx rename to src/api/SettingsSync/cloudSetup.tsx index 8895e419b..20a21859d 100644 --- a/src/utils/cloud.tsx +++ b/src/api/SettingsSync/cloudSetup.tsx @@ -1,30 +1,17 @@ /* - * Vencord, a modification for Discord's desktop app - * Copyright (c) 2023 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 . -*/ + * Vencord, a Discord client mod + * Copyright (c) 2025 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ import * as DataStore from "@api/DataStore"; import { showNotification } from "@api/Notifications"; import { Settings } from "@api/Settings"; +import { Logger } from "@utils/Logger"; +import { openModal } from "@utils/modal"; import { OAuth2AuthorizeModal, UserStore } from "@webpack/common"; -import { Logger } from "./Logger"; -import { openModal } from "./modal"; - -export const cloudLogger = new Logger("Cloud", "#39b7e0"); +export const logger = new Logger("SettingsSync:CloudSetup", "#39b7e0"); export const getCloudUrl = () => new URL(Settings.cloud.url); const getCloudUrlOrigin = () => getCloudUrl().origin; @@ -111,7 +98,7 @@ export async function authorizeCloud() { }); const { secret } = await res.json(); if (secret) { - cloudLogger.info("Authorized with secret"); + logger.info("Authorized with secret"); await setAuthorization(secret); showNotification({ title: "Cloud Integration", @@ -126,7 +113,7 @@ export async function authorizeCloud() { Settings.cloud.authenticated = false; } } catch (e: any) { - cloudLogger.error("Failed to authorize", e); + logger.error("Failed to authorize", e); showNotification({ title: "Cloud Integration", body: `Setup failed (${e.toString()}).` diff --git a/src/api/SettingsSync/cloudSync.ts b/src/api/SettingsSync/cloudSync.ts new file mode 100644 index 000000000..b8a1bedf6 --- /dev/null +++ b/src/api/SettingsSync/cloudSync.ts @@ -0,0 +1,224 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2025 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import { showNotification } from "@api/Notifications"; +import { PlainSettings, Settings } from "@api/Settings"; +import { Logger } from "@utils/Logger"; +import { relaunch } from "@utils/native"; +import { SettingsRouter } from "@webpack/common"; +import { deflateSync, inflateSync } from "fflate"; + +import { deauthorizeCloud, getCloudAuth, getCloudUrl } from "./cloudSetup"; +import { exportSettings, importSettings } from "./offline"; + +const logger = new Logger("SettingsSync:Cloud", "#39b7e0"); + +export async function putCloudSettings(manual?: boolean) { + const settings = await exportSettings({ minify: true }); + + try { + const res = await fetch(new URL("/v1/settings", getCloudUrl()), { + method: "PUT", + headers: { + Authorization: await getCloudAuth(), + "Content-Type": "application/octet-stream" + }, + body: deflateSync(new TextEncoder().encode(settings)) as Uint8Array + }); + + if (!res.ok) { + logger.error(`Failed to sync up, API returned ${res.status}`); + showNotification({ + title: "Cloud Settings", + body: `Could not synchronize settings to cloud (API returned ${res.status}).`, + color: "var(--red-360)" + }); + return; + } + + const { written } = await res.json(); + PlainSettings.cloud.settingsSyncVersion = written; + VencordNative.settings.set(PlainSettings); + + logger.info("Settings uploaded to cloud successfully"); + + if (manual) { + showNotification({ + title: "Cloud Settings", + body: "Synchronized settings to the cloud!", + noPersist: true, + }); + } + } catch (e: any) { + logger.error("Failed to sync up", e); + showNotification({ + title: "Cloud Settings", + body: `Could not synchronize settings to the cloud (${e.toString()}).`, + color: "var(--red-360)" + }); + } +} + +export async function getCloudSettings(shouldNotify = true, force = false) { + try { + const res = await fetch(new URL("/v1/settings", getCloudUrl()), { + method: "GET", + headers: { + Authorization: await getCloudAuth(), + Accept: "application/octet-stream", + "If-None-Match": Settings.cloud.settingsSyncVersion.toString() + }, + }); + + if (res.status === 401) { + // User switched to an account that isn't connected to cloud + showNotification({ + 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: () => SettingsRouter.open("VencordCloud") + }); + // Disable cloud sync globally + Settings.cloud.authenticated = false; + return false; + } + + if (res.status === 404) { + logger.info("No settings on the cloud"); + if (shouldNotify) + showNotification({ + title: "Cloud Settings", + body: "There are no settings in the cloud.", + noPersist: true + }); + return false; + } + + if (res.status === 304) { + logger.info("Settings up to date"); + if (shouldNotify) + showNotification({ + title: "Cloud Settings", + body: "Your settings are up to date.", + noPersist: true + }); + return false; + } + + if (!res.ok) { + logger.error(`Failed to sync down, API returned ${res.status}`); + showNotification({ + title: "Cloud Settings", + body: `Could not synchronize settings from the cloud (API returned ${res.status}).`, + color: "var(--red-360)" + }); + return false; + } + + const written = Number(res.headers.get("etag")!); + const localWritten = Settings.cloud.settingsSyncVersion; + + // don't need to check for written > localWritten because the server will return 304 due to if-none-match + if (!force && written < localWritten) { + if (shouldNotify) + showNotification({ + title: "Cloud Settings", + body: "Your local settings are newer than the cloud ones.", + noPersist: true, + }); + return; + } + + const data = await res.arrayBuffer(); + + const settings = new TextDecoder().decode(inflateSync(new Uint8Array(data))); + await importSettings(settings); + + // sync with server timestamp instead of local one + PlainSettings.cloud.settingsSyncVersion = written; + VencordNative.settings.set(PlainSettings); + + logger.info("Settings loaded from cloud successfully"); + if (shouldNotify) + showNotification({ + title: "Cloud Settings", + body: "Your settings have been updated! Click here to restart to fully apply changes!", + color: "var(--green-360)", + onClick: IS_WEB ? () => location.reload() : relaunch, + noPersist: true + }); + + return true; + } catch (e: any) { + logger.error("Failed to sync down", e); + showNotification({ + title: "Cloud Settings", + body: `Could not synchronize settings from the cloud (${e.toString()}).`, + color: "var(--red-360)" + }); + + return false; + } +} + +export async function deleteCloudSettings() { + try { + const res = await fetch(new URL("/v1/settings", getCloudUrl()), { + method: "DELETE", + headers: { Authorization: await getCloudAuth() }, + }); + + if (!res.ok) { + logger.error(`Failed to delete, API returned ${res.status}`); + showNotification({ + title: "Cloud Settings", + body: `Could not delete settings (API returned ${res.status}).`, + color: "var(--red-360)" + }); + return; + } + + logger.info("Settings deleted from cloud successfully"); + showNotification({ + title: "Cloud Settings", + body: "Settings deleted from cloud!", + color: "var(--green-360)" + }); + } catch (e: any) { + logger.error("Failed to delete", e); + showNotification({ + title: "Cloud Settings", + body: `Could not delete settings (${e.toString()}).`, + color: "var(--red-360)" + }); + } +} + +export async function eraseAllCloudData() { + const res = await fetch(new URL("/v1/", getCloudUrl()), { + method: "DELETE", + headers: { Authorization: await getCloudAuth() } + }); + + if (!res.ok) { + logger.error(`Failed to erase data, API returned ${res.status}`); + showNotification({ + title: "Cloud Integrations", + body: `Could not erase all data (API returned ${res.status}), please contact support.`, + color: "var(--red-360)" + }); + return; + } + + Settings.cloud.authenticated = false; + await deauthorizeCloud(); + + showNotification({ + title: "Cloud Integrations", + body: "Successfully erased all data.", + color: "var(--green-360)" + }); +} diff --git a/src/api/SettingsSync/offline.ts b/src/api/SettingsSync/offline.ts new file mode 100644 index 000000000..aced11e81 --- /dev/null +++ b/src/api/SettingsSync/offline.ts @@ -0,0 +1,95 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2025 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import { PlainSettings } from "@api/Settings"; +import { Logger } from "@utils/Logger"; +import { chooseFile, saveFile } from "@utils/web"; +import { moment, Toasts } from "@webpack/common"; + +const toast = (type: string, message: string) => + Toasts.show({ + type, + message, + id: Toasts.genId() + }); + +const toastSuccess = () => + toast(Toasts.Type.SUCCESS, "Settings successfully imported. Restart to apply changes!"); + +const toastFailure = (err: any) => + toast(Toasts.Type.FAILURE, `Failed to import settings: ${String(err)}`); + +const logger = new Logger("SettingsSync:Offline", "#39b7e0"); + +export async function importSettings(data: string) { + try { + var parsed = JSON.parse(data); + } catch (err) { + console.log(data); + throw new Error("Failed to parse JSON: " + String(err)); + } + + if ("settings" in parsed && "quickCss" in parsed) { + Object.assign(PlainSettings, parsed.settings); + await VencordNative.settings.set(parsed.settings); + await VencordNative.quickCss.set(parsed.quickCss); + } else + throw new Error("Invalid Settings. Is this even a Vencord Settings file?"); +} + +export async function exportSettings({ minify }: { minify?: boolean; } = {}) { + const settings = VencordNative.settings.get(); + const quickCss = await VencordNative.quickCss.get(); + return JSON.stringify({ settings, quickCss }, null, minify ? undefined : 4); +} + +export async function downloadSettingsBackup() { + const filename = `vencord-settings-backup-${moment().format("YYYY-MM-DD")}.json`; + const backup = await exportSettings(); + const data = new TextEncoder().encode(backup); + + if (IS_DISCORD_DESKTOP) { + DiscordNative.fileManager.saveWithDialog(data, filename); + } else { + saveFile(new File([data], filename, { type: "application/json" })); + } +} + +export async function uploadSettingsBackup(showToast = true): Promise { + if (IS_DISCORD_DESKTOP) { + const [file] = await DiscordNative.fileManager.openFiles({ + filters: [ + { name: "Vencord Settings Backup", extensions: ["json"] }, + { name: "all", extensions: ["*"] } + ] + }); + + if (file) { + try { + await importSettings(new TextDecoder().decode(file.data)); + if (showToast) toastSuccess(); + } catch (err) { + logger.error(err); + if (showToast) toastFailure(err); + } + } + } else { + const file = await chooseFile("application/json"); + if (!file) return; + + const reader = new FileReader(); + reader.onload = async () => { + try { + await importSettings(reader.result as string); + if (showToast) toastSuccess(); + } catch (err) { + logger.error(err); + if (showToast) toastFailure(err); + } + }; + reader.readAsText(file); + } +} diff --git a/src/api/Styles.ts b/src/api/Styles.ts index 6b0ac2cdf..fb40f72d8 100644 --- a/src/api/Styles.ts +++ b/src/api/Styles.ts @@ -16,9 +16,12 @@ * along with this program. If not, see . */ -import type { MapValue } from "type-fest/source/entry"; - -export type Style = MapValue; +export interface Style { + name: string; + source: string; + classNames: Record; + dom: HTMLStyleElement | null; +} export const styleMap = window.VencordStyles ??= new Map(); diff --git a/src/utils/quickCss.ts b/src/api/Themes.ts similarity index 88% rename from src/utils/quickCss.ts rename to src/api/Themes.ts index 82802c65b..525018531 100644 --- a/src/utils/quickCss.ts +++ b/src/api/Themes.ts @@ -17,9 +17,8 @@ */ import { Settings, SettingsStore } from "@api/Settings"; -import { ThemeStore } from "@webpack/common"; - -import { createAndAppendStyle } from "./css"; +import { createAndAppendStyle } from "@utils/css"; +import { ThemeStore } from "@vencord/discord-types"; let style: HTMLStyleElement; let themesStyle: HTMLStyleElement; @@ -54,14 +53,15 @@ async function initThemes() { const { enabledThemeLinks, enabledThemes } = Settings; - const enabledlinks: string[] = [...enabledThemeLinks]; + const { ThemeStore } = require("@webpack/common/stores") as typeof import("@webpack/common/stores"); + // "darker" and "midnight" both count as dark // This function is first called on DOMContentLoaded, so ThemeStore may not have been loaded yet const activeTheme = ThemeStore == null ? undefined : ThemeStore.theme === "light" ? "light" : "dark"; - const links = enabledlinks + const links = enabledThemeLinks .map(rawLink => { const match = /^@(light|dark) (.*)/.exec(rawLink); if (!match) return rawLink; @@ -103,16 +103,16 @@ document.addEventListener("DOMContentLoaded", () => { } }, { once: true }); -export function initQuickCssThemeStore() { +export function initQuickCssThemeStore(themeStore: ThemeStore) { if (IS_USERSCRIPT) return; initThemes(); - let currentTheme = ThemeStore.theme; - ThemeStore.addChangeListener(() => { - if (currentTheme === ThemeStore.theme) return; + let currentTheme = themeStore.theme; + themeStore.addChangeListener(() => { + if (currentTheme === themeStore.theme) return; - currentTheme = ThemeStore.theme; + currentTheme = themeStore.theme; initThemes(); }); } diff --git a/src/api/UserSettings.ts b/src/api/UserSettings.ts index 4de92a81a..9d68c1319 100644 --- a/src/api/UserSettings.ts +++ b/src/api/UserSettings.ts @@ -20,6 +20,8 @@ import { proxyLazy } from "@utils/lazy"; import { Logger } from "@utils/Logger"; import { findModuleId, proxyLazyWebpack, wreq } from "@webpack"; +import { isPluginEnabled } from "./PluginManager"; + interface UserSettingDefinition { /** * Get the setting value @@ -45,7 +47,7 @@ interface UserSettingDefinition { export const UserSettings: Record> | undefined = proxyLazyWebpack(() => { const modId = findModuleId('"textAndImages","renderSpoilers"'); - if (modId == null) return new Logger("UserSettingsAPI ").error("Didn't find settings module."); + if (modId == null) return new Logger("UserSettingsAPI").error("Didn't find settings module."); return wreq(modId as any); }); @@ -57,7 +59,7 @@ export const UserSettings: Record> | und * @param name The name of the setting */ export function getUserSetting(group: string, name: string): UserSettingDefinition | undefined { - if (!Vencord.Plugins.isPluginEnabled("UserSettingsAPI")) throw new Error("Cannot use UserSettingsAPI without setting as dependency."); + if (!isPluginEnabled("UserSettingsAPI")) throw new Error("Cannot use UserSettingsAPI without setting it as a dependency."); for (const key in UserSettings) { const userSetting = UserSettings[key]; diff --git a/src/api/index.ts b/src/api/index.ts index d3cb0ed38..2205b65fd 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -31,9 +31,11 @@ import * as $MessageUpdater from "./MessageUpdater"; import * as $NicknameIcons from "./NicknameIcons"; import * as $Notices from "./Notices"; import * as $Notifications from "./Notifications"; +export * as PluginManager from "./PluginManager"; import * as $ServerList from "./ServerList"; import * as $Settings from "./Settings"; import * as $Styles from "./Styles"; +import * as $Themes from "./Themes"; import * as $UserSettings from "./UserSettings"; /** @@ -137,6 +139,11 @@ export const MessageUpdater = $MessageUpdater; */ export const UserSettings = $UserSettings; +/** + * Don't use this + */ +export const Themes = $Themes; + /** * An API allowing you to add icons to the nickname, in profiles. */ diff --git a/src/components/Button.tsx b/src/components/Button.tsx index b3df68aba..b4390c232 100644 --- a/src/components/Button.tsx +++ b/src/components/Button.tsx @@ -12,6 +12,7 @@ import type { Button as DiscordButton } from "@vencord/discord-types"; import type { ComponentPropsWithRef } from "react"; import { OpenExternalIcon } from "./Icons"; +import { Link } from "./Link"; const btnCls = classNameFactory("vc-btn-"); const textBtnCls = classNameFactory("vc-text-btn-"); @@ -25,6 +26,11 @@ export type ButtonProps = ComponentPropsWithRef<"button"> & { size?: ButtonSize; }; +export type LinkButtonProps = ComponentPropsWithRef<"a"> & { + size?: ButtonSize; + variant?: ButtonVariant; +}; + export function Button({ variant = "primary", size = "medium", children, className, ...restProps }: ButtonProps) { return ( + + + + - - - You can import and export your Equicord settings as a JSON file. - This allows you to easily transfer your settings to another device, - or recover your settings after reinstalling Equicord or Discord. - - - Settings Export contains: -
    -
  • — Custom QuickCSS
  • -
  • — Theme Links
  • -
  • — Plugin Settings
  • -
  • — Plugin DataStores (e.g. Timezones or IRememberYou)
  • -
-
- - - - - - - + ); } diff --git a/src/components/settings/tabs/sync/CloudTab.tsx b/src/components/settings/tabs/sync/CloudTab.tsx index 046b609e9..a01cbee6a 100644 --- a/src/components/settings/tabs/sync/CloudTab.tsx +++ b/src/components/settings/tabs/sync/CloudTab.tsx @@ -16,8 +16,9 @@ * along with this program. If not, see . */ -import { showNotification } from "@api/Notifications"; -import { Settings, useSettings } from "@api/Settings"; +import { useSettings } from "@api/Settings"; +import { authorizeCloud, deauthorizeCloud } from "@api/SettingsSync/cloudSetup"; +import { deleteCloudSettings, eraseAllCloudData, getCloudSettings, putCloudSettings } from "@api/SettingsSync/cloudSync"; import { CheckedTextInput } from "@components/CheckedTextInput"; import { Divider } from "@components/Divider"; import { FormSwitch } from "@components/FormSwitch"; @@ -26,9 +27,7 @@ import { Heading } from "@components/Heading"; import { Link } from "@components/Link"; import { Paragraph } from "@components/Paragraph"; import { SettingsTab, wrapTab } from "@components/settings/tabs/BaseTab"; -import { authorizeCloud, cloudLogger, deauthorizeCloud, getCloudAuth, getCloudUrl } from "@utils/cloud"; import { Margins } from "@utils/margins"; -import { deleteCloudSettings, getCloudSettings, putCloudSettings } from "@utils/settingsSync"; import { Alerts, Button, Tooltip, useState } from "@webpack/common"; function validateUrl(url: string) { @@ -40,32 +39,6 @@ function validateUrl(url: string) { } } -async function eraseAllData() { - const res = await fetch(new URL("/v1/", getCloudUrl()), { - method: "DELETE", - headers: { Authorization: await getCloudAuth() } - }); - - if (!res.ok) { - cloudLogger.error(`Failed to erase data, API returned ${res.status}`); - showNotification({ - title: "Cloud Integrations", - body: `Could not erase all data (API returned ${res.status}), please contact support.`, - color: "var(--red-360)" - }); - return; - } - - Settings.cloud.authenticated = false; - await deauthorizeCloud(); - - showNotification({ - title: "Cloud Integrations", - body: "Successfully erased all data.", - color: "var(--green-360)" - }); -} - function SettingsSyncSection() { const { cloud } = useSettings(["cloud.authenticated", "cloud.settingsSync"]); const sectionEnabled = cloud.authenticated && cloud.settingsSync; @@ -196,7 +169,7 @@ function CloudTab() { onClick={() => Alerts.show({ title: "Are you sure?", body: "Once your data is erased, we cannot recover it. There's no going back!", - onConfirm: eraseAllData, + onConfirm: eraseAllCloudData, confirmText: "Erase it!", confirmColor: "vc-cloud-erase-data-danger-btn", cancelText: "Nevermind" diff --git a/src/components/settings/tabs/updater/Components.tsx b/src/components/settings/tabs/updater/Components.tsx index 935c24e46..8e3757c96 100644 --- a/src/components/settings/tabs/updater/Components.tsx +++ b/src/components/settings/tabs/updater/Components.tsx @@ -4,6 +4,7 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ +import { Card } from "@components/Card"; import { ErrorCard } from "@components/ErrorCard"; import { Flex } from "@components/Flex"; import { Link } from "@components/Link"; @@ -12,7 +13,7 @@ import { Margins } from "@utils/margins"; import { classes } from "@utils/misc"; import { relaunch } from "@utils/native"; import { changes, checkForUpdates, update, updateError } from "@utils/updater"; -import { Alerts, Button, Card, React, Toasts, useState } from "@webpack/common"; +import { Alerts, Button, React, Toasts, useState } from "@webpack/common"; import { runWithDispatch } from "./runWithDispatch"; @@ -31,7 +32,7 @@ export function HashLink({ repo, hash, disabled = false }: { repo: string, hash: export function Changes({ updates, repo, repoPending }: CommonProps & { updates: typeof changes; }) { return ( - + {updates.map(({ hash, author, message }) => (
!!( BadgeAPI.getDonorBadges(userId)?.length > 0 diff --git a/src/components/settings/tabs/vencord/index.tsx b/src/components/settings/tabs/vencord/index.tsx index 0c9afbde5..d339a6fa9 100644 --- a/src/components/settings/tabs/vencord/index.tsx +++ b/src/components/settings/tabs/vencord/index.tsx @@ -9,12 +9,12 @@ import "./VencordTab.css"; import { openNotificationLogModal } from "@api/Notifications/notificationLog"; import { useSettings } from "@api/Settings"; import { Divider } from "@components/Divider"; +import { Flex } from "@components/Flex"; import { FormSwitch } from "@components/FormSwitch"; import { Heading } from "@components/Heading"; import { FolderIcon, GithubIcon, LogIcon, PaintbrushIcon, RestartIcon } from "@components/Icons"; import { Paragraph } from "@components/Paragraph"; -import { openContributorModal, openPluginModal, SettingsTab, wrapTab } from "@components/settings"; -import { DonateButton, InviteButton } from "@components/settings/DonateButton"; +import { DonateButton, InviteButton, openContributorModal, openPluginModal, SettingsTab, wrapTab } from "@components/settings"; import { QuickAction, QuickActionCard } from "@components/settings/QuickAction"; import { SpecialCard } from "@components/settings/SpecialCard"; import { gitRemote } from "@shared/vencordUserAgent"; @@ -22,7 +22,7 @@ import { DONOR_ROLE_ID, GUILD_ID, VC_DONOR_ROLE_ID, VC_GUILD_ID } from "@utils/c import { Margins } from "@utils/margins"; import { identity, isAnyPluginDev } from "@utils/misc"; import { relaunch } from "@utils/native"; -import { Button, Flex, GuildMemberStore, React, Select, UserStore } from "@webpack/common"; +import { Button, GuildMemberStore, React, Select, UserStore } from "@webpack/common"; import BadgeAPI from "plugins/_api/badges"; import { openNotificationSettingsModal } from "./NotificationSettings"; diff --git a/src/debug/runReporter.ts b/src/debug/runReporter.ts index a7292013b..b61f9c742 100644 --- a/src/debug/runReporter.ts +++ b/src/debug/runReporter.ts @@ -4,12 +4,12 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ +import { addPatch } from "@api/PluginManager"; import { initWs } from "@plugins/devCompanion.dev/initWs"; import { Logger } from "@utils/Logger"; import * as Webpack from "@webpack"; -import { getBuildNumber, patchTimings } from "webpack/patchWebpack"; +import { getBuildNumber, patches, patchTimings } from "@webpack/patcher"; -import { addPatch, patches } from "../plugins"; import { loadLazyChunks } from "./loadLazyChunks"; import { reporterData } from "./reporterData"; diff --git a/src/equicordplugins/equicordToolbox/index.tsx b/src/equicordplugins/equicordToolbox/index.tsx index b7af3a2e5..42a3bd6d1 100644 --- a/src/equicordplugins/equicordToolbox/index.tsx +++ b/src/equicordplugins/equicordToolbox/index.tsx @@ -16,9 +16,10 @@ * along with this program. If not, see . */ -import "./style.css"; +import "./styles.css"; import { openNotificationLogModal } from "@api/Notifications/notificationLog"; +import { isPluginEnabled, plugins } from "@api/PluginManager"; import { migratePluginSettings, Settings, useSettings } from "@api/Settings"; import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; @@ -34,8 +35,8 @@ function VencordPopout(onClose: () => void) { const pluginEntries = [] as ReactNode[]; - for (const plugin of Object.values(Vencord.Plugins.plugins)) { - if (plugin.toolboxActions && Vencord.Plugins.isPluginEnabled(plugin.name)) { + for (const plugin of Object.values(plugins)) { + if (plugin.toolboxActions && isPluginEnabled(plugin.name)) { pluginEntries.push( . */ +import { isPluginEnabled } from "@api/PluginManager"; import { Settings } from "@api/Settings"; +import OpenInAppPlugin from "@plugins/openInApp"; import { findByProps, findByPropsLazy, proxyLazyWebpack } from "@webpack"; import { Flux, FluxDispatcher } from "@webpack/common"; @@ -89,7 +91,7 @@ export const SpotifyStore = proxyLazyWebpack(() => { public isSettingPosition = false; public openExternal(path: string) { - const url = Settings.plugins.MusicControls.useSpotifyUris || Vencord.Plugins.isPluginEnabled("OpenInApp") + const url = Settings.plugins.SpotifyControls.useSpotifyUris || isPluginEnabled(OpenInAppPlugin.name) ? "spotify:" + path.replaceAll("/", (_, idx) => idx === 0 ? "" : ":") : "https://open.spotify.com" + path; diff --git a/src/globals.d.ts b/src/globals.d.ts index db0e8172b..b4b127a45 100644 --- a/src/globals.d.ts +++ b/src/globals.d.ts @@ -16,6 +16,8 @@ * along with this program. If not, see . */ +import { Style } from "@api/Styles"; + declare global { /** * This exists only at build time, so references to it in patches should insert it @@ -47,12 +49,7 @@ declare global { export var VencordNative: typeof import("./VencordNative").default; export var Vencord: typeof import("./Vencord"); - export var VencordStyles: Map; - dom: HTMLStyleElement | null; - }>; + export var VencordStyles: Map; export var appSettings: { set(setting: string, v: any): void; }; diff --git a/src/plugins/_api/badges/index.tsx b/src/plugins/_api/badges/index.tsx index 871451d39..873bf6705 100644 --- a/src/plugins/_api/badges/index.tsx +++ b/src/plugins/_api/badges/index.tsx @@ -22,8 +22,9 @@ import { _getBadges, BadgePosition, BadgeUserArgs, ProfileBadge } from "@api/Bad import ErrorBoundary from "@components/ErrorBoundary"; import { openContributorModal } from "@components/settings/tabs"; import { Devs } from "@utils/constants"; +import { copyWithToast } from "@utils/discord"; import { Logger } from "@utils/Logger"; -import { copyWithToast, shouldShowContributorBadge, shouldShowEquicordContributorBadge } from "@utils/misc"; +import { shouldShowContributorBadge, shouldShowEquicordContributorBadge } from "@utils/misc"; import definePlugin from "@utils/types"; import { User } from "@vencord/discord-types"; import { ContextMenuApi, Menu, Toasts, UserStore } from "@webpack/common"; @@ -63,10 +64,11 @@ const UserPluginContributorBadge: ProfileBadge = { iconSrc: USERPLUGIN_CONTRIBUTOR_BADGE, position: BadgePosition.START, shouldShow: ({ userId }) => { + if (!IS_DEV) return false; const allPlugins = Object.values(Plugins); return allPlugins.some(p => { const pluginMeta = PluginMeta[p.name]; - return pluginMeta?.userPlugin && p.authors.some(a => a.id.toString() === userId) && IS_DEV; + return pluginMeta?.userPlugin && p.authors.some(a => a.id.toString() === userId); }); }, onClick: (_, { userId }) => openContributorModal(UserStore.getUser(userId)), diff --git a/src/plugins/_core/supportHelper.tsx b/src/plugins/_core/supportHelper.tsx index 0a30f49fe..b13cd7d8b 100644 --- a/src/plugins/_core/supportHelper.tsx +++ b/src/plugins/_core/supportHelper.tsx @@ -17,14 +17,16 @@ */ import { sendBotMessage } from "@api/Commands"; +import { isPluginEnabled } from "@api/PluginManager"; import { definePluginSettings } from "@api/Settings"; import { getUserSettingLazy } from "@api/UserSettings"; import { BaseText } from "@components/BaseText"; +import { Card } from "@components/Card"; import ErrorBoundary from "@components/ErrorBoundary"; import { Flex } from "@components/Flex"; import { Link } from "@components/Link"; import { Paragraph } from "@components/Paragraph"; -import { openUpdaterModal } from "@components/settings/tabs/updater"; +import { openUpdaterModal } from "@components/settings"; import { platformName } from "@equicordplugins/equicordHelper/utils"; import { gitHashShort } from "@shared/vencordUserAgent"; import { CONTRIB_ROLE_ID, Devs, DONOR_ROLE_ID, EQUIBOP_CONTRIB_ROLE_ID, EQUICORD_TEAM, GUILD_ID, SUPPORT_CHANNEL_ID, SUPPORT_CHANNEL_IDS, VC_CONTRIB_ROLE_ID, VC_DONOR_ROLE_ID, VC_GUILD_ID, VC_REGULAR_ROLE_ID, VC_SUPPORT_CHANNEL_IDS, VENCORD_CONTRIB_ROLE_ID } from "@utils/constants"; @@ -37,7 +39,7 @@ import { onlyOnce } from "@utils/onlyOnce"; import { makeCodeblock } from "@utils/text"; import definePlugin from "@utils/types"; import { checkForUpdates, isOutdated, update } from "@utils/updater"; -import { Alerts, Button, Card, ChannelStore, GuildMemberStore, Parser, PermissionsBits, PermissionStore, RelationshipStore, SelectedChannelStore, showToast, Toasts, UserStore } from "@webpack/common"; +import { Alerts, Button, ChannelStore, GuildMemberStore, Parser, PermissionsBits, PermissionStore, RelationshipStore, SelectedChannelStore, showToast, Toasts, UserStore } from "@webpack/common"; import { JSX } from "react"; import gitHash from "~git-hash"; @@ -137,7 +139,7 @@ function generatePluginList() { const isApiPlugin = (plugin: string) => plugin.endsWith("API") || plugins[plugin].required; const enabledPlugins = Object.keys(plugins) - .filter(p => Vencord.Plugins.isPluginEnabled(p) && !isApiPlugin(p)).sort(); + .filter(p => isPluginEnabled(p) && !isApiPlugin(p)); const enabledStockPlugins = enabledPlugins.filter(p => !PluginMeta[p].userPlugin); const enabledUserPlugins = enabledPlugins.filter(p => PluginMeta[p].userPlugin); @@ -408,8 +410,8 @@ export default definePlugin({ if (RelationshipStore.isFriend(userId) || isAnyPluginDev(UserStore.getCurrentUser()?.id)) return null; return ( - - Please do not private message plugin developers for support! + + Please do not private message Vencord plugin developers for support!
Instead, use the support channel: {Parser.parse("https://discord.com/channels/1173279886065029291/1297590739911573585")} {!ChannelStore.getChannel(SUPPORT_CHANNEL_ID) && " (Click the link to join)"} diff --git a/src/plugins/betterRoleDot/index.ts b/src/plugins/betterRoleDot/index.ts index 48c6b5b91..b6bc816fa 100644 --- a/src/plugins/betterRoleDot/index.ts +++ b/src/plugins/betterRoleDot/index.ts @@ -18,7 +18,7 @@ import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; -import { copyWithToast } from "@utils/misc"; +import { copyWithToast } from "@utils/discord"; import definePlugin, { OptionType } from "@utils/types"; const settings = definePluginSettings({ diff --git a/src/plugins/betterSessions/components/RenameButton.tsx b/src/plugins/betterSessions/components/RenameButton.tsx index 4fd81f1fb..b9857f01d 100644 --- a/src/plugins/betterSessions/components/RenameButton.tsx +++ b/src/plugins/betterSessions/components/RenameButton.tsx @@ -5,9 +5,9 @@ */ import { Button } from "@components/Button"; +import { SessionInfo } from "@plugins/betterSessions/types"; import { openModal } from "@utils/modal"; -import { SessionInfo } from "../types"; import { RenameModal } from "./RenameModal"; export function RenameButton({ session, state }: { session: SessionInfo["session"], state: [string, React.Dispatch>]; }) { diff --git a/src/plugins/betterSessions/components/RenameModal.tsx b/src/plugins/betterSessions/components/RenameModal.tsx index cd9a02d02..a2b15d447 100644 --- a/src/plugins/betterSessions/components/RenameModal.tsx +++ b/src/plugins/betterSessions/components/RenameModal.tsx @@ -16,14 +16,13 @@ * along with this program. If not, see . */ -import { Heading, HeadingTertiary } from "@components/Heading"; +import { Heading,HeadingTertiary } from "@components/Heading"; +import { SessionInfo } from "@plugins/betterSessions/types"; +import { getDefaultName, savedSessionsCache, saveSessionsToDataStore } from "@plugins/betterSessions/utils"; import { ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot } from "@utils/modal"; import { Button, React, TextInput } from "@webpack/common"; import { KeyboardEvent } from "react"; -import { SessionInfo } from "../types"; -import { getDefaultName, savedSessionsCache, saveSessionsToDataStore } from "../utils"; - export function RenameModal({ props, session, state }: { props: ModalProps, session: SessionInfo["session"], state: [string, React.Dispatch>]; }) { const [title, setTitle] = state; const [value, setValue] = React.useState(savedSessionsCache.get(session.id_hash)?.name ?? ""); diff --git a/src/plugins/betterSessions/utils.ts b/src/plugins/betterSessions/utils.ts index 3015dc47c..de9d70af2 100644 --- a/src/plugins/betterSessions/utils.ts +++ b/src/plugins/betterSessions/utils.ts @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import { DataStore } from "@api/index"; +import * as DataStore from "@api/DataStore"; import { UserStore } from "@webpack/common"; import { ChromeIcon, DiscordIcon, EdgeIcon, FirefoxIcon, IEIcon, MobileIcon, OperaIcon, SafariIcon, UnknownIcon } from "./components/icons"; diff --git a/src/plugins/betterSettings/PluginsSubmenu.tsx b/src/plugins/betterSettings/PluginsSubmenu.tsx index 8a3e5b2a0..14f835f99 100644 --- a/src/plugins/betterSettings/PluginsSubmenu.tsx +++ b/src/plugins/betterSettings/PluginsSubmenu.tsx @@ -4,6 +4,7 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ +import { isPluginEnabled } from "@api/PluginManager"; import { openPluginModal } from "@components/settings/tabs"; import { getIntlMessage } from "@utils/discord"; import { isObjectEmpty } from "@utils/misc"; @@ -28,7 +29,7 @@ export default function PluginsSubmenu() { const search = query.toLowerCase(); const include = (p: typeof Plugins[keyof typeof Plugins]) => ( - Vencord.Plugins.isPluginEnabled(p.name) + isPluginEnabled(p.name) && p.options && !isObjectEmpty(p.options) && ( p.name.toLowerCase().includes(search) diff --git a/src/plugins/clientTheme/components/Settings.tsx b/src/plugins/clientTheme/components/Settings.tsx index b2b9479f8..8298e2eed 100644 --- a/src/plugins/clientTheme/components/Settings.tsx +++ b/src/plugins/clientTheme/components/Settings.tsx @@ -6,15 +6,15 @@ import { classNameFactory } from "@api/Styles"; import { ErrorCard } from "@components/ErrorCard"; -import { HeadingPrimary, HeadingSecondary } from "@components/Heading"; +import { HeadingPrimary,HeadingSecondary } from "@components/Heading"; import { Paragraph } from "@components/Paragraph"; +import { relativeLuminance } from "@plugins/clientTheme/utils/colorUtils"; +import { createOrUpdateThemeColorVars } from "@plugins/clientTheme/utils/styleUtils"; import { Margins } from "@utils/margins"; import { findByCodeLazy, findStoreLazy } from "@webpack"; import { Button, ColorPicker, ThemeStore, useStateFromStores } from "@webpack/common"; import { settings } from ".."; -import { relativeLuminance } from "../utils/colorUtils"; -import { createOrUpdateThemeColorVars } from "../utils/styleUtils"; const saveClientTheme = findByCodeLazy('type:"UNSYNCED_USER_SETTINGS_UPDATE', '"system"==='); const NitroThemeStore = findStoreLazy("ClientThemesBackgroundStore"); diff --git a/src/plugins/consoleShortcuts/index.ts b/src/plugins/consoleShortcuts/index.ts index 01a07bf57..9343294c4 100644 --- a/src/plugins/consoleShortcuts/index.ts +++ b/src/plugins/consoleShortcuts/index.ts @@ -170,7 +170,7 @@ function makeShortcuts() { openModal: { getter: () => ModalAPI.openModal }, openModalLazy: { getter: () => ModalAPI.openModalLazy }, - Stores: Webpack.fluxStores, + Stores: { getter: () => Object.fromEntries(Webpack.fluxStores) }, // e.g. "2024-05_desktop_visual_refresh", 0 setExperiment: (id: string, bucket: number) => { diff --git a/src/plugins/copyEmojiMarkdown/index.tsx b/src/plugins/copyEmojiMarkdown/index.tsx index 58e7303a3..e03197fec 100644 --- a/src/plugins/copyEmojiMarkdown/index.tsx +++ b/src/plugins/copyEmojiMarkdown/index.tsx @@ -6,7 +6,7 @@ import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; -import { copyWithToast } from "@utils/misc"; +import { copyWithToast } from "@utils/discord"; import definePlugin, { OptionType } from "@utils/types"; import { findByPropsLazy } from "@webpack"; import { Menu } from "@webpack/common"; diff --git a/src/plugins/copyFileContents/index.tsx b/src/plugins/copyFileContents/index.tsx index 28b5bb92d..5bb79515c 100644 --- a/src/plugins/copyFileContents/index.tsx +++ b/src/plugins/copyFileContents/index.tsx @@ -9,7 +9,7 @@ import "./style.css"; import ErrorBoundary from "@components/ErrorBoundary"; import { CopyIcon, NoEntrySignIcon } from "@components/Icons"; import { Devs } from "@utils/constants"; -import { copyWithToast } from "@utils/misc"; +import { copyWithToast } from "@utils/discord"; import definePlugin from "@utils/types"; import { Tooltip, useState } from "@webpack/common"; diff --git a/src/plugins/copyStickerLinks/index.tsx b/src/plugins/copyStickerLinks/index.tsx index eaccc9b7c..635b8d313 100644 --- a/src/plugins/copyStickerLinks/index.tsx +++ b/src/plugins/copyStickerLinks/index.tsx @@ -17,12 +17,13 @@ */ import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/ContextMenu"; +import { isPluginEnabled } from "@api/PluginManager"; +import ExpressionClonerPlugin from "@plugins/expressionCloner"; import { Devs } from "@utils/constants"; -import { copyWithToast } from "@utils/misc"; +import { copyWithToast } from "@utils/discord"; import definePlugin from "@utils/types"; import { Message, Sticker } from "@vencord/discord-types"; import { Menu, React, StickersStore } from "@webpack/common"; -import ExpressionClonerPlugin from "plugins/expressionCloner"; const StickerExt = [, "png", "png", "json", "gif"] as const; @@ -79,7 +80,7 @@ const expressionPickerPatch: NavContextMenuPatchCallback = (children, props: { t const sticker = StickersStore.getStickerById(id); if (sticker) { - children.push(buildMenuItem(sticker, Vencord.Plugins.isPluginEnabled(ExpressionClonerPlugin.name))); + children.push(buildMenuItem(sticker, isPluginEnabled(ExpressionClonerPlugin.name))); } }; diff --git a/src/plugins/customIdle/index.ts b/src/plugins/customIdle/index.ts index 032a285a4..60ebf6ba7 100644 --- a/src/plugins/customIdle/index.ts +++ b/src/plugins/customIdle/index.ts @@ -4,7 +4,7 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -import { Notices } from "@api/index"; +import { currentNotice, noticesQueue, popNotice, showNotice } from "@api/Notices"; import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin, { makeRange, OptionType } from "@utils/types"; @@ -62,12 +62,12 @@ export default definePlugin({ const backOnlineMessage = "Welcome back! Click the button to go online. Click the X to stay idle until reload."; if ( - Notices.currentNotice?.[1] === backOnlineMessage || - Notices.noticesQueue.some(([, noticeMessage]) => noticeMessage === backOnlineMessage) + currentNotice?.[1] === backOnlineMessage || + noticesQueue.some(([, noticeMessage]) => noticeMessage === backOnlineMessage) ) return; - Notices.showNotice(backOnlineMessage, "Exit idle", () => { - Notices.popNotice(); + showNotice(backOnlineMessage, "Exit idle", () => { + popNotice(); FluxDispatcher.dispatch({ type: "IDLE", idle: false diff --git a/src/plugins/customRPC/RpcSettings.tsx b/src/plugins/customRPC/RpcSettings.tsx index 637d049e3..019cc431b 100644 --- a/src/plugins/customRPC/RpcSettings.tsx +++ b/src/plugins/customRPC/RpcSettings.tsx @@ -6,6 +6,7 @@ import "./settings.css"; +import { isPluginEnabled } from "@api/PluginManager"; import { classNameFactory } from "@api/Styles"; import { Divider } from "@components/Divider"; import { Heading } from "@components/Heading"; @@ -14,7 +15,7 @@ import { debounce } from "@shared/debounce"; import { ActivityType } from "@vencord/discord-types/enums"; import { Select, Text, TextInput, useState } from "@webpack/common"; -import { setRpc, settings, TimestampMode } from "."; +import CustomRPCPlugin, { setRpc, settings, TimestampMode } from "."; const cl = classNameFactory("vc-customRPC-settings-"); @@ -50,7 +51,7 @@ function isAppIdValid(value: string) { const updateRPC = debounce(() => { setRpc(true); - if (Vencord.Plugins.isPluginEnabled("CustomRPC")) setRpc(); + if (isPluginEnabled(CustomRPCPlugin.name)) setRpc(); }); function isStreamLinkDisabled() { diff --git a/src/plugins/decor/lib/stores/AuthorizationStore.tsx b/src/plugins/decor/lib/stores/AuthorizationStore.tsx index 7f3468fd0..a2e85a5de 100644 --- a/src/plugins/decor/lib/stores/AuthorizationStore.tsx +++ b/src/plugins/decor/lib/stores/AuthorizationStore.tsx @@ -4,14 +4,13 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -import { DataStore } from "@api/index"; +import * as DataStore from "@api/DataStore"; +import { AUTHORIZE_URL, CLIENT_ID } from "@plugins/decor/lib/constants"; import { proxyLazy } from "@utils/lazy"; import { Logger } from "@utils/Logger"; import { openModal } from "@utils/modal"; import { OAuth2AuthorizeModal, showToast, Toasts, UserStore, zustandCreate, zustandPersist } from "@webpack/common"; -import { AUTHORIZE_URL, CLIENT_ID } from "../constants"; - interface AuthorizationState { token: string | null; tokens: Record; diff --git a/src/plugins/decor/lib/stores/CurrentUserDecorationsStore.ts b/src/plugins/decor/lib/stores/CurrentUserDecorationsStore.ts index e2bba6c0a..780301ed4 100644 --- a/src/plugins/decor/lib/stores/CurrentUserDecorationsStore.ts +++ b/src/plugins/decor/lib/stores/CurrentUserDecorationsStore.ts @@ -4,11 +4,11 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ +import { Decoration, deleteDecoration, getUserDecoration, getUserDecorations, NewDecoration, setUserDecoration } from "@plugins/decor/lib/api"; +import { decorationToAsset } from "@plugins/decor/lib/utils/decoration"; import { proxyLazy } from "@utils/lazy"; import { UserStore, zustandCreate } from "@webpack/common"; -import { Decoration, deleteDecoration, getUserDecoration, getUserDecorations, NewDecoration, setUserDecoration } from "../api"; -import { decorationToAsset } from "../utils/decoration"; import { useUsersDecorationsStore } from "./UsersDecorationsStore"; interface UserDecorationsState { diff --git a/src/plugins/decor/lib/stores/UsersDecorationsStore.ts b/src/plugins/decor/lib/stores/UsersDecorationsStore.ts index 588bbdf97..3adb9847e 100644 --- a/src/plugins/decor/lib/stores/UsersDecorationsStore.ts +++ b/src/plugins/decor/lib/stores/UsersDecorationsStore.ts @@ -4,15 +4,14 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ +import { AvatarDecoration } from "@plugins/decor"; +import { getUsersDecorations } from "@plugins/decor/lib/api"; +import { DECORATION_FETCH_COOLDOWN, SKU_ID } from "@plugins/decor/lib/constants"; import { debounce } from "@shared/debounce"; import { proxyLazy } from "@utils/lazy"; import { User } from "@vencord/discord-types"; import { useEffect, useState, zustandCreate } from "@webpack/common"; -import { AvatarDecoration } from "../../"; -import { getUsersDecorations } from "../api"; -import { DECORATION_FETCH_COOLDOWN, SKU_ID } from "../constants"; - interface UserDecorationData { asset: string | null; fetchedAt: Date; diff --git a/src/plugins/decor/lib/utils/decoration.ts b/src/plugins/decor/lib/utils/decoration.ts index 176507ef8..265e8f584 100644 --- a/src/plugins/decor/lib/utils/decoration.ts +++ b/src/plugins/decor/lib/utils/decoration.ts @@ -4,9 +4,9 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -import { AvatarDecoration } from "../../"; -import { Decoration } from "../api"; -import { SKU_ID } from "../constants"; +import { AvatarDecoration } from "@plugins/decor"; +import { Decoration } from "@plugins/decor/lib/api"; +import { SKU_ID } from "@plugins/decor/lib/constants"; export function decorationToAsset(decoration: Decoration) { return `${decoration.animated ? "a_" : ""}${decoration.hash}`; diff --git a/src/plugins/decor/settings.tsx b/src/plugins/decor/settings.tsx index 1c559eda3..568b7ab9a 100644 --- a/src/plugins/decor/settings.tsx +++ b/src/plugins/decor/settings.tsx @@ -13,13 +13,14 @@ import { closeAllModals } from "@utils/modal"; import { OptionType } from "@utils/types"; import { FluxDispatcher } from "@webpack/common"; +import DecorPlugin from "."; import DecorSection from "./ui/components/DecorSection"; export const settings = definePluginSettings({ changeDecoration: { type: OptionType.COMPONENT, component() { - if (!Vencord.Plugins.plugins.Decor.started) return + if (!DecorPlugin.started) return Enable Decor and restart your client to change your avatar decoration. ; diff --git a/src/plugins/decor/ui/components/DecorDecorationGridDecoration.tsx b/src/plugins/decor/ui/components/DecorDecorationGridDecoration.tsx index deaeef630..b5693a453 100644 --- a/src/plugins/decor/ui/components/DecorDecorationGridDecoration.tsx +++ b/src/plugins/decor/ui/components/DecorDecorationGridDecoration.tsx @@ -4,11 +4,11 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ +import { Decoration } from "@plugins/decor/lib/api"; +import { decorationToAvatarDecoration } from "@plugins/decor/lib/utils/decoration"; import { ContextMenuApi } from "@webpack/common"; import type { HTMLProps } from "react"; -import { Decoration } from "../../lib/api"; -import { decorationToAvatarDecoration } from "../../lib/utils/decoration"; import { DecorationGridDecoration } from "."; import DecorationContextMenu from "./DecorationContextMenu"; diff --git a/src/plugins/decor/ui/components/DecorSection.tsx b/src/plugins/decor/ui/components/DecorSection.tsx index 912652855..5fe6cba5a 100644 --- a/src/plugins/decor/ui/components/DecorSection.tsx +++ b/src/plugins/decor/ui/components/DecorSection.tsx @@ -6,14 +6,13 @@ import { Button } from "@components/Button"; import { Flex } from "@components/Flex"; +import { useAuthorizationStore } from "@plugins/decor/lib/stores/AuthorizationStore"; +import { useCurrentUserDecorationsStore } from "@plugins/decor/lib/stores/CurrentUserDecorationsStore"; +import { cl } from "@plugins/decor/ui"; +import { openChangeDecorationModal } from "@plugins/decor/ui/modals/ChangeDecorationModal"; import { findComponentByCodeLazy } from "@webpack"; import { useEffect } from "@webpack/common"; -import { useAuthorizationStore } from "../../lib/stores/AuthorizationStore"; -import { useCurrentUserDecorationsStore } from "../../lib/stores/CurrentUserDecorationsStore"; -import { cl } from "../"; -import { openChangeDecorationModal } from "../modals/ChangeDecorationModal"; - const CustomizationSection = findComponentByCodeLazy(".customizationSectionBackground"); export interface DecorSectionProps { diff --git a/src/plugins/decor/ui/components/DecorationContextMenu.tsx b/src/plugins/decor/ui/components/DecorationContextMenu.tsx index db3f00908..71b700448 100644 --- a/src/plugins/decor/ui/components/DecorationContextMenu.tsx +++ b/src/plugins/decor/ui/components/DecorationContextMenu.tsx @@ -5,13 +5,12 @@ */ import { CopyIcon, DeleteIcon } from "@components/Icons"; +import { Decoration } from "@plugins/decor/lib/api"; +import { useCurrentUserDecorationsStore } from "@plugins/decor/lib/stores/CurrentUserDecorationsStore"; +import { cl } from "@plugins/decor/ui"; import { copyToClipboard } from "@utils/clipboard"; import { Alerts, ContextMenuApi, Menu, UserStore } from "@webpack/common"; -import { Decoration } from "../../lib/api"; -import { useCurrentUserDecorationsStore } from "../../lib/stores/CurrentUserDecorationsStore"; -import { cl } from "../"; - export default function DecorationContextMenu({ decoration }: { decoration: Decoration; }) { const { delete: deleteDecoration } = useCurrentUserDecorationsStore(); diff --git a/src/plugins/decor/ui/components/Grid.tsx b/src/plugins/decor/ui/components/Grid.tsx index 62d7b4baa..a43d6868c 100644 --- a/src/plugins/decor/ui/components/Grid.tsx +++ b/src/plugins/decor/ui/components/Grid.tsx @@ -4,11 +4,10 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ +import { cl } from "@plugins/decor/ui"; import { React } from "@webpack/common"; import { JSX } from "react"; -import { cl } from "../"; - export interface GridProps { renderItem: (item: ItemT) => JSX.Element; getItemKey: (item: ItemT) => string; diff --git a/src/plugins/decor/ui/components/SectionedGridList.tsx b/src/plugins/decor/ui/components/SectionedGridList.tsx index b5dc792ee..4352faddc 100644 --- a/src/plugins/decor/ui/components/SectionedGridList.tsx +++ b/src/plugins/decor/ui/components/SectionedGridList.tsx @@ -4,12 +4,12 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ +import { cl } from "@plugins/decor/ui"; import { classes } from "@utils/misc"; import { findByPropsLazy } from "@webpack"; import { React } from "@webpack/common"; import { JSX } from "react"; -import { cl } from "../"; import Grid, { GridProps } from "./Grid"; const ScrollerClasses = findByPropsLazy("managedReactiveScroller"); diff --git a/src/plugins/decor/ui/components/index.ts b/src/plugins/decor/ui/components/index.ts index 8fe41fc92..71b9c6707 100644 --- a/src/plugins/decor/ui/components/index.ts +++ b/src/plugins/decor/ui/components/index.ts @@ -4,12 +4,11 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ +import { AvatarDecoration } from "@plugins/decor"; import { findComponentByCode, LazyComponentWebpack } from "@webpack"; import { React } from "@webpack/common"; import type { ComponentType, HTMLProps, PropsWithChildren } from "react"; -import { AvatarDecoration } from "../.."; - type DecorationGridItemComponent = ComponentType> & { onSelect: () => void, isSelected: boolean, diff --git a/src/plugins/decor/ui/modals/ChangeDecorationModal.tsx b/src/plugins/decor/ui/modals/ChangeDecorationModal.tsx index 0c572b860..9dc07afe3 100644 --- a/src/plugins/decor/ui/modals/ChangeDecorationModal.tsx +++ b/src/plugins/decor/ui/modals/ChangeDecorationModal.tsx @@ -10,26 +10,25 @@ import ErrorBoundary from "@components/ErrorBoundary"; import { Flex } from "@components/Flex"; import { Heading } from "@components/Heading"; import { Paragraph } from "@components/Paragraph"; -import { openInviteModal } from "@utils/discord"; +import { Decoration, getPresets, Preset } from "@plugins/decor/lib/api"; +import { GUILD_ID, INVITE_KEY } from "@plugins/decor/lib/constants"; +import { useAuthorizationStore } from "@plugins/decor/lib/stores/AuthorizationStore"; +import { useCurrentUserDecorationsStore } from "@plugins/decor/lib/stores/CurrentUserDecorationsStore"; +import { decorationToAvatarDecoration } from "@plugins/decor/lib/utils/decoration"; +import { settings } from "@plugins/decor/settings"; +import { cl, DecorationModalStyles, requireAvatarDecorationModal } from "@plugins/decor/ui"; +import { AvatarDecorationModalPreview } from "@plugins/decor/ui/components"; +import DecorationGridCreate from "@plugins/decor/ui/components/DecorationGridCreate"; +import DecorationGridNone from "@plugins/decor/ui/components/DecorationGridNone"; +import DecorDecorationGridDecoration from "@plugins/decor/ui/components/DecorDecorationGridDecoration"; +import SectionedGridList from "@plugins/decor/ui/components/SectionedGridList"; +import { copyWithToast, openInviteModal } from "@utils/discord"; import { Margins } from "@utils/margins"; -import { copyWithToast } from "@utils/misc"; import { closeAllModals, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal"; import { Queue } from "@utils/Queue"; import { User } from "@vencord/discord-types"; import { Alerts, Button, FluxDispatcher, Forms, GuildStore, NavigationRouter, Parser, Tooltip, useEffect, UserStore, UserSummaryItem, UserUtils, useState } from "@webpack/common"; -import { Decoration, getPresets, Preset } from "../../lib/api"; -import { GUILD_ID, INVITE_KEY } from "../../lib/constants"; -import { useAuthorizationStore } from "../../lib/stores/AuthorizationStore"; -import { useCurrentUserDecorationsStore } from "../../lib/stores/CurrentUserDecorationsStore"; -import { decorationToAvatarDecoration } from "../../lib/utils/decoration"; -import { settings } from "../../settings"; -import { cl, DecorationModalStyles, requireAvatarDecorationModal } from "../"; -import { AvatarDecorationModalPreview } from "../components"; -import DecorationGridCreate from "../components/DecorationGridCreate"; -import DecorationGridNone from "../components/DecorationGridNone"; -import DecorDecorationGridDecoration from "../components/DecorDecorationGridDecoration"; -import SectionedGridList from "../components/SectionedGridList"; import { openCreateDecorationModal } from "./CreateDecorationModal"; import { openGuidelinesModal } from "./GuidelinesModal"; diff --git a/src/plugins/decor/ui/modals/CreateDecorationModal.tsx b/src/plugins/decor/ui/modals/CreateDecorationModal.tsx index 8a7abede4..868e0ab61 100644 --- a/src/plugins/decor/ui/modals/CreateDecorationModal.tsx +++ b/src/plugins/decor/ui/modals/CreateDecorationModal.tsx @@ -9,17 +9,16 @@ import ErrorBoundary from "@components/ErrorBoundary"; import { Heading } from "@components/Heading"; import { Link } from "@components/Link"; import { Paragraph } from "@components/Paragraph"; +import { GUILD_ID, INVITE_KEY, RAW_SKU_ID } from "@plugins/decor/lib/constants"; +import { useCurrentUserDecorationsStore } from "@plugins/decor/lib/stores/CurrentUserDecorationsStore"; +import { cl, DecorationModalStyles, requireAvatarDecorationModal, requireCreateStickerModal } from "@plugins/decor/ui"; +import { AvatarDecorationModalPreview } from "@plugins/decor/ui/components"; import { openInviteModal } from "@utils/discord"; import { Margins } from "@utils/margins"; import { closeAllModals, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal"; import { filters, findComponentByCodeLazy, mapMangledModuleLazy } from "@webpack"; import { Button, FluxDispatcher, GuildStore, NavigationRouter, TextInput, useEffect, useMemo, UserStore, useState } from "@webpack/common"; -import { GUILD_ID, INVITE_KEY, RAW_SKU_ID } from "../../lib/constants"; -import { useCurrentUserDecorationsStore } from "../../lib/stores/CurrentUserDecorationsStore"; -import { cl, DecorationModalStyles, requireAvatarDecorationModal, requireCreateStickerModal } from "../"; -import { AvatarDecorationModalPreview } from "../components"; - const FileUpload = findComponentByCodeLazy(".fileUpload),"); const { HelpMessage, HelpMessageTypes } = mapMangledModuleLazy('POSITIVE="positive', { diff --git a/src/plugins/decor/ui/modals/GuidelinesModal.tsx b/src/plugins/decor/ui/modals/GuidelinesModal.tsx index ce4962b84..c40b3160b 100644 --- a/src/plugins/decor/ui/modals/GuidelinesModal.tsx +++ b/src/plugins/decor/ui/modals/GuidelinesModal.tsx @@ -8,11 +8,11 @@ import { BaseText } from "@components/BaseText"; import { Flex } from "@components/Flex"; import { Link } from "@components/Link"; import { Paragraph } from "@components/Paragraph"; +import { settings } from "@plugins/decor/settings"; +import { cl, DecorationModalStyles, requireAvatarDecorationModal } from "@plugins/decor/ui"; import { ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal"; import { Button } from "@webpack/common"; -import { settings } from "../../settings"; -import { cl, DecorationModalStyles, requireAvatarDecorationModal } from "../"; import { openCreateDecorationModal } from "./CreateDecorationModal"; function GuidelinesModal(props: ModalProps) { diff --git a/src/plugins/fakeNitro/index.tsx b/src/plugins/fakeNitro/index.tsx index 4eb3d6de7..5f1747433 100644 --- a/src/plugins/fakeNitro/index.tsx +++ b/src/plugins/fakeNitro/index.tsx @@ -19,8 +19,8 @@ import { addMessagePreEditListener, addMessagePreSendListener, removeMessagePreEditListener, removeMessagePreSendListener } from "@api/MessageEvents"; import { definePluginSettings } from "@api/Settings"; import { Paragraph } from "@components/Paragraph"; +import { ApngBlendOp, ApngDisposeOp, parseAPNG } from "@utils/apng"; import { Devs } from "@utils/constants"; -import { ApngBlendOp, ApngDisposeOp, importApngJs } from "@utils/dependencies"; import { getCurrentGuild, getEmojiURL } from "@utils/discord"; import { Logger } from "@utils/Logger"; import definePlugin, { OptionType, Patch } from "@utils/types"; @@ -711,9 +711,10 @@ export default definePlugin({ }, async sendAnimatedSticker(stickerLink: string, stickerId: string, channelId: string) { - const { parseURL } = importApngJs(); - const { frames, width, height } = await parseURL(stickerLink); + const { frames, width, height } = await fetch(stickerLink) + .then(res => res.arrayBuffer()) + .then(parseAPNG); const gif = GIFEncoder(); const resolution = settings.store.stickerSize; @@ -762,7 +763,7 @@ export default definePlugin({ gif.finish(); - const file = new File([gif.bytesView()], `${stickerId}.gif`, { type: "image/gif" }); + const file = new File([gif.bytesView() as Uint8Array], `${stickerId}.gif`, { type: "image/gif" }); UploadHandler.promptToUpload([file], ChannelStore.getChannel(channelId), DraftType.ChannelMessage); }, diff --git a/src/plugins/fakeProfileThemes/index.tsx b/src/plugins/fakeProfileThemes/index.tsx index 714dbaaf1..1eb885698 100644 --- a/src/plugins/fakeProfileThemes/index.tsx +++ b/src/plugins/fakeProfileThemes/index.tsx @@ -17,23 +17,24 @@ */ // This plugin is a port from Alyxia's Vendetta plugin -import "./style.css"; +import "./styles.css"; import { definePluginSettings } from "@api/Settings"; import { BaseText } from "@components/BaseText"; import { Divider } from "@components/Divider"; import ErrorBoundary from "@components/ErrorBoundary"; +import { Flex } from "@components/Flex"; import { HeadingSecondary } from "@components/Heading"; import { Paragraph } from "@components/Paragraph"; import { Devs } from "@utils/constants"; -import { fetchUserProfile } from "@utils/discord"; +import { copyWithToast, fetchUserProfile } from "@utils/discord"; import { Margins } from "@utils/margins"; -import { classes, copyWithToast } from "@utils/misc"; +import { classes } from "@utils/misc"; import { useAwaiter } from "@utils/react"; import definePlugin, { OptionType } from "@utils/types"; import { User, UserProfile } from "@vencord/discord-types"; import { findComponentByCodeLazy } from "@webpack"; -import { Button, ColorPicker, Flex, React, UserProfileStore, UserStore, useState } from "@webpack/common"; +import { Button, ColorPicker, Forms, React, UserProfileStore, UserStore, useState } from "@webpack/common"; import virtualMerge from "virtual-merge"; interface Colors { @@ -122,23 +123,19 @@ function SettingsAboutComponent() { After enabling this plugin, you will see custom colors in the profiles of other people using compatible plugins.{" "} -
- To set your own colors: +
+ + To set your own profile theme colors:
    -
  • - • use the color pickers below to choose your colors -
  • -
  • • click the "Copy 3y3" button
  • -
  • • paste the invisible text anywhere in your bio
  • -

+
  • — use the color pickers below to choose your colors
  • +
  • — click the "Copy 3y3" button
  • +
  • — paste the invisible text anywhere in your bio
  • + - Color pickers - + Color pickers + Copy 3y3 diff --git a/src/plugins/fakeProfileThemes/styles.css b/src/plugins/fakeProfileThemes/styles.css new file mode 100644 index 000000000..1c9bebf2d --- /dev/null +++ b/src/plugins/fakeProfileThemes/styles.css @@ -0,0 +1,3 @@ +.vc-fpt-preview * { + pointer-events: none; +} diff --git a/src/plugins/imageZoom/components/Magnifier.tsx b/src/plugins/imageZoom/components/Magnifier.tsx index d68f916ec..dbe196072 100644 --- a/src/plugins/imageZoom/components/Magnifier.tsx +++ b/src/plugins/imageZoom/components/Magnifier.tsx @@ -18,12 +18,11 @@ import { classNameFactory } from "@api/Styles"; import ErrorBoundary from "@components/ErrorBoundary"; +import { settings } from "@plugins/imageZoom"; +import { ELEMENT_ID } from "@plugins/imageZoom/constants"; +import { waitFor } from "@plugins/imageZoom/utils/waitFor"; import { FluxDispatcher, useLayoutEffect, useMemo, useRef, useState } from "@webpack/common"; -import { ELEMENT_ID } from "../constants"; -import { settings } from "../index"; -import { waitFor } from "../utils/waitFor"; - interface Vec2 { x: number, y: number; diff --git a/src/plugins/invisibleChat.desktop/index.tsx b/src/plugins/invisibleChat.desktop/index.tsx deleted file mode 100644 index e6ba63e45..000000000 --- a/src/plugins/invisibleChat.desktop/index.tsx +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Vencord, a modification for Discord's desktop app - * Copyright (c) 2023 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 { ChatBarButton, ChatBarButtonFactory } from "@api/ChatButtons"; -import { updateMessage } from "@api/MessageUpdater"; -import { definePluginSettings } from "@api/Settings"; -import ErrorBoundary from "@components/ErrorBoundary"; -import { Devs } from "@utils/constants"; -import { getStegCloak } from "@utils/dependencies"; -import definePlugin, { OptionType, ReporterTestable } from "@utils/types"; -import { Message } from "@vencord/discord-types"; -import { ChannelStore, Constants, RestAPI, Tooltip } from "@webpack/common"; - -import { buildDecModal } from "./components/DecryptionModal"; -import { buildEncModal } from "./components/EncryptionModal"; - -let steggo: any; - -function PopOverIcon() { - return ( - - - - - ); -} - - -function Indicator() { - return ( - - {({ onMouseEnter, onMouseLeave }) => ( - - )} - - - ); - -} - -const ChatBarIcon: ChatBarButtonFactory = ({ isMainChat }) => { - if (!isMainChat) return null; - - return ( - buildEncModal()} - buttonProps={{ - "aria-haspopup": "dialog", - }} - > - - - - - ); -}; - -const settings = definePluginSettings({ - savedPasswords: { - type: OptionType.STRING, - default: "password, Password", - description: "Saved Passwords (Seperated with a , )" - } -}); - -export default definePlugin({ - name: "InvisibleChat", - description: "Encrypt your Messages in a non-suspicious way!", - authors: [Devs.SammCheese], - dependencies: ["MessageUpdaterAPI"], - reporterTestable: ReporterTestable.Patches, - settings, - - patches: [ - { - // Indicator - find: ".SEND_FAILED,", - replacement: { - match: /let\{className:\i,message:\i[^}]*\}=(\i)/, - replace: "try {$1 && $self.INV_REGEX.test($1.message.content) ? $1.content.push($self.indicator()) : null } catch {};$&" - } - }, - ], - - EMBED_API_URL: "https://embed.sammcheese.net", - INV_REGEX: new RegExp(/( \u200c|\u200d |[\u2060-\u2064])[^\u200b]/), - URL_REGEX: new RegExp( - /(http(s)?:\/\/.)?(www\.)?[-a-zA-Z0-9@:%._+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_+.~#?&//=]*)/, - ), - async start() { - const { default: StegCloak } = await getStegCloak(); - steggo = new StegCloak(true, false); - }, - - renderMessagePopoverButton(message) { - return this.INV_REGEX.test(message?.content) - ? { - label: "Decrypt Message", - icon: this.popOverIcon, - message: message, - channel: ChannelStore.getChannel(message.channel_id), - onClick: async () => { - const res = await iteratePasswords(message); - - if (res) - this.buildEmbed(message, res); - else - buildDecModal({ message }); - } - } - : null; - }, - - renderChatBarButton: ChatBarIcon, - - colorCodeFromNumber(color: number): string { - return `#${[color >> 16, color >> 8, color] - .map(x => (x & 0xFF).toString(16)) - .join("")}`; - }, - - // Gets the Embed of a Link - async getEmbed(url: URL): Promise { - const { body } = await RestAPI.post({ - url: Constants.Endpoints.UNFURL_EMBED_URLS, - body: { - urls: [url] - } - }); - // The endpoint returns the color as a number, but Discord expects a string - body.embeds[0].color = this.colorCodeFromNumber(body.embeds[0].color); - return await body.embeds[0]; - }, - - async buildEmbed(message: any, revealed: string): Promise { - const urlCheck = revealed.match(this.URL_REGEX); - - message.embeds.push({ - type: "rich", - rawTitle: "Decrypted Message", - color: "#45f5f5", - rawDescription: revealed, - footer: { - text: "Made with ❤️ by c0dine and Sammy!", - }, - }); - - if (urlCheck?.length) { - const embed = await this.getEmbed(new URL(urlCheck[0])); - if (embed) - message.embeds.push(embed); - } - - updateMessage(message.channel_id, message.id, { embeds: message.embeds }); - }, - - popOverIcon: () => , - indicator: ErrorBoundary.wrap(Indicator, { noop: true }) -}); - -export function encrypt(secret: string, password: string, cover: string): string { - return steggo.hide(secret + "\u200b", password, cover); -} - -export function decrypt(encrypted: string, password: string, removeIndicator: boolean): string { - const decrypted = steggo.reveal(encrypted, password); - return removeIndicator ? decrypted.replace("\u200b", "") : decrypted; -} - -export function isCorrectPassword(result: string): boolean { - return result.endsWith("\u200b"); -} - -export async function iteratePasswords(message: Message): Promise { - const passwords = settings.store.savedPasswords.split(",").map(s => s.trim()); - - if (!message?.content || !passwords?.length) return false; - - let { content } = message; - - // we use an extra variable so we dont have to edit the message content directly - if (/^\W/.test(message.content)) content = `d ${message.content}d`; - - for (let i = 0; i < passwords.length; i++) { - const result = decrypt(content, passwords[i], false); - if (isCorrectPassword(result)) { - return result; - } - } - - return false; -} diff --git a/src/plugins/lastfmRichPresence/index.tsx b/src/plugins/lastfmRichPresence/index.tsx index 412195bb0..ef32139ba 100644 --- a/src/plugins/lastfmRichPresence/index.tsx +++ b/src/plugins/lastfmRichPresence/index.tsx @@ -22,7 +22,7 @@ import { Logger } from "@utils/Logger"; import definePlugin, { OptionType } from "@utils/types"; import { Activity, ActivityAssets, ActivityButton } from "@vencord/discord-types"; import { ActivityFlags, ActivityStatusDisplayType, ActivityType } from "@vencord/discord-types/enums"; -import { ApplicationAssetUtils, FluxDispatcher, PresenceStore } from "@webpack/common"; +import { ApplicationAssetUtils, AuthenticationStore, FluxDispatcher, PresenceStore } from "@webpack/common"; interface TrackData { name: string; @@ -251,13 +251,13 @@ export default definePlugin({ async getActivity(): Promise { if (settings.store.hideWithActivity) { - if (PresenceStore.getActivities().some(a => a.application_id !== DISCORD_APP_ID)) { + if (PresenceStore.getActivities(AuthenticationStore.getId()).some(a => a.application_id !== DISCORD_APP_ID)) { return null; } } if (settings.store.hideWithSpotify) { - if (PresenceStore.getActivities().some(a => a.type === ActivityType.LISTENING && a.application_id !== DISCORD_APP_ID)) { + if (PresenceStore.getActivities(AuthenticationStore.getId()).some(a => a.type === ActivityType.LISTENING && a.application_id !== DISCORD_APP_ID)) { // there is already music status because of Spotify or richerCider (probably more) return null; } diff --git a/src/plugins/messageClickActions/index.ts b/src/plugins/messageClickActions/index.ts index 7ccc36f61..6404bd6f3 100644 --- a/src/plugins/messageClickActions/index.ts +++ b/src/plugins/messageClickActions/index.ts @@ -16,13 +16,14 @@ * along with this program. If not, see . */ +import { isPluginEnabled } from "@api/PluginManager"; import { definePluginSettings } from "@api/Settings"; +import NoReplyMentionPlugin from "@plugins/noReplyMention"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; import { MessageFlags } from "@vencord/discord-types/enums"; import { findByPropsLazy } from "@webpack"; import { FluxDispatcher, MessageTypeSets, PermissionsBits, PermissionStore, UserStore, WindowStore } from "@webpack/common"; -import NoReplyMentionPlugin from "plugins/noReplyMention"; const MessageActions = findByPropsLazy("deleteMessage", "startEditMessage"); const EditStore = findByPropsLazy("isEditing", "isEditingAny"); @@ -76,10 +77,36 @@ export default definePlugin({ onMessageClick(msg, channel, event) { const isMe = msg.author.id === UserStore.getCurrentUser().id; + if (!isDeletePressed) { + if (event.detail < 2) return; + if (settings.store.requireModifier && !event.ctrlKey && !event.shiftKey) return; + if (channel.guild_id && !PermissionStore.can(PermissionsBits.SEND_MESSAGES, channel)) return; + if (msg.deleted === true) return; - if (isDeletePressed) { - if (!settings.store.enableDeleteOnClick || !(isMe || PermissionStore.can(PermissionsBits.MANAGE_MESSAGES, channel))) return; + if (isMe) { + if (!settings.store.enableDoubleClickToEdit || EditStore.isEditing(channel.id, msg.id) || msg.state !== "SENT") return; + MessageActions.startEditMessage(channel.id, msg.id, msg.content); + event.preventDefault(); + } else { + if (!settings.store.enableDoubleClickToReply) return; + + if (!MessageTypeSets.REPLYABLE.has(msg.type) || msg.hasFlag(MessageFlags.EPHEMERAL)) return; + + const isShiftPress = event.shiftKey && !settings.store.requireModifier; + const shouldMention = isPluginEnabled(NoReplyMentionPlugin.name) + ? NoReplyMentionPlugin.shouldMention(msg, isShiftPress) + : !isShiftPress; + + FluxDispatcher.dispatch({ + type: "CREATE_PENDING_REPLY", + channel, + message: msg, + shouldMention, + showMentionToggle: channel.guild_id !== null + }); + } + } else if (settings.store.enableDeleteOnClick && (isMe || PermissionStore.can(PermissionsBits.MANAGE_MESSAGES, channel))) { if (msg.deleted) { FluxDispatcher.dispatch({ type: "MESSAGE_DELETE", @@ -90,40 +117,7 @@ export default definePlugin({ } else { MessageActions.deleteMessage(channel.id, msg.id); } - event.preventDefault(); - return; - } - - if (event.detail !== 2) return; - if (settings.store.requireModifier && !event.ctrlKey && !event.shiftKey) return; - if (channel.guild_id && !PermissionStore.can(PermissionsBits.SEND_MESSAGES, channel)) return; - if (msg.deleted === true) return; - - if (isMe) { - if (!settings.store.enableDoubleClickToEdit || EditStore.isEditing(channel.id, msg.id) || msg.state !== "SENT") return; - - MessageActions.startEditMessage(channel.id, msg.id, msg.content); - event.preventDefault(); - return; - } else { - if (!settings.store.enableDoubleClickToReply) return; - if (!MessageTypeSets.REPLYABLE.has(msg.type) || msg.hasFlag(MessageFlags.EPHEMERAL)) return; - - const isShiftPress = event.shiftKey && !settings.store.requireModifier; - const shouldMention = Vencord.Plugins.isPluginEnabled(NoReplyMentionPlugin.name) - ? NoReplyMentionPlugin.shouldMention(msg, isShiftPress) - : !isShiftPress; - - FluxDispatcher.dispatch({ - type: "CREATE_PENDING_REPLY", - channel, - message: msg, - shouldMention, - showMentionToggle: channel.guild_id !== null - }); - event.preventDefault(); - return; } }, }); diff --git a/src/plugins/messageLogger/deleteStyleOverlay.css b/src/plugins/messageLogger/deleteStyleOverlay.css index 59e4ac666..3da3fa998 100644 --- a/src/plugins/messageLogger/deleteStyleOverlay.css +++ b/src/plugins/messageLogger/deleteStyleOverlay.css @@ -1,3 +1,3 @@ .messagelogger-deleted { - background-color: hsla(var(--red-430-hsl, 0 85% 61%) / 15%) !important; -} + background-color: hsl(var(--red-430-hsl, 0 85% 61%) / 15%) !important; +} \ No newline at end of file diff --git a/src/plugins/permissionsViewer/components/RolesAndUsersPermissions.tsx b/src/plugins/permissionsViewer/components/RolesAndUsersPermissions.tsx index b21d3df56..6e53a2629 100644 --- a/src/plugins/permissionsViewer/components/RolesAndUsersPermissions.tsx +++ b/src/plugins/permissionsViewer/components/RolesAndUsersPermissions.tsx @@ -20,6 +20,7 @@ import { BaseText } from "@components/BaseText"; import ErrorBoundary from "@components/ErrorBoundary"; import { Flex } from "@components/Flex"; import { InfoIcon, OwnerCrownIcon } from "@components/Icons"; +import { cl, getGuildPermissionSpecMap } from "@plugins/permissionsViewer/utils"; import { copyToClipboard } from "@utils/clipboard"; import { getIntlMessage, getUniqueUsername } from "@utils/discord"; import { ModalCloseButton, ModalContent, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal"; @@ -28,7 +29,6 @@ import { findByCodeLazy } from "@webpack"; import { ContextMenuApi, FluxDispatcher, GuildMemberStore, GuildRoleStore, i18n, Menu, PermissionsBits, ScrollerThin, Tooltip, useEffect, useMemo, UserStore, useState, useStateFromStores } from "@webpack/common"; import { settings } from ".."; -import { cl, getGuildPermissionSpecMap } from "../utils"; import { PermissionAllowedIcon, PermissionDefaultIcon, PermissionDeniedIcon } from "./icons"; export const enum PermissionType { diff --git a/src/plugins/permissionsViewer/components/UserPermissions.tsx b/src/plugins/permissionsViewer/components/UserPermissions.tsx index ac949b37b..ca868473b 100644 --- a/src/plugins/permissionsViewer/components/UserPermissions.tsx +++ b/src/plugins/permissionsViewer/components/UserPermissions.tsx @@ -19,6 +19,7 @@ import { BaseText } from "@components/BaseText"; import ErrorBoundary from "@components/ErrorBoundary"; import { HeadingTertiary } from "@components/Heading"; +import { cl, getGuildPermissionSpecMap, getSortedRolesForMember, sortUserRoles } from "@plugins/permissionsViewer/utils"; import { getIntlMessage } from "@utils/discord"; import { classes } from "@utils/misc"; import type { Guild, GuildMember } from "@vencord/discord-types"; @@ -26,7 +27,6 @@ import { filters, findBulk, proxyLazyWebpack } from "@webpack"; import { PermissionsBits, Tooltip, useMemo, UserStore } from "@webpack/common"; import { PermissionsSortOrder, settings } from ".."; -import { cl, getGuildPermissionSpecMap, getSortedRolesForMember, sortUserRoles } from "../utils"; import openRolesAndUsersPermissionsModal, { PermissionType, type RoleOrUserPermission } from "./RolesAndUsersPermissions"; interface UserPermission { diff --git a/src/plugins/pinDms/components/CreateCategoryModal.tsx b/src/plugins/pinDms/components/CreateCategoryModal.tsx index 5d4f05c50..1bda1e8a4 100644 --- a/src/plugins/pinDms/components/CreateCategoryModal.tsx +++ b/src/plugins/pinDms/components/CreateCategoryModal.tsx @@ -8,13 +8,12 @@ import { classNameFactory } from "@api/Styles"; import { BaseText } from "@components/BaseText"; import { Divider } from "@components/Divider"; import { Heading } from "@components/Heading"; +import { DEFAULT_COLOR, SWATCHES } from "@plugins/pinDms/constants"; +import { categoryLen, createCategory, getCategory } from "@plugins/pinDms/data"; import { ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, openModalLazy } from "@utils/modal"; import { extractAndLoadChunksLazy, findComponentByCodeLazy } from "@webpack"; import { Button, ColorPicker, TextInput, Toasts, useMemo, useState } from "@webpack/common"; -import { DEFAULT_COLOR, SWATCHES } from "../constants"; -import { categoryLen, createCategory, getCategory } from "../data"; - interface ColorPickerWithSwatchesProps { defaultColor: number; colors: number[]; diff --git a/src/plugins/pinDms/components/contextMenu.tsx b/src/plugins/pinDms/components/contextMenu.tsx index 6fc4e6743..5a2415241 100644 --- a/src/plugins/pinDms/components/contextMenu.tsx +++ b/src/plugins/pinDms/components/contextMenu.tsx @@ -5,10 +5,10 @@ */ import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/ContextMenu"; +import { PinOrder, settings } from "@plugins/pinDms"; +import { addChannelToCategory, canMoveChannelInDirection, currentUserCategories, isPinned, moveChannel, removeChannelFromCategory } from "@plugins/pinDms/data"; import { Menu } from "@webpack/common"; -import { addChannelToCategory, canMoveChannelInDirection, currentUserCategories, isPinned, moveChannel, removeChannelFromCategory } from "../data"; -import { PinOrder, settings } from "../index"; import { openCategoryModal } from "./CreateCategoryModal"; function createPinMenuItem(channelId: string) { diff --git a/src/plugins/pinDms/data.ts b/src/plugins/pinDms/data.ts index 187822999..7671b54f3 100644 --- a/src/plugins/pinDms/data.ts +++ b/src/plugins/pinDms/data.ts @@ -4,11 +4,10 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ +import { PinOrder, PrivateChannelSortStore, settings } from "@plugins/pinDms"; import { useForceUpdater } from "@utils/react"; import { UserStore } from "@webpack/common"; -import { PinOrder, PrivateChannelSortStore, settings } from "./index"; - export interface Category { id: string; name: string; diff --git a/src/plugins/platformIndicators/index.tsx b/src/plugins/platformIndicators/index.tsx index e3b253ef6..9d1541dbc 100644 --- a/src/plugins/platformIndicators/index.tsx +++ b/src/plugins/platformIndicators/index.tsx @@ -25,7 +25,7 @@ import { definePluginSettings, migratePluginSetting, Settings } from "@api/Setti import { Devs } from "@utils/constants"; import { classes } from "@utils/misc"; import definePlugin, { OptionType } from "@utils/types"; -import { User } from "@vencord/discord-types"; +import { DiscordPlatform, User } from "@vencord/discord-types"; import { filters, findStoreLazy, mapMangledModuleLazy } from "@webpack"; import { AuthenticationStore, PresenceStore, Tooltip, UserStore, useStateFromStores } from "@webpack/common"; @@ -84,7 +84,8 @@ const Icons = { mobile: Icon("M 187 0 L 813 0 C 916.277 0 1000 83.723 1000 187 L 1000 1313 C 1000 1416.277 916.277 1500 813 1500 L 187 1500 C 83.723 1500 0 1416.277 0 1313 L 0 187 C 0 83.723 83.723 0 187 0 Z M 125 1000 L 875 1000 L 875 250 L 125 250 Z M 500 1125 C 430.964 1125 375 1180.964 375 1250 C 375 1319.036 430.964 1375 500 1375 C 569.036 1375 625 1319.036 625 1250 C 625 1180.964 569.036 1125 500 1125 Z", { viewBox: "0 0 1000 1500", height: 17, width: 17 }), embedded: Icon("M3.06 20.4q-1.53 0-2.37-1.065T.06 16.74l1.26-9q.27-1.8 1.605-2.97T6.06 3.6h11.88q1.8 0 3.135 1.17t1.605 2.97l1.26 9q.21 1.53-.63 2.595T20.94 20.4q-.63 0-1.17-.225T18.78 19.5l-2.7-2.7H7.92l-2.7 2.7q-.45.45-.99.675t-1.17.225Zm14.94-7.2q.51 0 .855-.345T19.2 12q0-.51-.345-.855T18 10.8q-.51 0-.855.345T16.8 12q0 .51.345 .855T18 13.2Zm-2.4-3.6q.51 0 .855-.345T16.8 8.4q0-.51-.345-.855T15.6 7.2q-.51 0-.855.345T14.4 8.4q0 .51.345 .855T15.6 9.6ZM6.9 13.2h1.8v-2.1h2.1v-1.8h-2.1v-2.1h-1.8v2.1h-2.1v1.8h2.1v2.1Z", { viewBox: "0 0 24 24", height: 20, width: 20 }), suncord: Icon("M7 4a6 6 0 00-6 6v4a6 6 0 006 6h10a6 6 0 006-6v-4a6 6 0 00-6-6H7zm0 11a1 1 0 01-1-1v-1H5a1 1 0 010-2h1v-1a1 1 0 012 0v1h1a1 1 0 010 2H8v1a1 1 0 01-1 1zm10-4a1 1 0 100-2 1 1 0 000 2zm1 3a1 1 0 11-2 0 1 1 0 012 0zm0-2a1 1 0 102 0 1 1 0 00-2 0zm-3 1a1 1 0 110-2 1 1 0 010 2z", { viewBox: "0 0 24 24", height: 24, width: 24 }), - vencord: Icon("M14.8 2.7 9 3.1V47h3.3c1.7 0 6.2.3 10 .7l6.7.6V2l-4.2.2c-2.4.1-6.9.3-10 .5zm1.8 6.4c1 1.7-1.3 3.6-2.7 2.2C12.7 10.1 13.5 8 15 8c.5 0 1.2.5 1.6 1.1zM16 33c0 6-.4 10-1 10s-1-4-1-10 .4-10 1-10 1 4 1 10zm15-8v23.3l3.8-.7c2-.3 4.7-.6 6-.6H43V3h-2.2c-1.3 0-4-.3-6-.6L31 1.7V25z", { viewBox: "0 0 50 50" }), + newVencord: Icon("M14.8 2.7 9 3.1V47h3.3c1.7 0 6.2.3 10 .7l6.7.6V2l-4.2.2c-2.4.1-6.9.3-10 .5zm1.8 6.4c1 1.7-1.3 3.6-2.7 2.2C12.7 10.1 13.5 8 15 8c.5 0 1.2.5 1.6 1.1zM16 33c0 6-.4 10-1 10s-1-4-1-10 .4-10 1-10 1 4 1 10zm15-8v23.3l3.8-.7c2-.3 4.7-.6 6-.6H43V3h-2.2c-1.3 0-4-.3-6-.6L31 1.7V25z", { viewBox: "0 0 50 50" }), + oldVencord: Icon("M14.8 2.7 9 3.1V47h3.3c1.7 0 6.2.3 10 .7l6.7.6V2l-4.2.2c-2.4.1-6.9.3-10 .5zm1.8 6.4c1 1.7-1.3 3.6-2.7 2.2C12.7 10.1 13.5 8 15 8c.5 0 1.2.5 1.6 1.1zM16 33c0 6-.4 10-1 10s-1-4-1-10 .4-10 1-10 1 4 1 10zm15-8v23.3l3.8-.7c2-.3 4.7-.6 6-.6H43V3h-2.2c-1.3 0-4-.3-6-.6L31 1.7V25z", { viewBox: "0 0 50 50" }), }; type Platform = keyof typeof Icons; @@ -102,11 +103,27 @@ const PlatformIcon = ({ platform, status, small }: PlatformIconProps) => { : platform[0].toUpperCase() + platform.slice(1); let Icon = Icons[platform] ?? Icons.desktop; const { ConsoleIcon } = settings.store; - if (platform === "embedded" && ConsoleIcon === "vencord") { - Icon = Icons.vencord; + if (platform === "embedded" && ConsoleIcon === "oldVencord") { + Icon = Icons.oldVencord; } - if (platform === "embedded" && ConsoleIcon === "suncord") { - Icon = Icons.suncord; + if (platform === "embedded") { + switch (ConsoleIcon) { + case "equicord": + Icon = Icons.embedded; + break; + case "suncord": + Icon = Icons.suncord; + break; + case "newVencord": + Icon = Icons.newVencord; + break; + case "oldVencord": + Icon = Icons.oldVencord; + break; + default: + Icon = Icons.embedded; + break; + } } return ; @@ -149,15 +166,13 @@ const PlatformIndicator = ({ user, isProfile, isMessage, isMemberList }: Platfor if (user == null || (user.bot && !Settings.plugins.PlatformIndicators.showBots)) return null; useEnsureOwnStatus(user); - const status: Record | undefined = useStateFromStores([PresenceStore], () => PresenceStore.getState()?.clientStatuses?.[user.id]); - if (status == null) { - return null; - } + const status = useStateFromStores([PresenceStore], () => PresenceStore.getClientStatus(user.id)); + if (!status) return null; const icons = Array.from(Object.entries(status), ([platform, status]) => ( @@ -248,8 +263,12 @@ const settings = definePluginSettings({ value: "suncord", }, { - label: "Vencord", - value: "vencord", + label: "Old Vencord Icon", + value: "newVencord", + }, + { + label: "Old Vencord Icon", + value: "oldVencord", }, ], } diff --git a/src/plugins/quickReply/index.ts b/src/plugins/quickReply/index.ts index e3af46ee6..372a417ae 100644 --- a/src/plugins/quickReply/index.ts +++ b/src/plugins/quickReply/index.ts @@ -16,14 +16,15 @@ * along with this program. If not, see . */ +import { isPluginEnabled } from "@api/PluginManager"; import { definePluginSettings } from "@api/Settings"; +import NoBlockedMessagesPlugin from "@plugins/noBlockedMessages"; +import NoReplyMentionPlugin from "@plugins/noReplyMention"; import { Devs, IS_MAC } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; import { Message } from "@vencord/discord-types"; import { MessageFlags } from "@vencord/discord-types/enums"; import { ChannelStore, ComponentDispatch, FluxDispatcher as Dispatcher, MessageActions, MessageStore, MessageTypeSets, PermissionsBits, PermissionStore, RelationshipStore, SelectedChannelStore, UserStore } from "@webpack/common"; -import NoBlockedMessagesPlugin from "plugins/noBlockedMessages"; -import NoReplyMentionPlugin from "plugins/noReplyMention"; let currentlyReplyingId: string | null = null; let currentlyEditingId: string | null = null; @@ -134,7 +135,7 @@ function getNextMessage(isUp: boolean, isReply: boolean) { let messages: Message[] = MessageStore.getMessages(SelectedChannelStore.getChannelId())._array; const meId = UserStore.getCurrentUser().id; - const hasNoBlockedMessages = Vencord.Plugins.isPluginEnabled(NoBlockedMessagesPlugin.name); + const hasNoBlockedMessages = isPluginEnabled(NoBlockedMessagesPlugin.name); messages = messages.filter(m => { if (m.deleted) return false; @@ -170,7 +171,7 @@ function getNextMessage(isUp: boolean, isReply: boolean) { function shouldMention(message: Message) { switch (settings.store.shouldMention) { case MentionOptions.NO_REPLY_MENTION_PLUGIN: - if (!Vencord.Plugins.isPluginEnabled(NoReplyMentionPlugin.name)) return true; + if (!isPluginEnabled(NoReplyMentionPlugin.name)) return true; return NoReplyMentionPlugin.shouldMention(message, false); case MentionOptions.DISABLED: return false; diff --git a/src/plugins/relationshipNotifier/utils.ts b/src/plugins/relationshipNotifier/utils.ts index 78371f13d..206cb63c7 100644 --- a/src/plugins/relationshipNotifier/utils.ts +++ b/src/plugins/relationshipNotifier/utils.ts @@ -16,7 +16,8 @@ * along with this program. If not, see . */ -import { DataStore, Notices } from "@api/index"; +import * as DataStore from "@api/DataStore"; +import { popNotice, showNotice } from "@api/Notices"; import { showNotification } from "@api/Notifications"; import { getUniqueUsername, openUserProfile } from "@utils/discord"; import { FluxStore } from "@vencord/discord-types"; @@ -111,7 +112,7 @@ export async function syncAndRunChecks() { export function notify(text: string, icon?: string, onClick?: () => void) { if (settings.store.notices) - Notices.showNotice(text, "OK", () => Notices.popNotice()); + showNotice(text, "OK", () => popNotice()); showNotification({ title: "Relationship Notifier", diff --git a/src/plugins/replaceGoogleSearch/index.tsx b/src/plugins/replaceGoogleSearch/index.tsx index 6bce7d6d9..be96c819b 100644 --- a/src/plugins/replaceGoogleSearch/index.tsx +++ b/src/plugins/replaceGoogleSearch/index.tsx @@ -6,9 +6,10 @@ import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/ContextMenu"; import { definePluginSettings, migratePluginSettings } from "@api/Settings"; +import { Flex } from "@components/Flex"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; -import { Flex, Menu } from "@webpack/common"; +import { Menu } from "@webpack/common"; const DefaultEngines = { Google: "https://www.google.com/search?q=", @@ -93,7 +94,7 @@ function makeSearchItem(src: string) { key={key} id={key} label={ - + diff --git a/src/plugins/reviewDB/components/ReviewBadge.tsx b/src/plugins/reviewDB/components/ReviewBadge.tsx index 665b9bb09..dc2485594 100644 --- a/src/plugins/reviewDB/components/ReviewBadge.tsx +++ b/src/plugins/reviewDB/components/ReviewBadge.tsx @@ -16,12 +16,11 @@ * along with this program. If not, see . */ +import { Badge } from "@plugins/reviewDB/entities"; +import { cl } from "@plugins/reviewDB/utils"; import { MaskedLink, React, Tooltip } from "@webpack/common"; import { HTMLAttributes } from "react"; -import { Badge } from "../entities"; -import { cl } from "../utils"; - export default function ReviewBadge(badge: Badge & { onClick?(): void; }) { const Wrapper = badge.redirectURL ? MaskedLink diff --git a/src/plugins/reviewDB/components/ReviewComponent.tsx b/src/plugins/reviewDB/components/ReviewComponent.tsx index 3922cc7f3..effd5c4ee 100644 --- a/src/plugins/reviewDB/components/ReviewComponent.tsx +++ b/src/plugins/reviewDB/components/ReviewComponent.tsx @@ -16,17 +16,17 @@ * along with this program. If not, see . */ +import { Auth, getToken } from "@plugins/reviewDB/auth"; +import { Review, ReviewType } from "@plugins/reviewDB/entities"; +import { blockUser, deleteReview, reportReview, unblockUser } from "@plugins/reviewDB/reviewDbApi"; +import { settings } from "@plugins/reviewDB/settings"; +import { canBlockReviewAuthor, canDeleteReview, canReportReview, cl, showToast } from "@plugins/reviewDB/utils"; import { openUserProfile } from "@utils/discord"; import { classes } from "@utils/misc"; import { LazyComponent } from "@utils/react"; import { filters, findBulk } from "@webpack"; import { Alerts, Parser, Timestamp, useState } from "@webpack/common"; -import { Auth, getToken } from "../auth"; -import { Review, ReviewType } from "../entities"; -import { blockUser, deleteReview, reportReview, unblockUser } from "../reviewDbApi"; -import { settings } from "../settings"; -import { canBlockReviewAuthor, canDeleteReview, canReportReview, cl, showToast } from "../utils"; import { openBlockModal } from "./BlockedUserModal"; import { BlockButton, DeleteButton, ReportButton } from "./MessageButton"; import ReviewBadge from "./ReviewBadge"; diff --git a/src/plugins/reviewDB/components/ReviewModal.tsx b/src/plugins/reviewDB/components/ReviewModal.tsx index 30a419e6d..720113498 100644 --- a/src/plugins/reviewDB/components/ReviewModal.tsx +++ b/src/plugins/reviewDB/components/ReviewModal.tsx @@ -18,14 +18,14 @@ import { BaseText } from "@components/BaseText"; import ErrorBoundary from "@components/ErrorBoundary"; +import { Auth } from "@plugins/reviewDB/auth"; +import { ReviewType } from "@plugins/reviewDB/entities"; +import { Response, REVIEWS_PER_PAGE } from "@plugins/reviewDB/reviewDbApi"; +import { cl } from "@plugins/reviewDB/utils"; import { ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalRoot, ModalSize, openModal } from "@utils/modal"; import { useForceUpdater } from "@utils/react"; import { Paginator, useRef, useState } from "@webpack/common"; -import { Auth } from "../auth"; -import { ReviewType } from "../entities"; -import { Response, REVIEWS_PER_PAGE } from "../reviewDbApi"; -import { cl } from "../utils"; import ReviewComponent from "./ReviewComponent"; import ReviewsView, { ReviewsInputComponent } from "./ReviewsView"; diff --git a/src/plugins/reviewDB/components/ReviewsView.tsx b/src/plugins/reviewDB/components/ReviewsView.tsx index 9329c87b0..799fa9ba5 100644 --- a/src/plugins/reviewDB/components/ReviewsView.tsx +++ b/src/plugins/reviewDB/components/ReviewsView.tsx @@ -17,15 +17,15 @@ */ import { Paragraph } from "@components/Paragraph"; +import { Auth, authorize } from "@plugins/reviewDB/auth"; +import { Review, ReviewType } from "@plugins/reviewDB/entities"; +import { addReview, getReviews, Response, REVIEWS_PER_PAGE } from "@plugins/reviewDB/reviewDbApi"; +import { settings } from "@plugins/reviewDB/settings"; +import { cl, showToast } from "@plugins/reviewDB/utils"; import { useAwaiter, useForceUpdater } from "@utils/react"; import { findByCodeLazy, findByPropsLazy, findComponentByCodeLazy } from "@webpack"; import { React, RelationshipStore, useRef, UserStore } from "@webpack/common"; -import { Auth, authorize } from "../auth"; -import { Review, ReviewType } from "../entities"; -import { addReview, getReviews, Response, REVIEWS_PER_PAGE } from "../reviewDbApi"; -import { settings } from "../settings"; -import { cl, showToast } from "../utils"; import ReviewComponent from "./ReviewComponent"; const Transforms = findByPropsLazy("insertNodes", "textToText"); diff --git a/src/plugins/seeSummaries/index.tsx b/src/plugins/seeSummaries/index.tsx index a5af9bc44..faa642fc7 100644 --- a/src/plugins/seeSummaries/index.tsx +++ b/src/plugins/seeSummaries/index.tsx @@ -4,7 +4,7 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -import { DataStore } from "@api/index"; +import * as DataStore from "@api/DataStore"; import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; import { hasGuildFeature } from "@utils/discord"; diff --git a/src/plugins/shikiCodeblocks.desktop/api/shiki.ts b/src/plugins/shikiCodeblocks.desktop/api/shiki.ts index 91e179b72..8ca9662ed 100644 --- a/src/plugins/shikiCodeblocks.desktop/api/shiki.ts +++ b/src/plugins/shikiCodeblocks.desktop/api/shiki.ts @@ -16,12 +16,12 @@ * along with this program. If not, see . */ +import { dispatchTheme } from "@plugins/shikiCodeblocks.desktop/hooks/useTheme"; +import type { ShikiSpec } from "@plugins/shikiCodeblocks.desktop/types"; import { shikiOnigasmSrc, shikiWorkerSrc } from "@utils/dependencies"; import { WorkerClient } from "@vap/core/ipc"; import type { IShikiTheme, IThemedToken } from "@vap/shiki"; -import { dispatchTheme } from "../hooks/useTheme"; -import type { ShikiSpec } from "../types"; import { getGrammar, languages, loadLanguages, resolveLang } from "./languages"; import { themes } from "./themes"; diff --git a/src/plugins/shikiCodeblocks.desktop/components/ButtonRow.tsx b/src/plugins/shikiCodeblocks.desktop/components/ButtonRow.tsx index 408de1543..efbf947e6 100644 --- a/src/plugins/shikiCodeblocks.desktop/components/ButtonRow.tsx +++ b/src/plugins/shikiCodeblocks.desktop/components/ButtonRow.tsx @@ -16,7 +16,8 @@ * along with this program. If not, see . */ -import { cl } from "../utils/misc"; +import { cl } from "@plugins/shikiCodeblocks.desktop/utils/misc"; + import { CopyButton } from "./CopyButton"; export interface ButtonRowProps { diff --git a/src/plugins/shikiCodeblocks.desktop/components/Code.tsx b/src/plugins/shikiCodeblocks.desktop/components/Code.tsx index 2794234df..5c924f8e9 100644 --- a/src/plugins/shikiCodeblocks.desktop/components/Code.tsx +++ b/src/plugins/shikiCodeblocks.desktop/components/Code.tsx @@ -16,11 +16,11 @@ * along with this program. If not, see . */ +import { cl } from "@plugins/shikiCodeblocks.desktop/utils/misc"; import type { IThemedToken } from "@vap/shiki"; import { hljs } from "@webpack/common"; import { JSX } from "react"; -import { cl } from "../utils/misc"; import { ThemeBase } from "./Highlighter"; export interface CodeProps { diff --git a/src/plugins/shikiCodeblocks.desktop/components/CopyButton.tsx b/src/plugins/shikiCodeblocks.desktop/components/CopyButton.tsx index 153b3cddb..6ec811054 100644 --- a/src/plugins/shikiCodeblocks.desktop/components/CopyButton.tsx +++ b/src/plugins/shikiCodeblocks.desktop/components/CopyButton.tsx @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import { useCopyCooldown } from "../hooks/useCopyCooldown"; +import { useCopyCooldown } from "@plugins/shikiCodeblocks.desktop/hooks/useCopyCooldown"; export interface CopyButtonProps extends React.DetailedHTMLProps, HTMLButtonElement> { content: string; diff --git a/src/plugins/shikiCodeblocks.desktop/components/Header.tsx b/src/plugins/shikiCodeblocks.desktop/components/Header.tsx index 320dde973..7f2888c5a 100644 --- a/src/plugins/shikiCodeblocks.desktop/components/Header.tsx +++ b/src/plugins/shikiCodeblocks.desktop/components/Header.tsx @@ -16,9 +16,9 @@ * along with this program. If not, see . */ -import { Language } from "../api/languages"; -import { DeviconSetting } from "../types"; -import { cl } from "../utils/misc"; +import { Language } from "@plugins/shikiCodeblocks.desktop/api/languages"; +import { DeviconSetting } from "@plugins/shikiCodeblocks.desktop/types"; +import { cl } from "@plugins/shikiCodeblocks.desktop/utils/misc"; export interface HeaderProps { langName?: string; diff --git a/src/plugins/shikiCodeblocks.desktop/components/Highlighter.tsx b/src/plugins/shikiCodeblocks.desktop/components/Highlighter.tsx index b4682240c..8bacf0cb8 100644 --- a/src/plugins/shikiCodeblocks.desktop/components/Highlighter.tsx +++ b/src/plugins/shikiCodeblocks.desktop/components/Highlighter.tsx @@ -17,15 +17,15 @@ */ import ErrorBoundary from "@components/ErrorBoundary"; +import { resolveLang } from "@plugins/shikiCodeblocks.desktop/api/languages"; +import { shiki } from "@plugins/shikiCodeblocks.desktop/api/shiki"; +import { useShikiSettings } from "@plugins/shikiCodeblocks.desktop/hooks/useShikiSettings"; +import { useTheme } from "@plugins/shikiCodeblocks.desktop/hooks/useTheme"; +import { hex2Rgb } from "@plugins/shikiCodeblocks.desktop/utils/color"; +import { cl, shouldUseHljs } from "@plugins/shikiCodeblocks.desktop/utils/misc"; import { useAwaiter, useIntersection } from "@utils/react"; import { hljs, React } from "@webpack/common"; -import { resolveLang } from "../api/languages"; -import { shiki } from "../api/shiki"; -import { useShikiSettings } from "../hooks/useShikiSettings"; -import { useTheme } from "../hooks/useTheme"; -import { hex2Rgb } from "../utils/color"; -import { cl, shouldUseHljs } from "../utils/misc"; import { ButtonRow } from "./ButtonRow"; import { Code } from "./Code"; import { Header } from "./Header"; diff --git a/src/plugins/shikiCodeblocks.desktop/hooks/useShikiSettings.ts b/src/plugins/shikiCodeblocks.desktop/hooks/useShikiSettings.ts index 020d77dba..5413db0e6 100644 --- a/src/plugins/shikiCodeblocks.desktop/hooks/useShikiSettings.ts +++ b/src/plugins/shikiCodeblocks.desktop/hooks/useShikiSettings.ts @@ -16,11 +16,10 @@ * along with this program. If not, see . */ +import { shiki } from "@plugins/shikiCodeblocks.desktop/api/shiki"; +import { settings as pluginSettings, ShikiSettings } from "@plugins/shikiCodeblocks.desktop/settings"; import { React } from "@webpack/common"; -import { shiki } from "../api/shiki"; -import { settings as pluginSettings, ShikiSettings } from "../settings"; - export function useShikiSettings(settingKeys: F[]) { const settings = pluginSettings.use([...settingKeys, "customTheme", "theme"]); const [isLoading, setLoading] = React.useState(false); diff --git a/src/plugins/shikiCodeblocks.desktop/utils/misc.ts b/src/plugins/shikiCodeblocks.desktop/utils/misc.ts index 1319a2f24..ee782ec05 100644 --- a/src/plugins/shikiCodeblocks.desktop/utils/misc.ts +++ b/src/plugins/shikiCodeblocks.desktop/utils/misc.ts @@ -17,12 +17,11 @@ */ import { classNameFactory } from "@api/Styles"; +import { resolveLang } from "@plugins/shikiCodeblocks.desktop/api/languages"; +import { HighlighterProps } from "@plugins/shikiCodeblocks.desktop/components/Highlighter"; +import { HljsSetting } from "@plugins/shikiCodeblocks.desktop/types"; import { hljs } from "@webpack/common"; -import { resolveLang } from "../api/languages"; -import { HighlighterProps } from "../components/Highlighter"; -import { HljsSetting } from "../types"; - export const cl = classNameFactory("vc-shiki-"); export const shouldUseHljs = ({ diff --git a/src/plugins/showConnections/index.tsx b/src/plugins/showConnections/index.tsx index 03181a01b..6128b6046 100644 --- a/src/plugins/showConnections/index.tsx +++ b/src/plugins/showConnections/index.tsx @@ -18,17 +18,18 @@ import "./styles.css"; +import { isPluginEnabled } from "@api/PluginManager"; import { definePluginSettings } from "@api/Settings"; import ErrorBoundary from "@components/ErrorBoundary"; import { Flex } from "@components/Flex"; import { CopyIcon, LinkIcon } from "@components/Icons"; +import OpenInAppPlugin from "@plugins/openInApp"; import { Devs } from "@utils/constants"; -import { copyWithToast } from "@utils/misc"; +import { copyWithToast } from "@utils/discord"; import definePlugin, { OptionType } from "@utils/types"; import { ConnectedAccount, User } from "@vencord/discord-types"; import { findByCodeLazy, findByPropsLazy } from "@webpack"; import { Tooltip, UserProfileStore } from "@webpack/common"; -import OpenInAppPlugin from "plugins/openInApp"; import { VerifiedIcon } from "./VerifiedIcon"; @@ -133,7 +134,7 @@ function CompactConnectionComponent({ connection, theme }: { connection: Connect target="_blank" rel="noreferrer" onClick={e => { - if (Vencord.Plugins.isPluginEnabled("OpenInApp")) { + if (isPluginEnabled(OpenInAppPlugin.name)) { // handleLink will .preventDefault() if applicable OpenInAppPlugin.handleLink(e.currentTarget, e); } @@ -170,7 +171,7 @@ export default definePlugin({ { find: ".hasAvatarForGuild(null==", replacement: { - match: /currentUser:\i,guild:\i.{0,15}\}\)(?<=user:(\i),bio:null==(\i)\?.+?)/, + match: /currentUser:\i,guild:\i[^}]*?\}\)(?=])(?<=user:(\i),bio:null==(\i)\?.+?)/, replace: "$&,$self.profilePopoutComponent({ user: $1, displayProfile: $2 })" } } diff --git a/src/plugins/showHiddenChannels/components/HiddenChannelLockScreen.tsx b/src/plugins/showHiddenChannels/components/HiddenChannelLockScreen.tsx index 8402e6360..645682752 100644 --- a/src/plugins/showHiddenChannels/components/HiddenChannelLockScreen.tsx +++ b/src/plugins/showHiddenChannels/components/HiddenChannelLockScreen.tsx @@ -16,17 +16,19 @@ * along with this program. If not, see . */ +import { isPluginEnabled } from "@api/PluginManager"; import { Settings } from "@api/Settings"; import { BaseText } from "@components/BaseText"; import ErrorBoundary from "@components/ErrorBoundary"; +import PermissionsViewerPlugin from "@plugins/permissionsViewer"; +import openRolesAndUsersPermissionsModal, { PermissionType, RoleOrUserPermission } from "@plugins/permissionsViewer/components/RolesAndUsersPermissions"; +import { sortPermissionOverwrites } from "@plugins/permissionsViewer/utils"; import { classes } from "@utils/misc"; import { formatDuration } from "@utils/text"; import type { Channel } from "@vencord/discord-types"; import { findByPropsLazy, findComponentByCodeLazy } from "@webpack"; import { EmojiStore, FluxDispatcher, GuildMemberStore, GuildStore, Parser, PermissionsBits, PermissionStore, SnowflakeUtils, Timestamp, Tooltip, useEffect, useState } from "@webpack/common"; -import openRolesAndUsersPermissionsModal, { PermissionType, RoleOrUserPermission } from "../../permissionsViewer/components/RolesAndUsersPermissions"; -import { sortPermissionOverwrites } from "../../permissionsViewer/utils"; import { cl, settings } from ".."; const enum SortOrderTypes { @@ -287,7 +289,7 @@ function HiddenChannelLockScreen({ channel }: { channel: ExtendedChannel; }) { }
    - {Vencord.Plugins.isPluginEnabled("PermissionsViewer") && ( + {isPluginEnabled(PermissionsViewerPlugin.name) && ( {({ onMouseLeave, onMouseEnter }) => (
    - + diff --git a/src/plugins/voiceMessages/index.tsx b/src/plugins/voiceMessages/index.tsx index 73055ebe1..27421efc6 100644 --- a/src/plugins/voiceMessages/index.tsx +++ b/src/plugins/voiceMessages/index.tsx @@ -21,10 +21,12 @@ import "./styles.css"; import { NavContextMenuPatchCallback } from "@api/ContextMenu"; import { definePluginSettings } from "@api/Settings"; import { classNameFactory } from "@api/Styles"; +import { Card } from "@components/Card"; import { Heading } from "@components/Heading"; import { Microphone } from "@components/Icons"; import { Link } from "@components/Link"; import { Paragraph } from "@components/Paragraph"; +import { lastState as silentMessageEnabled } from "@plugins/silentMessageToggle"; import { Devs, EquicordDevs } from "@utils/constants"; import { Margins } from "@utils/margins"; import { ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, openModal } from "@utils/modal"; @@ -34,9 +36,8 @@ import { chooseFile } from "@utils/web"; import { CloudUpload } from "@vencord/discord-types"; import { CloudUploadPlatform } from "@vencord/discord-types/enums"; import { findByPropsLazy, findLazy, findStoreLazy } from "@webpack"; -import { Button, Card, Constants, FluxDispatcher, lodash, Menu, MessageActions, PermissionsBits, PermissionStore, RestAPI, SelectedChannelStore, showToast, SnowflakeUtils, Toasts, useEffect, useState } from "@webpack/common"; +import { Button, Constants, FluxDispatcher, Forms, lodash, Menu, MessageActions, PermissionsBits, PermissionStore, RestAPI, SelectedChannelStore, showToast, SnowflakeUtils, Toasts, useEffect, useState } from "@webpack/common"; -import { lastState as silentMessageEnabled } from "../silentMessageToggle"; import { VoiceRecorderDesktop } from "./components/DesktopRecorder"; import { VoicePreview } from "./components/VoicePreview"; import { VoiceRecorderWeb } from "./components/WebRecorder"; @@ -240,8 +241,8 @@ function Modal({ modalProps }: { modalProps: ModalProps; }) { )} {isUnsupportedFormat && ( - - Voice Messages have to be OggOpus to be playable on iOS. This file is {blob.type} so it will not be playable on iOS. + + Voice Messages have to be OggOpus to be playable on iOS. This file is {blob.type} so it will not be playable on iOS. To fix it, first convert it to OggOpus, for example using the convertio web converter diff --git a/src/utils/apng-canvas.js b/src/utils/apng-canvas.js deleted file mode 100644 index 62203a751..000000000 --- a/src/utils/apng-canvas.js +++ /dev/null @@ -1,1155 +0,0 @@ -/* eslint-disable */ - -/** - * apng-canvas v2.1.2 - * - * @copyright 2011-2019 David Mzareulyan - * @link https://github.com/davidmz/apng-canvas - * @license MIT - */ -!(function i(o, a, s) { - function u(n, t) { - if (!a[n]) { - if (!o[n]) { - var e = "function" == typeof require && require; - if (!t && e) return e(n, !0); - if (c) return c(n, !0); - throw new Error("Cannot find module '" + n + "'"); - } - var r = (a[n] = { exports: {} }); - o[n][0].call( - r.exports, - function (t) { - var e = o[n][1][t]; - return u(e || t); - }, - r, - r.exports, - i, - o, - a, - s - ); - } - return a[n].exports; - } - for ( - var c = "function" == typeof require && require, t = 0; - t < s.length; - t++ - ) - u(s[t]); - return u; -})( - { - 1: [ - function (Y, n, r) { - (function (G, q) { - var t, e; - (t = this), - (e = function () { - "use strict"; - function u(t) { - return "function" == typeof t; - } - var n = Array.isArray - ? Array.isArray - : function (t) { - return ( - "[object Array]" === - Object.prototype.toString.call(t) - ); - }, - r = 0, - e = void 0, - i = void 0, - a = function (t, e) { - (l[r] = t), - (l[r + 1] = e), - 2 === (r += 2) && (i ? i(d) : g()); - }; - var t = - "undefined" != typeof window - ? window - : void 0, - o = t || {}, - s = - o.MutationObserver || - o.WebKitMutationObserver, - c = - "undefined" == typeof self && - void 0 !== G && - "[object process]" === {}.toString.call(G), - f = - "undefined" != typeof Uint8ClampedArray && - "undefined" != typeof importScripts && - "undefined" != typeof MessageChannel; - function h() { - var t = setTimeout; - return function () { - return t(d, 1); - }; - } - var l = new Array(1e3); - function d() { - for (var t = 0; t < r; t += 2) { - (0, l[t])(l[t + 1]), - (l[t] = void 0), - (l[t + 1] = void 0); - } - r = 0; - } - var p, - v, - A, - m, - g = void 0; - function w(t, e) { - var n = this, - r = new this.constructor(b); - void 0 === r[_] && j(r); - var i = n._state; - if (i) { - var o = arguments[i - 1]; - a(function () { - return L(i, r, o, n._result); - }); - } else U(n, r, t, e); - return r; - } - function y(t) { - if ( - t && - "object" == typeof t && - t.constructor === this - ) - return t; - var e = new this(b); - return T(e, t), e; - } - g = c - ? function () { - return G.nextTick(d); - } - : s - ? ((v = 0), - (A = new s(d)), - (m = document.createTextNode("")), - A.observe(m, { characterData: !0 }), - function () { - m.data = v = ++v % 2; - }) - : f - ? (((p = new MessageChannel()).port1.onmessage = - d), - function () { - return p.port2.postMessage(0); - }) - : void 0 === t && "function" == typeof Y - ? (function () { - try { - var t = - Function("return this")().require( - "vertx" - ); - return void 0 !== - (e = - t.runOnLoop || t.runOnContext) - ? function () { - e(d); - } - : h(); - } catch (t) { - return h(); - } - })() - : h(); - var _ = Math.random().toString(36).substring(2); - function b() { } - var E = void 0, - P = 1, - x = 2; - function N(t, r, i) { - a(function (e) { - var n = !1, - t = (function (t, e, n, r) { - try { - t.call(e, n, r); - } catch (t) { - return t; - } - })( - i, - r, - function (t) { - n || - ((n = !0), - r !== t - ? T(e, t) - : O(e, t)); - }, - function (t) { - n || ((n = !0), R(e, t)); - }, - e._label - ); - !n && t && ((n = !0), R(e, t)); - }, t); - } - function C(t, e, n) { - e.constructor === t.constructor && - n === w && - e.constructor.resolve === y - ? (function (e, t) { - t._state === P - ? O(e, t._result) - : t._state === x - ? R(e, t._result) - : U( - t, - void 0, - function (t) { - return T(e, t); - }, - function (t) { - return R(e, t); - } - ); - })(t, e) - : void 0 === n - ? O(t, e) - : u(n) - ? N(t, e, n) - : O(t, e); - } - function T(e, t) { - if (e === t) - R( - e, - new TypeError( - "You cannot resolve a promise with itself" - ) - ); - else if ( - (function (t) { - var e = typeof t; - return ( - null !== t && - ("object" == e || "function" == e) - ); - })(t) - ) { - var n = void 0; - try { - n = t.then; - } catch (t) { - return void R(e, t); - } - C(e, t, n); - } else O(e, t); - } - function B(t) { - t._onerror && t._onerror(t._result), I(t); - } - function O(t, e) { - t._state === E && - ((t._result = e), - (t._state = P), - 0 !== t._subscribers.length && a(I, t)); - } - function R(t, e) { - t._state === E && - ((t._state = x), (t._result = e), a(B, t)); - } - function U(t, e, n, r) { - var i = t._subscribers, - o = i.length; - (t._onerror = null), - (i[o] = e), - (i[o + P] = n), - (i[o + x] = r), - 0 === o && t._state && a(I, t); - } - function I(t) { - var e = t._subscribers, - n = t._state; - if (0 !== e.length) { - for ( - var r = void 0, - i = void 0, - o = t._result, - a = 0; - a < e.length; - a += 3 - ) - (r = e[a]), - (i = e[a + n]), - r ? L(n, r, i, o) : i(o); - t._subscribers.length = 0; - } - } - function L(t, e, n, r) { - var i = u(n), - o = void 0, - a = void 0, - s = !0; - if (i) { - try { - o = n(r); - } catch (t) { - (s = !1), (a = t); - } - if (e === o) - return void R( - e, - new TypeError( - "A promises callback cannot return that same promise." - ) - ); - } else o = r; - e._state !== E || - (i && s - ? T(e, o) - : !1 === s - ? R(e, a) - : t === P - ? O(e, o) - : t === x && R(e, o)); - } - var D = 0; - function j(t) { - (t[_] = D++), - (t._state = void 0), - (t._result = void 0), - (t._subscribers = []); - } - var k = - ((F.prototype._enumerate = function (t) { - for ( - var e = 0; - this._state === E && e < t.length; - e++ - ) - this._eachEntry(t[e], e); - }), - (F.prototype._eachEntry = function (e, t) { - var n = this._instanceConstructor, - r = n.resolve; - if (r === y) { - var i = void 0, - o = void 0, - a = !1; - try { - i = e.then; - } catch (t) { - (a = !0), (o = t); - } - if (i === w && e._state !== E) - this._settledAt( - e._state, - t, - e._result - ); - else if ("function" != typeof i) - this._remaining--, - (this._result[t] = e); - else if (n === S) { - var s = new n(b); - a ? R(s, o) : C(s, e, i), - this._willSettleAt(s, t); - } else - this._willSettleAt( - new n(function (t) { - return t(e); - }), - t - ); - } else this._willSettleAt(r(e), t); - }), - (F.prototype._settledAt = function (t, e, n) { - var r = this.promise; - r._state === E && - (this._remaining--, - t === x - ? R(r, n) - : (this._result[e] = n)), - 0 === this._remaining && - O(r, this._result); - }), - (F.prototype._willSettleAt = function (t, e) { - var n = this; - U( - t, - void 0, - function (t) { - return n._settledAt(P, e, t); - }, - function (t) { - return n._settledAt(x, e, t); - } - ); - }), - F); - function F(t, e) { - (this._instanceConstructor = t), - (this.promise = new t(b)), - this.promise[_] || j(this.promise), - n(e) - ? ((this.length = e.length), - (this._remaining = e.length), - (this._result = new Array( - this.length - )), - 0 === this.length - ? O(this.promise, this._result) - : ((this.length = - this.length || 0), - this._enumerate(e), - 0 === this._remaining && - O( - this.promise, - this._result - ))) - : R( - this.promise, - new Error( - "Array Methods must be provided an Array" - ) - ); - } - var S = - ((M.prototype.catch = function (t) { - return this.then(null, t); - }), - (M.prototype.finally = function (e) { - var n = this.constructor; - return u(e) - ? this.then( - function (t) { - return n - .resolve(e()) - .then(function () { - return t; - }); - }, - function (t) { - return n - .resolve(e()) - .then(function () { - throw t; - }); - } - ) - : this.then(e, e); - }), - M); - function M(t) { - (this[_] = D++), - (this._result = this._state = void 0), - (this._subscribers = []), - b !== t && - ("function" != typeof t && - (function () { - throw new TypeError( - "You must pass a resolver function as the first argument to the promise constructor" - ); - })(), - this instanceof M - ? (function (e, t) { - try { - t( - function (t) { - T(e, t); - }, - function (t) { - R(e, t); - } - ); - } catch (t) { - R(e, t); - } - })(this, t) - : (function () { - throw new TypeError( - "Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function." - ); - })()); - } - return ( - (S.prototype.then = w), - (S.all = function (t) { - return new k(this, t).promise; - }), - (S.race = function (i) { - var o = this; - return n(i) - ? new o(function (t, e) { - for ( - var n = i.length, r = 0; - r < n; - r++ - ) - o.resolve(i[r]).then(t, e); - }) - : new o(function (t, e) { - return e( - new TypeError( - "You must pass an array to race." - ) - ); - }); - }), - (S.resolve = y), - (S.reject = function (t) { - var e = new this(b); - return R(e, t), e; - }), - (S._setScheduler = function (t) { - i = t; - }), - (S._setAsap = function (t) { - a = t; - }), - (S._asap = a), - (S.polyfill = function () { - var t = void 0; - if (void 0 !== q) t = q; - else if ("undefined" != typeof self) - t = self; - else - try { - t = Function("return this")(); - } catch (t) { - throw new Error( - "polyfill failed because global object is unavailable in this environment" - ); - } - var e = t.Promise; - if (e) { - var n = null; - try { - n = Object.prototype.toString.call( - e.resolve() - ); - } catch (t) { } - if ("[object Promise]" === n && !e.cast) - return; - } - t.Promise = S; - }), - (S.Promise = S) - ); - }), - "object" == typeof r && void 0 !== n - ? (n.exports = e()) - : "function" == typeof define && define.amd - ? define(e) - : (t.ES6Promise = e()); - }).call( - this, - Y("VCmEsw"), - module.exports - ); - }, - { VCmEsw: 2 }, - ], - 2: [ - function (t, e, n) { - var r = (e.exports = {}); - function i() { } - (r.nextTick = (function () { - var t = "undefined" != typeof window && window.setImmediate, - e = - "undefined" != typeof window && - window.postMessage && - window.addEventListener; - if (t) - return function (t) { - return window.setImmediate(t); - }; - if (e) { - var n = []; - return ( - window.addEventListener( - "message", - function (t) { - var e = t.source; - (e !== window && null !== e) || - "process-tick" !== t.data || - (t.stopPropagation(), - 0 < n.length && n.shift()()); - }, - !0 - ), - function (t) { - n.push(t), - window.postMessage("process-tick", "*"); - } - ); - } - return function (t) { - setTimeout(t, 0); - }; - })()), - (r.title = "browser"), - (r.browser = !0), - (r.env = {}), - (r.argv = []), - (r.on = i), - (r.addListener = i), - (r.once = i), - (r.off = i), - (r.removeListener = i), - (r.removeAllListeners = i), - (r.emit = i), - (r.binding = function (t) { - throw new Error("process.binding is not supported"); - }), - (r.cwd = function () { - return "/"; - }), - (r.chdir = function (t) { - throw new Error("process.chdir is not supported"); - }); - }, - {}, - ], - 3: [ - function (t, e, n) { - "use strict"; - e.exports = function () { - (this.width = 0), - (this.height = 0), - (this.numPlays = 0), - (this.playTime = 0), - (this.frames = []), - (this.play = function () { - s || - u || - (this.rewind(), - (s = !0), - requestAnimationFrame(e)); - }), - (this.rewind = function () { - (o = i = 0), (a = null), (u = s = !1); - }), - (this.addContext = function (t) { - if (0 < c.length) { - var e = c[0].getImageData( - 0, - 0, - this.width, - this.height - ); - t.putImageData(e, 0, 0); - } - c.push(t), (t._apng_animation = this); - }), - (this.removeContext = function (t) { - var e = c.indexOf(t); - -1 !== e && - (c.splice(e, 1), - 0 === c.length && this.rewind(), - "_apng_animation" in t && - delete t._apng_animation); - }), - (this.isPlayed = function () { - return s; - }), - (this.isFinished = function () { - return u; - }); - var r = this, - i = 0, - o = 0, - a = null, - s = !1, - u = !1, - c = [], - e = function (t) { - for (; s && i <= t;) n(t); - s && requestAnimationFrame(e); - }, - n = function (t) { - var e = o++ % r.frames.length, - n = r.frames[e]; - if ( - 0 == r.numPlays || - o / r.frames.length <= r.numPlays - ) { - for ( - 0 == e && - (c.forEach(function (t) { - t.clearRect( - 0, - 0, - r.width, - r.height - ); - }), - (a = null), - 2 == n.disposeOp && (n.disposeOp = 1)), - a && 1 == a.disposeOp - ? c.forEach(function (t) { - t.clearRect( - a.left, - a.top, - a.width, - a.height - ); - }) - : a && - 2 == a.disposeOp && - c.forEach(function (t) { - t.putImageData( - a.iData, - a.left, - a.top - ); - }), - (a = n).iData = null, - 2 == a.disposeOp && - (a.iData = c[0].getImageData( - n.left, - n.top, - n.width, - n.height - )), - 0 == n.blendOp && - c.forEach(function (t) { - t.clearRect( - n.left, - n.top, - n.width, - n.height - ); - }), - c.forEach(function (t) { - t.drawImage(n.img, n.left, n.top); - }), - 0 == i && (i = t); - t > i + r.playTime; - - ) - i += r.playTime; - i += n.delay; - } else u = !(s = !1); - }; - }; - }, - {}, - ], - 4: [ - function (t, e, n) { - "use strict"; - for (var a = new Uint32Array(256), r = 0; r < 256; r++) { - for (var i = r, o = 0; o < 8; o++) - i = 1 & i ? 3988292384 ^ (i >>> 1) : i >>> 1; - a[r] = i; - } - e.exports = function (t, e, n) { - for ( - var r = -1, - i = (e = e || 0), - o = e + (n = n || t.length - e); - i < o; - i++ - ) - r = (r >>> 8) ^ a[255 & (r ^ t[i])]; - return -1 ^ r; - }; - }, - {}, - ], - 5: [ - function (a, t, e) { - (function (t) { - "use strict"; - var e = a("./support-test"), - n = a("./parser"), - r = a("./loader"), - i = (t.APNG = {}); - (i.checkNativeFeatures = e.checkNativeFeatures), - (i.ifNeeded = e.ifNeeded), - (i.parseBuffer = function (t) { - return n(t); - }); - var o = {}; - (i.parseURL = function (t) { - return t in o || (o[t] = r(t).then(n)), o[t]; - }), - (i.animateContext = function (t, e) { - return i.parseURL(t).then(function (t) { - return t.addContext(e), t.play(), t; - }); - }), - (i.animateImage = function (s) { - return ( - s.setAttribute("data-is-apng", "progress"), - i.parseURL(s.src).then( - function (t) { - s.setAttribute("data-is-apng", "yes"); - var e = - document.createElement("canvas"); - (e.width = t.width), - (e.height = t.height), - Array.prototype.slice - .call(s.attributes) - .forEach(function (t) { - -1 == - [ - "alt", - "src", - "usemap", - "ismap", - "data-is-apng", - "width", - "height", - ].indexOf(t.nodeName) && - e.setAttributeNode( - t.cloneNode(!1) - ); - }), - e.setAttribute( - "data-apng-src", - s.src - ), - "" != s.alt && - e.appendChild( - document.createTextNode( - s.alt - ) - ); - var n = "", - r = "", - i = 0, - o = ""; - "" != s.style.width && - "auto" != s.style.width - ? (n = s.style.width) - : s.hasAttribute("width") && - (n = - s.getAttribute("width") + - "px"), - "" != s.style.height && - "auto" != s.style.height - ? (r = s.style.height) - : s.hasAttribute("height") && - (r = - s.getAttribute("height") + - "px"), - "" != n && - "" == r && - ((i = parseFloat(n)), - (o = n.match(/\D+$/)[0]), - (r = - Math.round( - (e.height * i) / e.width - ) + o)), - "" != r && - "" == n && - ((i = parseFloat(r)), - (o = r.match(/\D+$/)[0]), - (n = - Math.round( - (e.width * i) / e.height - ) + o)), - (e.style.width = n), - (e.style.height = r); - var a = s.parentNode; - a.insertBefore(e, s), - a.removeChild(s), - t.addContext(e.getContext("2d")), - t.play(); - }, - function () { - s.setAttribute("data-is-apng", "no"); - } - ) - ); - }), - (i.releaseCanvas = function (t) { - var e = t.getContext("2d"); - "_apng_animation" in e && - e._apng_animation.removeContext(e); - }); - }).call( - this, - module.exports - ); - }, - { "./loader": 6, "./parser": 7, "./support-test": 8 }, - ], - 6: [ - function (t, e, n) { - "use strict"; - var i = i || t("es6-promise").Promise; - e.exports = function (r) { - return new i(function (t, e) { - var n = new XMLHttpRequest(); - n.open("GET", r), - (n.responseType = "arraybuffer"), - (n.onload = function () { - 200 == this.status ? t(this.response) : e(this); - }), - n.send(); - }); - }; - }, - { "es6-promise": 1 }, - ], - 7: [ - function (t, e, n) { - "use strict"; - var r = r || t("es6-promise").Promise, - m = t("./animation"), - o = t("./crc32"), - g = new Uint8Array([137, 80, 78, 71, 13, 10, 26, 10]); - e.exports = function (t) { - var A = new Uint8Array(t); - return new r(function (t, e) { - for (var n = 0; n < g.length; n++) - if (g[n] != A[n]) - return void e( - "Not a PNG file (invalid file signature)" - ); - var r = !1; - if ( - (w(A, function (t) { - return "acTL" != t || !(r = !0); - }), - r) - ) { - var a = [], - s = [], - u = null, - c = null, - f = new m(); - if ( - (w(A, function (t, e, n, r) { - switch (t) { - case "IHDR": - (u = e.subarray(n + 8, n + 8 + r)), - (f.width = y(e, n + 8)), - (f.height = y(e, n + 12)); - break; - case "acTL": - f.numPlays = y(e, n + 8 + 4); - break; - case "fcTL": - c && f.frames.push(c), - ((c = {}).width = y( - e, - n + 8 + 4 - )), - (c.height = y(e, n + 8 + 8)), - (c.left = y(e, n + 8 + 12)), - (c.top = y(e, n + 8 + 16)); - var i = _(e, n + 8 + 20), - o = _(e, n + 8 + 22); - 0 == o && (o = 100), - (c.delay = (1e3 * i) / o), - c.delay <= 10 && - (c.delay = 100), - (f.playTime += c.delay), - (c.disposeOp = b( - e, - n + 8 + 24 - )), - (c.blendOp = b(e, n + 8 + 25)), - (c.dataParts = []); - break; - case "fdAT": - c && - c.dataParts.push( - e.subarray( - n + 8 + 4, - n + 8 + r - ) - ); - break; - case "IDAT": - c && - c.dataParts.push( - e.subarray(n + 8, n + 8 + r) - ); - break; - case "IEND": - s.push(E(e, n, 12 + r)); - break; - default: - a.push(E(e, n, 12 + r)); - } - }), - c && f.frames.push(c), - 0 != f.frames.length) - ) - for ( - var i = 0, - o = new Blob(a), - h = new Blob(s), - l = 0; - l < f.frames.length; - l++ - ) { - c = f.frames[l]; - var d = []; - d.push(g), - u.set(P(c.width), 0), - u.set(P(c.height), 4), - d.push(x("IHDR", u)), - d.push(o); - for (var p = 0; p < c.dataParts.length; p++) - d.push(x("IDAT", c.dataParts[p])); - d.push(h); - var v = URL.createObjectURL( - new Blob(d, { type: "image/png" }) - ); - delete c.dataParts, - (d = null), - (c.img = document.createElement("img")), - (c.img.onload = function () { - URL.revokeObjectURL(this.src), - ++i == f.frames.length && t(f); - }), - (c.img.onerror = function () { - e("Image creation error"); - }), - (c.img.src = v); - } - else e("Not an animated PNG"); - } else e("Not an animated PNG"); - }); - }; - var w = function (t, e) { - var n = 8; - do { - var r = y(t, n), - i = a(t, n + 4, 4), - o = e(i, t, n, r); - n += 12 + r; - } while (!1 !== o && "IEND" != i && n < t.length); - }, - y = function (t, e) { - var n = 0; - n += (t[0 + e] << 24) >>> 0; - for (var r = 1; r < 4; r++) - n += t[r + e] << (8 * (3 - r)); - return n; - }, - _ = function (t, e) { - for (var n = 0, r = 0; r < 2; r++) - n += t[r + e] << (8 * (1 - r)); - return n; - }, - b = function (t, e) { - return t[e]; - }, - E = function (t, e, n) { - var r = new Uint8Array(n); - return r.set(t.subarray(e, e + n)), r; - }, - a = function (t, e, n) { - var r = Array.prototype.slice.call( - t.subarray(e, e + n) - ); - return String.fromCharCode.apply(String, r); - }, - P = function (t) { - return [ - (t >>> 24) & 255, - (t >>> 16) & 255, - (t >>> 8) & 255, - 255 & t, - ]; - }, - x = function (t, e) { - var n = t.length + e.length, - r = new Uint8Array(new ArrayBuffer(n + 8)); - r.set(P(e.length), 0), - r.set( - (function (t) { - for (var e = [], n = 0; n < t.length; n++) - e.push(t.charCodeAt(n)); - return e; - })(t), - 4 - ), - r.set(e, 8); - var i = o(r, 4, n); - return r.set(P(i), n + 4), r; - }; - }, - { "./animation": 3, "./crc32": 4, "es6-promise": 1 }, - ], - 8: [ - function (o, a, t) { - (function (t) { - "use strict"; - var e, - n, - r = r || o("es6-promise").Promise, - i = - ((e = function (e) { - var n = document.createElement("canvas"), - r = { - TypedArrays: "ArrayBuffer" in t, - BlobURLs: "URL" in t, - requestAnimationFrame: - "requestAnimationFrame" in t, - pageProtocol: - "http:" == location.protocol || - "https:" == location.protocol, - canvas: - "getContext" in - document.createElement("canvas"), - APNG: !1, - }; - if (r.canvas) { - var i = new Image(); - (i.onload = function () { - var t = n.getContext("2d"); - t.drawImage(i, 0, 0), - (r.APNG = - 0 === - t.getImageData(0, 0, 1, 1) - .data[3]), - e(r); - }), - (i.src = - "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACGFjVEwAAAABAAAAAcMq2TYAAAANSURBVAiZY2BgYPgPAAEEAQB9ssjfAAAAGmZjVEwAAAAAAAAAAQAAAAEAAAAAAAAAAAD6A+gBAbNU+2sAAAARZmRBVAAAAAEImWNgYGBgAAAABQAB6MzFdgAAAABJRU5ErkJggg=="); - } else e(r); - }), - (n = null), - function (t) { - return (n = n || new r(e)), t && n.then(t), n; - }); - a.exports = { - checkNativeFeatures: i, - ifNeeded: function (r) { - return ( - void 0 === r && (r = !1), - i().then(function (t) { - if (t.APNG && !r) reject(); - else { - var e = !0; - for (var n in t) - t.hasOwnProperty(n) && - "APNG" != n && - (e = e && t[n]); - } - }) - ); - }, - }; - }).call( - this, - module.exports - ); - }, - { "es6-promise": 1 }, - ], - }, - {}, - [5] -); diff --git a/src/utils/apng.ts b/src/utils/apng.ts new file mode 100644 index 000000000..de27910da --- /dev/null +++ b/src/utils/apng.ts @@ -0,0 +1,258 @@ +/* eslint-disable */ + +/** + * apng-canvas v2.1.2 - heavily modified and converted to Typescript + * + * @copyright 2011-2019 David Mzareulyan + * @link https://github.com/davidmz/apng-canvas + * @license MIT + */ + +// https://wiki.mozilla.org/APNG_Specification#.60fcTL.60:_The_Frame_Control_Chunk +export const enum ApngDisposeOp { + /** + * no disposal is done on this frame before rendering the next; the contents of the output buffer are left as is. + */ + NONE, + /** + * the frame's region of the output buffer is to be cleared to fully transparent black before rendering the next frame. + */ + BACKGROUND, + /** + * the frame's region of the output buffer is to be reverted to the previous contents before rendering the next frame. + */ + PREVIOUS +} + +// TODO: Might need to somehow implement this +export const enum ApngBlendOp { + SOURCE, + OVER +} + +interface Frame { + width: number; + height: number; + left: number; + top: number; + delay: number; + disposeOp: ApngDisposeOp; + blendOp: ApngBlendOp; + dataParts?: U8Arr[]; + img: HTMLImageElement; +} + +class Animation { + width = 0; + height = 0; + numPlays = 0; + playTime = 0; + frames: Frame[] = []; +} + +// Typescript has become more strict, requiring you to explicitly specify the ArrayBuffer generic +type U8Arr = Uint8Array; + +const table = new Uint32Array(256); + +for (let i = 0; i < 256; i++) { + let c = i; + for (let k = 0; k < 8; k++) c = (c & 1) ? 0xEDB88320 ^ (c >>> 1) : c >>> 1; + table[i] = c; +} + +function crc32(bytes: U8Arr, start: number = 0, length?: number): number { + length = length ?? (bytes.length - start); + let crc = -1; + for (let i = start, l = start + length; i < l; i++) { + crc = (crc >>> 8) ^ table[(crc ^ bytes[i]) & 0xFF]; + } + return crc ^ (-1); +} + + +const PNG_SIGNATURE_BYTES = new Uint8Array([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]); + +export function parseAPNG(buffer: ArrayBuffer): Promise { + const bytes = new Uint8Array(buffer); + return new Promise(function (resolve, reject) { + + for (let i = 0; i < PNG_SIGNATURE_BYTES.length; i++) { + if (PNG_SIGNATURE_BYTES[i] != bytes[i]) { + reject("Not a PNG file (invalid file signature)"); + return; + } + } + + // fast animation test + let isAnimated = false; + parseChunks(bytes, function (type) { + if (type == "acTL") { + isAnimated = true; + return false; + } + return true; + }); + if (!isAnimated) { + reject("Not an animated PNG"); + return; + } + + const preDataParts: U8Arr[] = []; + const postDataParts: U8Arr[] = []; + let headerDataBytes: U8Arr | null = null; + let frame: Frame | null = null; + const anim = new Animation(); + + parseChunks(bytes, function (type, bytes, off, length) { + switch (type) { + case "IHDR": + headerDataBytes = bytes.subarray(off + 8, off + 8 + length); + anim.width = readDWord(bytes, off + 8); + anim.height = readDWord(bytes, off + 12); + break; + case "acTL": + anim.numPlays = readDWord(bytes, off + 8 + 4); + break; + case "fcTL": + if (frame) anim.frames.push(frame); + frame = {} as Frame; + frame.width = readDWord(bytes, off + 8 + 4); + frame.height = readDWord(bytes, off + 8 + 8); + frame.left = readDWord(bytes, off + 8 + 12); + frame.top = readDWord(bytes, off + 8 + 16); + let delayN = readWord(bytes, off + 8 + 20); + let delayD = readWord(bytes, off + 8 + 22); + if (delayD == 0) delayD = 100; + frame.delay = 1000 * delayN / delayD; + // see http://mxr.mozilla.org/mozilla/source/gfx/src/shared/gfxImageFrame.cpp#343 + if (frame.delay <= 10) frame.delay = 100; + anim.playTime += frame.delay; + frame.disposeOp = readByte(bytes, off + 8 + 24); + frame.blendOp = readByte(bytes, off + 8 + 25); + frame.dataParts = []; + break; + case "fdAT": + if (frame) frame.dataParts!.push(bytes.subarray(off + 8 + 4, off + 8 + length)); + break; + case "IDAT": + if (frame) frame.dataParts!.push(bytes.subarray(off + 8, off + 8 + length)); + break; + case "IEND": + postDataParts.push(subBuffer(bytes, off, 12 + length)); + break; + default: + preDataParts.push(subBuffer(bytes, off, 12 + length)); + } + }); + + if (frame) anim.frames.push(frame); + + if (anim.frames.length == 0) { + reject("Not an animated PNG"); + return; + } + + // creating images + let createdImages = 0; + const preBlob = new Blob(preDataParts); + const postBlob = new Blob(postDataParts); + for (let f = 0; f < anim.frames.length; f++) { + frame = anim.frames[f]; + + const bb: (U8Arr | Blob)[] = []; + bb.push(PNG_SIGNATURE_BYTES); + headerDataBytes!.set(makeDWordArray(frame.width), 0); + headerDataBytes!.set(makeDWordArray(frame.height), 4); + bb.push(makeChunkBytes("IHDR", headerDataBytes!)); + bb.push(preBlob); + for (let j = 0; j < frame.dataParts!.length; j++) { + bb.push(makeChunkBytes("IDAT", frame.dataParts![j])); + } + bb.push(postBlob); + const url = URL.createObjectURL(new Blob(bb, { "type": "image/png" })); + delete frame.dataParts; + + /** + * Using "createElement" instead of "new Image" because of bug in Chrome 27 + * https://code.google.com/p/chromium/issues/detail?id=238071 + * http://stackoverflow.com/questions/16377375/using-canvas-drawimage-in-chrome-extension-content-script/16378270 + */ + const img = frame.img = new Image(); + img.onload = function () { + URL.revokeObjectURL(img.src); + createdImages++; + if (createdImages == anim.frames.length) { + resolve(anim); + } + }; + img.onerror = function () { + reject("Image creation error"); + }; + img.src = url; + } + }); +} + +function parseChunks(bytes: U8Arr, callback: (type: string, bytes: U8Arr, off: number, length: number) => boolean | void): void { + let off = 8; + let res: boolean | void; + let type: string; + + do { + const length = readDWord(bytes, off); + type = readString(bytes, off + 4, 4); + res = callback(type, bytes, off, length); + off += 12 + length; + } while (res !== false && type != "IEND" && off < bytes.length); +} + +function readDWord(bytes: U8Arr, off: number): number { + let x = 0; + // Force the most-significant byte to unsigned. + x += ((bytes[0 + off] << 24) >>> 0); + for (let i = 1; i < 4; i++) x += ((bytes[i + off] << ((3 - i) * 8))); + return x; +} + +function readWord(bytes: U8Arr, off: number): number { + let x = 0; + for (let i = 0; i < 2; i++) x += (bytes[i + off] << ((1 - i) * 8)); + return x; +} + +function readByte(bytes: U8Arr, off: number): number { + return bytes[off]; +} + +function subBuffer(bytes: U8Arr, start: number, length: number): U8Arr { + const a = new Uint8Array(length); + a.set(bytes.subarray(start, start + length)); + return a; +} + +function readString(bytes: U8Arr, off: number, length: number): string { + const chars = Array.prototype.slice.call(bytes.subarray(off, off + length)); + return String.fromCharCode.apply(String, chars); +} + +function makeDWordArray(x: number): number[] { + return [(x >>> 24) & 0xff, (x >>> 16) & 0xff, (x >>> 8) & 0xff, x & 0xff]; +} + +function makeStringArray(x: string): number[] { + const res: number[] = []; + for (let i = 0; i < x.length; i++) res.push(x.charCodeAt(i)); + return res; +} + +function makeChunkBytes(type: string, dataBytes: U8Arr): U8Arr { + const crcLen = type.length + dataBytes.length; + const bytes = new Uint8Array(new ArrayBuffer(crcLen + 8)); + bytes.set(makeDWordArray(dataBytes.length), 0); + bytes.set(makeStringArray(type), 4); + bytes.set(dataBytes, 8); + const crc = crc32(bytes, 4, crcLen); + bytes.set(makeDWordArray(crc), crcLen + 4); + return bytes; +}; diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 8df382bbb..330de4326 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -50,6 +50,9 @@ const platform = navigator.platform.toLowerCase(); export const IS_WINDOWS = platform.startsWith("win"); export const IS_MAC = platform.startsWith("mac"); export const IS_LINUX = platform.startsWith("linux"); +// https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent#mobile_tablet_or_desktop +// "In summary, we recommend looking for the string Mobi anywhere in the User Agent to detect a mobile device." +export const IS_MOBILE = navigator.userAgent.includes("Mobi"); export interface Dev { name: string; diff --git a/src/utils/dependencies.ts b/src/utils/dependencies.ts index 0d73ee056..c2f61e5d2 100644 --- a/src/utils/dependencies.ts +++ b/src/utils/dependencies.ts @@ -21,54 +21,6 @@ import type LessStatic from "less"; import { makeLazy } from "./lazy"; -/* - Add dynamically loaded dependencies for plugins here. - */ - -// needed to parse APNGs in the nitroBypass plugin -export const importApngJs = makeLazy(() => { - return require("./apng-canvas").APNG as { parseURL(url: string): Promise; }; -}); - -// https://wiki.mozilla.org/APNG_Specification#.60fcTL.60:_The_Frame_Control_Chunk -export const enum ApngDisposeOp { - /** - * no disposal is done on this frame before rendering the next; the contents of the output buffer are left as is. - */ - NONE, - /** - * the frame's region of the output buffer is to be cleared to fully transparent black before rendering the next frame. - */ - BACKGROUND, - /** - * the frame's region of the output buffer is to be reverted to the previous contents before rendering the next frame. - */ - PREVIOUS -} - -// TODO: Might need to somehow implement this -export const enum ApngBlendOp { - SOURCE, - OVER -} -export interface ApngFrame { - left: number; - top: number; - width: number; - height: number; - img: HTMLImageElement; - delay: number; - blendOp: ApngBlendOp; - disposeOp: ApngDisposeOp; -} - -export interface ApngFrameData { - width: number; - height: number; - frames: ApngFrame[]; - playTime: number; -} - // The below code is only used on the Desktop (electron) build of Vencord. // Browser (extension) builds do not contain these remote imports. diff --git a/src/utils/discord.tsx b/src/utils/discord.tsx index 1242e03cf..08c9c3497 100644 --- a/src/utils/discord.tsx +++ b/src/utils/discord.tsx @@ -16,11 +16,12 @@ * along with this program. If not, see . */ -import { MessageObject } from "@api/MessageEvents"; -import { Channel, CloudUpload, Guild, GuildFeatures, Message, User } from "@vencord/discord-types"; -import { ChannelActionCreators, ChannelStore, ComponentDispatch, Constants, FluxDispatcher, GuildStore, i18n, IconUtils, InviteActions, MessageActions, RestAPI, SelectedChannelStore, SelectedGuildStore, UserProfileActions, UserProfileStore, UserSettingsActionCreators, UserUtils } from "@webpack/common"; +import type { MessageObject } from "@api/MessageEvents"; +import type { Channel, CloudUpload, Guild, GuildFeatures, Message, User } from "@vencord/discord-types"; +import { ChannelActionCreators, ChannelStore, ComponentDispatch, Constants, FluxDispatcher, GuildStore, i18n, IconUtils, InviteActions, MessageActions, RestAPI, SelectedChannelStore, SelectedGuildStore, Toasts, UserProfileActions, UserProfileStore, UserSettingsActionCreators, UserUtils } from "@webpack/common"; import { Except } from "type-fest"; +import { copyToClipboard } from "./clipboard"; import { runtimeHashMessageKey, runtimeHashMessageKeyLegacy } from "./intlHash"; import { Logger } from "./Logger"; import { MediaModalItem, MediaModalProps, openMediaModal } from "./modal"; @@ -116,6 +117,15 @@ export function insertTextIntoChatInputBox(text: string) { }); } +export async function copyWithToast(text: string, toastMessage = "Copied to clipboard!") { + await copyToClipboard(text); + Toasts.show({ + message: toastMessage, + id: Toasts.genId(), + type: Toasts.Type.SUCCESS + }); +} + interface MessageOptions { messageReference: Message["messageReference"]; allowedMentions: { diff --git a/src/utils/index.ts b/src/utils/index.ts index 3e7aa0e14..f41bcbfcb 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -22,6 +22,7 @@ export * from "./ChangeList"; export * from "./clipboard"; export * from "./constants"; export * from "./cspViolations"; +export * from "./css"; export * from "./discord"; export * from "./guards"; export * from "./intlHash"; diff --git a/src/utils/misc.ts b/src/utils/misc.ts index b5bdbd352..0c27b15da 100644 --- a/src/utils/misc.ts +++ b/src/utils/misc.ts @@ -16,9 +16,8 @@ * along with this program. If not, see . */ -import { ChannelStore, GuildMemberStore, Toasts } from "@webpack/common"; +import { ChannelStore, GuildMemberStore } from "@webpack/common"; -import { copyToClipboard } from "./clipboard"; import { EQUICORD_HELPERS, EquicordDevsById, GUILD_ID, SUPPORT_CHANNEL_ID, VencordDevsById } from "./constants"; /** @@ -36,15 +35,6 @@ export function sleep(ms: number): Promise { return new Promise(r => setTimeout(r, ms)); } -export async function copyWithToast(text: string, toastMessage = "Copied to clipboard!") { - await copyToClipboard(text); - Toasts.show({ - message: toastMessage, - id: Toasts.genId(), - type: Toasts.Type.SUCCESS - }); -} - /** * Check if obj is a true object: of type "object" and not null or array */ @@ -87,10 +77,6 @@ export function identity(value: T): T { return value; } -// https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent#mobile_tablet_or_desktop -// "In summary, we recommend looking for the string Mobi anywhere in the User Agent to detect a mobile device." -export const isMobile = navigator.userAgent.includes("Mobi"); - export const isPluginDev = (id: string) => Object.hasOwn(VencordDevsById, id); export const shouldShowContributorBadge = (id: string) => isPluginDev(id) && VencordDevsById[id].badge !== false; diff --git a/src/utils/native.ts b/src/utils/native.ts index d84ed16f2..f797a8167 100644 --- a/src/utils/native.ts +++ b/src/utils/native.ts @@ -19,13 +19,8 @@ export function relaunch() { if (IS_DISCORD_DESKTOP) window.DiscordNative.app.relaunch(); - else + else if (IS_VESKTOP) window.VesktopNative.app.relaunch(); -} - -export function showItemInFolder(path: string) { - if (IS_DISCORD_DESKTOP) - window.DiscordNative.fileManager.showItemInFolder(path); else - window.VesktopNative.fileManager.showItemInFolder(path); + location.reload(); } diff --git a/src/utils/react.tsx b/src/utils/react.tsx index e88c463fd..eb3a7a01d 100644 --- a/src/utils/react.tsx +++ b/src/utils/react.tsx @@ -17,7 +17,7 @@ */ import { React, useEffect, useMemo, useReducer, useState } from "@webpack/common"; -import { ActionDispatch, ReactNode } from "react"; +import type { ActionDispatch, ReactNode } from "react"; import { checkIntersecting } from "./misc"; diff --git a/src/utils/settingsSync.ts b/src/utils/settingsSync.ts deleted file mode 100644 index 4567f80b6..000000000 --- a/src/utils/settingsSync.ts +++ /dev/null @@ -1,342 +0,0 @@ -/* - * 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 { DataStore } from "@api/index"; -import { showNotification } from "@api/Notifications"; -import { PlainSettings, Settings } from "@api/Settings"; -import { moment, SettingsRouter, Toasts } from "@webpack/common"; -import { deflateSync, inflateSync } from "fflate"; - -import { getCloudAuth, getCloudUrl } from "./cloud"; -import { Logger } from "./Logger"; -import { relaunch } from "./native"; -import { chooseFile, saveFile } from "./web"; - -export async function importSettings(data: string) { - let parsed: any; - try { - parsed = JSON.parse(data); - } catch (err) { - console.log(data); - throw new Error("Failed to parse JSON: " + String(err)); - } - - if ("settings" in parsed) { - Object.assign(PlainSettings, parsed.settings); - await VencordNative.settings.set(parsed.settings); - } - - if ("quickCss" in parsed) { - await VencordNative.quickCss.set(parsed.quickCss); - } - - if ("dataStore" in parsed) { - await DataStore.setMany(parsed.dataStore); - } - - if (!("settings" in parsed || "quickCss" in parsed || "dataStore" in parsed)) { - throw new Error("Invalid Settings. Is this even an Equicord Settings file?"); - } -} - -export async function exportSettings({ minify }: { minify?: boolean; } = {}) { - const settings = VencordNative.settings.get(); - const quickCss = await VencordNative.quickCss.get(); - const dataStore = await DataStore.entries(); - return JSON.stringify({ settings, quickCss, dataStore }, null, minify ? undefined : 4); -} - -export async function exportPlugins({ minify }: { minify?: boolean; } = {}) { - const { plugins } = VencordNative.settings.get(); - return JSON.stringify({ settings: { plugins } }, null, minify ? undefined : 4); -} - -export async function exportCSS({ minify }: { minify?: boolean; } = {}) { - const quickCss = await VencordNative.quickCss.get(); - return JSON.stringify({ quickCss }, null, minify ? undefined : 4); -} - -export async function exportDataStores({ minify }: { minify?: boolean; } = {}) { - const dataStore = await DataStore.entries(); - return JSON.stringify({ dataStore }, null, minify ? undefined : 4); -} - -type BackupType = "settings" | "plugins" | "css" | "datastore"; - -export async function downloadSettingsBackup(type: BackupType, { minify }: { minify?: boolean; } = {}) { - let backup: string; - - switch (type) { - case "settings": - backup = await exportSettings({ minify }); - break; - case "plugins": - backup = await exportPlugins({ minify }); - break; - case "css": - backup = await exportCSS({ minify }); - break; - case "datastore": - backup = await exportDataStores({ minify }); - break; - default: - throw new Error("Invalid backup type"); - } - - const filename = `equicord-${type}-backup-${moment().format("YYYY-MM-DD")}.json`; - const data = new TextEncoder().encode(backup); - - if (IS_DISCORD_DESKTOP) { - DiscordNative.fileManager.saveWithDialog(data, filename); - } else { - saveFile(new File([data], filename, { type: "application/json" })); - } -} - -const toast = (type: string, message: string) => - Toasts.show({ - type, - message, - id: Toasts.genId() - }); - -const toastSuccess = () => - toast(Toasts.Type.SUCCESS, "Settings successfully imported. Restart to apply changes!"); - -const toastFailure = (err: any) => - toast(Toasts.Type.FAILURE, `Failed to import settings: ${String(err)}`); - -export async function uploadSettingsBackup(showToast = true): Promise { - if (IS_DISCORD_DESKTOP) { - const [file] = await DiscordNative.fileManager.openFiles({ - filters: [ - { name: "Equicord Settings Backup", extensions: ["json"] }, - { name: "all", extensions: ["*"] } - ] - }); - - if (file) { - try { - await importSettings(new TextDecoder().decode(file.data)); - if (showToast) toastSuccess(); - } catch (err) { - new Logger("SettingsSync").error(err); - if (showToast) toastFailure(err); - } - } - } else { - const file = await chooseFile("application/json"); - if (!file) return; - - const reader = new FileReader(); - reader.onload = async () => { - try { - await importSettings(reader.result as string); - if (showToast) toastSuccess(); - } catch (err) { - new Logger("SettingsSync").error(err); - if (showToast) toastFailure(err); - } - }; - reader.readAsText(file); - } -} - -// Cloud settings -const cloudSettingsLogger = new Logger("Cloud:Settings", "#39b7e0"); - -export async function putCloudSettings(manual?: boolean) { - const settings = await exportSettings({ minify: true }); - - try { - const res = await fetch(new URL("/v1/settings", getCloudUrl()), { - method: "PUT", - headers: { - Authorization: await getCloudAuth(), - "Content-Type": "application/octet-stream" - }, - body: deflateSync(new TextEncoder().encode(settings)) - }); - - if (!res.ok) { - cloudSettingsLogger.error(`Failed to sync up, API returned ${res.status}`); - showNotification({ - title: "Cloud Settings", - body: `Could not synchronize settings to cloud (API returned ${res.status}).`, - color: "var(--red-360)" - }); - return; - } - - const { written } = await res.json(); - PlainSettings.cloud.settingsSyncVersion = written; - VencordNative.settings.set(PlainSettings); - - cloudSettingsLogger.info("Settings uploaded to cloud successfully"); - - if (manual) { - showNotification({ - title: "Cloud Settings", - body: "Synchronized settings to the cloud!", - noPersist: true, - }); - } - } catch (e: any) { - cloudSettingsLogger.error("Failed to sync up", e); - showNotification({ - title: "Cloud Settings", - body: `Could not synchronize settings to the cloud (${e.toString()}).`, - color: "var(--red-360)" - }); - } -} - -export async function getCloudSettings(shouldNotify = true, force = false) { - try { - const res = await fetch(new URL("/v1/settings", getCloudUrl()), { - method: "GET", - headers: { - Authorization: await getCloudAuth(), - Accept: "application/octet-stream", - "If-None-Match": Settings.cloud.settingsSyncVersion.toString() - }, - }); - - if (res.status === 401) { - // User switched to an account that isn't connected to cloud - showNotification({ - 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: () => SettingsRouter.open("VencordCloud") - }); - // Disable cloud sync globally - Settings.cloud.authenticated = false; - return false; - } - - if (res.status === 404) { - cloudSettingsLogger.info("No settings on the cloud"); - if (shouldNotify) - showNotification({ - title: "Cloud Settings", - body: "There are no settings in the cloud.", - noPersist: true - }); - return false; - } - - if (res.status === 304) { - cloudSettingsLogger.info("Settings up to date"); - if (shouldNotify) - showNotification({ - title: "Cloud Settings", - body: "Your settings are up to date.", - noPersist: true - }); - return false; - } - - if (!res.ok) { - cloudSettingsLogger.error(`Failed to sync down, API returned ${res.status}`); - showNotification({ - title: "Cloud Settings", - body: `Could not synchronize settings from the cloud (API returned ${res.status}).`, - color: "var(--red-360)" - }); - return false; - } - - const written = Number(res.headers.get("etag")!); - const localWritten = Settings.cloud.settingsSyncVersion; - - // don't need to check for written > localWritten because the server will return 304 due to if-none-match - if (!force && written < localWritten) { - if (shouldNotify) - showNotification({ - title: "Cloud Settings", - body: "Your local settings are newer than the cloud ones.", - noPersist: true, - }); - return; - } - - const data = await res.arrayBuffer(); - - const settings = new TextDecoder().decode(inflateSync(new Uint8Array(data))); - await importSettings(settings); - - // sync with server timestamp instead of local one - PlainSettings.cloud.settingsSyncVersion = written; - VencordNative.settings.set(PlainSettings); - - cloudSettingsLogger.info("Settings loaded from cloud successfully"); - if (shouldNotify) - showNotification({ - title: "Cloud Settings", - body: "Your settings have been updated! Click here to restart to fully apply changes!", - color: "var(--green-360)", - onClick: IS_WEB ? () => location.reload() : relaunch, - noPersist: true - }); - - return true; - } catch (e: any) { - cloudSettingsLogger.error("Failed to sync down", e); - showNotification({ - title: "Cloud Settings", - body: `Could not synchronize settings from the cloud (${e.toString()}).`, - color: "var(--red-360)" - }); - - return false; - } -} - -export async function deleteCloudSettings() { - try { - const res = await fetch(new URL("/v1/settings", getCloudUrl()), { - method: "DELETE", - headers: { Authorization: await getCloudAuth() }, - }); - - if (!res.ok) { - cloudSettingsLogger.error(`Failed to delete, API returned ${res.status}`); - showNotification({ - title: "Cloud Settings", - body: `Could not delete settings (API returned ${res.status}).`, - color: "var(--red-360)" - }); - return; - } - - cloudSettingsLogger.info("Settings deleted from cloud successfully"); - showNotification({ - title: "Cloud Settings", - body: "Settings deleted from cloud!", - color: "var(--green-360)" - }); - } catch (e: any) { - cloudSettingsLogger.error("Failed to delete", e); - showNotification({ - title: "Cloud Settings", - body: `Could not delete settings (${e.toString()}).`, - color: "var(--red-360)" - }); - } -} diff --git a/src/utils/text.ts b/src/utils/text.ts index 0203a85dc..2d84fecd0 100644 --- a/src/utils/text.ts +++ b/src/utils/text.ts @@ -16,8 +16,6 @@ * along with this program. If not, see . */ -import { moment } from "@webpack/common"; - // Utils for readable text transformations eg: `toTitle(fromKebab())` // Case style to words @@ -54,6 +52,7 @@ function getUnitStr(unit: Units, isOne: boolean, short: boolean) { * @param short Whether to use short units like "d" instead of "days" */ export function formatDuration(time: number, unit: Units, short: boolean = false) { + const { moment } = require("@webpack/common") as typeof import("@webpack/common"); const dur = moment.duration(time, unit); let unitsAmounts = units.map(unit => ({ amount: dur[unit](), unit })); diff --git a/src/utils/types.ts b/src/utils/types.ts index ed2b51cb6..84ad8ae79 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -16,18 +16,18 @@ * along with this program. If not, see . */ -import { ProfileBadge } from "@api/Badges"; -import { ChatBarButtonFactory } from "@api/ChatButtons"; -import { NavContextMenuPatchCallback } from "@api/ContextMenu"; -import { MemberListDecoratorFactory } from "@api/MemberListDecorators"; -import { MessageAccessoryFactory } from "@api/MessageAccessories"; -import { MessageDecorationFactory } from "@api/MessageDecorations"; -import { MessageClickListener, MessageEditListener, MessageSendListener } from "@api/MessageEvents"; -import { MessagePopoverButtonFactory } from "@api/MessagePopover"; -import { NicknameIconFactory } from "@api/NicknameIcons"; -import { Command, FluxEvents } from "@vencord/discord-types"; -import { ReactNode } from "react"; -import { LiteralUnion } from "type-fest"; +import type { ProfileBadge } from "@api/Badges"; +import type { ChatBarButtonFactory } from "@api/ChatButtons"; +import type { NavContextMenuPatchCallback } from "@api/ContextMenu"; +import type { MemberListDecoratorFactory } from "@api/MemberListDecorators"; +import type { MessageAccessoryFactory } from "@api/MessageAccessories"; +import type { MessageDecorationFactory } from "@api/MessageDecorations"; +import type { MessageClickListener, MessageEditListener, MessageSendListener } from "@api/MessageEvents"; +import type { MessagePopoverButtonFactory } from "@api/MessagePopover"; +import type { NicknameIconFactory } from "@api/NicknameIcons"; +import type { Command, FluxEvents } from "@vencord/discord-types"; +import type { ReactNode } from "react"; +import type { LiteralUnion } from "type-fest"; // exists to export default definePlugin({...}) export default function definePlugin

    (p: P & Record) { diff --git a/src/webpack/common/components.ts b/src/webpack/common/components.ts index cc282fd91..659cd8dfd 100644 --- a/src/webpack/common/components.ts +++ b/src/webpack/common/components.ts @@ -30,7 +30,9 @@ import { waitForComponent } from "./internal"; export const Forms = { // TODO: Stop using this and use Heading/Paragraph directly + /** @deprecated use Heading from Vencord */ FormTitle: Heading, + /** @deprecated use Paragraph from Vencord */ FormText: Paragraph, /** @deprecated don't use this */ FormSection: "section" as never, // Backwards compat since Vesktop uses this @@ -39,12 +41,15 @@ export const Forms = { }; // TODO: Stop using this and use Paragraph/Span directly +/** @deprecated use Paragraph, Span, or BaseText from Vencord */ export const Text = TextCompat; +/** @deprecated use Button from Vencord */ export const Button = ButtonCompat; /** @deprecated Use FormSwitch from Vencord */ export const Switch = FormSwitchCompat as never; -export const Card = waitForComponent("Card", filters.componentByCode(".editable),", ".outline:")); +/** @deprecated Use Card from Vencord */ +export const Card = waitForComponent("Card", filters.componentByCode(".editable),", ".outline:")); export const Checkbox = waitForComponent("Checkbox", filters.componentByCode(".checkboxWrapperDisabled:")); const Tooltips = mapMangledModuleLazy(".tooltipTop,bottom:", { @@ -55,6 +60,7 @@ const Tooltips = mapMangledModuleLazy(".tooltipTop,bottom:", { TooltipContainer: t.TooltipContainer; }; +// TODO: if these finds break, they should just return their children export const Tooltip = LazyComponent(() => Tooltips.Tooltip); export const TooltipContainer = LazyComponent(() => Tooltips.TooltipContainer); @@ -67,6 +73,7 @@ export const Popout = waitForComponent("Popout", filters.componentByCo export const Dialog = waitForComponent("Dialog", filters.componentByCode('role:"dialog",tabIndex:-1')); export const TabBar = waitForComponent("TabBar", filters.componentByCode("ref:this.tabBarRef,className:")); export const Paginator = waitForComponent("Paginator", filters.componentByCode('rel:"prev",children:')); +// TODO: remake this component export const Clickable = waitForComponent("Clickable", filters.componentByCode("this.context?this.renderNonInteractive():")); export const Avatar = waitForComponent("Avatar", filters.componentByCode(".size-1.375*")); @@ -106,7 +113,6 @@ waitFor(m => { export const MaskedLink = waitForComponent("MaskedLink", filters.componentByCode("MASKED_LINK)")); export const Timestamp = waitForComponent("Timestamp", filters.componentByCode("#{intl::MESSAGE_EDITED_TIMESTAMP_A11Y_LABEL}")); -export const Flex = waitForComponent("Flex", ["Justify", "Align", "Wrap"]); export const OAuth2AuthorizeModal = waitForComponent("OAuth2AuthorizeModal", filters.componentByCode(".authorize,children:", ".contentBackground")); export const Animations = mapMangledModuleLazy(".assign({colorNames:", { diff --git a/src/webpack/common/stores.ts b/src/webpack/common/stores.ts index 1a0bd6f3a..dd07ed89d 100644 --- a/src/webpack/common/stores.ts +++ b/src/webpack/common/stores.ts @@ -34,7 +34,7 @@ export let MessageStore: Omit & GenericStore & { export let PermissionStore: GenericStore; export let GuildChannelStore: GenericStore; export let ReadStateStore: GenericStore; -export let PresenceStore: GenericStore; +export let PresenceStore: t.PresenceStore; export let GuildStore: t.GuildStore; export let GuildRoleStore: t.GuildRoleStore; @@ -92,6 +92,7 @@ waitForStore("StreamerModeStore", m => StreamerModeStore = m); waitForStore("OverridePremiumTypeStore", m => OverridePremiumTypeStore = m); waitForStore("ThemeStore", m => { ThemeStore = m; - // Importing this directly can easily cause circular imports. For this reason, use a non import access here. - Vencord.QuickCss.initQuickCssThemeStore(); + // Importing this directly causes all webpack commons to be imported, which can easily cause circular dependencies. + // For this reason, use a non import access here. + Vencord.Api.Themes.initQuickCssThemeStore(m); }); diff --git a/src/webpack/common/utils.ts b/src/webpack/common/utils.ts index 63778f5cc..011f2e410 100644 --- a/src/webpack/common/utils.ts +++ b/src/webpack/common/utils.ts @@ -22,8 +22,9 @@ import { _resolveReady, filters, findByCodeLazy, findByPropsLazy, findLazy, mapM export let FluxDispatcher: t.FluxDispatcher; waitFor(["dispatch", "subscribe"], m => { FluxDispatcher = m; - // Non import access to avoid circular dependency - Vencord.Plugins.subscribeAllPluginsFluxEvents(m); + // Importing this directly causes all webpack commons to be imported, which can easily cause circular dependencies. + // For this reason, use a non import access here. + Vencord.Api.PluginManager.subscribeAllPluginsFluxEvents(m); const cb = () => { m.unsubscribe("CONNECTION_OPEN", cb); diff --git a/src/webpack/patchWebpack.ts b/src/webpack/patchWebpack.ts index 64cfdd7c9..e261b07a2 100644 --- a/src/webpack/patchWebpack.ts +++ b/src/webpack/patchWebpack.ts @@ -538,7 +538,7 @@ function patchFactory(moduleId: PropertyKey, originalFactory: AnyModuleFactory): const previousFactory = originalFactory; let markedAsPatched = false; - // We change all patch.replacement to array in plugins/index + // We change all patch.replacement to array in PluginManager for (const replacement of patch.replacement as PatchReplacement[]) { if ( shouldCheckBuildNumber && diff --git a/src/webpack/webpack.ts b/src/webpack/webpack.ts index d8f6d95c3..2d8813ab4 100644 --- a/src/webpack/webpack.ts +++ b/src/webpack/webpack.ts @@ -20,12 +20,11 @@ import { makeLazy, proxyLazy } from "@utils/lazy"; import { LazyComponent } from "@utils/lazyReact"; import { Logger } from "@utils/Logger"; import { canonicalizeMatch } from "@utils/patches"; -import { FluxStore } from "@vencord/discord-types"; -import { ModuleExports, WebpackRequire } from "@vencord/discord-types/webpack"; +import type { FluxStore } from "@vencord/discord-types"; +import type { ModuleExports, WebpackRequire } from "@vencord/discord-types/webpack"; import { traceFunction } from "../debug/Tracer"; -import { Flux } from "./common"; -import { AnyModuleFactory, AnyWebpackRequire } from "./types"; +import type { AnyModuleFactory, AnyWebpackRequire } from "./types"; const logger = new Logger("Webpack"); @@ -39,7 +38,7 @@ export const onceReady = new Promise(r => _resolveReady = r); export let wreq: WebpackRequire; export let cache: WebpackRequire["c"]; -export const fluxStores: Record = {}; +export const fluxStores = new Map(); export type FilterFn = (mod: any) => boolean; @@ -75,7 +74,7 @@ export const filters = { componentByCode: (...code: CodeFilter): FilterFn => { const byCodeFilter = filters.byCode(...code); - const filter = m => { + const filter = (m: any) => { let inner = m; while (inner != null) { @@ -457,55 +456,50 @@ export function findByCodeLazy(...code: CodeFilter) { return proxyLazy(() => findByCode(...code)); } +function populateFluxStoreMap() { + const { Flux } = require("./common") as typeof import("./common"); + + Flux.Store.getAll?.().forEach(store => + fluxStores.set(store.getName(), store) + ); + + try { + const getLibdiscore = findByCode("libdiscoreWasm is not initialized"); + const libdiscoreExports = getLibdiscore(); + + for (const libdiscoreExportName in libdiscoreExports) { + if (!libdiscoreExportName.endsWith("Store")) { + continue; + } + + const storeName = libdiscoreExportName; + const store = libdiscoreExports[storeName]; + + fluxStores.set(storeName, store); + } + } catch { } +} + /** * Find a store by its displayName */ export function findStore(name: StoreNameFilter) { - let res = fluxStores[name] as any; - if (res == null) { - for (const store of Flux.Store.getAll?.() ?? []) { - const storeName = store.getName(); - - if (storeName === name) { - res = store; - } - - if (fluxStores[storeName] == null) { - fluxStores[storeName] = store; - } - } - - try { - const getLibdiscore = findByCode("libdiscoreWasm is not initialized"); - const libdiscoreExports = getLibdiscore(); - - for (const libdiscoreExportName in libdiscoreExports) { - if (!libdiscoreExportName.endsWith("Store")) { - continue; - } - - const storeName = libdiscoreExportName; - const store = libdiscoreExports[storeName]; - - if (storeName === name) { - res = store; - } - - if (fluxStores[storeName] == null) { - fluxStores[storeName] = store; - } - } - - } catch { } - - if (res == null) { - res = find(filters.byStoreName(name), { isIndirect: true }); - } + if (!fluxStores.has(name)) { + populateFluxStoreMap(); } - if (!res) - handleModuleNotFound("findStore", name); - return res; + if (fluxStores.has(name)) { + return fluxStores.get(name); + } + + const res = find(filters.byStoreName(name), { isIndirect: true }); + if (res) { + fluxStores.set(name, res); + return res; + } + + handleModuleNotFound("findStore", name); + return null; } /** diff --git a/tsconfig.json b/tsconfig.json index ff6756143..4a9a031cc 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -14,7 +14,7 @@ "esnext.symbol" ], "module": "esnext", - "moduleResolution": "node", + "moduleResolution": "bundler", "strict": true, "noImplicitAny": false, "target": "ESNEXT", @@ -25,8 +25,10 @@ "@api/*": ["./api/*"], "@components/*": ["./components/*"], "@utils/*": ["./utils/*"], + "@plugins/*": ["./plugins/*"], "@shared/*": ["./shared/*"], "@webpack/common": ["./webpack/common"], + "@webpack/common/*": ["./webpack/common/*"], "@webpack": ["./webpack/webpack"], "@webpack/patcher": ["./webpack/patchWebpack"], "@webpack/wreq.d": ["./webpack/wreq.d"],