diff --git a/browser/VencordNativeStub.ts b/browser/VencordNativeStub.ts index c99c176c..64961275 100644 --- a/browser/VencordNativeStub.ts +++ b/browser/VencordNativeStub.ts @@ -19,14 +19,16 @@ /// /// +// 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 { getThemeInfo } from "../src/main/themes"; -import { Settings } from "../src/Vencord"; +import * as DataStore from "@api/DataStore"; +import type { Settings } from "@api/Settings"; +import { getThemeInfo } from "@main/themes"; +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/package.json b/package.json index d9f62d97..2fe739f5 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "@types/chrome": "^0.0.312", "@types/diff": "^7.0.2", "@types/lodash": "^4.17.14", - "@types/node": "^22.13.13", + "@types/node": "^24.10.1", "@types/react": "^19.0.10", "@types/react-dom": "^19.0.4", "@types/yazl": "^2.4.5", @@ -74,7 +74,7 @@ "ts-pattern": "^5.6.0", "tsx": "^4.19.3", "type-fest": "^4.38.0", - "typescript": "^5.8.2", + "typescript": "^5.9.3", "typescript-eslint": "^8.28.0", "typescript-transform-paths": "^3.5.5", "zip-local": "^0.3.5" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2ba2d317..74de8197 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -43,7 +43,7 @@ importers: devDependencies: '@stylistic/eslint-plugin': specifier: ^4.2.0 - version: 4.2.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2) + version: 4.2.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.9.3) '@types/chrome': specifier: ^0.0.312 version: 0.0.312 @@ -54,8 +54,8 @@ importers: specifier: ^4.17.14 version: 4.17.15 '@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 @@ -79,7 +79,7 @@ importers: version: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215) 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.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.9.3))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))) eslint-plugin-path-alias: specifier: 2.1.0 version: 2.1.0(patch_hash=87545cb13985b338c8fa2ea7b0a3c75c57ad7fbc81c56b38d6c9438329957727)(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)) @@ -94,7 +94,7 @@ importers: version: 12.1.1(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)) 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)) + 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.9.3))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.9.3))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)) highlight.js: specifier: 11.11.1 version: 11.11.1 @@ -112,10 +112,10 @@ importers: version: 34.2.0 stylelint: specifier: ^16.17.0 - version: 16.17.0(typescript@5.8.2) + version: 16.17.0(typescript@5.9.3) stylelint-config-standard: specifier: ^37.0.0 - version: 37.0.0(stylelint@16.17.0(typescript@5.8.2)) + version: 37.0.0(stylelint@16.17.0(typescript@5.9.3)) ts-patch: specifier: ^3.3.0 version: 3.3.0 @@ -129,14 +129,14 @@ importers: specifier: ^4.38.0 version: 4.38.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) + version: 8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(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 @@ -163,13 +163,13 @@ importers: version: 22.13.13 '@types/react': specifier: 18.3.1 - version: 19.0.12 + version: 18.3.1 '@types/react-dom': specifier: 18.3.1 version: 18.3.1 '@vencord/discord-types': specifier: ^1.0.0 - version: 1.0.0(@types/react@19.0.12) + version: 1.0.0(@types/react@18.3.1) highlight.js: specifier: 11.11.1 version: 11.11.1 @@ -529,6 +529,15 @@ packages: '@types/node@22.13.13': resolution: {integrity: sha512-ClsL5nMwKaBRwPcCvH8E7+nU4GxHVx1axNvMZTFHMEfNI7oahimt26P5zjVCRrjiIWj6YFXfE1v3dEp94wLcGQ==} + '@types/node@22.19.1': + resolution: {integrity: sha512-LCCV0HdSZZZb34qifBsyWlUmok6W7ouER+oQIGBScS8EsZsQbrtFTUrDX4hOl+CS6p7cnNC4td+qrSVGSCTUfQ==} + + '@types/node@24.10.1': + resolution: {integrity: sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==} + + '@types/prop-types@15.7.15': + resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==} + '@types/react-dom@18.3.1': resolution: {integrity: sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==} @@ -537,6 +546,9 @@ packages: peerDependencies: '@types/react': ^19.0.0 + '@types/react@18.3.1': + resolution: {integrity: sha512-V0kuGBX3+prX+DQ/7r2qsv1NsdfnCLnTgnRJ1pYnxykBhGMz+qj+box5lq7XsO5mtZsBqpjwwTu/7wszPfMBcw==} + '@types/react@19.0.12': resolution: {integrity: sha512-V6Ar115dBDrjbtXSrS+/Oruobc+qVbbUxDFC1RSbRqLt5SYvxxyIDrSC85RWml54g+jfNeEMZhEj7wW07ONQhA==} @@ -651,6 +663,10 @@ packages: resolution: {integrity: sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==} engines: {node: '>= 0.4'} + array-includes@3.1.9: + resolution: {integrity: sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==} + engines: {node: '>= 0.4'} + array-union@2.1.0: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} @@ -887,6 +903,9 @@ packages: csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + csstype@3.2.1: + resolution: {integrity: sha512-98XGutrXoh75MlgLihlNxAGbUuFQc7l1cqcnEZlLNKc0UrVdPndgmaDmYTDDh929VS/eqTZV0rozmhu2qqT1/g==} + data-uri-to-buffer@6.0.2: resolution: {integrity: sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==} engines: {node: '>= 14'} @@ -1002,6 +1021,10 @@ packages: resolution: {integrity: sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==} engines: {node: '>= 0.4'} + es-abstract@1.24.0: + resolution: {integrity: sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==} + engines: {node: '>= 0.4'} + es-define-property@1.0.1: resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} engines: {node: '>= 0.4'} @@ -1057,8 +1080,8 @@ packages: eslint-import-resolver-node@0.3.9: resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} - eslint-module-utils@2.12.0: - resolution: {integrity: sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==} + eslint-module-utils@2.12.1: + resolution: {integrity: sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==} engines: {node: '>=4'} peerDependencies: '@typescript-eslint/parser': '*' @@ -1560,6 +1583,10 @@ packages: resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} engines: {node: '>= 0.4'} + is-negative-zero@2.0.3: + resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} + engines: {node: '>= 0.4'} + is-number-object@1.1.1: resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} engines: {node: '>= 0.4'} @@ -2063,6 +2090,11 @@ packages: engines: {node: '>= 0.4'} hasBin: true + resolve@1.22.11: + resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} + engines: {node: '>= 0.4'} + hasBin: true + resolve@2.0.0-next.5: resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==} hasBin: true @@ -2207,6 +2239,10 @@ packages: resolution: {integrity: sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==} engines: {node: '>=0.10.0'} + stop-iteration-iterator@1.1.0: + resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} + engines: {node: '>= 0.4'} + streamx@2.22.0: resolution: {integrity: sha512-sLh1evHOzBy/iWRiR6d1zRcLao4gGZr3C1kzNz4fopCOKJb6xD9ub8Mpi9Mr1R6id5o43S+d93fI48UC5uM9aw==} @@ -2374,8 +2410,8 @@ packages: 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 @@ -2386,6 +2422,12 @@ packages: undici-types@6.20.0: resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + + undici-types@7.16.0: + resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} + union-value@1.0.1: resolution: {integrity: sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==} engines: {node: '>=0.10.0'} @@ -2719,9 +2761,9 @@ snapshots: '@rtsao/scc@1.1.0': {} - '@stylistic/eslint-plugin@4.2.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2)': + '@stylistic/eslint-plugin@4.2.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.9.3)': dependencies: - '@typescript-eslint/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.9.3) eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215) eslint-visitor-keys: 4.2.0 espree: 10.3.0 @@ -2769,53 +2811,68 @@ snapshots: dependencies: undici-types: 6.20.0 + '@types/node@22.19.1': + dependencies: + undici-types: 6.21.0 + + '@types/node@24.10.1': + dependencies: + undici-types: 7.16.0 + + '@types/prop-types@15.7.15': {} + '@types/react-dom@18.3.1': dependencies: - '@types/react': 19.0.12 + '@types/react': 18.3.1 '@types/react-dom@19.0.4(@types/react@19.0.12)': dependencies: '@types/react': 19.0.12 + '@types/react@18.3.1': + dependencies: + '@types/prop-types': 15.7.15 + csstype: 3.2.1 + '@types/react@19.0.12': dependencies: csstype: 3.1.3 '@types/yauzl@2.10.3': dependencies: - '@types/node': 22.13.13 + '@types/node': 24.10.1 optional: true '@types/yazl@2.4.6': 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.28.0(@typescript-eslint/parser@8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.9.3))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(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/parser': 8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.9.3) '@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/type-utils': 8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.9.3) + '@typescript-eslint/utils': 8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.9.3) '@typescript-eslint/visitor-keys': 8.28.0 eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215) graphemer: 1.4.0 ignore: 5.3.2 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.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(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/typescript-estree': 8.28.0(typescript@5.9.3) '@typescript-eslint/visitor-keys': 8.28.0 debug: 4.4.0 eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215) - typescript: 5.8.2 + typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -2824,20 +2881,20 @@ snapshots: '@typescript-eslint/types': 8.28.0 '@typescript-eslint/visitor-keys': 8.28.0 - '@typescript-eslint/type-utils@8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2)': + '@typescript-eslint/type-utils@8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.9.3)': 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) + '@typescript-eslint/typescript-estree': 8.28.0(typescript@5.9.3) + '@typescript-eslint/utils': 8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.9.3) 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 + ts-api-utils: 2.1.0(typescript@5.9.3) + typescript: 5.9.3 transitivePeerDependencies: - supports-color '@typescript-eslint/types@8.28.0': {} - '@typescript-eslint/typescript-estree@8.28.0(typescript@5.8.2)': + '@typescript-eslint/typescript-estree@8.28.0(typescript@5.9.3)': dependencies: '@typescript-eslint/types': 8.28.0 '@typescript-eslint/visitor-keys': 8.28.0 @@ -2846,19 +2903,19 @@ snapshots: 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 + 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.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(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) + '@typescript-eslint/typescript-estree': 8.28.0(typescript@5.9.3) eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215) - typescript: 5.8.2 + typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -2877,9 +2934,9 @@ snapshots: vscode-oniguruma: 1.7.0 vscode-textmate: 5.2.0 - '@vencord/discord-types@1.0.0(@types/react@19.0.12)': + '@vencord/discord-types@1.0.0(@types/react@18.3.1)': dependencies: - '@types/react': 19.0.12 + '@types/react': 18.3.1 moment: 2.30.1 type-fest: 4.41.0 @@ -2931,6 +2988,17 @@ snapshots: get-intrinsic: 1.3.0 is-string: 1.1.1 + array-includes@3.1.9: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + is-string: 1.1.1 + math-intrinsics: 1.1.0 + array-union@2.1.0: {} array-unique@0.3.2: {} @@ -2949,7 +3017,7 @@ snapshots: call-bind: 1.0.8 call-bound: 1.0.4 define-properties: 1.2.1 - es-abstract: 1.23.9 + es-abstract: 1.24.0 es-errors: 1.3.0 es-object-atoms: 1.1.1 es-shim-unscopables: 1.1.0 @@ -3163,14 +3231,14 @@ snapshots: copy-descriptor@0.1.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: @@ -3189,6 +3257,8 @@ snapshots: csstype@3.1.3: {} + csstype@3.2.1: {} + data-uri-to-buffer@6.0.2: {} data-view-buffer@1.0.2: @@ -3347,6 +3417,63 @@ snapshots: unbox-primitive: 1.1.0 which-typed-array: 1.1.19 + es-abstract@1.24.0: + dependencies: + array-buffer-byte-length: 1.0.2 + arraybuffer.prototype.slice: 1.0.4 + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + call-bound: 1.0.4 + data-view-buffer: 1.0.2 + data-view-byte-length: 1.0.2 + data-view-byte-offset: 1.0.1 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + es-set-tostringtag: 2.1.0 + es-to-primitive: 1.3.0 + function.prototype.name: 1.1.8 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + get-symbol-description: 1.1.0 + globalthis: 1.0.4 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + has-proto: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + internal-slot: 1.1.0 + is-array-buffer: 3.0.5 + is-callable: 1.2.7 + is-data-view: 1.0.2 + is-negative-zero: 2.0.3 + is-regex: 1.2.1 + is-set: 2.0.3 + is-shared-array-buffer: 1.0.4 + is-string: 1.1.1 + is-typed-array: 1.1.15 + is-weakref: 1.1.1 + math-intrinsics: 1.1.0 + object-inspect: 1.13.4 + object-keys: 1.1.1 + object.assign: 4.1.7 + own-keys: 1.0.1 + regexp.prototype.flags: 1.5.4 + safe-array-concat: 1.1.3 + safe-push-apply: 1.0.0 + safe-regex-test: 1.1.0 + set-proto: 1.0.0 + stop-iteration-iterator: 1.1.0 + string.prototype.trim: 1.2.10 + string.prototype.trimend: 1.0.9 + string.prototype.trimstart: 1.0.8 + typed-array-buffer: 1.0.3 + typed-array-byte-length: 1.0.3 + typed-array-byte-offset: 1.0.4 + typed-array-length: 1.0.7 + unbox-primitive: 1.1.0 + which-typed-array: 1.1.19 + es-define-property@1.0.1: {} es-errors@1.3.0: {} @@ -3431,32 +3558,32 @@ 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.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.9.3))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))): 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.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.9.3))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)) eslint-import-resolver-node@0.3.9: dependencies: debug: 3.2.7 is-core-module: 2.16.1 - resolve: 1.22.10 + resolve: 1.22.11 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.1(@typescript-eslint/parser@8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)): dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 8.28.0(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.9.3) eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215) 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.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.9.3))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)): dependencies: '@rtsao/scc': 1.1.0 - array-includes: 3.1.8 + array-includes: 3.1.9 array.prototype.findlastindex: 1.2.6 array.prototype.flat: 1.3.3 array.prototype.flatmap: 1.3.3 @@ -3464,7 +3591,7 @@ snapshots: doctrine: 2.1.0 eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215) 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.1(@typescript-eslint/parser@8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -3476,7 +3603,7 @@ 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.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.9.3) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack @@ -3521,11 +3648,11 @@ snapshots: dependencies: eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215) - 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.1.4(@typescript-eslint/eslint-plugin@8.28.0(@typescript-eslint/parser@8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.9.3))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.9.3))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)): dependencies: eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215) 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.28.0(@typescript-eslint/parser@8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.9.3))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.9.3) eslint-scope@8.3.0: dependencies: @@ -4020,6 +4147,8 @@ snapshots: is-map@2.0.3: {} + is-negative-zero@2.0.3: {} + is-number-object@1.1.1: dependencies: call-bound: 1.0.4 @@ -4307,7 +4436,7 @@ snapshots: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.9 + es-abstract: 1.24.0 object.pick@1.3.0: dependencies: @@ -4531,6 +4660,12 @@ snapshots: path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 + resolve@1.22.11: + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + resolve@2.0.0-next.5: dependencies: is-core-module: 2.16.1 @@ -4702,13 +4837,18 @@ snapshots: standalone-electron-types@34.2.0: dependencies: - '@types/node': 22.13.13 + '@types/node': 22.19.1 static-extend@0.1.2: dependencies: define-property: 0.2.5 object-copy: 0.1.0 + stop-iteration-iterator@1.1.0: + dependencies: + es-errors: 1.3.0 + internal-slot: 1.1.0 + streamx@2.22.0: dependencies: fast-fifo: 1.3.2 @@ -4774,16 +4914,16 @@ snapshots: strip-json-comments@3.1.1: {} - stylelint-config-recommended@15.0.0(stylelint@16.17.0(typescript@5.8.2)): + stylelint-config-recommended@15.0.0(stylelint@16.17.0(typescript@5.9.3)): dependencies: - stylelint: 16.17.0(typescript@5.8.2) + stylelint: 16.17.0(typescript@5.9.3) - stylelint-config-standard@37.0.0(stylelint@16.17.0(typescript@5.8.2)): + stylelint-config-standard@37.0.0(stylelint@16.17.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.17.0(typescript@5.9.3) + stylelint-config-recommended: 15.0.0(stylelint@16.17.0(typescript@5.9.3)) - stylelint@16.17.0(typescript@5.8.2): + stylelint@16.17.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 @@ -4792,7 +4932,7 @@ snapshots: '@dual-bundle/import-meta-resolve': 4.1.0 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 @@ -4890,9 +5030,9 @@ snapshots: regex-not: 1.0.2 safe-regex: 1.1.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: @@ -4964,22 +5104,22 @@ 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.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(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) + '@typescript-eslint/eslint-plugin': 8.28.0(@typescript-eslint/parser@8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.9.3))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.9.3) + '@typescript-eslint/parser': 8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.9.3) + '@typescript-eslint/utils': 8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.9.3) eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215) - typescript: 5.8.2 + 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: @@ -4990,6 +5130,10 @@ snapshots: undici-types@6.20.0: {} + undici-types@6.21.0: {} + + undici-types@7.16.0: {} + union-value@1.0.1: dependencies: arr-union: 3.1.0 diff --git a/src/Vencord.ts b/src/Vencord.ts index e5e8cc95..ebbeeb30 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"); @@ -90,6 +88,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; @@ -161,6 +171,7 @@ async function init() { } } +initPluginManager(); startAllPlugins(StartAt.Init); init(); diff --git a/src/api/Badges.ts b/src/api/Badges.ts index 8299dafa..f909b0e3 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 77% rename from src/plugins/index.ts rename to src/api/PluginManager.ts index 5bb60a13..11097678 100644 --- a/src/plugins/index.ts +++ b/src/api/PluginManager.ts @@ -28,6 +28,7 @@ import { addMessagePopoverButton, removeMessagePopoverButton } from "@api/Messag import { Settings, SettingsStore } from "@api/Settings"; import { disableStyle, enableStyle } from "@api/Styles"; 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"; @@ -35,27 +36,23 @@ 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; - export function isPluginEnabled(p: string) { return ( Plugins[p]?.required || Plugins[p]?.isDependency || - settings[p]?.enabled + Settings.plugins[p]?.enabled ) ?? false; } @@ -94,85 +91,6 @@ function isReporterTestable(p: Plugin, part: ReporterTestable) { : (p.reporterTestable & part) === part; } -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.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); - } - } - } -} - export const startAllPlugins = traceFunction("startAllPlugins", function startAllPlugins(target: StartAt) { logger.info(`Starting plugins (stage ${target})`); for (const name in Plugins) { @@ -188,6 +106,7 @@ export const startAllPlugins = traceFunction("startAllPlugins", function startAl }); export function startDependenciesRecursive(p: Plugin) { + const settings = Settings.plugins; let restartNeeded = false; const failures: string[] = []; @@ -379,3 +298,87 @@ 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.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 5c8965bf..b4c2f770 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"; @@ -111,14 +108,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({ @@ -161,8 +150,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 81% rename from src/utils/cloud.tsx rename to src/api/SettingsSync/cloudSetup.tsx index 3b482d4d..8e77d5fb 100644 --- a/src/utils/cloud.tsx +++ b/src/api/SettingsSync/cloudSetup.tsx @@ -1,31 +1,18 @@ /* - * 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 { relaunch } from "@utils/native"; import { Alerts, OAuth2AuthorizeModal, UserStore } from "@webpack/common"; -import { Logger } from "./Logger"; -import { openModal } from "./modal"; -import { relaunch } from "./native"; - -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; @@ -137,7 +124,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", @@ -152,7 +139,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/utils/settingsSync.ts b/src/api/SettingsSync/cloudSync.ts similarity index 53% rename from src/utils/settingsSync.ts rename to src/api/SettingsSync/cloudSync.ts index c711aacd..3784e3e5 100644 --- a/src/utils/settingsSync.ts +++ b/src/api/SettingsSync/cloudSync.ts @@ -1,116 +1,19 @@ /* - * 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 . -*/ + * 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 { moment, Toasts } from "@webpack/common"; +import { Logger } from "@utils/Logger"; +import { relaunch } from "@utils/native"; import { deflateSync, inflateSync } from "fflate"; -import { checkCloudUrlCsp, getCloudAuth, getCloudUrl } from "./cloud"; -import { Logger } from "./Logger"; -import { relaunch } from "./native"; -import { chooseFile, saveFile } from "./web"; +import { checkCloudUrlCsp, deauthorizeCloud, getCloudAuth, getCloudUrl } from "./cloudSetup"; +import { exportSettings, importSettings } from "./offline"; -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" })); - } -} - -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: "Vencord 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"); +const logger = new Logger("SettingsSync:Cloud", "#39b7e0"); export async function putCloudSettings(manual?: boolean) { const settings = await exportSettings({ minify: true }); @@ -124,11 +27,11 @@ export async function putCloudSettings(manual?: boolean) { Authorization: await getCloudAuth(), "Content-Type": "application/octet-stream" }, - body: deflateSync(new TextEncoder().encode(settings)) + body: deflateSync(new TextEncoder().encode(settings)) as Uint8Array }); if (!res.ok) { - cloudSettingsLogger.error(`Failed to sync up, API returned ${res.status}`); + 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}).`, @@ -141,7 +44,7 @@ export async function putCloudSettings(manual?: boolean) { PlainSettings.cloud.settingsSyncVersion = written; VencordNative.settings.set(PlainSettings); - cloudSettingsLogger.info("Settings uploaded to cloud successfully"); + logger.info("Settings uploaded to cloud successfully"); if (manual) { showNotification({ @@ -151,7 +54,7 @@ export async function putCloudSettings(manual?: boolean) { }); } } catch (e: any) { - cloudSettingsLogger.error("Failed to sync up", e); + logger.error("Failed to sync up", e); showNotification({ title: "Cloud Settings", body: `Could not synchronize settings to the cloud (${e.toString()}).`, @@ -174,7 +77,7 @@ export async function getCloudSettings(shouldNotify = true, force = false) { }); if (res.status === 404) { - cloudSettingsLogger.info("No settings on the cloud"); + logger.info("No settings on the cloud"); if (shouldNotify) showNotification({ title: "Cloud Settings", @@ -185,7 +88,7 @@ export async function getCloudSettings(shouldNotify = true, force = false) { } if (res.status === 304) { - cloudSettingsLogger.info("Settings up to date"); + logger.info("Settings up to date"); if (shouldNotify) showNotification({ title: "Cloud Settings", @@ -196,7 +99,7 @@ export async function getCloudSettings(shouldNotify = true, force = false) { } if (!res.ok) { - cloudSettingsLogger.error(`Failed to sync down, API returned ${res.status}`); + 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}).`, @@ -228,7 +131,7 @@ export async function getCloudSettings(shouldNotify = true, force = false) { PlainSettings.cloud.settingsSyncVersion = written; VencordNative.settings.set(PlainSettings); - cloudSettingsLogger.info("Settings loaded from cloud successfully"); + logger.info("Settings loaded from cloud successfully"); if (shouldNotify) showNotification({ title: "Cloud Settings", @@ -240,7 +143,7 @@ export async function getCloudSettings(shouldNotify = true, force = false) { return true; } catch (e: any) { - cloudSettingsLogger.error("Failed to sync down", e); + logger.error("Failed to sync down", e); showNotification({ title: "Cloud Settings", body: `Could not synchronize settings from the cloud (${e.toString()}).`, @@ -261,7 +164,7 @@ export async function deleteCloudSettings() { }); if (!res.ok) { - cloudSettingsLogger.error(`Failed to delete, API returned ${res.status}`); + logger.error(`Failed to delete, API returned ${res.status}`); showNotification({ title: "Cloud Settings", body: `Could not delete settings (API returned ${res.status}).`, @@ -270,14 +173,14 @@ export async function deleteCloudSettings() { return; } - cloudSettingsLogger.info("Settings deleted from cloud successfully"); + logger.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); + logger.error("Failed to delete", e); showNotification({ title: "Cloud Settings", body: `Could not delete settings (${e.toString()}).`, @@ -285,3 +188,31 @@ export async function deleteCloudSettings() { }); } } + +export async function eraseAllCloudData() { + if (!await checkCloudUrlCsp()) return; + + 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 00000000..aced11e8 --- /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/utils/quickCss.ts b/src/api/Themes.ts similarity index 88% rename from src/utils/quickCss.ts rename to src/api/Themes.ts index 68969920..9fdfdba5 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,6 +53,8 @@ async function initThemes() { const { themeLinks, enabledThemes } = Settings; + 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 @@ -102,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 4de92a81..9d68c131 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 d4d7b461..98d66db0 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -29,9 +29,11 @@ import * as $MessagePopover from "./MessagePopover"; import * as $MessageUpdater from "./MessageUpdater"; 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"; /** @@ -122,3 +124,8 @@ export const MessageUpdater = $MessageUpdater; * An API allowing you to get an user setting */ export const UserSettings = $UserSettings; + +/** + * Don't use this + */ +export const Themes = $Themes; diff --git a/src/components/settings/tabs/patchHelper/index.tsx b/src/components/settings/tabs/patchHelper/index.tsx index 17412bd0..2d33a029 100644 --- a/src/components/settings/tabs/patchHelper/index.tsx +++ b/src/components/settings/tabs/patchHelper/index.tsx @@ -22,8 +22,8 @@ import { Flex } from "@components/Flex"; import { HeadingTertiary } from "@components/Heading"; import { SettingsTab, wrapTab } from "@components/settings/tabs/BaseTab"; import { debounce } from "@shared/debounce"; +import { copyWithToast } from "@utils/discord"; import { Margins } from "@utils/margins"; -import { copyWithToast } from "@utils/misc"; import { stripIndent } from "@utils/text"; import { ReplaceFn } from "@utils/types"; import { search } from "@webpack"; diff --git a/src/components/settings/tabs/plugins/PluginCard.tsx b/src/components/settings/tabs/plugins/PluginCard.tsx index da8696d5..a0c9cbc4 100644 --- a/src/components/settings/tabs/plugins/PluginCard.tsx +++ b/src/components/settings/tabs/plugins/PluginCard.tsx @@ -5,9 +5,9 @@ */ import { showNotice } from "@api/Notices"; +import { isPluginEnabled, startDependenciesRecursive, startPlugin, stopPlugin } from "@api/PluginManager"; import { CogWheel, InfoIcon } from "@components/Icons"; import { AddonCard } from "@components/settings/AddonCard"; -import { proxyLazy } from "@utils/lazy"; import { isObjectEmpty } from "@utils/misc"; import { Plugin } from "@utils/types"; import { React, showToast, Toasts } from "@webpack/common"; @@ -16,9 +16,6 @@ import { Settings } from "Vencord"; import { cl, logger } from "."; import { openPluginModal } from "./PluginModal"; -// Avoid circular dependency -const { startDependenciesRecursive, startPlugin, stopPlugin, isPluginEnabled } = proxyLazy(() => require("plugins") as typeof import("plugins")); - interface PluginCardProps extends React.HTMLProps { plugin: Plugin; disabled: boolean; diff --git a/src/components/settings/tabs/plugins/index.tsx b/src/components/settings/tabs/plugins/index.tsx index b9e721f1..cb8776ae 100644 --- a/src/components/settings/tabs/plugins/index.tsx +++ b/src/components/settings/tabs/plugins/index.tsx @@ -19,6 +19,7 @@ import "./styles.css"; import * as DataStore from "@api/DataStore"; +import { isPluginEnabled } from "@api/PluginManager"; import { useSettings } from "@api/Settings"; import { classNameFactory } from "@api/Styles"; import { Divider } from "@components/Divider"; @@ -157,7 +158,7 @@ function PluginSettings() { const pluginFilter = (plugin: typeof Plugins[keyof typeof Plugins]) => { const { status } = searchValue; - const enabled = Vencord.Plugins.isPluginEnabled(plugin.name); + const enabled = isPluginEnabled(plugin.name); switch (status) { case SearchStatus.DISABLED: diff --git a/src/components/settings/tabs/sync/BackupAndRestoreTab.tsx b/src/components/settings/tabs/sync/BackupAndRestoreTab.tsx index 077b8792..2356c4c2 100644 --- a/src/components/settings/tabs/sync/BackupAndRestoreTab.tsx +++ b/src/components/settings/tabs/sync/BackupAndRestoreTab.tsx @@ -16,11 +16,11 @@ * along with this program. If not, see . */ +import { downloadSettingsBackup, uploadSettingsBackup } from "@api/SettingsSync/offline"; import { Flex } from "@components/Flex"; import { SettingsTab, wrapTab } from "@components/settings/tabs/BaseTab"; import { Margins } from "@utils/margins"; import { classes } from "@utils/misc"; -import { downloadSettingsBackup, uploadSettingsBackup } from "@utils/settingsSync"; import { Button, Card, Text } from "@webpack/common"; function BackupAndRestoreTab() { diff --git a/src/components/settings/tabs/sync/CloudTab.tsx b/src/components/settings/tabs/sync/CloudTab.tsx index 175e76ef..73526bcd 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"; @@ -25,9 +26,7 @@ import { Grid } from "@components/Grid"; import { Link } from "@components/Link"; import { Paragraph } from "@components/Paragraph"; import { SettingsTab, wrapTab } from "@components/settings/tabs/BaseTab"; -import { authorizeCloud, checkCloudUrlCsp, cloudLogger, deauthorizeCloud, getCloudAuth, getCloudUrl } from "@utils/cloud"; import { Margins } from "@utils/margins"; -import { deleteCloudSettings, getCloudSettings, putCloudSettings } from "@utils/settingsSync"; import { Alerts, Button, Forms, Tooltip } from "@webpack/common"; function validateUrl(url: string) { @@ -39,34 +38,6 @@ function validateUrl(url: string) { } } -async function eraseAllData() { - if (!await checkCloudUrlCsp()) return; - - 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; @@ -181,7 +152,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/themes/LocalThemesTab.tsx b/src/components/settings/tabs/themes/LocalThemesTab.tsx index a958ab77..cea4d730 100644 --- a/src/components/settings/tabs/themes/LocalThemesTab.tsx +++ b/src/components/settings/tabs/themes/LocalThemesTab.tsx @@ -4,6 +4,7 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ +import { isPluginEnabled } from "@api/PluginManager"; import { Settings, useSettings } from "@api/Settings"; import { classNameFactory } from "@api/Styles"; import { FolderIcon, PaintbrushIcon, PencilIcon, PlusIcon, RestartIcon } from "@components/Icons"; @@ -11,9 +12,9 @@ import { Link } from "@components/Link"; import { QuickAction, QuickActionCard } from "@components/settings/QuickAction"; import { openPluginModal } from "@components/settings/tabs/plugins/PluginModal"; import { UserThemeHeader } from "@main/themes"; +import ClientThemePlugin from "@plugins/clientTheme"; import { findLazy } from "@webpack"; import { Card, Forms, useEffect, useRef, useState } from "@webpack/common"; -import ClientThemePlugin from "plugins/clientTheme"; import type { ComponentType, Ref, SyntheticEvent } from "react"; import { ThemeCard } from "./ThemeCard"; @@ -140,7 +141,7 @@ export function LocalThemesTab() { Icon={PaintbrushIcon} /> - {Vencord.Plugins.isPluginEnabled(ClientThemePlugin.name) && ( + {isPluginEnabled(ClientThemePlugin.name) && ( openPluginModal(ClientThemePlugin)} diff --git a/src/components/settings/tabs/vencord/DonateButton.tsx b/src/components/settings/tabs/vencord/DonateButton.tsx index b9910e66..14975377 100644 --- a/src/components/settings/tabs/vencord/DonateButton.tsx +++ b/src/components/settings/tabs/vencord/DonateButton.tsx @@ -5,9 +5,9 @@ */ import DonateButton from "@components/settings/DonateButton"; +import BadgeAPI from "@plugins/_api/badges"; import { DONOR_ROLE_ID, VENCORD_GUILD_ID } from "@utils/constants"; import { Button, GuildMemberStore } from "@webpack/common"; -import BadgeAPI from "plugins/_api/badges"; export const isDonor = (userId: string) => !!( BadgeAPI.getDonorBadges(userId)?.length > 0 diff --git a/src/components/settings/tabs/vencord/index.tsx b/src/components/settings/tabs/vencord/index.tsx index d02f978d..a4d63747 100644 --- a/src/components/settings/tabs/vencord/index.tsx +++ b/src/components/settings/tabs/vencord/index.tsx @@ -20,7 +20,7 @@ import { openNotificationLogModal } from "@api/Notifications/notificationLog"; import { useSettings } from "@api/Settings"; import { Divider } from "@components/Divider"; import { FormSwitch } from "@components/FormSwitch"; -import { FolderIcon, GithubIcon, LogIcon, PaintbrushIcon, RestartIcon } from "@components/index"; +import { FolderIcon, GithubIcon, LogIcon, PaintbrushIcon, RestartIcon } from "@components/Icons"; import { QuickAction, QuickActionCard } from "@components/settings/QuickAction"; import { SpecialCard } from "@components/settings/SpecialCard"; import { SettingsTab, wrapTab } from "@components/settings/tabs/BaseTab"; diff --git a/src/debug/runReporter.ts b/src/debug/runReporter.ts index 39071a0c..529123cd 100644 --- a/src/debug/runReporter.ts +++ b/src/debug/runReporter.ts @@ -4,11 +4,11 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ +import { addPatch } from "@api/PluginManager"; import { Logger } from "@utils/Logger"; import * as Webpack from "@webpack"; -import { getBuildNumber, patchTimings } from "@webpack/patcher"; +import { getBuildNumber, patches, patchTimings } from "@webpack/patcher"; -import { addPatch, patches } from "../plugins"; import { loadLazyChunks } from "./loadLazyChunks"; async function runReporter() { diff --git a/src/plugins/_api/badges/index.tsx b/src/plugins/_api/badges/index.tsx index 4c346689..d3109b75 100644 --- a/src/plugins/_api/badges/index.tsx +++ b/src/plugins/_api/badges/index.tsx @@ -25,9 +25,10 @@ import { Heart } from "@components/Heart"; import DonateButton from "@components/settings/DonateButton"; import { openContributorModal } from "@components/settings/tabs"; import { Devs } from "@utils/constants"; +import { copyWithToast } from "@utils/discord"; import { Logger } from "@utils/Logger"; import { Margins } from "@utils/margins"; -import { copyWithToast, shouldShowContributorBadge } from "@utils/misc"; +import { shouldShowContributorBadge } from "@utils/misc"; import { closeModal, ModalContent, ModalFooter, ModalHeader, ModalRoot, openModal } from "@utils/modal"; import definePlugin from "@utils/types"; import { User } from "@vencord/discord-types"; diff --git a/src/plugins/_core/supportHelper.tsx b/src/plugins/_core/supportHelper.tsx index cdae5a3a..b72050bf 100644 --- a/src/plugins/_core/supportHelper.tsx +++ b/src/plugins/_core/supportHelper.tsx @@ -16,6 +16,7 @@ * along with this program. If not, see . */ +import { isPluginEnabled } from "@api/PluginManager"; import { definePluginSettings } from "@api/Settings"; import { getUserSettingLazy } from "@api/UserSettings"; import ErrorBoundary from "@components/ErrorBoundary"; @@ -95,7 +96,6 @@ async function generateDebugInfoMessage() { } const commonIssues = { - "NoRPC enabled": Vencord.Plugins.isPluginEnabled("NoRPC"), "Activity Sharing disabled": tryOrElse(() => !ShowCurrentGame.getSetting(), false), "Vencord DevBuild": !IS_STANDALONE, "Has UserPlugins": Object.values(PluginMeta).some(m => m.userPlugin), @@ -114,7 +114,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)); + .filter(p => isPluginEnabled(p) && !isApiPlugin(p)); const enabledStockPlugins = enabledPlugins.filter(p => !PluginMeta[p].userPlugin); const enabledUserPlugins = enabledPlugins.filter(p => PluginMeta[p].userPlugin); diff --git a/src/plugins/betterRoleDot/index.ts b/src/plugins/betterRoleDot/index.ts index bdafe02c..9928a2a4 100644 --- a/src/plugins/betterRoleDot/index.ts +++ b/src/plugins/betterRoleDot/index.ts @@ -18,7 +18,7 @@ import { Settings } from "@api/Settings"; import { Devs } from "@utils/constants"; -import { copyWithToast } from "@utils/misc"; +import { copyWithToast } from "@utils/discord"; import definePlugin, { OptionType } from "@utils/types"; export default definePlugin({ diff --git a/src/plugins/betterSessions/components/RenameButton.tsx b/src/plugins/betterSessions/components/RenameButton.tsx index 4fd81f1f..b9857f01 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 568e2632..e3faa209 100644 --- a/src/plugins/betterSessions/components/RenameModal.tsx +++ b/src/plugins/betterSessions/components/RenameModal.tsx @@ -16,13 +16,12 @@ * along with this program. If not, see . */ +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, Forms, 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 3015dc47..de9d70af 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 8a3e5b2a..14f835f9 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 9e7f867e..7035387e 100644 --- a/src/plugins/clientTheme/components/Settings.tsx +++ b/src/plugins/clientTheme/components/Settings.tsx @@ -6,13 +6,13 @@ import { classNameFactory } from "@api/Styles"; import { ErrorCard } from "@components/ErrorCard"; +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, Forms, 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 feeada9e..884d3d5c 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 58e7303a..e03197fe 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 28b5bb92..5bb79515 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 eaccc9b7..635b8d31 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 78f4f9d0..225386a0 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 637d049e..019cc431 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 7f3468fd..a2e85a5d 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 e2bba6c0..780301ed 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 588bbdf9..3adb9847 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 176507ef..265e8f58 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 361ecf89..6b94a7b6 100644 --- a/src/plugins/decor/settings.tsx +++ b/src/plugins/decor/settings.tsx @@ -12,13 +12,14 @@ import { closeAllModals } from "@utils/modal"; import { OptionType } from "@utils/types"; import { FluxDispatcher, Forms } 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 deaeef63..b5693a45 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 91265285..5fe6cba5 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 db3f0090..71b70044 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 62d7b4ba..a43d6868 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 b5dc792e..4352fadd 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 8fe41fc9..71b9c670 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 6b572055..df50c02a 100644 --- a/src/plugins/decor/ui/modals/ChangeDecorationModal.tsx +++ b/src/plugins/decor/ui/modals/ChangeDecorationModal.tsx @@ -7,26 +7,25 @@ import { Button as NewButton } from "@components/Button"; import ErrorBoundary from "@components/ErrorBoundary"; import { Flex } from "@components/Flex"; -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, Text, 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 9c9ac371..e668f65a 100644 --- a/src/plugins/decor/ui/modals/CreateDecorationModal.tsx +++ b/src/plugins/decor/ui/modals/CreateDecorationModal.tsx @@ -6,17 +6,16 @@ import ErrorBoundary from "@components/ErrorBoundary"; import { Link } from "@components/Link"; +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, Forms, GuildStore, NavigationRouter, Text, 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 49a816db..a4d6624d 100644 --- a/src/plugins/decor/ui/modals/GuidelinesModal.tsx +++ b/src/plugins/decor/ui/modals/GuidelinesModal.tsx @@ -6,11 +6,11 @@ import { Flex } from "@components/Flex"; import { Link } from "@components/Link"; +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, Forms, Text } 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 bb9a6daa..9621b3e0 100644 --- a/src/plugins/fakeNitro/index.tsx +++ b/src/plugins/fakeNitro/index.tsx @@ -18,8 +18,8 @@ import { addMessagePreEditListener, addMessagePreSendListener, removeMessagePreEditListener, removeMessagePreSendListener } from "@api/MessageEvents"; import { definePluginSettings } from "@api/Settings"; +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"; @@ -706,9 +706,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; @@ -757,7 +758,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 f69e24c7..e6de5df0 100644 --- a/src/plugins/fakeProfileThemes/index.tsx +++ b/src/plugins/fakeProfileThemes/index.tsx @@ -17,15 +17,15 @@ */ // This plugin is a port from Alyxia's Vendetta plugin -import "./index.css"; +import "./styles.css"; import { definePluginSettings } from "@api/Settings"; import { Divider } from "@components/Divider"; import ErrorBoundary from "@components/ErrorBoundary"; 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"; diff --git a/src/plugins/fakeProfileThemes/index.css b/src/plugins/fakeProfileThemes/styles.css similarity index 100% rename from src/plugins/fakeProfileThemes/index.css rename to src/plugins/fakeProfileThemes/styles.css diff --git a/src/plugins/imageZoom/components/Magnifier.tsx b/src/plugins/imageZoom/components/Magnifier.tsx index d68f916e..dbe19607 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/components/DecryptionModal.tsx b/src/plugins/invisibleChat.desktop/components/DecryptionModal.tsx deleted file mode 100644 index b4bf6eb9..00000000 --- a/src/plugins/invisibleChat.desktop/components/DecryptionModal.tsx +++ /dev/null @@ -1,77 +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 { - ModalContent, - ModalFooter, - ModalHeader, - ModalRoot, - openModal, -} from "@utils/modal"; -import { Button, Forms, React, TextInput } from "@webpack/common"; - -import { decrypt } from "../index"; - -export function DecModal(props: any) { - const encryptedMessage: string = props?.message?.content; - const [password, setPassword] = React.useState("password"); - - return ( - - - Decrypt Message - - - - Message with Encryption - - Password - - - - - - - - - ); -} - -export function buildDecModal(msg: any): any { - openModal((props: any) => ); -} diff --git a/src/plugins/invisibleChat.desktop/components/EncryptionModal.tsx b/src/plugins/invisibleChat.desktop/components/EncryptionModal.tsx deleted file mode 100644 index ecc0c136..00000000 --- a/src/plugins/invisibleChat.desktop/components/EncryptionModal.tsx +++ /dev/null @@ -1,112 +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 { FormSwitch } from "@components/FormSwitch"; -import { insertTextIntoChatInputBox } from "@utils/discord"; -import { - ModalContent, - ModalFooter, - ModalHeader, - ModalProps, - ModalRoot, - openModal, -} from "@utils/modal"; -import { Button, Forms, React, TextInput } from "@webpack/common"; - -import { encrypt } from "../index"; - -function EncModal(props: ModalProps) { - const [secret, setSecret] = React.useState(""); - const [cover, setCover] = React.useState(""); - const [password, setPassword] = React.useState("password"); - const [noCover, setNoCover] = React.useState(false); - - const isValid = secret && (noCover || (cover && cover.trim().split(" ").length > 1)); - - return ( - - - Encrypt Message - - - - Secret - { - setSecret(e); - }} - /> - Cover (2 or more Words!!) - { - setCover(e); - }} - /> - Password - { - setPassword(e); - }} - /> - { - setNoCover(e); - }} - /> - - - - - - - - ); -} - -export function buildEncModal(): any { - openModal(props => ); -} diff --git a/src/plugins/invisibleChat.desktop/index.tsx b/src/plugins/invisibleChat.desktop/index.tsx deleted file mode 100644 index e6ba63e4..00000000 --- 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/messageClickActions/index.ts b/src/plugins/messageClickActions/index.ts index 148998f8..6404bd6f 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"); @@ -93,7 +94,7 @@ export default definePlugin({ 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) + const shouldMention = isPluginEnabled(NoReplyMentionPlugin.name) ? NoReplyMentionPlugin.shouldMention(msg, isShiftPress) : !isShiftPress; diff --git a/src/plugins/permissionsViewer/components/RolesAndUsersPermissions.tsx b/src/plugins/permissionsViewer/components/RolesAndUsersPermissions.tsx index 0b28f117..996b25f1 100644 --- a/src/plugins/permissionsViewer/components/RolesAndUsersPermissions.tsx +++ b/src/plugins/permissionsViewer/components/RolesAndUsersPermissions.tsx @@ -19,6 +19,7 @@ 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"; @@ -27,7 +28,6 @@ import { findByCodeLazy } from "@webpack"; import { ContextMenuApi, FluxDispatcher, GuildMemberStore, GuildRoleStore, i18n, Menu, PermissionsBits, ScrollerThin, Text, 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 e5bb2722..1219d2fc 100644 --- a/src/plugins/permissionsViewer/components/UserPermissions.tsx +++ b/src/plugins/permissionsViewer/components/UserPermissions.tsx @@ -18,6 +18,7 @@ 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"; @@ -25,7 +26,6 @@ import { filters, findBulk, proxyLazyWebpack } from "@webpack"; import { PermissionsBits, Text, 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 61f564ec..e18ad2ab 100644 --- a/src/plugins/pinDms/components/CreateCategoryModal.tsx +++ b/src/plugins/pinDms/components/CreateCategoryModal.tsx @@ -6,13 +6,12 @@ import { classNameFactory } from "@api/Styles"; import { Divider } from "@components/Divider"; +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, Forms, Text, 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 6fc4e674..5a241524 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 18782299..7671b54f 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/quickReply/index.ts b/src/plugins/quickReply/index.ts index f620be41..6dc34dee 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 78371f13..206cb63c 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/reviewDB/auth.tsx b/src/plugins/reviewDB/auth.tsx index 8d9789dd..e25119e5 100644 --- a/src/plugins/reviewDB/auth.tsx +++ b/src/plugins/reviewDB/auth.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 { Logger } from "@utils/Logger"; import { openModal } from "@utils/modal"; import { OAuth2AuthorizeModal, showToast, Toasts, UserStore } from "@webpack/common"; diff --git a/src/plugins/reviewDB/components/BlockedUserModal.tsx b/src/plugins/reviewDB/components/BlockedUserModal.tsx index 8b827174..5ad48948 100644 --- a/src/plugins/reviewDB/components/BlockedUserModal.tsx +++ b/src/plugins/reviewDB/components/BlockedUserModal.tsx @@ -4,16 +4,15 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ +import { Auth } from "@plugins/reviewDB/auth"; +import { ReviewDBUser } from "@plugins/reviewDB/entities"; +import { fetchBlocks, unblockUser } from "@plugins/reviewDB/reviewDbApi"; +import { cl } from "@plugins/reviewDB/utils"; import { Logger } from "@utils/Logger"; import { ModalCloseButton, ModalContent, ModalHeader, ModalRoot, openModal } from "@utils/modal"; import { useAwaiter } from "@utils/react"; import { Forms, Tooltip, useState } from "@webpack/common"; -import { Auth } from "../auth"; -import { ReviewDBUser } from "../entities"; -import { fetchBlocks, unblockUser } from "../reviewDbApi"; -import { cl } from "../utils"; - function UnblockButton(props: { onClick?(): void; }) { return ( diff --git a/src/plugins/reviewDB/components/ReviewBadge.tsx b/src/plugins/reviewDB/components/ReviewBadge.tsx index 665b9bb0..dc248559 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 3922cc7f..effd5c4e 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 1485022d..9cc1e577 100644 --- a/src/plugins/reviewDB/components/ReviewModal.tsx +++ b/src/plugins/reviewDB/components/ReviewModal.tsx @@ -17,14 +17,14 @@ */ 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, Text, 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 42ab0938..7de4044a 100644 --- a/src/plugins/reviewDB/components/ReviewsView.tsx +++ b/src/plugins/reviewDB/components/ReviewsView.tsx @@ -16,15 +16,15 @@ * along with this program. If not, see . */ +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 { Forms, 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 a5af9bc4..faa642fc 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 91e179b7..8ca9662e 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 408de154..efbf947e 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 2794234d..5c924f8e 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 153b3cdd..6ec81105 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 320dde97..7f2888c5 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 b4682240..8bacf0cb 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 020d77db..5413db0e 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 1319a2f2..ee782ec0 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 c0080a68..ee15fc5a 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); } diff --git a/src/plugins/showHiddenChannels/components/HiddenChannelLockScreen.tsx b/src/plugins/showHiddenChannels/components/HiddenChannelLockScreen.tsx index 4543301b..7dec55ac 100644 --- a/src/plugins/showHiddenChannels/components/HiddenChannelLockScreen.tsx +++ b/src/plugins/showHiddenChannels/components/HiddenChannelLockScreen.tsx @@ -16,16 +16,18 @@ * along with this program. If not, see . */ +import { isPluginEnabled } from "@api/PluginManager"; import { Settings } from "@api/Settings"; 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, Text, 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 { @@ -274,7 +276,7 @@ function HiddenChannelLockScreen({ channel }: { channel: ExtendedChannel; }) { }
- {Vencord.Plugins.isPluginEnabled("PermissionsViewer") && ( + {isPluginEnabled(PermissionsViewerPlugin.name) && ( {({ onMouseLeave, onMouseEnter }) => (