refactor: fix circular dependency issues & improve organisation (#3729)
Co-authored-by: Nuckyz <61953774+Nuckyz@users.noreply.github.com>
This commit is contained in:
parent
40fe13feda
commit
6afcce39dd
106 changed files with 1039 additions and 2273 deletions
|
|
@ -19,14 +19,16 @@
|
||||||
/// <reference path="../src/modules.d.ts" />
|
/// <reference path="../src/modules.d.ts" />
|
||||||
/// <reference path="../src/globals.d.ts" />
|
/// <reference path="../src/globals.d.ts" />
|
||||||
|
|
||||||
|
// 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 monacoHtmlLocal from "file://monacoWin.html?minify";
|
||||||
import * as DataStore from "../src/api/DataStore";
|
import * as DataStore from "@api/DataStore";
|
||||||
import { debounce, localStorage } from "../src/utils";
|
import type { Settings } from "@api/Settings";
|
||||||
import { EXTENSION_BASE_URL } from "../src/utils/web-metadata";
|
import { getThemeInfo } from "@main/themes";
|
||||||
import { getTheme, Theme } from "../src/utils/discord";
|
import { debounce } from "@shared/debounce";
|
||||||
import { getThemeInfo } from "../src/main/themes";
|
import { localStorage } from "@utils/localStorage";
|
||||||
import { Settings } from "../src/Vencord";
|
|
||||||
import { getStylusWebStoreUrl } from "@utils/web";
|
import { getStylusWebStoreUrl } from "@utils/web";
|
||||||
|
import { EXTENSION_BASE_URL } from "@utils/web-metadata";
|
||||||
|
|
||||||
// listeners for ipc.on
|
// listeners for ipc.on
|
||||||
const cssListeners = new Set<(css: string) => void>();
|
const cssListeners = new Set<(css: string) => void>();
|
||||||
|
|
@ -90,6 +92,8 @@ window.VencordNative = {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { getTheme, Theme } = require("@utils/discord");
|
||||||
|
|
||||||
win.baseUrl = EXTENSION_BASE_URL;
|
win.baseUrl = EXTENSION_BASE_URL;
|
||||||
win.setCss = setCssDebounced;
|
win.setCss = setCssDebounced;
|
||||||
win.getCurrentCss = () => VencordNative.quickCss.get();
|
win.getCurrentCss = () => VencordNative.quickCss.get();
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@
|
||||||
"@types/chrome": "^0.0.312",
|
"@types/chrome": "^0.0.312",
|
||||||
"@types/diff": "^7.0.2",
|
"@types/diff": "^7.0.2",
|
||||||
"@types/lodash": "^4.17.14",
|
"@types/lodash": "^4.17.14",
|
||||||
"@types/node": "^22.13.13",
|
"@types/node": "^24.10.1",
|
||||||
"@types/react": "^19.0.10",
|
"@types/react": "^19.0.10",
|
||||||
"@types/react-dom": "^19.0.4",
|
"@types/react-dom": "^19.0.4",
|
||||||
"@types/yazl": "^2.4.5",
|
"@types/yazl": "^2.4.5",
|
||||||
|
|
@ -74,7 +74,7 @@
|
||||||
"ts-pattern": "^5.6.0",
|
"ts-pattern": "^5.6.0",
|
||||||
"tsx": "^4.19.3",
|
"tsx": "^4.19.3",
|
||||||
"type-fest": "^4.38.0",
|
"type-fest": "^4.38.0",
|
||||||
"typescript": "^5.8.2",
|
"typescript": "^5.9.3",
|
||||||
"typescript-eslint": "^8.28.0",
|
"typescript-eslint": "^8.28.0",
|
||||||
"typescript-transform-paths": "^3.5.5",
|
"typescript-transform-paths": "^3.5.5",
|
||||||
"zip-local": "^0.3.5"
|
"zip-local": "^0.3.5"
|
||||||
|
|
|
||||||
298
pnpm-lock.yaml
generated
298
pnpm-lock.yaml
generated
|
|
@ -43,7 +43,7 @@ importers:
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@stylistic/eslint-plugin':
|
'@stylistic/eslint-plugin':
|
||||||
specifier: ^4.2.0
|
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':
|
'@types/chrome':
|
||||||
specifier: ^0.0.312
|
specifier: ^0.0.312
|
||||||
version: 0.0.312
|
version: 0.0.312
|
||||||
|
|
@ -54,8 +54,8 @@ importers:
|
||||||
specifier: ^4.17.14
|
specifier: ^4.17.14
|
||||||
version: 4.17.15
|
version: 4.17.15
|
||||||
'@types/node':
|
'@types/node':
|
||||||
specifier: ^22.13.13
|
specifier: ^24.10.1
|
||||||
version: 22.13.13
|
version: 24.10.1
|
||||||
'@types/react':
|
'@types/react':
|
||||||
specifier: ^19.0.10
|
specifier: ^19.0.10
|
||||||
version: 19.0.12
|
version: 19.0.12
|
||||||
|
|
@ -79,7 +79,7 @@ importers:
|
||||||
version: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)
|
version: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)
|
||||||
eslint-import-resolver-alias:
|
eslint-import-resolver-alias:
|
||||||
specifier: ^1.1.2
|
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:
|
eslint-plugin-path-alias:
|
||||||
specifier: 2.1.0
|
specifier: 2.1.0
|
||||||
version: 2.1.0(patch_hash=87545cb13985b338c8fa2ea7b0a3c75c57ad7fbc81c56b38d6c9438329957727)(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))
|
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))
|
version: 12.1.1(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))
|
||||||
eslint-plugin-unused-imports:
|
eslint-plugin-unused-imports:
|
||||||
specifier: ^4.1.4
|
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:
|
highlight.js:
|
||||||
specifier: 11.11.1
|
specifier: 11.11.1
|
||||||
version: 11.11.1
|
version: 11.11.1
|
||||||
|
|
@ -112,10 +112,10 @@ importers:
|
||||||
version: 34.2.0
|
version: 34.2.0
|
||||||
stylelint:
|
stylelint:
|
||||||
specifier: ^16.17.0
|
specifier: ^16.17.0
|
||||||
version: 16.17.0(typescript@5.8.2)
|
version: 16.17.0(typescript@5.9.3)
|
||||||
stylelint-config-standard:
|
stylelint-config-standard:
|
||||||
specifier: ^37.0.0
|
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:
|
ts-patch:
|
||||||
specifier: ^3.3.0
|
specifier: ^3.3.0
|
||||||
version: 3.3.0
|
version: 3.3.0
|
||||||
|
|
@ -129,14 +129,14 @@ importers:
|
||||||
specifier: ^4.38.0
|
specifier: ^4.38.0
|
||||||
version: 4.38.0
|
version: 4.38.0
|
||||||
typescript:
|
typescript:
|
||||||
specifier: ^5.8.2
|
specifier: ^5.9.3
|
||||||
version: 5.8.2
|
version: 5.9.3
|
||||||
typescript-eslint:
|
typescript-eslint:
|
||||||
specifier: ^8.28.0
|
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:
|
typescript-transform-paths:
|
||||||
specifier: ^3.5.5
|
specifier: ^3.5.5
|
||||||
version: 3.5.5(typescript@5.8.2)
|
version: 3.5.5(typescript@5.9.3)
|
||||||
zip-local:
|
zip-local:
|
||||||
specifier: ^0.3.5
|
specifier: ^0.3.5
|
||||||
version: 0.3.5
|
version: 0.3.5
|
||||||
|
|
@ -163,13 +163,13 @@ importers:
|
||||||
version: 22.13.13
|
version: 22.13.13
|
||||||
'@types/react':
|
'@types/react':
|
||||||
specifier: 18.3.1
|
specifier: 18.3.1
|
||||||
version: 19.0.12
|
version: 18.3.1
|
||||||
'@types/react-dom':
|
'@types/react-dom':
|
||||||
specifier: 18.3.1
|
specifier: 18.3.1
|
||||||
version: 18.3.1
|
version: 18.3.1
|
||||||
'@vencord/discord-types':
|
'@vencord/discord-types':
|
||||||
specifier: ^1.0.0
|
specifier: ^1.0.0
|
||||||
version: 1.0.0(@types/react@19.0.12)
|
version: 1.0.0(@types/react@18.3.1)
|
||||||
highlight.js:
|
highlight.js:
|
||||||
specifier: 11.11.1
|
specifier: 11.11.1
|
||||||
version: 11.11.1
|
version: 11.11.1
|
||||||
|
|
@ -529,6 +529,15 @@ packages:
|
||||||
'@types/node@22.13.13':
|
'@types/node@22.13.13':
|
||||||
resolution: {integrity: sha512-ClsL5nMwKaBRwPcCvH8E7+nU4GxHVx1axNvMZTFHMEfNI7oahimt26P5zjVCRrjiIWj6YFXfE1v3dEp94wLcGQ==}
|
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':
|
'@types/react-dom@18.3.1':
|
||||||
resolution: {integrity: sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==}
|
resolution: {integrity: sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==}
|
||||||
|
|
||||||
|
|
@ -537,6 +546,9 @@ packages:
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@types/react': ^19.0.0
|
'@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':
|
'@types/react@19.0.12':
|
||||||
resolution: {integrity: sha512-V6Ar115dBDrjbtXSrS+/Oruobc+qVbbUxDFC1RSbRqLt5SYvxxyIDrSC85RWml54g+jfNeEMZhEj7wW07ONQhA==}
|
resolution: {integrity: sha512-V6Ar115dBDrjbtXSrS+/Oruobc+qVbbUxDFC1RSbRqLt5SYvxxyIDrSC85RWml54g+jfNeEMZhEj7wW07ONQhA==}
|
||||||
|
|
||||||
|
|
@ -651,6 +663,10 @@ packages:
|
||||||
resolution: {integrity: sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==}
|
resolution: {integrity: sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
array-includes@3.1.9:
|
||||||
|
resolution: {integrity: sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==}
|
||||||
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
array-union@2.1.0:
|
array-union@2.1.0:
|
||||||
resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
|
resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
@ -887,6 +903,9 @@ packages:
|
||||||
csstype@3.1.3:
|
csstype@3.1.3:
|
||||||
resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
|
resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
|
||||||
|
|
||||||
|
csstype@3.2.1:
|
||||||
|
resolution: {integrity: sha512-98XGutrXoh75MlgLihlNxAGbUuFQc7l1cqcnEZlLNKc0UrVdPndgmaDmYTDDh929VS/eqTZV0rozmhu2qqT1/g==}
|
||||||
|
|
||||||
data-uri-to-buffer@6.0.2:
|
data-uri-to-buffer@6.0.2:
|
||||||
resolution: {integrity: sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==}
|
resolution: {integrity: sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==}
|
||||||
engines: {node: '>= 14'}
|
engines: {node: '>= 14'}
|
||||||
|
|
@ -1002,6 +1021,10 @@ packages:
|
||||||
resolution: {integrity: sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==}
|
resolution: {integrity: sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==}
|
||||||
engines: {node: '>= 0.4'}
|
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:
|
es-define-property@1.0.1:
|
||||||
resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==}
|
resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
@ -1057,8 +1080,8 @@ packages:
|
||||||
eslint-import-resolver-node@0.3.9:
|
eslint-import-resolver-node@0.3.9:
|
||||||
resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==}
|
resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==}
|
||||||
|
|
||||||
eslint-module-utils@2.12.0:
|
eslint-module-utils@2.12.1:
|
||||||
resolution: {integrity: sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==}
|
resolution: {integrity: sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==}
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@typescript-eslint/parser': '*'
|
'@typescript-eslint/parser': '*'
|
||||||
|
|
@ -1560,6 +1583,10 @@ packages:
|
||||||
resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==}
|
resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
is-negative-zero@2.0.3:
|
||||||
|
resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==}
|
||||||
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
is-number-object@1.1.1:
|
is-number-object@1.1.1:
|
||||||
resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==}
|
resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
@ -2063,6 +2090,11 @@ packages:
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
resolve@1.22.11:
|
||||||
|
resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==}
|
||||||
|
engines: {node: '>= 0.4'}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
resolve@2.0.0-next.5:
|
resolve@2.0.0-next.5:
|
||||||
resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==}
|
resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
@ -2207,6 +2239,10 @@ packages:
|
||||||
resolution: {integrity: sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==}
|
resolution: {integrity: sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==}
|
||||||
engines: {node: '>=0.10.0'}
|
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:
|
streamx@2.22.0:
|
||||||
resolution: {integrity: sha512-sLh1evHOzBy/iWRiR6d1zRcLao4gGZr3C1kzNz4fopCOKJb6xD9ub8Mpi9Mr1R6id5o43S+d93fI48UC5uM9aw==}
|
resolution: {integrity: sha512-sLh1evHOzBy/iWRiR6d1zRcLao4gGZr3C1kzNz4fopCOKJb6xD9ub8Mpi9Mr1R6id5o43S+d93fI48UC5uM9aw==}
|
||||||
|
|
||||||
|
|
@ -2374,8 +2410,8 @@ packages:
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
typescript: '>=3.6.5'
|
typescript: '>=3.6.5'
|
||||||
|
|
||||||
typescript@5.8.2:
|
typescript@5.9.3:
|
||||||
resolution: {integrity: sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==}
|
resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
|
||||||
engines: {node: '>=14.17'}
|
engines: {node: '>=14.17'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
|
@ -2386,6 +2422,12 @@ packages:
|
||||||
undici-types@6.20.0:
|
undici-types@6.20.0:
|
||||||
resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==}
|
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:
|
union-value@1.0.1:
|
||||||
resolution: {integrity: sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==}
|
resolution: {integrity: sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
@ -2719,9 +2761,9 @@ snapshots:
|
||||||
|
|
||||||
'@rtsao/scc@1.1.0': {}
|
'@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:
|
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: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)
|
||||||
eslint-visitor-keys: 4.2.0
|
eslint-visitor-keys: 4.2.0
|
||||||
espree: 10.3.0
|
espree: 10.3.0
|
||||||
|
|
@ -2769,53 +2811,68 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
undici-types: 6.20.0
|
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':
|
'@types/react-dom@18.3.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/react': 19.0.12
|
'@types/react': 18.3.1
|
||||||
|
|
||||||
'@types/react-dom@19.0.4(@types/react@19.0.12)':
|
'@types/react-dom@19.0.4(@types/react@19.0.12)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/react': 19.0.12
|
'@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':
|
'@types/react@19.0.12':
|
||||||
dependencies:
|
dependencies:
|
||||||
csstype: 3.1.3
|
csstype: 3.1.3
|
||||||
|
|
||||||
'@types/yauzl@2.10.3':
|
'@types/yauzl@2.10.3':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 22.13.13
|
'@types/node': 24.10.1
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@types/yazl@2.4.6':
|
'@types/yazl@2.4.6':
|
||||||
dependencies:
|
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:
|
dependencies:
|
||||||
'@eslint-community/regexpp': 4.12.1
|
'@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/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/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.8.2)
|
'@typescript-eslint/utils': 8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.9.3)
|
||||||
'@typescript-eslint/visitor-keys': 8.28.0
|
'@typescript-eslint/visitor-keys': 8.28.0
|
||||||
eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)
|
eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)
|
||||||
graphemer: 1.4.0
|
graphemer: 1.4.0
|
||||||
ignore: 5.3.2
|
ignore: 5.3.2
|
||||||
natural-compare: 1.4.0
|
natural-compare: 1.4.0
|
||||||
ts-api-utils: 2.1.0(typescript@5.8.2)
|
ts-api-utils: 2.1.0(typescript@5.9.3)
|
||||||
typescript: 5.8.2
|
typescript: 5.9.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- 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:
|
dependencies:
|
||||||
'@typescript-eslint/scope-manager': 8.28.0
|
'@typescript-eslint/scope-manager': 8.28.0
|
||||||
'@typescript-eslint/types': 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
|
'@typescript-eslint/visitor-keys': 8.28.0
|
||||||
debug: 4.4.0
|
debug: 4.4.0
|
||||||
eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)
|
eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)
|
||||||
typescript: 5.8.2
|
typescript: 5.9.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
|
@ -2824,20 +2881,20 @@ snapshots:
|
||||||
'@typescript-eslint/types': 8.28.0
|
'@typescript-eslint/types': 8.28.0
|
||||||
'@typescript-eslint/visitor-keys': 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:
|
dependencies:
|
||||||
'@typescript-eslint/typescript-estree': 8.28.0(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.8.2)
|
'@typescript-eslint/utils': 8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.9.3)
|
||||||
debug: 4.4.0
|
debug: 4.4.0
|
||||||
eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)
|
eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)
|
||||||
ts-api-utils: 2.1.0(typescript@5.8.2)
|
ts-api-utils: 2.1.0(typescript@5.9.3)
|
||||||
typescript: 5.8.2
|
typescript: 5.9.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@typescript-eslint/types@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)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/types': 8.28.0
|
'@typescript-eslint/types': 8.28.0
|
||||||
'@typescript-eslint/visitor-keys': 8.28.0
|
'@typescript-eslint/visitor-keys': 8.28.0
|
||||||
|
|
@ -2846,19 +2903,19 @@ snapshots:
|
||||||
is-glob: 4.0.3
|
is-glob: 4.0.3
|
||||||
minimatch: 9.0.5
|
minimatch: 9.0.5
|
||||||
semver: 7.7.1
|
semver: 7.7.1
|
||||||
ts-api-utils: 2.1.0(typescript@5.8.2)
|
ts-api-utils: 2.1.0(typescript@5.9.3)
|
||||||
typescript: 5.8.2
|
typescript: 5.9.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- 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:
|
dependencies:
|
||||||
'@eslint-community/eslint-utils': 4.5.1(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))
|
'@eslint-community/eslint-utils': 4.5.1(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))
|
||||||
'@typescript-eslint/scope-manager': 8.28.0
|
'@typescript-eslint/scope-manager': 8.28.0
|
||||||
'@typescript-eslint/types': 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)
|
eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)
|
||||||
typescript: 5.8.2
|
typescript: 5.9.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
|
@ -2877,9 +2934,9 @@ snapshots:
|
||||||
vscode-oniguruma: 1.7.0
|
vscode-oniguruma: 1.7.0
|
||||||
vscode-textmate: 5.2.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:
|
dependencies:
|
||||||
'@types/react': 19.0.12
|
'@types/react': 18.3.1
|
||||||
moment: 2.30.1
|
moment: 2.30.1
|
||||||
type-fest: 4.41.0
|
type-fest: 4.41.0
|
||||||
|
|
||||||
|
|
@ -2931,6 +2988,17 @@ snapshots:
|
||||||
get-intrinsic: 1.3.0
|
get-intrinsic: 1.3.0
|
||||||
is-string: 1.1.1
|
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-union@2.1.0: {}
|
||||||
|
|
||||||
array-unique@0.3.2: {}
|
array-unique@0.3.2: {}
|
||||||
|
|
@ -2949,7 +3017,7 @@ snapshots:
|
||||||
call-bind: 1.0.8
|
call-bind: 1.0.8
|
||||||
call-bound: 1.0.4
|
call-bound: 1.0.4
|
||||||
define-properties: 1.2.1
|
define-properties: 1.2.1
|
||||||
es-abstract: 1.23.9
|
es-abstract: 1.24.0
|
||||||
es-errors: 1.3.0
|
es-errors: 1.3.0
|
||||||
es-object-atoms: 1.1.1
|
es-object-atoms: 1.1.1
|
||||||
es-shim-unscopables: 1.1.0
|
es-shim-unscopables: 1.1.0
|
||||||
|
|
@ -3163,14 +3231,14 @@ snapshots:
|
||||||
|
|
||||||
copy-descriptor@0.1.1: {}
|
copy-descriptor@0.1.1: {}
|
||||||
|
|
||||||
cosmiconfig@9.0.0(typescript@5.8.2):
|
cosmiconfig@9.0.0(typescript@5.9.3):
|
||||||
dependencies:
|
dependencies:
|
||||||
env-paths: 2.2.1
|
env-paths: 2.2.1
|
||||||
import-fresh: 3.3.1
|
import-fresh: 3.3.1
|
||||||
js-yaml: 4.1.0
|
js-yaml: 4.1.0
|
||||||
parse-json: 5.2.0
|
parse-json: 5.2.0
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
typescript: 5.8.2
|
typescript: 5.9.3
|
||||||
|
|
||||||
cross-spawn@7.0.6:
|
cross-spawn@7.0.6:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
@ -3189,6 +3257,8 @@ snapshots:
|
||||||
|
|
||||||
csstype@3.1.3: {}
|
csstype@3.1.3: {}
|
||||||
|
|
||||||
|
csstype@3.2.1: {}
|
||||||
|
|
||||||
data-uri-to-buffer@6.0.2: {}
|
data-uri-to-buffer@6.0.2: {}
|
||||||
|
|
||||||
data-view-buffer@1.0.2:
|
data-view-buffer@1.0.2:
|
||||||
|
|
@ -3347,6 +3417,63 @@ snapshots:
|
||||||
unbox-primitive: 1.1.0
|
unbox-primitive: 1.1.0
|
||||||
which-typed-array: 1.1.19
|
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-define-property@1.0.1: {}
|
||||||
|
|
||||||
es-errors@1.3.0: {}
|
es-errors@1.3.0: {}
|
||||||
|
|
@ -3431,32 +3558,32 @@ snapshots:
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
source-map: 0.6.1
|
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:
|
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:
|
eslint-import-resolver-node@0.3.9:
|
||||||
dependencies:
|
dependencies:
|
||||||
debug: 3.2.7
|
debug: 3.2.7
|
||||||
is-core-module: 2.16.1
|
is-core-module: 2.16.1
|
||||||
resolve: 1.22.10
|
resolve: 1.22.11
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- 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:
|
dependencies:
|
||||||
debug: 3.2.7
|
debug: 3.2.7
|
||||||
optionalDependencies:
|
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: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)
|
||||||
eslint-import-resolver-node: 0.3.9
|
eslint-import-resolver-node: 0.3.9
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- 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:
|
dependencies:
|
||||||
'@rtsao/scc': 1.1.0
|
'@rtsao/scc': 1.1.0
|
||||||
array-includes: 3.1.8
|
array-includes: 3.1.9
|
||||||
array.prototype.findlastindex: 1.2.6
|
array.prototype.findlastindex: 1.2.6
|
||||||
array.prototype.flat: 1.3.3
|
array.prototype.flat: 1.3.3
|
||||||
array.prototype.flatmap: 1.3.3
|
array.prototype.flatmap: 1.3.3
|
||||||
|
|
@ -3464,7 +3591,7 @@ snapshots:
|
||||||
doctrine: 2.1.0
|
doctrine: 2.1.0
|
||||||
eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)
|
eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)
|
||||||
eslint-import-resolver-node: 0.3.9
|
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
|
hasown: 2.0.2
|
||||||
is-core-module: 2.16.1
|
is-core-module: 2.16.1
|
||||||
is-glob: 4.0.3
|
is-glob: 4.0.3
|
||||||
|
|
@ -3476,7 +3603,7 @@ snapshots:
|
||||||
string.prototype.trimend: 1.0.9
|
string.prototype.trimend: 1.0.9
|
||||||
tsconfig-paths: 3.15.0
|
tsconfig-paths: 3.15.0
|
||||||
optionalDependencies:
|
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:
|
transitivePeerDependencies:
|
||||||
- eslint-import-resolver-typescript
|
- eslint-import-resolver-typescript
|
||||||
- eslint-import-resolver-webpack
|
- eslint-import-resolver-webpack
|
||||||
|
|
@ -3521,11 +3648,11 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)
|
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:
|
dependencies:
|
||||||
eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)
|
eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)
|
||||||
optionalDependencies:
|
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:
|
eslint-scope@8.3.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
@ -4020,6 +4147,8 @@ snapshots:
|
||||||
|
|
||||||
is-map@2.0.3: {}
|
is-map@2.0.3: {}
|
||||||
|
|
||||||
|
is-negative-zero@2.0.3: {}
|
||||||
|
|
||||||
is-number-object@1.1.1:
|
is-number-object@1.1.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
call-bound: 1.0.4
|
call-bound: 1.0.4
|
||||||
|
|
@ -4307,7 +4436,7 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
call-bind: 1.0.8
|
call-bind: 1.0.8
|
||||||
define-properties: 1.2.1
|
define-properties: 1.2.1
|
||||||
es-abstract: 1.23.9
|
es-abstract: 1.24.0
|
||||||
|
|
||||||
object.pick@1.3.0:
|
object.pick@1.3.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
@ -4531,6 +4660,12 @@ snapshots:
|
||||||
path-parse: 1.0.7
|
path-parse: 1.0.7
|
||||||
supports-preserve-symlinks-flag: 1.0.0
|
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:
|
resolve@2.0.0-next.5:
|
||||||
dependencies:
|
dependencies:
|
||||||
is-core-module: 2.16.1
|
is-core-module: 2.16.1
|
||||||
|
|
@ -4702,13 +4837,18 @@ snapshots:
|
||||||
|
|
||||||
standalone-electron-types@34.2.0:
|
standalone-electron-types@34.2.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 22.13.13
|
'@types/node': 22.19.1
|
||||||
|
|
||||||
static-extend@0.1.2:
|
static-extend@0.1.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
define-property: 0.2.5
|
define-property: 0.2.5
|
||||||
object-copy: 0.1.0
|
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:
|
streamx@2.22.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
fast-fifo: 1.3.2
|
fast-fifo: 1.3.2
|
||||||
|
|
@ -4774,16 +4914,16 @@ snapshots:
|
||||||
|
|
||||||
strip-json-comments@3.1.1: {}
|
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:
|
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:
|
dependencies:
|
||||||
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.8.2))
|
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:
|
dependencies:
|
||||||
'@csstools/css-parser-algorithms': 3.0.4(@csstools/css-tokenizer@3.0.3)
|
'@csstools/css-parser-algorithms': 3.0.4(@csstools/css-tokenizer@3.0.3)
|
||||||
'@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
|
'@dual-bundle/import-meta-resolve': 4.1.0
|
||||||
balanced-match: 2.0.0
|
balanced-match: 2.0.0
|
||||||
colord: 2.9.3
|
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-functions-list: 3.2.3
|
||||||
css-tree: 3.1.0
|
css-tree: 3.1.0
|
||||||
debug: 4.4.0
|
debug: 4.4.0
|
||||||
|
|
@ -4890,9 +5030,9 @@ snapshots:
|
||||||
regex-not: 1.0.2
|
regex-not: 1.0.2
|
||||||
safe-regex: 1.1.0
|
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:
|
dependencies:
|
||||||
typescript: 5.8.2
|
typescript: 5.9.3
|
||||||
|
|
||||||
ts-patch@3.3.0:
|
ts-patch@3.3.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
@ -4964,22 +5104,22 @@ snapshots:
|
||||||
|
|
||||||
typed-query-selector@2.12.0: {}
|
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:
|
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/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.8.2)
|
'@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.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: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)
|
||||||
typescript: 5.8.2
|
typescript: 5.9.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
typescript-transform-paths@3.5.5(typescript@5.8.2):
|
typescript-transform-paths@3.5.5(typescript@5.9.3):
|
||||||
dependencies:
|
dependencies:
|
||||||
minimatch: 9.0.5
|
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:
|
unbox-primitive@1.1.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
@ -4990,6 +5130,10 @@ snapshots:
|
||||||
|
|
||||||
undici-types@6.20.0: {}
|
undici-types@6.20.0: {}
|
||||||
|
|
||||||
|
undici-types@6.21.0: {}
|
||||||
|
|
||||||
|
undici-types@7.16.0: {}
|
||||||
|
|
||||||
union-value@1.0.1:
|
union-value@1.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
arr-union: 3.1.0
|
arr-union: 3.1.0
|
||||||
|
|
|
||||||
|
|
@ -20,34 +20,32 @@
|
||||||
import "~plugins";
|
import "~plugins";
|
||||||
|
|
||||||
export * as Api from "./api";
|
export * as Api from "./api";
|
||||||
|
export * as Plugins from "./api/PluginManager";
|
||||||
export * as Components from "./components";
|
export * as Components from "./components";
|
||||||
export * as Plugins from "./plugins";
|
|
||||||
export * as Util from "./utils";
|
export * as Util from "./utils";
|
||||||
export * as QuickCss from "./utils/quickCss";
|
|
||||||
export * as Updater from "./utils/updater";
|
export * as Updater from "./utils/updater";
|
||||||
export * as Webpack from "./webpack";
|
export * as Webpack from "./webpack";
|
||||||
export * as WebpackPatcher from "./webpack/patchWebpack";
|
export * as WebpackPatcher from "./webpack/patchWebpack";
|
||||||
export { PlainSettings, Settings };
|
export { PlainSettings, Settings };
|
||||||
|
|
||||||
import "./utils/quickCss";
|
|
||||||
import "./webpack/patchWebpack";
|
|
||||||
|
|
||||||
import { addVencordUiStyles } from "@components/css";
|
import { addVencordUiStyles } from "@components/css";
|
||||||
import { openUpdaterModal } from "@components/settings/tabs/updater";
|
import { openUpdaterModal } from "@components/settings/tabs/updater";
|
||||||
|
import { debounce } from "@shared/debounce";
|
||||||
import { IS_WINDOWS } from "@utils/constants";
|
import { IS_WINDOWS } from "@utils/constants";
|
||||||
import { createAndAppendStyle } from "@utils/css";
|
import { createAndAppendStyle } from "@utils/css";
|
||||||
import { StartAt } from "@utils/types";
|
import { StartAt } from "@utils/types";
|
||||||
|
|
||||||
import { get as dsGet } from "./api/DataStore";
|
import { get as dsGet } from "./api/DataStore";
|
||||||
import { NotificationData, showNotification } from "./api/Notifications";
|
import { NotificationData, showNotification } from "./api/Notifications";
|
||||||
import { PlainSettings, Settings } from "./api/Settings";
|
import { initPluginManager, PMLogger, startAllPlugins } from "./api/PluginManager";
|
||||||
import { patches, PMLogger, startAllPlugins } from "./plugins";
|
import { PlainSettings, Settings, SettingsStore } from "./api/Settings";
|
||||||
|
import { getCloudSettings, putCloudSettings } from "./api/SettingsSync/cloudSync";
|
||||||
import { localStorage } from "./utils/localStorage";
|
import { localStorage } from "./utils/localStorage";
|
||||||
import { relaunch } from "./utils/native";
|
import { relaunch } from "./utils/native";
|
||||||
import { getCloudSettings, putCloudSettings } from "./utils/settingsSync";
|
|
||||||
import { checkForUpdates, update, UpdateLogger } from "./utils/updater";
|
import { checkForUpdates, update, UpdateLogger } from "./utils/updater";
|
||||||
import { onceReady } from "./webpack";
|
import { onceReady } from "./webpack";
|
||||||
import { SettingsRouter } from "./webpack/common";
|
import { SettingsRouter } from "./webpack/common";
|
||||||
|
import { patches } from "./webpack/patchWebpack";
|
||||||
|
|
||||||
if (IS_REPORTER) {
|
if (IS_REPORTER) {
|
||||||
require("./debug/runReporter");
|
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;
|
let notifiedForUpdatesThisSession = false;
|
||||||
|
|
@ -161,6 +171,7 @@ async function init() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
initPluginManager();
|
||||||
startAllPlugins(StartAt.Init);
|
startAllPlugins(StartAt.Init);
|
||||||
init();
|
init();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import BadgeAPIPlugin from "plugins/_api/badges";
|
import BadgeAPIPlugin from "@plugins/_api/badges";
|
||||||
import { ComponentType, HTMLProps } from "react";
|
import { ComponentType, HTMLProps } from "react";
|
||||||
|
|
||||||
export const enum BadgePosition {
|
export const enum BadgePosition {
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ import { addMessagePopoverButton, removeMessagePopoverButton } from "@api/Messag
|
||||||
import { Settings, SettingsStore } from "@api/Settings";
|
import { Settings, SettingsStore } from "@api/Settings";
|
||||||
import { disableStyle, enableStyle } from "@api/Styles";
|
import { disableStyle, enableStyle } from "@api/Styles";
|
||||||
import { Logger } from "@utils/Logger";
|
import { Logger } from "@utils/Logger";
|
||||||
|
import { onlyOnce } from "@utils/onlyOnce";
|
||||||
import { canonicalizeFind, canonicalizeReplacement } from "@utils/patches";
|
import { canonicalizeFind, canonicalizeReplacement } from "@utils/patches";
|
||||||
import { Patch, Plugin, PluginDef, ReporterTestable, StartAt } from "@utils/types";
|
import { Patch, Plugin, PluginDef, ReporterTestable, StartAt } from "@utils/types";
|
||||||
import { FluxEvents } from "@vencord/discord-types";
|
import { FluxEvents } from "@vencord/discord-types";
|
||||||
|
|
@ -35,27 +36,23 @@ import { FluxDispatcher } from "@webpack/common";
|
||||||
import { patches } from "@webpack/patcher";
|
import { patches } from "@webpack/patcher";
|
||||||
|
|
||||||
import Plugins from "~plugins";
|
import Plugins from "~plugins";
|
||||||
|
export { Plugins as plugins };
|
||||||
|
|
||||||
import { traceFunction } from "../debug/Tracer";
|
import { traceFunction } from "../debug/Tracer";
|
||||||
|
|
||||||
const logger = new Logger("PluginManager", "#a6d189");
|
const logger = new Logger("PluginManager", "#a6d189");
|
||||||
|
|
||||||
export const PMLogger = logger;
|
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 */
|
/** Whether we have subscribed to flux events of all the enabled plugins when FluxDispatcher was ready */
|
||||||
let enabledPluginsSubscribedFlux = false;
|
let enabledPluginsSubscribedFlux = false;
|
||||||
const subscribedFluxEventsPlugins = new Set<string>();
|
const subscribedFluxEventsPlugins = new Set<string>();
|
||||||
|
|
||||||
const pluginsValues = Object.values(Plugins);
|
|
||||||
const settings = Settings.plugins;
|
|
||||||
|
|
||||||
export function isPluginEnabled(p: string) {
|
export function isPluginEnabled(p: string) {
|
||||||
return (
|
return (
|
||||||
Plugins[p]?.required ||
|
Plugins[p]?.required ||
|
||||||
Plugins[p]?.isDependency ||
|
Plugins[p]?.isDependency ||
|
||||||
settings[p]?.enabled
|
Settings.plugins[p]?.enabled
|
||||||
) ?? false;
|
) ?? false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -94,85 +91,6 @@ function isReporterTestable(p: Plugin, part: ReporterTestable) {
|
||||||
: (p.reporterTestable & part) === part;
|
: (p.reporterTestable & part) === part;
|
||||||
}
|
}
|
||||||
|
|
||||||
const pluginKeysToBind: Array<keyof PluginDef & `${"on" | "render"}${string}`> = [
|
|
||||||
"onBeforeMessageEdit", "onBeforeMessageSend", "onMessageClick",
|
|
||||||
"renderChatBarButton", "renderMemberListDecorator", "renderMessageAccessory", "renderMessageDecoration", "renderMessagePopoverButton"
|
|
||||||
];
|
|
||||||
|
|
||||||
const neededApiPlugins = new Set<string>();
|
|
||||||
|
|
||||||
// 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) {
|
export const startAllPlugins = traceFunction("startAllPlugins", function startAllPlugins(target: StartAt) {
|
||||||
logger.info(`Starting plugins (stage ${target})`);
|
logger.info(`Starting plugins (stage ${target})`);
|
||||||
for (const name in Plugins) {
|
for (const name in Plugins) {
|
||||||
|
|
@ -188,6 +106,7 @@ export const startAllPlugins = traceFunction("startAllPlugins", function startAl
|
||||||
});
|
});
|
||||||
|
|
||||||
export function startDependenciesRecursive(p: Plugin) {
|
export function startDependenciesRecursive(p: Plugin) {
|
||||||
|
const settings = Settings.plugins;
|
||||||
let restartNeeded = false;
|
let restartNeeded = false;
|
||||||
const failures: string[] = [];
|
const failures: string[] = [];
|
||||||
|
|
||||||
|
|
@ -379,3 +298,87 @@ export const stopPlugin = traceFunction("stopPlugin", function stopPlugin(p: Plu
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}, p => `stopPlugin ${p.name}`);
|
}, p => `stopPlugin ${p.name}`);
|
||||||
|
|
||||||
|
export const initPluginManager = onlyOnce(function init() {
|
||||||
|
const pluginsValues = Object.values(Plugins);
|
||||||
|
const settings = Settings.plugins;
|
||||||
|
|
||||||
|
const pluginKeysToBind: Array<keyof PluginDef & `${"on" | "render"}${string}`> = [
|
||||||
|
"onBeforeMessageEdit", "onBeforeMessageSend", "onMessageClick",
|
||||||
|
"renderChatBarButton", "renderMemberListDecorator", "renderMessageAccessory", "renderMessageDecoration", "renderMessagePopoverButton"
|
||||||
|
];
|
||||||
|
|
||||||
|
const neededApiPlugins = new Set<string>();
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
@ -16,12 +16,9 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { debounce } from "@shared/debounce";
|
|
||||||
import { SettingsStore as SettingsStoreClass } from "@shared/SettingsStore";
|
import { SettingsStore as SettingsStoreClass } from "@shared/SettingsStore";
|
||||||
import { localStorage } from "@utils/localStorage";
|
|
||||||
import { Logger } from "@utils/Logger";
|
import { Logger } from "@utils/Logger";
|
||||||
import { mergeDefaults } from "@utils/mergeDefaults";
|
import { mergeDefaults } from "@utils/mergeDefaults";
|
||||||
import { putCloudSettings } from "@utils/settingsSync";
|
|
||||||
import { DefinedSettings, OptionType, SettingsChecks, SettingsDefinition } from "@utils/types";
|
import { DefinedSettings, OptionType, SettingsChecks, SettingsDefinition } from "@utils/types";
|
||||||
import { React, useEffect } from "@webpack/common";
|
import { React, useEffect } from "@webpack/common";
|
||||||
|
|
||||||
|
|
@ -111,14 +108,6 @@ const DefaultSettings: Settings = {
|
||||||
const settings = !IS_REPORTER ? VencordNative.settings.get() : {} as Settings;
|
const settings = !IS_REPORTER ? VencordNative.settings.get() : {} as Settings;
|
||||||
mergeDefaults(settings, DefaultSettings);
|
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, {
|
export const SettingsStore = new SettingsStoreClass(settings, {
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
getDefaultValue({
|
getDefaultValue({
|
||||||
|
|
@ -161,8 +150,6 @@ export const SettingsStore = new SettingsStoreClass(settings, {
|
||||||
if (!IS_REPORTER) {
|
if (!IS_REPORTER) {
|
||||||
SettingsStore.addGlobalChangeListener((_, path) => {
|
SettingsStore.addGlobalChangeListener((_, path) => {
|
||||||
SettingsStore.plain.cloud.settingsSyncVersion = Date.now();
|
SettingsStore.plain.cloud.settingsSyncVersion = Date.now();
|
||||||
localStorage.Vencord_settingsDirty = true;
|
|
||||||
saveSettingsOnFrequentAction();
|
|
||||||
VencordNative.settings.set(SettingsStore.plain, path);
|
VencordNative.settings.set(SettingsStore.plain, path);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,31 +1,18 @@
|
||||||
/*
|
/*
|
||||||
* Vencord, a modification for Discord's desktop app
|
* Vencord, a Discord client mod
|
||||||
* Copyright (c) 2023 Vendicated and contributors
|
* Copyright (c) 2025 Vendicated and contributors
|
||||||
*
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import * as DataStore from "@api/DataStore";
|
import * as DataStore from "@api/DataStore";
|
||||||
import { showNotification } from "@api/Notifications";
|
import { showNotification } from "@api/Notifications";
|
||||||
import { Settings } from "@api/Settings";
|
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 { Alerts, OAuth2AuthorizeModal, UserStore } from "@webpack/common";
|
||||||
|
|
||||||
import { Logger } from "./Logger";
|
export const logger = new Logger("SettingsSync:CloudSetup", "#39b7e0");
|
||||||
import { openModal } from "./modal";
|
|
||||||
import { relaunch } from "./native";
|
|
||||||
|
|
||||||
export const cloudLogger = new Logger("Cloud", "#39b7e0");
|
|
||||||
|
|
||||||
export const getCloudUrl = () => new URL(Settings.cloud.url);
|
export const getCloudUrl = () => new URL(Settings.cloud.url);
|
||||||
const getCloudUrlOrigin = () => getCloudUrl().origin;
|
const getCloudUrlOrigin = () => getCloudUrl().origin;
|
||||||
|
|
@ -137,7 +124,7 @@ export async function authorizeCloud() {
|
||||||
});
|
});
|
||||||
const { secret } = await res.json();
|
const { secret } = await res.json();
|
||||||
if (secret) {
|
if (secret) {
|
||||||
cloudLogger.info("Authorized with secret");
|
logger.info("Authorized with secret");
|
||||||
await setAuthorization(secret);
|
await setAuthorization(secret);
|
||||||
showNotification({
|
showNotification({
|
||||||
title: "Cloud Integration",
|
title: "Cloud Integration",
|
||||||
|
|
@ -152,7 +139,7 @@ export async function authorizeCloud() {
|
||||||
Settings.cloud.authenticated = false;
|
Settings.cloud.authenticated = false;
|
||||||
}
|
}
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
cloudLogger.error("Failed to authorize", e);
|
logger.error("Failed to authorize", e);
|
||||||
showNotification({
|
showNotification({
|
||||||
title: "Cloud Integration",
|
title: "Cloud Integration",
|
||||||
body: `Setup failed (${e.toString()}).`
|
body: `Setup failed (${e.toString()}).`
|
||||||
|
|
@ -1,116 +1,19 @@
|
||||||
/*
|
/*
|
||||||
* Vencord, a modification for Discord's desktop app
|
* Vencord, a Discord client mod
|
||||||
* Copyright (c) 2022 Vendicated and contributors
|
* Copyright (c) 2025 Vendicated and contributors
|
||||||
*
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { showNotification } from "@api/Notifications";
|
import { showNotification } from "@api/Notifications";
|
||||||
import { PlainSettings, Settings } from "@api/Settings";
|
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 { deflateSync, inflateSync } from "fflate";
|
||||||
|
|
||||||
import { checkCloudUrlCsp, getCloudAuth, getCloudUrl } from "./cloud";
|
import { checkCloudUrlCsp, deauthorizeCloud, getCloudAuth, getCloudUrl } from "./cloudSetup";
|
||||||
import { Logger } from "./Logger";
|
import { exportSettings, importSettings } from "./offline";
|
||||||
import { relaunch } from "./native";
|
|
||||||
import { chooseFile, saveFile } from "./web";
|
|
||||||
|
|
||||||
export async function importSettings(data: string) {
|
const logger = new Logger("SettingsSync:Cloud", "#39b7e0");
|
||||||
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<void> {
|
|
||||||
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");
|
|
||||||
|
|
||||||
export async function putCloudSettings(manual?: boolean) {
|
export async function putCloudSettings(manual?: boolean) {
|
||||||
const settings = await exportSettings({ minify: true });
|
const settings = await exportSettings({ minify: true });
|
||||||
|
|
@ -124,11 +27,11 @@ export async function putCloudSettings(manual?: boolean) {
|
||||||
Authorization: await getCloudAuth(),
|
Authorization: await getCloudAuth(),
|
||||||
"Content-Type": "application/octet-stream"
|
"Content-Type": "application/octet-stream"
|
||||||
},
|
},
|
||||||
body: deflateSync(new TextEncoder().encode(settings))
|
body: deflateSync(new TextEncoder().encode(settings)) as Uint8Array<ArrayBuffer>
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
cloudSettingsLogger.error(`Failed to sync up, API returned ${res.status}`);
|
logger.error(`Failed to sync up, API returned ${res.status}`);
|
||||||
showNotification({
|
showNotification({
|
||||||
title: "Cloud Settings",
|
title: "Cloud Settings",
|
||||||
body: `Could not synchronize settings to cloud (API returned ${res.status}).`,
|
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;
|
PlainSettings.cloud.settingsSyncVersion = written;
|
||||||
VencordNative.settings.set(PlainSettings);
|
VencordNative.settings.set(PlainSettings);
|
||||||
|
|
||||||
cloudSettingsLogger.info("Settings uploaded to cloud successfully");
|
logger.info("Settings uploaded to cloud successfully");
|
||||||
|
|
||||||
if (manual) {
|
if (manual) {
|
||||||
showNotification({
|
showNotification({
|
||||||
|
|
@ -151,7 +54,7 @@ export async function putCloudSettings(manual?: boolean) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
cloudSettingsLogger.error("Failed to sync up", e);
|
logger.error("Failed to sync up", e);
|
||||||
showNotification({
|
showNotification({
|
||||||
title: "Cloud Settings",
|
title: "Cloud Settings",
|
||||||
body: `Could not synchronize settings to the cloud (${e.toString()}).`,
|
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) {
|
if (res.status === 404) {
|
||||||
cloudSettingsLogger.info("No settings on the cloud");
|
logger.info("No settings on the cloud");
|
||||||
if (shouldNotify)
|
if (shouldNotify)
|
||||||
showNotification({
|
showNotification({
|
||||||
title: "Cloud Settings",
|
title: "Cloud Settings",
|
||||||
|
|
@ -185,7 +88,7 @@ export async function getCloudSettings(shouldNotify = true, force = false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res.status === 304) {
|
if (res.status === 304) {
|
||||||
cloudSettingsLogger.info("Settings up to date");
|
logger.info("Settings up to date");
|
||||||
if (shouldNotify)
|
if (shouldNotify)
|
||||||
showNotification({
|
showNotification({
|
||||||
title: "Cloud Settings",
|
title: "Cloud Settings",
|
||||||
|
|
@ -196,7 +99,7 @@ export async function getCloudSettings(shouldNotify = true, force = false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
cloudSettingsLogger.error(`Failed to sync down, API returned ${res.status}`);
|
logger.error(`Failed to sync down, API returned ${res.status}`);
|
||||||
showNotification({
|
showNotification({
|
||||||
title: "Cloud Settings",
|
title: "Cloud Settings",
|
||||||
body: `Could not synchronize settings from the cloud (API returned ${res.status}).`,
|
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;
|
PlainSettings.cloud.settingsSyncVersion = written;
|
||||||
VencordNative.settings.set(PlainSettings);
|
VencordNative.settings.set(PlainSettings);
|
||||||
|
|
||||||
cloudSettingsLogger.info("Settings loaded from cloud successfully");
|
logger.info("Settings loaded from cloud successfully");
|
||||||
if (shouldNotify)
|
if (shouldNotify)
|
||||||
showNotification({
|
showNotification({
|
||||||
title: "Cloud Settings",
|
title: "Cloud Settings",
|
||||||
|
|
@ -240,7 +143,7 @@ export async function getCloudSettings(shouldNotify = true, force = false) {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
cloudSettingsLogger.error("Failed to sync down", e);
|
logger.error("Failed to sync down", e);
|
||||||
showNotification({
|
showNotification({
|
||||||
title: "Cloud Settings",
|
title: "Cloud Settings",
|
||||||
body: `Could not synchronize settings from the cloud (${e.toString()}).`,
|
body: `Could not synchronize settings from the cloud (${e.toString()}).`,
|
||||||
|
|
@ -261,7 +164,7 @@ export async function deleteCloudSettings() {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
cloudSettingsLogger.error(`Failed to delete, API returned ${res.status}`);
|
logger.error(`Failed to delete, API returned ${res.status}`);
|
||||||
showNotification({
|
showNotification({
|
||||||
title: "Cloud Settings",
|
title: "Cloud Settings",
|
||||||
body: `Could not delete settings (API returned ${res.status}).`,
|
body: `Could not delete settings (API returned ${res.status}).`,
|
||||||
|
|
@ -270,14 +173,14 @@ export async function deleteCloudSettings() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cloudSettingsLogger.info("Settings deleted from cloud successfully");
|
logger.info("Settings deleted from cloud successfully");
|
||||||
showNotification({
|
showNotification({
|
||||||
title: "Cloud Settings",
|
title: "Cloud Settings",
|
||||||
body: "Settings deleted from cloud!",
|
body: "Settings deleted from cloud!",
|
||||||
color: "var(--green-360)"
|
color: "var(--green-360)"
|
||||||
});
|
});
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
cloudSettingsLogger.error("Failed to delete", e);
|
logger.error("Failed to delete", e);
|
||||||
showNotification({
|
showNotification({
|
||||||
title: "Cloud Settings",
|
title: "Cloud Settings",
|
||||||
body: `Could not delete settings (${e.toString()}).`,
|
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)"
|
||||||
|
});
|
||||||
|
}
|
||||||
95
src/api/SettingsSync/offline.ts
Normal file
95
src/api/SettingsSync/offline.ts
Normal file
|
|
@ -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<void> {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -17,9 +17,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Settings, SettingsStore } from "@api/Settings";
|
import { Settings, SettingsStore } from "@api/Settings";
|
||||||
import { ThemeStore } from "@webpack/common";
|
import { createAndAppendStyle } from "@utils/css";
|
||||||
|
import { ThemeStore } from "@vencord/discord-types";
|
||||||
import { createAndAppendStyle } from "./css";
|
|
||||||
|
|
||||||
let style: HTMLStyleElement;
|
let style: HTMLStyleElement;
|
||||||
let themesStyle: HTMLStyleElement;
|
let themesStyle: HTMLStyleElement;
|
||||||
|
|
@ -54,6 +53,8 @@ async function initThemes() {
|
||||||
|
|
||||||
const { themeLinks, enabledThemes } = Settings;
|
const { themeLinks, enabledThemes } = Settings;
|
||||||
|
|
||||||
|
const { ThemeStore } = require("@webpack/common/stores") as typeof import("@webpack/common/stores");
|
||||||
|
|
||||||
// "darker" and "midnight" both count as dark
|
// "darker" and "midnight" both count as dark
|
||||||
// This function is first called on DOMContentLoaded, so ThemeStore may not have been loaded yet
|
// This function is first called on DOMContentLoaded, so ThemeStore may not have been loaded yet
|
||||||
const activeTheme = ThemeStore == null
|
const activeTheme = ThemeStore == null
|
||||||
|
|
@ -102,16 +103,16 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||||
}
|
}
|
||||||
}, { once: true });
|
}, { once: true });
|
||||||
|
|
||||||
export function initQuickCssThemeStore() {
|
export function initQuickCssThemeStore(themeStore: ThemeStore) {
|
||||||
if (IS_USERSCRIPT) return;
|
if (IS_USERSCRIPT) return;
|
||||||
|
|
||||||
initThemes();
|
initThemes();
|
||||||
|
|
||||||
let currentTheme = ThemeStore.theme;
|
let currentTheme = themeStore.theme;
|
||||||
ThemeStore.addChangeListener(() => {
|
themeStore.addChangeListener(() => {
|
||||||
if (currentTheme === ThemeStore.theme) return;
|
if (currentTheme === themeStore.theme) return;
|
||||||
|
|
||||||
currentTheme = ThemeStore.theme;
|
currentTheme = themeStore.theme;
|
||||||
initThemes();
|
initThemes();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -20,6 +20,8 @@ import { proxyLazy } from "@utils/lazy";
|
||||||
import { Logger } from "@utils/Logger";
|
import { Logger } from "@utils/Logger";
|
||||||
import { findModuleId, proxyLazyWebpack, wreq } from "@webpack";
|
import { findModuleId, proxyLazyWebpack, wreq } from "@webpack";
|
||||||
|
|
||||||
|
import { isPluginEnabled } from "./PluginManager";
|
||||||
|
|
||||||
interface UserSettingDefinition<T> {
|
interface UserSettingDefinition<T> {
|
||||||
/**
|
/**
|
||||||
* Get the setting value
|
* Get the setting value
|
||||||
|
|
@ -45,7 +47,7 @@ interface UserSettingDefinition<T> {
|
||||||
|
|
||||||
export const UserSettings: Record<PropertyKey, UserSettingDefinition<any>> | undefined = proxyLazyWebpack(() => {
|
export const UserSettings: Record<PropertyKey, UserSettingDefinition<any>> | undefined = proxyLazyWebpack(() => {
|
||||||
const modId = findModuleId('"textAndImages","renderSpoilers"');
|
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);
|
return wreq(modId as any);
|
||||||
});
|
});
|
||||||
|
|
@ -57,7 +59,7 @@ export const UserSettings: Record<PropertyKey, UserSettingDefinition<any>> | und
|
||||||
* @param name The name of the setting
|
* @param name The name of the setting
|
||||||
*/
|
*/
|
||||||
export function getUserSetting<T = any>(group: string, name: string): UserSettingDefinition<T> | undefined {
|
export function getUserSetting<T = any>(group: string, name: string): UserSettingDefinition<T> | 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) {
|
for (const key in UserSettings) {
|
||||||
const userSetting = UserSettings[key];
|
const userSetting = UserSettings[key];
|
||||||
|
|
|
||||||
|
|
@ -29,9 +29,11 @@ import * as $MessagePopover from "./MessagePopover";
|
||||||
import * as $MessageUpdater from "./MessageUpdater";
|
import * as $MessageUpdater from "./MessageUpdater";
|
||||||
import * as $Notices from "./Notices";
|
import * as $Notices from "./Notices";
|
||||||
import * as $Notifications from "./Notifications";
|
import * as $Notifications from "./Notifications";
|
||||||
|
export * as PluginManager from "./PluginManager";
|
||||||
import * as $ServerList from "./ServerList";
|
import * as $ServerList from "./ServerList";
|
||||||
import * as $Settings from "./Settings";
|
import * as $Settings from "./Settings";
|
||||||
import * as $Styles from "./Styles";
|
import * as $Styles from "./Styles";
|
||||||
|
import * as $Themes from "./Themes";
|
||||||
import * as $UserSettings from "./UserSettings";
|
import * as $UserSettings from "./UserSettings";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -122,3 +124,8 @@ export const MessageUpdater = $MessageUpdater;
|
||||||
* An API allowing you to get an user setting
|
* An API allowing you to get an user setting
|
||||||
*/
|
*/
|
||||||
export const UserSettings = $UserSettings;
|
export const UserSettings = $UserSettings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Don't use this
|
||||||
|
*/
|
||||||
|
export const Themes = $Themes;
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,8 @@ import { Flex } from "@components/Flex";
|
||||||
import { HeadingTertiary } from "@components/Heading";
|
import { HeadingTertiary } from "@components/Heading";
|
||||||
import { SettingsTab, wrapTab } from "@components/settings/tabs/BaseTab";
|
import { SettingsTab, wrapTab } from "@components/settings/tabs/BaseTab";
|
||||||
import { debounce } from "@shared/debounce";
|
import { debounce } from "@shared/debounce";
|
||||||
|
import { copyWithToast } from "@utils/discord";
|
||||||
import { Margins } from "@utils/margins";
|
import { Margins } from "@utils/margins";
|
||||||
import { copyWithToast } from "@utils/misc";
|
|
||||||
import { stripIndent } from "@utils/text";
|
import { stripIndent } from "@utils/text";
|
||||||
import { ReplaceFn } from "@utils/types";
|
import { ReplaceFn } from "@utils/types";
|
||||||
import { search } from "@webpack";
|
import { search } from "@webpack";
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { showNotice } from "@api/Notices";
|
import { showNotice } from "@api/Notices";
|
||||||
|
import { isPluginEnabled, startDependenciesRecursive, startPlugin, stopPlugin } from "@api/PluginManager";
|
||||||
import { CogWheel, InfoIcon } from "@components/Icons";
|
import { CogWheel, InfoIcon } from "@components/Icons";
|
||||||
import { AddonCard } from "@components/settings/AddonCard";
|
import { AddonCard } from "@components/settings/AddonCard";
|
||||||
import { proxyLazy } from "@utils/lazy";
|
|
||||||
import { isObjectEmpty } from "@utils/misc";
|
import { isObjectEmpty } from "@utils/misc";
|
||||||
import { Plugin } from "@utils/types";
|
import { Plugin } from "@utils/types";
|
||||||
import { React, showToast, Toasts } from "@webpack/common";
|
import { React, showToast, Toasts } from "@webpack/common";
|
||||||
|
|
@ -16,9 +16,6 @@ import { Settings } from "Vencord";
|
||||||
import { cl, logger } from ".";
|
import { cl, logger } from ".";
|
||||||
import { openPluginModal } from "./PluginModal";
|
import { openPluginModal } from "./PluginModal";
|
||||||
|
|
||||||
// Avoid circular dependency
|
|
||||||
const { startDependenciesRecursive, startPlugin, stopPlugin, isPluginEnabled } = proxyLazy(() => require("plugins") as typeof import("plugins"));
|
|
||||||
|
|
||||||
interface PluginCardProps extends React.HTMLProps<HTMLDivElement> {
|
interface PluginCardProps extends React.HTMLProps<HTMLDivElement> {
|
||||||
plugin: Plugin;
|
plugin: Plugin;
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
import "./styles.css";
|
import "./styles.css";
|
||||||
|
|
||||||
import * as DataStore from "@api/DataStore";
|
import * as DataStore from "@api/DataStore";
|
||||||
|
import { isPluginEnabled } from "@api/PluginManager";
|
||||||
import { useSettings } from "@api/Settings";
|
import { useSettings } from "@api/Settings";
|
||||||
import { classNameFactory } from "@api/Styles";
|
import { classNameFactory } from "@api/Styles";
|
||||||
import { Divider } from "@components/Divider";
|
import { Divider } from "@components/Divider";
|
||||||
|
|
@ -157,7 +158,7 @@ function PluginSettings() {
|
||||||
|
|
||||||
const pluginFilter = (plugin: typeof Plugins[keyof typeof Plugins]) => {
|
const pluginFilter = (plugin: typeof Plugins[keyof typeof Plugins]) => {
|
||||||
const { status } = searchValue;
|
const { status } = searchValue;
|
||||||
const enabled = Vencord.Plugins.isPluginEnabled(plugin.name);
|
const enabled = isPluginEnabled(plugin.name);
|
||||||
|
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case SearchStatus.DISABLED:
|
case SearchStatus.DISABLED:
|
||||||
|
|
|
||||||
|
|
@ -16,11 +16,11 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { downloadSettingsBackup, uploadSettingsBackup } from "@api/SettingsSync/offline";
|
||||||
import { Flex } from "@components/Flex";
|
import { Flex } from "@components/Flex";
|
||||||
import { SettingsTab, wrapTab } from "@components/settings/tabs/BaseTab";
|
import { SettingsTab, wrapTab } from "@components/settings/tabs/BaseTab";
|
||||||
import { Margins } from "@utils/margins";
|
import { Margins } from "@utils/margins";
|
||||||
import { classes } from "@utils/misc";
|
import { classes } from "@utils/misc";
|
||||||
import { downloadSettingsBackup, uploadSettingsBackup } from "@utils/settingsSync";
|
|
||||||
import { Button, Card, Text } from "@webpack/common";
|
import { Button, Card, Text } from "@webpack/common";
|
||||||
|
|
||||||
function BackupAndRestoreTab() {
|
function BackupAndRestoreTab() {
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,9 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { showNotification } from "@api/Notifications";
|
import { useSettings } from "@api/Settings";
|
||||||
import { Settings, 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 { CheckedTextInput } from "@components/CheckedTextInput";
|
||||||
import { Divider } from "@components/Divider";
|
import { Divider } from "@components/Divider";
|
||||||
import { FormSwitch } from "@components/FormSwitch";
|
import { FormSwitch } from "@components/FormSwitch";
|
||||||
|
|
@ -25,9 +26,7 @@ import { Grid } from "@components/Grid";
|
||||||
import { Link } from "@components/Link";
|
import { Link } from "@components/Link";
|
||||||
import { Paragraph } from "@components/Paragraph";
|
import { Paragraph } from "@components/Paragraph";
|
||||||
import { SettingsTab, wrapTab } from "@components/settings/tabs/BaseTab";
|
import { SettingsTab, wrapTab } from "@components/settings/tabs/BaseTab";
|
||||||
import { authorizeCloud, checkCloudUrlCsp, cloudLogger, deauthorizeCloud, getCloudAuth, getCloudUrl } from "@utils/cloud";
|
|
||||||
import { Margins } from "@utils/margins";
|
import { Margins } from "@utils/margins";
|
||||||
import { deleteCloudSettings, getCloudSettings, putCloudSettings } from "@utils/settingsSync";
|
|
||||||
import { Alerts, Button, Forms, Tooltip } from "@webpack/common";
|
import { Alerts, Button, Forms, Tooltip } from "@webpack/common";
|
||||||
|
|
||||||
function validateUrl(url: string) {
|
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() {
|
function SettingsSyncSection() {
|
||||||
const { cloud } = useSettings(["cloud.authenticated", "cloud.settingsSync"]);
|
const { cloud } = useSettings(["cloud.authenticated", "cloud.settingsSync"]);
|
||||||
const sectionEnabled = cloud.authenticated && cloud.settingsSync;
|
const sectionEnabled = cloud.authenticated && cloud.settingsSync;
|
||||||
|
|
@ -181,7 +152,7 @@ function CloudTab() {
|
||||||
onClick={() => Alerts.show({
|
onClick={() => Alerts.show({
|
||||||
title: "Are you sure?",
|
title: "Are you sure?",
|
||||||
body: "Once your data is erased, we cannot recover it. There's no going back!",
|
body: "Once your data is erased, we cannot recover it. There's no going back!",
|
||||||
onConfirm: eraseAllData,
|
onConfirm: eraseAllCloudData,
|
||||||
confirmText: "Erase it!",
|
confirmText: "Erase it!",
|
||||||
confirmColor: "vc-cloud-erase-data-danger-btn",
|
confirmColor: "vc-cloud-erase-data-danger-btn",
|
||||||
cancelText: "Nevermind"
|
cancelText: "Nevermind"
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { isPluginEnabled } from "@api/PluginManager";
|
||||||
import { Settings, useSettings } from "@api/Settings";
|
import { Settings, useSettings } from "@api/Settings";
|
||||||
import { classNameFactory } from "@api/Styles";
|
import { classNameFactory } from "@api/Styles";
|
||||||
import { FolderIcon, PaintbrushIcon, PencilIcon, PlusIcon, RestartIcon } from "@components/Icons";
|
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 { QuickAction, QuickActionCard } from "@components/settings/QuickAction";
|
||||||
import { openPluginModal } from "@components/settings/tabs/plugins/PluginModal";
|
import { openPluginModal } from "@components/settings/tabs/plugins/PluginModal";
|
||||||
import { UserThemeHeader } from "@main/themes";
|
import { UserThemeHeader } from "@main/themes";
|
||||||
|
import ClientThemePlugin from "@plugins/clientTheme";
|
||||||
import { findLazy } from "@webpack";
|
import { findLazy } from "@webpack";
|
||||||
import { Card, Forms, useEffect, useRef, useState } from "@webpack/common";
|
import { Card, Forms, useEffect, useRef, useState } from "@webpack/common";
|
||||||
import ClientThemePlugin from "plugins/clientTheme";
|
|
||||||
import type { ComponentType, Ref, SyntheticEvent } from "react";
|
import type { ComponentType, Ref, SyntheticEvent } from "react";
|
||||||
|
|
||||||
import { ThemeCard } from "./ThemeCard";
|
import { ThemeCard } from "./ThemeCard";
|
||||||
|
|
@ -140,7 +141,7 @@ export function LocalThemesTab() {
|
||||||
Icon={PaintbrushIcon}
|
Icon={PaintbrushIcon}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{Vencord.Plugins.isPluginEnabled(ClientThemePlugin.name) && (
|
{isPluginEnabled(ClientThemePlugin.name) && (
|
||||||
<QuickAction
|
<QuickAction
|
||||||
text="Edit ClientTheme"
|
text="Edit ClientTheme"
|
||||||
action={() => openPluginModal(ClientThemePlugin)}
|
action={() => openPluginModal(ClientThemePlugin)}
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import DonateButton from "@components/settings/DonateButton";
|
import DonateButton from "@components/settings/DonateButton";
|
||||||
|
import BadgeAPI from "@plugins/_api/badges";
|
||||||
import { DONOR_ROLE_ID, VENCORD_GUILD_ID } from "@utils/constants";
|
import { DONOR_ROLE_ID, VENCORD_GUILD_ID } from "@utils/constants";
|
||||||
import { Button, GuildMemberStore } from "@webpack/common";
|
import { Button, GuildMemberStore } from "@webpack/common";
|
||||||
import BadgeAPI from "plugins/_api/badges";
|
|
||||||
|
|
||||||
export const isDonor = (userId: string) => !!(
|
export const isDonor = (userId: string) => !!(
|
||||||
BadgeAPI.getDonorBadges(userId)?.length > 0
|
BadgeAPI.getDonorBadges(userId)?.length > 0
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ import { openNotificationLogModal } from "@api/Notifications/notificationLog";
|
||||||
import { useSettings } from "@api/Settings";
|
import { useSettings } from "@api/Settings";
|
||||||
import { Divider } from "@components/Divider";
|
import { Divider } from "@components/Divider";
|
||||||
import { FormSwitch } from "@components/FormSwitch";
|
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 { QuickAction, QuickActionCard } from "@components/settings/QuickAction";
|
||||||
import { SpecialCard } from "@components/settings/SpecialCard";
|
import { SpecialCard } from "@components/settings/SpecialCard";
|
||||||
import { SettingsTab, wrapTab } from "@components/settings/tabs/BaseTab";
|
import { SettingsTab, wrapTab } from "@components/settings/tabs/BaseTab";
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,11 @@
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { addPatch } from "@api/PluginManager";
|
||||||
import { Logger } from "@utils/Logger";
|
import { Logger } from "@utils/Logger";
|
||||||
import * as Webpack from "@webpack";
|
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";
|
import { loadLazyChunks } from "./loadLazyChunks";
|
||||||
|
|
||||||
async function runReporter() {
|
async function runReporter() {
|
||||||
|
|
|
||||||
|
|
@ -25,9 +25,10 @@ import { Heart } from "@components/Heart";
|
||||||
import DonateButton from "@components/settings/DonateButton";
|
import DonateButton from "@components/settings/DonateButton";
|
||||||
import { openContributorModal } from "@components/settings/tabs";
|
import { openContributorModal } from "@components/settings/tabs";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
|
import { copyWithToast } from "@utils/discord";
|
||||||
import { Logger } from "@utils/Logger";
|
import { Logger } from "@utils/Logger";
|
||||||
import { Margins } from "@utils/margins";
|
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 { closeModal, ModalContent, ModalFooter, ModalHeader, ModalRoot, openModal } from "@utils/modal";
|
||||||
import definePlugin from "@utils/types";
|
import definePlugin from "@utils/types";
|
||||||
import { User } from "@vencord/discord-types";
|
import { User } from "@vencord/discord-types";
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { isPluginEnabled } from "@api/PluginManager";
|
||||||
import { definePluginSettings } from "@api/Settings";
|
import { definePluginSettings } from "@api/Settings";
|
||||||
import { getUserSettingLazy } from "@api/UserSettings";
|
import { getUserSettingLazy } from "@api/UserSettings";
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
|
|
@ -95,7 +96,6 @@ async function generateDebugInfoMessage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const commonIssues = {
|
const commonIssues = {
|
||||||
"NoRPC enabled": Vencord.Plugins.isPluginEnabled("NoRPC"),
|
|
||||||
"Activity Sharing disabled": tryOrElse(() => !ShowCurrentGame.getSetting(), false),
|
"Activity Sharing disabled": tryOrElse(() => !ShowCurrentGame.getSetting(), false),
|
||||||
"Vencord DevBuild": !IS_STANDALONE,
|
"Vencord DevBuild": !IS_STANDALONE,
|
||||||
"Has UserPlugins": Object.values(PluginMeta).some(m => m.userPlugin),
|
"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 isApiPlugin = (plugin: string) => plugin.endsWith("API") || plugins[plugin].required;
|
||||||
|
|
||||||
const enabledPlugins = Object.keys(plugins)
|
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 enabledStockPlugins = enabledPlugins.filter(p => !PluginMeta[p].userPlugin);
|
||||||
const enabledUserPlugins = enabledPlugins.filter(p => PluginMeta[p].userPlugin);
|
const enabledUserPlugins = enabledPlugins.filter(p => PluginMeta[p].userPlugin);
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
import { Settings } from "@api/Settings";
|
import { Settings } from "@api/Settings";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import { copyWithToast } from "@utils/misc";
|
import { copyWithToast } from "@utils/discord";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
|
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Button } from "@components/Button";
|
import { Button } from "@components/Button";
|
||||||
|
import { SessionInfo } from "@plugins/betterSessions/types";
|
||||||
import { openModal } from "@utils/modal";
|
import { openModal } from "@utils/modal";
|
||||||
|
|
||||||
import { SessionInfo } from "../types";
|
|
||||||
import { RenameModal } from "./RenameModal";
|
import { RenameModal } from "./RenameModal";
|
||||||
|
|
||||||
export function RenameButton({ session, state }: { session: SessionInfo["session"], state: [string, React.Dispatch<React.SetStateAction<string>>]; }) {
|
export function RenameButton({ session, state }: { session: SessionInfo["session"], state: [string, React.Dispatch<React.SetStateAction<string>>]; }) {
|
||||||
|
|
|
||||||
|
|
@ -16,13 +16,12 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { SessionInfo } from "@plugins/betterSessions/types";
|
||||||
|
import { getDefaultName, savedSessionsCache, saveSessionsToDataStore } from "@plugins/betterSessions/utils";
|
||||||
import { ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot } from "@utils/modal";
|
import { ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot } from "@utils/modal";
|
||||||
import { Button, Forms, React, TextInput } from "@webpack/common";
|
import { Button, Forms, React, TextInput } from "@webpack/common";
|
||||||
import { KeyboardEvent } from "react";
|
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<React.SetStateAction<string>>]; }) {
|
export function RenameModal({ props, session, state }: { props: ModalProps, session: SessionInfo["session"], state: [string, React.Dispatch<React.SetStateAction<string>>]; }) {
|
||||||
const [title, setTitle] = state;
|
const [title, setTitle] = state;
|
||||||
const [value, setValue] = React.useState(savedSessionsCache.get(session.id_hash)?.name ?? "");
|
const [value, setValue] = React.useState(savedSessionsCache.get(session.id_hash)?.name ?? "");
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { DataStore } from "@api/index";
|
import * as DataStore from "@api/DataStore";
|
||||||
import { UserStore } from "@webpack/common";
|
import { UserStore } from "@webpack/common";
|
||||||
|
|
||||||
import { ChromeIcon, DiscordIcon, EdgeIcon, FirefoxIcon, IEIcon, MobileIcon, OperaIcon, SafariIcon, UnknownIcon } from "./components/icons";
|
import { ChromeIcon, DiscordIcon, EdgeIcon, FirefoxIcon, IEIcon, MobileIcon, OperaIcon, SafariIcon, UnknownIcon } from "./components/icons";
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { isPluginEnabled } from "@api/PluginManager";
|
||||||
import { openPluginModal } from "@components/settings/tabs";
|
import { openPluginModal } from "@components/settings/tabs";
|
||||||
import { getIntlMessage } from "@utils/discord";
|
import { getIntlMessage } from "@utils/discord";
|
||||||
import { isObjectEmpty } from "@utils/misc";
|
import { isObjectEmpty } from "@utils/misc";
|
||||||
|
|
@ -28,7 +29,7 @@ export default function PluginsSubmenu() {
|
||||||
|
|
||||||
const search = query.toLowerCase();
|
const search = query.toLowerCase();
|
||||||
const include = (p: typeof Plugins[keyof typeof Plugins]) => (
|
const include = (p: typeof Plugins[keyof typeof Plugins]) => (
|
||||||
Vencord.Plugins.isPluginEnabled(p.name)
|
isPluginEnabled(p.name)
|
||||||
&& p.options && !isObjectEmpty(p.options)
|
&& p.options && !isObjectEmpty(p.options)
|
||||||
&& (
|
&& (
|
||||||
p.name.toLowerCase().includes(search)
|
p.name.toLowerCase().includes(search)
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,13 @@
|
||||||
|
|
||||||
import { classNameFactory } from "@api/Styles";
|
import { classNameFactory } from "@api/Styles";
|
||||||
import { ErrorCard } from "@components/ErrorCard";
|
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 { Margins } from "@utils/margins";
|
||||||
import { findByCodeLazy, findStoreLazy } from "@webpack";
|
import { findByCodeLazy, findStoreLazy } from "@webpack";
|
||||||
import { Button, ColorPicker, Forms, ThemeStore, useStateFromStores } from "@webpack/common";
|
import { Button, ColorPicker, Forms, ThemeStore, useStateFromStores } from "@webpack/common";
|
||||||
|
|
||||||
import { settings } from "..";
|
import { settings } from "..";
|
||||||
import { relativeLuminance } from "../utils/colorUtils";
|
|
||||||
import { createOrUpdateThemeColorVars } from "../utils/styleUtils";
|
|
||||||
|
|
||||||
const saveClientTheme = findByCodeLazy('type:"UNSYNCED_USER_SETTINGS_UPDATE', '"system"===');
|
const saveClientTheme = findByCodeLazy('type:"UNSYNCED_USER_SETTINGS_UPDATE', '"system"===');
|
||||||
const NitroThemeStore = findStoreLazy("ClientThemesBackgroundStore");
|
const NitroThemeStore = findStoreLazy("ClientThemesBackgroundStore");
|
||||||
|
|
|
||||||
|
|
@ -170,7 +170,7 @@ function makeShortcuts() {
|
||||||
openModal: { getter: () => ModalAPI.openModal },
|
openModal: { getter: () => ModalAPI.openModal },
|
||||||
openModalLazy: { getter: () => ModalAPI.openModalLazy },
|
openModalLazy: { getter: () => ModalAPI.openModalLazy },
|
||||||
|
|
||||||
Stores: Webpack.fluxStores,
|
Stores: { getter: () => Object.fromEntries(Webpack.fluxStores) },
|
||||||
|
|
||||||
// e.g. "2024-05_desktop_visual_refresh", 0
|
// e.g. "2024-05_desktop_visual_refresh", 0
|
||||||
setExperiment: (id: string, bucket: number) => {
|
setExperiment: (id: string, bucket: number) => {
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
import { definePluginSettings } from "@api/Settings";
|
import { definePluginSettings } from "@api/Settings";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import { copyWithToast } from "@utils/misc";
|
import { copyWithToast } from "@utils/discord";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { findByPropsLazy } from "@webpack";
|
import { findByPropsLazy } from "@webpack";
|
||||||
import { Menu } from "@webpack/common";
|
import { Menu } from "@webpack/common";
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import "./style.css";
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { CopyIcon, NoEntrySignIcon } from "@components/Icons";
|
import { CopyIcon, NoEntrySignIcon } from "@components/Icons";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import { copyWithToast } from "@utils/misc";
|
import { copyWithToast } from "@utils/discord";
|
||||||
import definePlugin from "@utils/types";
|
import definePlugin from "@utils/types";
|
||||||
import { Tooltip, useState } from "@webpack/common";
|
import { Tooltip, useState } from "@webpack/common";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,12 +17,13 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/ContextMenu";
|
import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/ContextMenu";
|
||||||
|
import { isPluginEnabled } from "@api/PluginManager";
|
||||||
|
import ExpressionClonerPlugin from "@plugins/expressionCloner";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import { copyWithToast } from "@utils/misc";
|
import { copyWithToast } from "@utils/discord";
|
||||||
import definePlugin from "@utils/types";
|
import definePlugin from "@utils/types";
|
||||||
import { Message, Sticker } from "@vencord/discord-types";
|
import { Message, Sticker } from "@vencord/discord-types";
|
||||||
import { Menu, React, StickersStore } from "@webpack/common";
|
import { Menu, React, StickersStore } from "@webpack/common";
|
||||||
import ExpressionClonerPlugin from "plugins/expressionCloner";
|
|
||||||
|
|
||||||
const StickerExt = [, "png", "png", "json", "gif"] as const;
|
const StickerExt = [, "png", "png", "json", "gif"] as const;
|
||||||
|
|
||||||
|
|
@ -79,7 +80,7 @@ const expressionPickerPatch: NavContextMenuPatchCallback = (children, props: { t
|
||||||
|
|
||||||
const sticker = StickersStore.getStickerById(id);
|
const sticker = StickersStore.getStickerById(id);
|
||||||
if (sticker) {
|
if (sticker) {
|
||||||
children.push(buildMenuItem(sticker, Vencord.Plugins.isPluginEnabled(ExpressionClonerPlugin.name)));
|
children.push(buildMenuItem(sticker, isPluginEnabled(ExpressionClonerPlugin.name)));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* 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 { definePluginSettings } from "@api/Settings";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin, { makeRange, OptionType } from "@utils/types";
|
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.";
|
const backOnlineMessage = "Welcome back! Click the button to go online. Click the X to stay idle until reload.";
|
||||||
if (
|
if (
|
||||||
Notices.currentNotice?.[1] === backOnlineMessage ||
|
currentNotice?.[1] === backOnlineMessage ||
|
||||||
Notices.noticesQueue.some(([, noticeMessage]) => noticeMessage === backOnlineMessage)
|
noticesQueue.some(([, noticeMessage]) => noticeMessage === backOnlineMessage)
|
||||||
) return;
|
) return;
|
||||||
|
|
||||||
Notices.showNotice(backOnlineMessage, "Exit idle", () => {
|
showNotice(backOnlineMessage, "Exit idle", () => {
|
||||||
Notices.popNotice();
|
popNotice();
|
||||||
FluxDispatcher.dispatch({
|
FluxDispatcher.dispatch({
|
||||||
type: "IDLE",
|
type: "IDLE",
|
||||||
idle: false
|
idle: false
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
import "./settings.css";
|
import "./settings.css";
|
||||||
|
|
||||||
|
import { isPluginEnabled } from "@api/PluginManager";
|
||||||
import { classNameFactory } from "@api/Styles";
|
import { classNameFactory } from "@api/Styles";
|
||||||
import { Divider } from "@components/Divider";
|
import { Divider } from "@components/Divider";
|
||||||
import { Heading } from "@components/Heading";
|
import { Heading } from "@components/Heading";
|
||||||
|
|
@ -14,7 +15,7 @@ import { debounce } from "@shared/debounce";
|
||||||
import { ActivityType } from "@vencord/discord-types/enums";
|
import { ActivityType } from "@vencord/discord-types/enums";
|
||||||
import { Select, Text, TextInput, useState } from "@webpack/common";
|
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-");
|
const cl = classNameFactory("vc-customRPC-settings-");
|
||||||
|
|
||||||
|
|
@ -50,7 +51,7 @@ function isAppIdValid(value: string) {
|
||||||
|
|
||||||
const updateRPC = debounce(() => {
|
const updateRPC = debounce(() => {
|
||||||
setRpc(true);
|
setRpc(true);
|
||||||
if (Vencord.Plugins.isPluginEnabled("CustomRPC")) setRpc();
|
if (isPluginEnabled(CustomRPCPlugin.name)) setRpc();
|
||||||
});
|
});
|
||||||
|
|
||||||
function isStreamLinkDisabled() {
|
function isStreamLinkDisabled() {
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,13 @@
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* 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 { proxyLazy } from "@utils/lazy";
|
||||||
import { Logger } from "@utils/Logger";
|
import { Logger } from "@utils/Logger";
|
||||||
import { openModal } from "@utils/modal";
|
import { openModal } from "@utils/modal";
|
||||||
import { OAuth2AuthorizeModal, showToast, Toasts, UserStore, zustandCreate, zustandPersist } from "@webpack/common";
|
import { OAuth2AuthorizeModal, showToast, Toasts, UserStore, zustandCreate, zustandPersist } from "@webpack/common";
|
||||||
|
|
||||||
import { AUTHORIZE_URL, CLIENT_ID } from "../constants";
|
|
||||||
|
|
||||||
interface AuthorizationState {
|
interface AuthorizationState {
|
||||||
token: string | null;
|
token: string | null;
|
||||||
tokens: Record<string, string>;
|
tokens: Record<string, string>;
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,11 @@
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* 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 { proxyLazy } from "@utils/lazy";
|
||||||
import { UserStore, zustandCreate } from "@webpack/common";
|
import { UserStore, zustandCreate } from "@webpack/common";
|
||||||
|
|
||||||
import { Decoration, deleteDecoration, getUserDecoration, getUserDecorations, NewDecoration, setUserDecoration } from "../api";
|
|
||||||
import { decorationToAsset } from "../utils/decoration";
|
|
||||||
import { useUsersDecorationsStore } from "./UsersDecorationsStore";
|
import { useUsersDecorationsStore } from "./UsersDecorationsStore";
|
||||||
|
|
||||||
interface UserDecorationsState {
|
interface UserDecorationsState {
|
||||||
|
|
|
||||||
|
|
@ -4,15 +4,14 @@
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* 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 { debounce } from "@shared/debounce";
|
||||||
import { proxyLazy } from "@utils/lazy";
|
import { proxyLazy } from "@utils/lazy";
|
||||||
import { User } from "@vencord/discord-types";
|
import { User } from "@vencord/discord-types";
|
||||||
import { useEffect, useState, zustandCreate } from "@webpack/common";
|
import { useEffect, useState, zustandCreate } from "@webpack/common";
|
||||||
|
|
||||||
import { AvatarDecoration } from "../../";
|
|
||||||
import { getUsersDecorations } from "../api";
|
|
||||||
import { DECORATION_FETCH_COOLDOWN, SKU_ID } from "../constants";
|
|
||||||
|
|
||||||
interface UserDecorationData {
|
interface UserDecorationData {
|
||||||
asset: string | null;
|
asset: string | null;
|
||||||
fetchedAt: Date;
|
fetchedAt: Date;
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,9 @@
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { AvatarDecoration } from "../../";
|
import { AvatarDecoration } from "@plugins/decor";
|
||||||
import { Decoration } from "../api";
|
import { Decoration } from "@plugins/decor/lib/api";
|
||||||
import { SKU_ID } from "../constants";
|
import { SKU_ID } from "@plugins/decor/lib/constants";
|
||||||
|
|
||||||
export function decorationToAsset(decoration: Decoration) {
|
export function decorationToAsset(decoration: Decoration) {
|
||||||
return `${decoration.animated ? "a_" : ""}${decoration.hash}`;
|
return `${decoration.animated ? "a_" : ""}${decoration.hash}`;
|
||||||
|
|
|
||||||
|
|
@ -12,13 +12,14 @@ import { closeAllModals } from "@utils/modal";
|
||||||
import { OptionType } from "@utils/types";
|
import { OptionType } from "@utils/types";
|
||||||
import { FluxDispatcher, Forms } from "@webpack/common";
|
import { FluxDispatcher, Forms } from "@webpack/common";
|
||||||
|
|
||||||
|
import DecorPlugin from ".";
|
||||||
import DecorSection from "./ui/components/DecorSection";
|
import DecorSection from "./ui/components/DecorSection";
|
||||||
|
|
||||||
export const settings = definePluginSettings({
|
export const settings = definePluginSettings({
|
||||||
changeDecoration: {
|
changeDecoration: {
|
||||||
type: OptionType.COMPONENT,
|
type: OptionType.COMPONENT,
|
||||||
component() {
|
component() {
|
||||||
if (!Vencord.Plugins.plugins.Decor.started) return <Forms.FormText>
|
if (!DecorPlugin.started) return <Forms.FormText>
|
||||||
Enable Decor and restart your client to change your avatar decoration.
|
Enable Decor and restart your client to change your avatar decoration.
|
||||||
</Forms.FormText>;
|
</Forms.FormText>;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,11 @@
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* 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 { ContextMenuApi } from "@webpack/common";
|
||||||
import type { HTMLProps } from "react";
|
import type { HTMLProps } from "react";
|
||||||
|
|
||||||
import { Decoration } from "../../lib/api";
|
|
||||||
import { decorationToAvatarDecoration } from "../../lib/utils/decoration";
|
|
||||||
import { DecorationGridDecoration } from ".";
|
import { DecorationGridDecoration } from ".";
|
||||||
import DecorationContextMenu from "./DecorationContextMenu";
|
import DecorationContextMenu from "./DecorationContextMenu";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,14 +6,13 @@
|
||||||
|
|
||||||
import { Button } from "@components/Button";
|
import { Button } from "@components/Button";
|
||||||
import { Flex } from "@components/Flex";
|
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 { findComponentByCodeLazy } from "@webpack";
|
||||||
import { useEffect } from "@webpack/common";
|
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");
|
const CustomizationSection = findComponentByCodeLazy(".customizationSectionBackground");
|
||||||
|
|
||||||
export interface DecorSectionProps {
|
export interface DecorSectionProps {
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,12 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { CopyIcon, DeleteIcon } from "@components/Icons";
|
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 { copyToClipboard } from "@utils/clipboard";
|
||||||
import { Alerts, ContextMenuApi, Menu, UserStore } from "@webpack/common";
|
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; }) {
|
export default function DecorationContextMenu({ decoration }: { decoration: Decoration; }) {
|
||||||
const { delete: deleteDecoration } = useCurrentUserDecorationsStore();
|
const { delete: deleteDecoration } = useCurrentUserDecorationsStore();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,10 @@
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { cl } from "@plugins/decor/ui";
|
||||||
import { React } from "@webpack/common";
|
import { React } from "@webpack/common";
|
||||||
import { JSX } from "react";
|
import { JSX } from "react";
|
||||||
|
|
||||||
import { cl } from "../";
|
|
||||||
|
|
||||||
export interface GridProps<ItemT> {
|
export interface GridProps<ItemT> {
|
||||||
renderItem: (item: ItemT) => JSX.Element;
|
renderItem: (item: ItemT) => JSX.Element;
|
||||||
getItemKey: (item: ItemT) => string;
|
getItemKey: (item: ItemT) => string;
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,12 @@
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { cl } from "@plugins/decor/ui";
|
||||||
import { classes } from "@utils/misc";
|
import { classes } from "@utils/misc";
|
||||||
import { findByPropsLazy } from "@webpack";
|
import { findByPropsLazy } from "@webpack";
|
||||||
import { React } from "@webpack/common";
|
import { React } from "@webpack/common";
|
||||||
import { JSX } from "react";
|
import { JSX } from "react";
|
||||||
|
|
||||||
import { cl } from "../";
|
|
||||||
import Grid, { GridProps } from "./Grid";
|
import Grid, { GridProps } from "./Grid";
|
||||||
|
|
||||||
const ScrollerClasses = findByPropsLazy("managedReactiveScroller");
|
const ScrollerClasses = findByPropsLazy("managedReactiveScroller");
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,11 @@
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { AvatarDecoration } from "@plugins/decor";
|
||||||
import { findComponentByCode, LazyComponentWebpack } from "@webpack";
|
import { findComponentByCode, LazyComponentWebpack } from "@webpack";
|
||||||
import { React } from "@webpack/common";
|
import { React } from "@webpack/common";
|
||||||
import type { ComponentType, HTMLProps, PropsWithChildren } from "react";
|
import type { ComponentType, HTMLProps, PropsWithChildren } from "react";
|
||||||
|
|
||||||
import { AvatarDecoration } from "../..";
|
|
||||||
|
|
||||||
type DecorationGridItemComponent = ComponentType<PropsWithChildren<HTMLProps<HTMLDivElement>> & {
|
type DecorationGridItemComponent = ComponentType<PropsWithChildren<HTMLProps<HTMLDivElement>> & {
|
||||||
onSelect: () => void,
|
onSelect: () => void,
|
||||||
isSelected: boolean,
|
isSelected: boolean,
|
||||||
|
|
|
||||||
|
|
@ -7,26 +7,25 @@
|
||||||
import { Button as NewButton } from "@components/Button";
|
import { Button as NewButton } from "@components/Button";
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { Flex } from "@components/Flex";
|
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 { Margins } from "@utils/margins";
|
||||||
import { copyWithToast } from "@utils/misc";
|
|
||||||
import { closeAllModals, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal";
|
import { closeAllModals, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal";
|
||||||
import { Queue } from "@utils/Queue";
|
import { Queue } from "@utils/Queue";
|
||||||
import { User } from "@vencord/discord-types";
|
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 { 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 { openCreateDecorationModal } from "./CreateDecorationModal";
|
||||||
import { openGuidelinesModal } from "./GuidelinesModal";
|
import { openGuidelinesModal } from "./GuidelinesModal";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,17 +6,16 @@
|
||||||
|
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { Link } from "@components/Link";
|
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 { openInviteModal } from "@utils/discord";
|
||||||
import { Margins } from "@utils/margins";
|
import { Margins } from "@utils/margins";
|
||||||
import { closeAllModals, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal";
|
import { closeAllModals, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal";
|
||||||
import { filters, findComponentByCodeLazy, mapMangledModuleLazy } from "@webpack";
|
import { filters, findComponentByCodeLazy, mapMangledModuleLazy } from "@webpack";
|
||||||
import { Button, FluxDispatcher, Forms, GuildStore, NavigationRouter, Text, TextInput, useEffect, useMemo, UserStore, useState } from "@webpack/common";
|
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 FileUpload = findComponentByCodeLazy(".fileUpload),");
|
||||||
|
|
||||||
const { HelpMessage, HelpMessageTypes } = mapMangledModuleLazy('POSITIVE="positive', {
|
const { HelpMessage, HelpMessageTypes } = mapMangledModuleLazy('POSITIVE="positive', {
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,11 @@
|
||||||
|
|
||||||
import { Flex } from "@components/Flex";
|
import { Flex } from "@components/Flex";
|
||||||
import { Link } from "@components/Link";
|
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 { ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal";
|
||||||
import { Button, Forms, Text } from "@webpack/common";
|
import { Button, Forms, Text } from "@webpack/common";
|
||||||
|
|
||||||
import { settings } from "../../settings";
|
|
||||||
import { cl, DecorationModalStyles, requireAvatarDecorationModal } from "../";
|
|
||||||
import { openCreateDecorationModal } from "./CreateDecorationModal";
|
import { openCreateDecorationModal } from "./CreateDecorationModal";
|
||||||
|
|
||||||
function GuidelinesModal(props: ModalProps) {
|
function GuidelinesModal(props: ModalProps) {
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,8 @@
|
||||||
|
|
||||||
import { addMessagePreEditListener, addMessagePreSendListener, removeMessagePreEditListener, removeMessagePreSendListener } from "@api/MessageEvents";
|
import { addMessagePreEditListener, addMessagePreSendListener, removeMessagePreEditListener, removeMessagePreSendListener } from "@api/MessageEvents";
|
||||||
import { definePluginSettings } from "@api/Settings";
|
import { definePluginSettings } from "@api/Settings";
|
||||||
|
import { ApngBlendOp, ApngDisposeOp, parseAPNG } from "@utils/apng";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import { ApngBlendOp, ApngDisposeOp, importApngJs } from "@utils/dependencies";
|
|
||||||
import { getCurrentGuild, getEmojiURL } from "@utils/discord";
|
import { getCurrentGuild, getEmojiURL } from "@utils/discord";
|
||||||
import { Logger } from "@utils/Logger";
|
import { Logger } from "@utils/Logger";
|
||||||
import definePlugin, { OptionType, Patch } from "@utils/types";
|
import definePlugin, { OptionType, Patch } from "@utils/types";
|
||||||
|
|
@ -706,9 +706,10 @@ export default definePlugin({
|
||||||
},
|
},
|
||||||
|
|
||||||
async sendAnimatedSticker(stickerLink: string, stickerId: string, channelId: string) {
|
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 gif = GIFEncoder();
|
||||||
const resolution = settings.store.stickerSize;
|
const resolution = settings.store.stickerSize;
|
||||||
|
|
@ -757,7 +758,7 @@ export default definePlugin({
|
||||||
|
|
||||||
gif.finish();
|
gif.finish();
|
||||||
|
|
||||||
const file = new File([gif.bytesView()], `${stickerId}.gif`, { type: "image/gif" });
|
const file = new File([gif.bytesView() as Uint8Array<ArrayBuffer>], `${stickerId}.gif`, { type: "image/gif" });
|
||||||
UploadHandler.promptToUpload([file], ChannelStore.getChannel(channelId), DraftType.ChannelMessage);
|
UploadHandler.promptToUpload([file], ChannelStore.getChannel(channelId), DraftType.ChannelMessage);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,15 +17,15 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// This plugin is a port from Alyxia's Vendetta plugin
|
// This plugin is a port from Alyxia's Vendetta plugin
|
||||||
import "./index.css";
|
import "./styles.css";
|
||||||
|
|
||||||
import { definePluginSettings } from "@api/Settings";
|
import { definePluginSettings } from "@api/Settings";
|
||||||
import { Divider } from "@components/Divider";
|
import { Divider } from "@components/Divider";
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import { fetchUserProfile } from "@utils/discord";
|
import { copyWithToast, fetchUserProfile } from "@utils/discord";
|
||||||
import { Margins } from "@utils/margins";
|
import { Margins } from "@utils/margins";
|
||||||
import { classes, copyWithToast } from "@utils/misc";
|
import { classes } from "@utils/misc";
|
||||||
import { useAwaiter } from "@utils/react";
|
import { useAwaiter } from "@utils/react";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { User, UserProfile } from "@vencord/discord-types";
|
import { User, UserProfile } from "@vencord/discord-types";
|
||||||
|
|
|
||||||
|
|
@ -18,12 +18,11 @@
|
||||||
|
|
||||||
import { classNameFactory } from "@api/Styles";
|
import { classNameFactory } from "@api/Styles";
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
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 { FluxDispatcher, useLayoutEffect, useMemo, useRef, useState } from "@webpack/common";
|
||||||
|
|
||||||
import { ELEMENT_ID } from "../constants";
|
|
||||||
import { settings } from "../index";
|
|
||||||
import { waitFor } from "../utils/waitFor";
|
|
||||||
|
|
||||||
interface Vec2 {
|
interface Vec2 {
|
||||||
x: number,
|
x: number,
|
||||||
y: number;
|
y: number;
|
||||||
|
|
|
||||||
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
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 (
|
|
||||||
<ModalRoot {...props}>
|
|
||||||
<ModalHeader>
|
|
||||||
<Forms.FormTitle tag="h4">Decrypt Message</Forms.FormTitle>
|
|
||||||
</ModalHeader>
|
|
||||||
|
|
||||||
<ModalContent>
|
|
||||||
<Forms.FormTitle tag="h5" style={{ marginTop: "10px" }}>Message with Encryption</Forms.FormTitle>
|
|
||||||
<TextInput defaultValue={encryptedMessage} disabled={true}></TextInput>
|
|
||||||
<Forms.FormTitle tag="h5" style={{ marginTop: "10px" }}>Password</Forms.FormTitle>
|
|
||||||
<TextInput
|
|
||||||
style={{ marginBottom: "20px" }}
|
|
||||||
onChange={setPassword}
|
|
||||||
/>
|
|
||||||
</ModalContent>
|
|
||||||
|
|
||||||
<ModalFooter>
|
|
||||||
<Button
|
|
||||||
color={Button.Colors.GREEN}
|
|
||||||
onClick={() => {
|
|
||||||
const toSend = decrypt(encryptedMessage, password, true);
|
|
||||||
if (!toSend || !props?.message) return;
|
|
||||||
// @ts-expect-error
|
|
||||||
Vencord.Plugins.plugins.InvisibleChat.buildEmbed(props?.message, toSend);
|
|
||||||
props.onClose();
|
|
||||||
}}>
|
|
||||||
Decrypt
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
color={Button.Colors.TRANSPARENT}
|
|
||||||
look={Button.Looks.LINK}
|
|
||||||
style={{ left: 15, position: "absolute" }}
|
|
||||||
onClick={props.onClose}
|
|
||||||
>
|
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
</ModalFooter>
|
|
||||||
</ModalRoot>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function buildDecModal(msg: any): any {
|
|
||||||
openModal((props: any) => <DecModal {...props} {...msg} />);
|
|
||||||
}
|
|
||||||
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
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 (
|
|
||||||
<ModalRoot {...props}>
|
|
||||||
<ModalHeader>
|
|
||||||
<Forms.FormTitle tag="h4">Encrypt Message</Forms.FormTitle>
|
|
||||||
</ModalHeader>
|
|
||||||
|
|
||||||
<ModalContent>
|
|
||||||
<Forms.FormTitle tag="h5" style={{ marginTop: "10px" }}>Secret</Forms.FormTitle>
|
|
||||||
<TextInput
|
|
||||||
onChange={(e: string) => {
|
|
||||||
setSecret(e);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Forms.FormTitle tag="h5" style={{ marginTop: "10px" }}>Cover (2 or more Words!!)</Forms.FormTitle>
|
|
||||||
<TextInput
|
|
||||||
disabled={noCover}
|
|
||||||
onChange={(e: string) => {
|
|
||||||
setCover(e);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Forms.FormTitle tag="h5" style={{ marginTop: "10px" }}>Password</Forms.FormTitle>
|
|
||||||
<TextInput
|
|
||||||
style={{ marginBottom: "20px" }}
|
|
||||||
defaultValue={"password"}
|
|
||||||
onChange={(e: string) => {
|
|
||||||
setPassword(e);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<FormSwitch
|
|
||||||
title="Don't use a Cover"
|
|
||||||
value={noCover}
|
|
||||||
onChange={(e: boolean) => {
|
|
||||||
setNoCover(e);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</ModalContent>
|
|
||||||
|
|
||||||
<ModalFooter>
|
|
||||||
<Button
|
|
||||||
color={Button.Colors.GREEN}
|
|
||||||
disabled={!isValid}
|
|
||||||
onClick={() => {
|
|
||||||
if (!isValid) return;
|
|
||||||
const encrypted = encrypt(secret, password, noCover ? "d d" : cover);
|
|
||||||
const toSend = noCover ? encrypted.replaceAll("d", "") : encrypted;
|
|
||||||
if (!toSend) return;
|
|
||||||
|
|
||||||
insertTextIntoChatInputBox(toSend);
|
|
||||||
|
|
||||||
props.onClose();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Send
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
color={Button.Colors.TRANSPARENT}
|
|
||||||
look={Button.Looks.LINK}
|
|
||||||
style={{ left: 15, position: "absolute" }}
|
|
||||||
onClick={() => {
|
|
||||||
props.onClose();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
</ModalFooter>
|
|
||||||
</ModalRoot>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function buildEncModal(): any {
|
|
||||||
openModal(props => <EncModal {...props} />);
|
|
||||||
}
|
|
||||||
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
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 (
|
|
||||||
|
|
||||||
<svg
|
|
||||||
fill="var(--header-secondary)"
|
|
||||||
width={24} height={24}
|
|
||||||
viewBox={"0 0 64 64"}
|
|
||||||
>
|
|
||||||
<path d="M 32 9 C 24.832 9 19 14.832 19 22 L 19 27.347656 C 16.670659 28.171862 15 30.388126 15 33 L 15 49 C 15 52.314 17.686 55 21 55 L 43 55 C 46.314 55 49 52.314 49 49 L 49 33 C 49 30.388126 47.329341 28.171862 45 27.347656 L 45 22 C 45 14.832 39.168 9 32 9 z M 32 13 C 36.963 13 41 17.038 41 22 L 41 27 L 23 27 L 23 22 C 23 17.038 27.037 13 32 13 z" />
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function Indicator() {
|
|
||||||
return (
|
|
||||||
<Tooltip text="This message has a hidden message! (InvisibleChat)">
|
|
||||||
{({ onMouseEnter, onMouseLeave }) => (
|
|
||||||
<img
|
|
||||||
aria-label="Hidden Message Indicator (InvisibleChat)"
|
|
||||||
onMouseEnter={onMouseEnter}
|
|
||||||
onMouseLeave={onMouseLeave}
|
|
||||||
src="https://github.com/SammCheese/invisible-chat/raw/NewReplugged/src/assets/lock.png"
|
|
||||||
width={20}
|
|
||||||
height={20}
|
|
||||||
style={{ transform: "translateY(4p)", paddingInline: 4 }}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Tooltip>
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const ChatBarIcon: ChatBarButtonFactory = ({ isMainChat }) => {
|
|
||||||
if (!isMainChat) return null;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ChatBarButton
|
|
||||||
tooltip="Encrypt Message"
|
|
||||||
onClick={() => buildEncModal()}
|
|
||||||
buttonProps={{
|
|
||||||
"aria-haspopup": "dialog",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
aria-hidden
|
|
||||||
role="img"
|
|
||||||
width="20"
|
|
||||||
height="20"
|
|
||||||
viewBox={"0 0 64 64"}
|
|
||||||
style={{ scale: "1.39", translate: "0 -1px" }}
|
|
||||||
>
|
|
||||||
<path fill="currentColor" d="M 32 9 C 24.832 9 19 14.832 19 22 L 19 27.347656 C 16.670659 28.171862 15 30.388126 15 33 L 15 49 C 15 52.314 17.686 55 21 55 L 43 55 C 46.314 55 49 52.314 49 49 L 49 33 C 49 30.388126 47.329341 28.171862 45 27.347656 L 45 22 C 45 14.832 39.168 9 32 9 z M 32 13 C 36.963 13 41 17.038 41 22 L 41 27 L 23 27 L 23 22 C 23 17.038 27.037 13 32 13 z" />
|
|
||||||
</svg>
|
|
||||||
</ChatBarButton>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
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<Object | {}> {
|
|
||||||
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<void> {
|
|
||||||
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: () => <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<string | false> {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
@ -16,13 +16,14 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { isPluginEnabled } from "@api/PluginManager";
|
||||||
import { definePluginSettings } from "@api/Settings";
|
import { definePluginSettings } from "@api/Settings";
|
||||||
|
import NoReplyMentionPlugin from "@plugins/noReplyMention";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { MessageFlags } from "@vencord/discord-types/enums";
|
import { MessageFlags } from "@vencord/discord-types/enums";
|
||||||
import { findByPropsLazy } from "@webpack";
|
import { findByPropsLazy } from "@webpack";
|
||||||
import { FluxDispatcher, MessageTypeSets, PermissionsBits, PermissionStore, UserStore, WindowStore } from "@webpack/common";
|
import { FluxDispatcher, MessageTypeSets, PermissionsBits, PermissionStore, UserStore, WindowStore } from "@webpack/common";
|
||||||
import NoReplyMentionPlugin from "plugins/noReplyMention";
|
|
||||||
|
|
||||||
const MessageActions = findByPropsLazy("deleteMessage", "startEditMessage");
|
const MessageActions = findByPropsLazy("deleteMessage", "startEditMessage");
|
||||||
const EditStore = findByPropsLazy("isEditing", "isEditingAny");
|
const EditStore = findByPropsLazy("isEditing", "isEditingAny");
|
||||||
|
|
@ -93,7 +94,7 @@ export default definePlugin({
|
||||||
if (!MessageTypeSets.REPLYABLE.has(msg.type) || msg.hasFlag(MessageFlags.EPHEMERAL)) return;
|
if (!MessageTypeSets.REPLYABLE.has(msg.type) || msg.hasFlag(MessageFlags.EPHEMERAL)) return;
|
||||||
|
|
||||||
const isShiftPress = event.shiftKey && !settings.store.requireModifier;
|
const isShiftPress = event.shiftKey && !settings.store.requireModifier;
|
||||||
const shouldMention = Vencord.Plugins.isPluginEnabled(NoReplyMentionPlugin.name)
|
const shouldMention = isPluginEnabled(NoReplyMentionPlugin.name)
|
||||||
? NoReplyMentionPlugin.shouldMention(msg, isShiftPress)
|
? NoReplyMentionPlugin.shouldMention(msg, isShiftPress)
|
||||||
: !isShiftPress;
|
: !isShiftPress;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { Flex } from "@components/Flex";
|
import { Flex } from "@components/Flex";
|
||||||
import { InfoIcon, OwnerCrownIcon } from "@components/Icons";
|
import { InfoIcon, OwnerCrownIcon } from "@components/Icons";
|
||||||
|
import { cl, getGuildPermissionSpecMap } from "@plugins/permissionsViewer/utils";
|
||||||
import { copyToClipboard } from "@utils/clipboard";
|
import { copyToClipboard } from "@utils/clipboard";
|
||||||
import { getIntlMessage, getUniqueUsername } from "@utils/discord";
|
import { getIntlMessage, getUniqueUsername } from "@utils/discord";
|
||||||
import { ModalCloseButton, ModalContent, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal";
|
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 { ContextMenuApi, FluxDispatcher, GuildMemberStore, GuildRoleStore, i18n, Menu, PermissionsBits, ScrollerThin, Text, Tooltip, useEffect, useMemo, UserStore, useState, useStateFromStores } from "@webpack/common";
|
||||||
|
|
||||||
import { settings } from "..";
|
import { settings } from "..";
|
||||||
import { cl, getGuildPermissionSpecMap } from "../utils";
|
|
||||||
import { PermissionAllowedIcon, PermissionDefaultIcon, PermissionDeniedIcon } from "./icons";
|
import { PermissionAllowedIcon, PermissionDefaultIcon, PermissionDeniedIcon } from "./icons";
|
||||||
|
|
||||||
export const enum PermissionType {
|
export const enum PermissionType {
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { HeadingTertiary } from "@components/Heading";
|
import { HeadingTertiary } from "@components/Heading";
|
||||||
|
import { cl, getGuildPermissionSpecMap, getSortedRolesForMember, sortUserRoles } from "@plugins/permissionsViewer/utils";
|
||||||
import { getIntlMessage } from "@utils/discord";
|
import { getIntlMessage } from "@utils/discord";
|
||||||
import { classes } from "@utils/misc";
|
import { classes } from "@utils/misc";
|
||||||
import type { Guild, GuildMember } from "@vencord/discord-types";
|
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 { PermissionsBits, Text, Tooltip, useMemo, UserStore } from "@webpack/common";
|
||||||
|
|
||||||
import { PermissionsSortOrder, settings } from "..";
|
import { PermissionsSortOrder, settings } from "..";
|
||||||
import { cl, getGuildPermissionSpecMap, getSortedRolesForMember, sortUserRoles } from "../utils";
|
|
||||||
import openRolesAndUsersPermissionsModal, { PermissionType, type RoleOrUserPermission } from "./RolesAndUsersPermissions";
|
import openRolesAndUsersPermissionsModal, { PermissionType, type RoleOrUserPermission } from "./RolesAndUsersPermissions";
|
||||||
|
|
||||||
interface UserPermission {
|
interface UserPermission {
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,12 @@
|
||||||
|
|
||||||
import { classNameFactory } from "@api/Styles";
|
import { classNameFactory } from "@api/Styles";
|
||||||
import { Divider } from "@components/Divider";
|
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 { ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, openModalLazy } from "@utils/modal";
|
||||||
import { extractAndLoadChunksLazy, findComponentByCodeLazy } from "@webpack";
|
import { extractAndLoadChunksLazy, findComponentByCodeLazy } from "@webpack";
|
||||||
import { Button, ColorPicker, Forms, Text, TextInput, Toasts, useMemo, useState } from "@webpack/common";
|
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 {
|
interface ColorPickerWithSwatchesProps {
|
||||||
defaultColor: number;
|
defaultColor: number;
|
||||||
colors: number[];
|
colors: number[];
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/ContextMenu";
|
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 { Menu } from "@webpack/common";
|
||||||
|
|
||||||
import { addChannelToCategory, canMoveChannelInDirection, currentUserCategories, isPinned, moveChannel, removeChannelFromCategory } from "../data";
|
|
||||||
import { PinOrder, settings } from "../index";
|
|
||||||
import { openCategoryModal } from "./CreateCategoryModal";
|
import { openCategoryModal } from "./CreateCategoryModal";
|
||||||
|
|
||||||
function createPinMenuItem(channelId: string) {
|
function createPinMenuItem(channelId: string) {
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,10 @@
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { PinOrder, PrivateChannelSortStore, settings } from "@plugins/pinDms";
|
||||||
import { useForceUpdater } from "@utils/react";
|
import { useForceUpdater } from "@utils/react";
|
||||||
import { UserStore } from "@webpack/common";
|
import { UserStore } from "@webpack/common";
|
||||||
|
|
||||||
import { PinOrder, PrivateChannelSortStore, settings } from "./index";
|
|
||||||
|
|
||||||
export interface Category {
|
export interface Category {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
|
|
||||||
|
|
@ -16,14 +16,15 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { isPluginEnabled } from "@api/PluginManager";
|
||||||
import { definePluginSettings } from "@api/Settings";
|
import { definePluginSettings } from "@api/Settings";
|
||||||
|
import NoBlockedMessagesPlugin from "@plugins/noBlockedMessages";
|
||||||
|
import NoReplyMentionPlugin from "@plugins/noReplyMention";
|
||||||
import { Devs, IS_MAC } from "@utils/constants";
|
import { Devs, IS_MAC } from "@utils/constants";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { Message } from "@vencord/discord-types";
|
import { Message } from "@vencord/discord-types";
|
||||||
import { MessageFlags } from "@vencord/discord-types/enums";
|
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 { 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 currentlyReplyingId: string | null = null;
|
||||||
let currentlyEditingId: 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;
|
let messages: Message[] = MessageStore.getMessages(SelectedChannelStore.getChannelId())._array;
|
||||||
|
|
||||||
const meId = UserStore.getCurrentUser().id;
|
const meId = UserStore.getCurrentUser().id;
|
||||||
const hasNoBlockedMessages = Vencord.Plugins.isPluginEnabled(NoBlockedMessagesPlugin.name);
|
const hasNoBlockedMessages = isPluginEnabled(NoBlockedMessagesPlugin.name);
|
||||||
|
|
||||||
messages = messages.filter(m => {
|
messages = messages.filter(m => {
|
||||||
if (m.deleted) return false;
|
if (m.deleted) return false;
|
||||||
|
|
@ -170,7 +171,7 @@ function getNextMessage(isUp: boolean, isReply: boolean) {
|
||||||
function shouldMention(message: Message) {
|
function shouldMention(message: Message) {
|
||||||
switch (settings.store.shouldMention) {
|
switch (settings.store.shouldMention) {
|
||||||
case MentionOptions.NO_REPLY_MENTION_PLUGIN:
|
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);
|
return NoReplyMentionPlugin.shouldMention(message, false);
|
||||||
case MentionOptions.DISABLED:
|
case MentionOptions.DISABLED:
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,8 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { DataStore, Notices } from "@api/index";
|
import * as DataStore from "@api/DataStore";
|
||||||
|
import { popNotice, showNotice } from "@api/Notices";
|
||||||
import { showNotification } from "@api/Notifications";
|
import { showNotification } from "@api/Notifications";
|
||||||
import { getUniqueUsername, openUserProfile } from "@utils/discord";
|
import { getUniqueUsername, openUserProfile } from "@utils/discord";
|
||||||
import { FluxStore } from "@vencord/discord-types";
|
import { FluxStore } from "@vencord/discord-types";
|
||||||
|
|
@ -111,7 +112,7 @@ export async function syncAndRunChecks() {
|
||||||
|
|
||||||
export function notify(text: string, icon?: string, onClick?: () => void) {
|
export function notify(text: string, icon?: string, onClick?: () => void) {
|
||||||
if (settings.store.notices)
|
if (settings.store.notices)
|
||||||
Notices.showNotice(text, "OK", () => Notices.popNotice());
|
showNotice(text, "OK", () => popNotice());
|
||||||
|
|
||||||
showNotification({
|
showNotification({
|
||||||
title: "Relationship Notifier",
|
title: "Relationship Notifier",
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* 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 { Logger } from "@utils/Logger";
|
||||||
import { openModal } from "@utils/modal";
|
import { openModal } from "@utils/modal";
|
||||||
import { OAuth2AuthorizeModal, showToast, Toasts, UserStore } from "@webpack/common";
|
import { OAuth2AuthorizeModal, showToast, Toasts, UserStore } from "@webpack/common";
|
||||||
|
|
|
||||||
|
|
@ -4,16 +4,15 @@
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* 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 { Logger } from "@utils/Logger";
|
||||||
import { ModalCloseButton, ModalContent, ModalHeader, ModalRoot, openModal } from "@utils/modal";
|
import { ModalCloseButton, ModalContent, ModalHeader, ModalRoot, openModal } from "@utils/modal";
|
||||||
import { useAwaiter } from "@utils/react";
|
import { useAwaiter } from "@utils/react";
|
||||||
import { Forms, Tooltip, useState } from "@webpack/common";
|
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; }) {
|
function UnblockButton(props: { onClick?(): void; }) {
|
||||||
return (
|
return (
|
||||||
<Tooltip text="Unblock user">
|
<Tooltip text="Unblock user">
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,11 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { Badge } from "@plugins/reviewDB/entities";
|
||||||
|
import { cl } from "@plugins/reviewDB/utils";
|
||||||
import { MaskedLink, React, Tooltip } from "@webpack/common";
|
import { MaskedLink, React, Tooltip } from "@webpack/common";
|
||||||
import { HTMLAttributes } from "react";
|
import { HTMLAttributes } from "react";
|
||||||
|
|
||||||
import { Badge } from "../entities";
|
|
||||||
import { cl } from "../utils";
|
|
||||||
|
|
||||||
export default function ReviewBadge(badge: Badge & { onClick?(): void; }) {
|
export default function ReviewBadge(badge: Badge & { onClick?(): void; }) {
|
||||||
const Wrapper = badge.redirectURL
|
const Wrapper = badge.redirectURL
|
||||||
? MaskedLink
|
? MaskedLink
|
||||||
|
|
|
||||||
|
|
@ -16,17 +16,17 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
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 { openUserProfile } from "@utils/discord";
|
||||||
import { classes } from "@utils/misc";
|
import { classes } from "@utils/misc";
|
||||||
import { LazyComponent } from "@utils/react";
|
import { LazyComponent } from "@utils/react";
|
||||||
import { filters, findBulk } from "@webpack";
|
import { filters, findBulk } from "@webpack";
|
||||||
import { Alerts, Parser, Timestamp, useState } from "@webpack/common";
|
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 { openBlockModal } from "./BlockedUserModal";
|
||||||
import { BlockButton, DeleteButton, ReportButton } from "./MessageButton";
|
import { BlockButton, DeleteButton, ReportButton } from "./MessageButton";
|
||||||
import ReviewBadge from "./ReviewBadge";
|
import ReviewBadge from "./ReviewBadge";
|
||||||
|
|
|
||||||
|
|
@ -17,14 +17,14 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
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 { ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalRoot, ModalSize, openModal } from "@utils/modal";
|
||||||
import { useForceUpdater } from "@utils/react";
|
import { useForceUpdater } from "@utils/react";
|
||||||
import { Paginator, Text, useRef, useState } from "@webpack/common";
|
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 ReviewComponent from "./ReviewComponent";
|
||||||
import ReviewsView, { ReviewsInputComponent } from "./ReviewsView";
|
import ReviewsView, { ReviewsInputComponent } from "./ReviewsView";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,15 +16,15 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
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 { useAwaiter, useForceUpdater } from "@utils/react";
|
||||||
import { findByCodeLazy, findByPropsLazy, findComponentByCodeLazy } from "@webpack";
|
import { findByCodeLazy, findByPropsLazy, findComponentByCodeLazy } from "@webpack";
|
||||||
import { Forms, React, RelationshipStore, useRef, UserStore } from "@webpack/common";
|
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";
|
import ReviewComponent from "./ReviewComponent";
|
||||||
|
|
||||||
const Transforms = findByPropsLazy("insertNodes", "textToText");
|
const Transforms = findByPropsLazy("insertNodes", "textToText");
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* 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 { definePluginSettings } from "@api/Settings";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import { hasGuildFeature } from "@utils/discord";
|
import { hasGuildFeature } from "@utils/discord";
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,12 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { dispatchTheme } from "@plugins/shikiCodeblocks.desktop/hooks/useTheme";
|
||||||
|
import type { ShikiSpec } from "@plugins/shikiCodeblocks.desktop/types";
|
||||||
import { shikiOnigasmSrc, shikiWorkerSrc } from "@utils/dependencies";
|
import { shikiOnigasmSrc, shikiWorkerSrc } from "@utils/dependencies";
|
||||||
import { WorkerClient } from "@vap/core/ipc";
|
import { WorkerClient } from "@vap/core/ipc";
|
||||||
import type { IShikiTheme, IThemedToken } from "@vap/shiki";
|
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 { getGrammar, languages, loadLanguages, resolveLang } from "./languages";
|
||||||
import { themes } from "./themes";
|
import { themes } from "./themes";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,8 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { cl } from "../utils/misc";
|
import { cl } from "@plugins/shikiCodeblocks.desktop/utils/misc";
|
||||||
|
|
||||||
import { CopyButton } from "./CopyButton";
|
import { CopyButton } from "./CopyButton";
|
||||||
|
|
||||||
export interface ButtonRowProps {
|
export interface ButtonRowProps {
|
||||||
|
|
|
||||||
|
|
@ -16,11 +16,11 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { cl } from "@plugins/shikiCodeblocks.desktop/utils/misc";
|
||||||
import type { IThemedToken } from "@vap/shiki";
|
import type { IThemedToken } from "@vap/shiki";
|
||||||
import { hljs } from "@webpack/common";
|
import { hljs } from "@webpack/common";
|
||||||
import { JSX } from "react";
|
import { JSX } from "react";
|
||||||
|
|
||||||
import { cl } from "../utils/misc";
|
|
||||||
import { ThemeBase } from "./Highlighter";
|
import { ThemeBase } from "./Highlighter";
|
||||||
|
|
||||||
export interface CodeProps {
|
export interface CodeProps {
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { useCopyCooldown } from "../hooks/useCopyCooldown";
|
import { useCopyCooldown } from "@plugins/shikiCodeblocks.desktop/hooks/useCopyCooldown";
|
||||||
|
|
||||||
export interface CopyButtonProps extends React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement> {
|
export interface CopyButtonProps extends React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement> {
|
||||||
content: string;
|
content: string;
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,9 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Language } from "../api/languages";
|
import { Language } from "@plugins/shikiCodeblocks.desktop/api/languages";
|
||||||
import { DeviconSetting } from "../types";
|
import { DeviconSetting } from "@plugins/shikiCodeblocks.desktop/types";
|
||||||
import { cl } from "../utils/misc";
|
import { cl } from "@plugins/shikiCodeblocks.desktop/utils/misc";
|
||||||
|
|
||||||
export interface HeaderProps {
|
export interface HeaderProps {
|
||||||
langName?: string;
|
langName?: string;
|
||||||
|
|
|
||||||
|
|
@ -17,15 +17,15 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
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 { useAwaiter, useIntersection } from "@utils/react";
|
||||||
import { hljs, React } from "@webpack/common";
|
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 { ButtonRow } from "./ButtonRow";
|
||||||
import { Code } from "./Code";
|
import { Code } from "./Code";
|
||||||
import { Header } from "./Header";
|
import { Header } from "./Header";
|
||||||
|
|
|
||||||
|
|
@ -16,11 +16,10 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { shiki } from "@plugins/shikiCodeblocks.desktop/api/shiki";
|
||||||
|
import { settings as pluginSettings, ShikiSettings } from "@plugins/shikiCodeblocks.desktop/settings";
|
||||||
import { React } from "@webpack/common";
|
import { React } from "@webpack/common";
|
||||||
|
|
||||||
import { shiki } from "../api/shiki";
|
|
||||||
import { settings as pluginSettings, ShikiSettings } from "../settings";
|
|
||||||
|
|
||||||
export function useShikiSettings<F extends keyof ShikiSettings>(settingKeys: F[]) {
|
export function useShikiSettings<F extends keyof ShikiSettings>(settingKeys: F[]) {
|
||||||
const settings = pluginSettings.use([...settingKeys, "customTheme", "theme"]);
|
const settings = pluginSettings.use([...settingKeys, "customTheme", "theme"]);
|
||||||
const [isLoading, setLoading] = React.useState(false);
|
const [isLoading, setLoading] = React.useState(false);
|
||||||
|
|
|
||||||
|
|
@ -17,12 +17,11 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { classNameFactory } from "@api/Styles";
|
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 { 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 cl = classNameFactory("vc-shiki-");
|
||||||
|
|
||||||
export const shouldUseHljs = ({
|
export const shouldUseHljs = ({
|
||||||
|
|
|
||||||
|
|
@ -18,17 +18,18 @@
|
||||||
|
|
||||||
import "./styles.css";
|
import "./styles.css";
|
||||||
|
|
||||||
|
import { isPluginEnabled } from "@api/PluginManager";
|
||||||
import { definePluginSettings } from "@api/Settings";
|
import { definePluginSettings } from "@api/Settings";
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { Flex } from "@components/Flex";
|
import { Flex } from "@components/Flex";
|
||||||
import { CopyIcon, LinkIcon } from "@components/Icons";
|
import { CopyIcon, LinkIcon } from "@components/Icons";
|
||||||
|
import OpenInAppPlugin from "@plugins/openInApp";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import { copyWithToast } from "@utils/misc";
|
import { copyWithToast } from "@utils/discord";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { ConnectedAccount, User } from "@vencord/discord-types";
|
import { ConnectedAccount, User } from "@vencord/discord-types";
|
||||||
import { findByCodeLazy, findByPropsLazy } from "@webpack";
|
import { findByCodeLazy, findByPropsLazy } from "@webpack";
|
||||||
import { Tooltip, UserProfileStore } from "@webpack/common";
|
import { Tooltip, UserProfileStore } from "@webpack/common";
|
||||||
import OpenInAppPlugin from "plugins/openInApp";
|
|
||||||
|
|
||||||
import { VerifiedIcon } from "./VerifiedIcon";
|
import { VerifiedIcon } from "./VerifiedIcon";
|
||||||
|
|
||||||
|
|
@ -133,7 +134,7 @@ function CompactConnectionComponent({ connection, theme }: { connection: Connect
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
onClick={e => {
|
onClick={e => {
|
||||||
if (Vencord.Plugins.isPluginEnabled("OpenInApp")) {
|
if (isPluginEnabled(OpenInAppPlugin.name)) {
|
||||||
// handleLink will .preventDefault() if applicable
|
// handleLink will .preventDefault() if applicable
|
||||||
OpenInAppPlugin.handleLink(e.currentTarget, e);
|
OpenInAppPlugin.handleLink(e.currentTarget, e);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,16 +16,18 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { isPluginEnabled } from "@api/PluginManager";
|
||||||
import { Settings } from "@api/Settings";
|
import { Settings } from "@api/Settings";
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
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 { classes } from "@utils/misc";
|
||||||
import { formatDuration } from "@utils/text";
|
import { formatDuration } from "@utils/text";
|
||||||
import type { Channel } from "@vencord/discord-types";
|
import type { Channel } from "@vencord/discord-types";
|
||||||
import { findByPropsLazy, findComponentByCodeLazy } from "@webpack";
|
import { findByPropsLazy, findComponentByCodeLazy } from "@webpack";
|
||||||
import { EmojiStore, FluxDispatcher, GuildMemberStore, GuildStore, Parser, PermissionsBits, PermissionStore, SnowflakeUtils, Text, Timestamp, Tooltip, useEffect, useState } from "@webpack/common";
|
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 "..";
|
import { cl, settings } from "..";
|
||||||
|
|
||||||
const enum SortOrderTypes {
|
const enum SortOrderTypes {
|
||||||
|
|
@ -274,7 +276,7 @@ function HiddenChannelLockScreen({ channel }: { channel: ExtendedChannel; }) {
|
||||||
}
|
}
|
||||||
<div className={cl("allowed-users-and-roles-container")}>
|
<div className={cl("allowed-users-and-roles-container")}>
|
||||||
<div className={cl("allowed-users-and-roles-container-title")}>
|
<div className={cl("allowed-users-and-roles-container-title")}>
|
||||||
{Vencord.Plugins.isPluginEnabled("PermissionsViewer") && (
|
{isPluginEnabled(PermissionsViewerPlugin.name) && (
|
||||||
<Tooltip text="Permission Details">
|
<Tooltip text="Permission Details">
|
||||||
{({ onMouseLeave, onMouseEnter }) => (
|
{({ onMouseLeave, onMouseEnter }) => (
|
||||||
<button
|
<button
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,8 @@ import { CopyIcon, ImageIcon, LinkIcon, OpenExternalIcon } from "@components/Ico
|
||||||
import { Paragraph } from "@components/Paragraph";
|
import { Paragraph } from "@components/Paragraph";
|
||||||
import { Span } from "@components/Span";
|
import { Span } from "@components/Span";
|
||||||
import { debounce } from "@shared/debounce";
|
import { debounce } from "@shared/debounce";
|
||||||
import { openImageModal } from "@utils/discord";
|
import { copyWithToast, openImageModal } from "@utils/discord";
|
||||||
import { classes, copyWithToast } from "@utils/misc";
|
import { classes } from "@utils/misc";
|
||||||
import { ContextMenuApi, FluxDispatcher, Menu, React, useEffect, useState, useStateFromStores } from "@webpack/common";
|
import { ContextMenuApi, FluxDispatcher, Menu, React, useEffect, useState, useStateFromStores } from "@webpack/common";
|
||||||
|
|
||||||
import { SeekBar } from "./SeekBar";
|
import { SeekBar } from "./SeekBar";
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,9 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { isPluginEnabled } from "@api/PluginManager";
|
||||||
import { Settings } from "@api/Settings";
|
import { Settings } from "@api/Settings";
|
||||||
|
import OpenInAppPlugin from "@plugins/openInApp";
|
||||||
import { findByProps, findByPropsLazy, proxyLazyWebpack } from "@webpack";
|
import { findByProps, findByPropsLazy, proxyLazyWebpack } from "@webpack";
|
||||||
import { Flux, FluxDispatcher } from "@webpack/common";
|
import { Flux, FluxDispatcher } from "@webpack/common";
|
||||||
|
|
||||||
|
|
@ -89,7 +91,7 @@ export const SpotifyStore = proxyLazyWebpack(() => {
|
||||||
public isSettingPosition = false;
|
public isSettingPosition = false;
|
||||||
|
|
||||||
public openExternal(path: string) {
|
public openExternal(path: string) {
|
||||||
const url = Settings.plugins.SpotifyControls.useSpotifyUris || Vencord.Plugins.isPluginEnabled("OpenInApp")
|
const url = Settings.plugins.SpotifyControls.useSpotifyUris || isPluginEnabled(OpenInAppPlugin.name)
|
||||||
? "spotify:" + path.replaceAll("/", (_, idx) => idx === 0 ? "" : ":")
|
? "spotify:" + path.replaceAll("/", (_, idx) => idx === 0 ? "" : ":")
|
||||||
: "https://open.spotify.com" + path;
|
: "https://open.spotify.com" + path;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,14 +20,13 @@ import "./style.css";
|
||||||
|
|
||||||
import { definePluginSettings, Settings } from "@api/Settings";
|
import { definePluginSettings, Settings } from "@api/Settings";
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
|
import { buildSeveralUsers } from "@plugins/typingTweaks";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import { getIntlMessage } from "@utils/discord";
|
import { getIntlMessage } from "@utils/discord";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { findComponentByCodeLazy, findStoreLazy } from "@webpack";
|
import { findComponentByCodeLazy, findStoreLazy } from "@webpack";
|
||||||
import { GuildMemberStore, RelationshipStore, SelectedChannelStore, Tooltip, TypingStore, UserStore, UserSummaryItem, useStateFromStores } from "@webpack/common";
|
import { GuildMemberStore, RelationshipStore, SelectedChannelStore, Tooltip, TypingStore, UserStore, UserSummaryItem, useStateFromStores } from "@webpack/common";
|
||||||
|
|
||||||
import { buildSeveralUsers } from "../typingTweaks";
|
|
||||||
|
|
||||||
const ThreeDots = findComponentByCodeLazy(".dots,", "dotRadius:");
|
const ThreeDots = findComponentByCodeLazy(".dots,", "dotRadius:");
|
||||||
|
|
||||||
const UserGuildSettingsStore = findStoreLazy("UserGuildSettingsStore");
|
const UserGuildSettingsStore = findStoreLazy("UserGuildSettingsStore");
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ export default definePlugin({
|
||||||
find: "inQuote:",
|
find: "inQuote:",
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /,content:([^,]+),inQuote/,
|
match: /,content:([^,]+),inQuote/,
|
||||||
replace: (_, content) => `,content:Vencord.Plugins.plugins.Unindent.unindent(${content}),inQuote`
|
replace: (_, content) => `,content:$self.unindent(${content}),inQuote`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,10 @@
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { isPluginEnabled } from "@api/PluginManager";
|
||||||
import { classNameFactory } from "@api/Styles";
|
import { classNameFactory } from "@api/Styles";
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
|
import ShowHiddenChannelsPlugin from "@plugins/showHiddenChannels";
|
||||||
import { classes } from "@utils/misc";
|
import { classes } from "@utils/misc";
|
||||||
import { Channel } from "@vencord/discord-types";
|
import { Channel } from "@vencord/discord-types";
|
||||||
import { filters, findByPropsLazy, mapMangledModuleLazy } from "@webpack";
|
import { filters, findByPropsLazy, mapMangledModuleLazy } from "@webpack";
|
||||||
|
|
@ -141,7 +143,7 @@ export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId, isProfile, is
|
||||||
if (channel == null) return null;
|
if (channel == null) return null;
|
||||||
|
|
||||||
const isDM = channel.isDM() || channel.isMultiUserDM();
|
const isDM = channel.isDM() || channel.isMultiUserDM();
|
||||||
if (!isDM && !PermissionStore.can(PermissionsBits.VIEW_CHANNEL, channel) && !Vencord.Plugins.isPluginEnabled("ShowHiddenChannels")) return null;
|
if (!isDM && !PermissionStore.can(PermissionsBits.VIEW_CHANNEL, channel) && !isPluginEnabled(ShowHiddenChannelsPlugin.name)) return null;
|
||||||
|
|
||||||
const isLocked = !isDM && (!PermissionStore.can(PermissionsBits.VIEW_CHANNEL, channel) || !PermissionStore.can(PermissionsBits.CONNECT, channel));
|
const isLocked = !isDM && (!PermissionStore.can(PermissionsBits.VIEW_CHANNEL, channel) || !PermissionStore.can(PermissionsBits.CONNECT, channel));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,10 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import "./index.css";
|
import "./styles.css";
|
||||||
|
|
||||||
import { openNotificationLogModal } from "@api/Notifications/notificationLog";
|
import { openNotificationLogModal } from "@api/Notifications/notificationLog";
|
||||||
|
import { isPluginEnabled, plugins } from "@api/PluginManager";
|
||||||
import { Settings, useSettings } from "@api/Settings";
|
import { Settings, useSettings } from "@api/Settings";
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
|
|
@ -34,8 +35,8 @@ function VencordPopout(onClose: () => void) {
|
||||||
|
|
||||||
const pluginEntries = [] as ReactNode[];
|
const pluginEntries = [] as ReactNode[];
|
||||||
|
|
||||||
for (const plugin of Object.values(Vencord.Plugins.plugins)) {
|
for (const plugin of Object.values(plugins)) {
|
||||||
if (plugin.toolboxActions && Vencord.Plugins.isPluginEnabled(plugin.name)) {
|
if (plugin.toolboxActions && isPluginEnabled(plugin.name)) {
|
||||||
pluginEntries.push(
|
pluginEntries.push(
|
||||||
<Menu.MenuGroup
|
<Menu.MenuGroup
|
||||||
label={plugin.name}
|
label={plugin.name}
|
||||||
|
|
|
||||||
|
|
@ -23,9 +23,8 @@ import { Divider } from "@components/Divider";
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { Flex } from "@components/Flex";
|
import { Flex } from "@components/Flex";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import { getCurrentGuild, getIntlMessage } from "@utils/discord";
|
import { copyWithToast, getCurrentGuild, getIntlMessage } from "@utils/discord";
|
||||||
import { Margins } from "@utils/margins";
|
import { Margins } from "@utils/margins";
|
||||||
import { copyWithToast } from "@utils/misc";
|
|
||||||
import { closeModal, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalRoot, ModalSize, openModal } from "@utils/modal";
|
import { closeModal, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalRoot, ModalSize, openModal } from "@utils/modal";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { Message } from "@vencord/discord-types";
|
import { Message } from "@vencord/discord-types";
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
258
src/utils/apng.ts
Normal file
258
src/utils/apng.ts
Normal file
|
|
@ -0,0 +1,258 @@
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* apng-canvas v2.1.2 - heavily modified and converted to Typescript
|
||||||
|
*
|
||||||
|
* @copyright 2011-2019 David Mzareulyan
|
||||||
|
* @link https://github.com/davidmz/apng-canvas
|
||||||
|
* @license MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
// https://wiki.mozilla.org/APNG_Specification#.60fcTL.60:_The_Frame_Control_Chunk
|
||||||
|
export const enum ApngDisposeOp {
|
||||||
|
/**
|
||||||
|
* no disposal is done on this frame before rendering the next; the contents of the output buffer are left as is.
|
||||||
|
*/
|
||||||
|
NONE,
|
||||||
|
/**
|
||||||
|
* the frame's region of the output buffer is to be cleared to fully transparent black before rendering the next frame.
|
||||||
|
*/
|
||||||
|
BACKGROUND,
|
||||||
|
/**
|
||||||
|
* the frame's region of the output buffer is to be reverted to the previous contents before rendering the next frame.
|
||||||
|
*/
|
||||||
|
PREVIOUS
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Might need to somehow implement this
|
||||||
|
export const enum ApngBlendOp {
|
||||||
|
SOURCE,
|
||||||
|
OVER
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Frame {
|
||||||
|
width: number;
|
||||||
|
height: number;
|
||||||
|
left: number;
|
||||||
|
top: number;
|
||||||
|
delay: number;
|
||||||
|
disposeOp: ApngDisposeOp;
|
||||||
|
blendOp: ApngBlendOp;
|
||||||
|
dataParts?: U8Arr[];
|
||||||
|
img: HTMLImageElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Animation {
|
||||||
|
width = 0;
|
||||||
|
height = 0;
|
||||||
|
numPlays = 0;
|
||||||
|
playTime = 0;
|
||||||
|
frames: Frame[] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Typescript has become more strict, requiring you to explicitly specify the ArrayBuffer generic
|
||||||
|
type U8Arr = Uint8Array<ArrayBuffer>;
|
||||||
|
|
||||||
|
const table = new Uint32Array(256);
|
||||||
|
|
||||||
|
for (let i = 0; i < 256; i++) {
|
||||||
|
let c = i;
|
||||||
|
for (let k = 0; k < 8; k++) c = (c & 1) ? 0xEDB88320 ^ (c >>> 1) : c >>> 1;
|
||||||
|
table[i] = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
function crc32(bytes: U8Arr, start: number = 0, length?: number): number {
|
||||||
|
length = length ?? (bytes.length - start);
|
||||||
|
let crc = -1;
|
||||||
|
for (let i = start, l = start + length; i < l; i++) {
|
||||||
|
crc = (crc >>> 8) ^ table[(crc ^ bytes[i]) & 0xFF];
|
||||||
|
}
|
||||||
|
return crc ^ (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const PNG_SIGNATURE_BYTES = new Uint8Array([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
|
||||||
|
|
||||||
|
export function parseAPNG(buffer: ArrayBuffer): Promise<Animation> {
|
||||||
|
const bytes = new Uint8Array(buffer);
|
||||||
|
return new Promise(function (resolve, reject) {
|
||||||
|
|
||||||
|
for (let i = 0; i < PNG_SIGNATURE_BYTES.length; i++) {
|
||||||
|
if (PNG_SIGNATURE_BYTES[i] != bytes[i]) {
|
||||||
|
reject("Not a PNG file (invalid file signature)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fast animation test
|
||||||
|
let isAnimated = false;
|
||||||
|
parseChunks(bytes, function (type) {
|
||||||
|
if (type == "acTL") {
|
||||||
|
isAnimated = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
if (!isAnimated) {
|
||||||
|
reject("Not an animated PNG");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const preDataParts: U8Arr[] = [];
|
||||||
|
const postDataParts: U8Arr[] = [];
|
||||||
|
let headerDataBytes: U8Arr | null = null;
|
||||||
|
let frame: Frame | null = null;
|
||||||
|
const anim = new Animation();
|
||||||
|
|
||||||
|
parseChunks(bytes, function (type, bytes, off, length) {
|
||||||
|
switch (type) {
|
||||||
|
case "IHDR":
|
||||||
|
headerDataBytes = bytes.subarray(off + 8, off + 8 + length);
|
||||||
|
anim.width = readDWord(bytes, off + 8);
|
||||||
|
anim.height = readDWord(bytes, off + 12);
|
||||||
|
break;
|
||||||
|
case "acTL":
|
||||||
|
anim.numPlays = readDWord(bytes, off + 8 + 4);
|
||||||
|
break;
|
||||||
|
case "fcTL":
|
||||||
|
if (frame) anim.frames.push(frame);
|
||||||
|
frame = {} as Frame;
|
||||||
|
frame.width = readDWord(bytes, off + 8 + 4);
|
||||||
|
frame.height = readDWord(bytes, off + 8 + 8);
|
||||||
|
frame.left = readDWord(bytes, off + 8 + 12);
|
||||||
|
frame.top = readDWord(bytes, off + 8 + 16);
|
||||||
|
let delayN = readWord(bytes, off + 8 + 20);
|
||||||
|
let delayD = readWord(bytes, off + 8 + 22);
|
||||||
|
if (delayD == 0) delayD = 100;
|
||||||
|
frame.delay = 1000 * delayN / delayD;
|
||||||
|
// see http://mxr.mozilla.org/mozilla/source/gfx/src/shared/gfxImageFrame.cpp#343
|
||||||
|
if (frame.delay <= 10) frame.delay = 100;
|
||||||
|
anim.playTime += frame.delay;
|
||||||
|
frame.disposeOp = readByte(bytes, off + 8 + 24);
|
||||||
|
frame.blendOp = readByte(bytes, off + 8 + 25);
|
||||||
|
frame.dataParts = [];
|
||||||
|
break;
|
||||||
|
case "fdAT":
|
||||||
|
if (frame) frame.dataParts!.push(bytes.subarray(off + 8 + 4, off + 8 + length));
|
||||||
|
break;
|
||||||
|
case "IDAT":
|
||||||
|
if (frame) frame.dataParts!.push(bytes.subarray(off + 8, off + 8 + length));
|
||||||
|
break;
|
||||||
|
case "IEND":
|
||||||
|
postDataParts.push(subBuffer(bytes, off, 12 + length));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
preDataParts.push(subBuffer(bytes, off, 12 + length));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (frame) anim.frames.push(frame);
|
||||||
|
|
||||||
|
if (anim.frames.length == 0) {
|
||||||
|
reject("Not an animated PNG");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// creating images
|
||||||
|
let createdImages = 0;
|
||||||
|
const preBlob = new Blob(preDataParts);
|
||||||
|
const postBlob = new Blob(postDataParts);
|
||||||
|
for (let f = 0; f < anim.frames.length; f++) {
|
||||||
|
frame = anim.frames[f];
|
||||||
|
|
||||||
|
const bb: (U8Arr | Blob)[] = [];
|
||||||
|
bb.push(PNG_SIGNATURE_BYTES);
|
||||||
|
headerDataBytes!.set(makeDWordArray(frame.width), 0);
|
||||||
|
headerDataBytes!.set(makeDWordArray(frame.height), 4);
|
||||||
|
bb.push(makeChunkBytes("IHDR", headerDataBytes!));
|
||||||
|
bb.push(preBlob);
|
||||||
|
for (let j = 0; j < frame.dataParts!.length; j++) {
|
||||||
|
bb.push(makeChunkBytes("IDAT", frame.dataParts![j]));
|
||||||
|
}
|
||||||
|
bb.push(postBlob);
|
||||||
|
const url = URL.createObjectURL(new Blob(bb, { "type": "image/png" }));
|
||||||
|
delete frame.dataParts;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Using "createElement" instead of "new Image" because of bug in Chrome 27
|
||||||
|
* https://code.google.com/p/chromium/issues/detail?id=238071
|
||||||
|
* http://stackoverflow.com/questions/16377375/using-canvas-drawimage-in-chrome-extension-content-script/16378270
|
||||||
|
*/
|
||||||
|
const img = frame.img = new Image();
|
||||||
|
img.onload = function () {
|
||||||
|
URL.revokeObjectURL(img.src);
|
||||||
|
createdImages++;
|
||||||
|
if (createdImages == anim.frames.length) {
|
||||||
|
resolve(anim);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
img.onerror = function () {
|
||||||
|
reject("Image creation error");
|
||||||
|
};
|
||||||
|
img.src = url;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseChunks(bytes: U8Arr, callback: (type: string, bytes: U8Arr, off: number, length: number) => boolean | void): void {
|
||||||
|
let off = 8;
|
||||||
|
let res: boolean | void;
|
||||||
|
let type: string;
|
||||||
|
|
||||||
|
do {
|
||||||
|
const length = readDWord(bytes, off);
|
||||||
|
type = readString(bytes, off + 4, 4);
|
||||||
|
res = callback(type, bytes, off, length);
|
||||||
|
off += 12 + length;
|
||||||
|
} while (res !== false && type != "IEND" && off < bytes.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
function readDWord(bytes: U8Arr, off: number): number {
|
||||||
|
let x = 0;
|
||||||
|
// Force the most-significant byte to unsigned.
|
||||||
|
x += ((bytes[0 + off] << 24) >>> 0);
|
||||||
|
for (let i = 1; i < 4; i++) x += ((bytes[i + off] << ((3 - i) * 8)));
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
function readWord(bytes: U8Arr, off: number): number {
|
||||||
|
let x = 0;
|
||||||
|
for (let i = 0; i < 2; i++) x += (bytes[i + off] << ((1 - i) * 8));
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
function readByte(bytes: U8Arr, off: number): number {
|
||||||
|
return bytes[off];
|
||||||
|
}
|
||||||
|
|
||||||
|
function subBuffer(bytes: U8Arr, start: number, length: number): U8Arr {
|
||||||
|
const a = new Uint8Array(length);
|
||||||
|
a.set(bytes.subarray(start, start + length));
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
function readString(bytes: U8Arr, off: number, length: number): string {
|
||||||
|
const chars = Array.prototype.slice.call(bytes.subarray(off, off + length));
|
||||||
|
return String.fromCharCode.apply(String, chars);
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeDWordArray(x: number): number[] {
|
||||||
|
return [(x >>> 24) & 0xff, (x >>> 16) & 0xff, (x >>> 8) & 0xff, x & 0xff];
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeStringArray(x: string): number[] {
|
||||||
|
const res: number[] = [];
|
||||||
|
for (let i = 0; i < x.length; i++) res.push(x.charCodeAt(i));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeChunkBytes(type: string, dataBytes: U8Arr): U8Arr {
|
||||||
|
const crcLen = type.length + dataBytes.length;
|
||||||
|
const bytes = new Uint8Array(new ArrayBuffer(crcLen + 8));
|
||||||
|
bytes.set(makeDWordArray(dataBytes.length), 0);
|
||||||
|
bytes.set(makeStringArray(type), 4);
|
||||||
|
bytes.set(dataBytes, 8);
|
||||||
|
const crc = crc32(bytes, 4, crcLen);
|
||||||
|
bytes.set(makeDWordArray(crc), crcLen + 4);
|
||||||
|
return bytes;
|
||||||
|
};
|
||||||
|
|
@ -30,6 +30,9 @@ const platform = navigator.platform.toLowerCase();
|
||||||
export const IS_WINDOWS = platform.startsWith("win");
|
export const IS_WINDOWS = platform.startsWith("win");
|
||||||
export const IS_MAC = platform.startsWith("mac");
|
export const IS_MAC = platform.startsWith("mac");
|
||||||
export const IS_LINUX = platform.startsWith("linux");
|
export const IS_LINUX = platform.startsWith("linux");
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent#mobile_tablet_or_desktop
|
||||||
|
// "In summary, we recommend looking for the string Mobi anywhere in the User Agent to detect a mobile device."
|
||||||
|
export const IS_MOBILE = navigator.userAgent.includes("Mobi");
|
||||||
|
|
||||||
export interface Dev {
|
export interface Dev {
|
||||||
name: string;
|
name: string;
|
||||||
|
|
|
||||||
|
|
@ -16,61 +16,8 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { makeLazy } from "./lazy";
|
|
||||||
|
|
||||||
/*
|
|
||||||
Add dynamically loaded dependencies for plugins here.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// needed to parse APNGs in the nitroBypass plugin
|
|
||||||
export const importApngJs = makeLazy(() => {
|
|
||||||
return require("./apng-canvas").APNG as { parseURL(url: string): Promise<ApngFrameData>; };
|
|
||||||
});
|
|
||||||
|
|
||||||
// https://wiki.mozilla.org/APNG_Specification#.60fcTL.60:_The_Frame_Control_Chunk
|
|
||||||
export const enum ApngDisposeOp {
|
|
||||||
/**
|
|
||||||
* no disposal is done on this frame before rendering the next; the contents of the output buffer are left as is.
|
|
||||||
*/
|
|
||||||
NONE,
|
|
||||||
/**
|
|
||||||
* the frame's region of the output buffer is to be cleared to fully transparent black before rendering the next frame.
|
|
||||||
*/
|
|
||||||
BACKGROUND,
|
|
||||||
/**
|
|
||||||
* the frame's region of the output buffer is to be reverted to the previous contents before rendering the next frame.
|
|
||||||
*/
|
|
||||||
PREVIOUS
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Might need to somehow implement this
|
|
||||||
export const enum ApngBlendOp {
|
|
||||||
SOURCE,
|
|
||||||
OVER
|
|
||||||
}
|
|
||||||
export interface ApngFrame {
|
|
||||||
left: number;
|
|
||||||
top: number;
|
|
||||||
width: number;
|
|
||||||
height: number;
|
|
||||||
img: HTMLImageElement;
|
|
||||||
delay: number;
|
|
||||||
blendOp: ApngBlendOp;
|
|
||||||
disposeOp: ApngDisposeOp;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ApngFrameData {
|
|
||||||
width: number;
|
|
||||||
height: number;
|
|
||||||
frames: ApngFrame[];
|
|
||||||
playTime: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The below code is only used on the Desktop (electron) build of Vencord.
|
// The below code is only used on the Desktop (electron) build of Vencord.
|
||||||
// Browser (extension) builds do not contain these remote imports.
|
// Browser (extension) builds do not contain these remote imports.
|
||||||
|
|
||||||
export const shikiWorkerSrc = `https://cdn.jsdelivr.net/npm/@vap/shiki-worker@0.0.8/dist/${IS_DEV ? "index.js" : "index.min.js"}`;
|
export const shikiWorkerSrc = `https://cdn.jsdelivr.net/npm/@vap/shiki-worker@0.0.8/dist/${IS_DEV ? "index.js" : "index.min.js"}`;
|
||||||
export const shikiOnigasmSrc = "https://cdn.jsdelivr.net/npm/@vap/shiki@0.10.3/dist/onig.wasm";
|
export const shikiOnigasmSrc = "https://cdn.jsdelivr.net/npm/@vap/shiki@0.10.3/dist/onig.wasm";
|
||||||
|
|
||||||
// @ts-expect-error
|
|
||||||
export const getStegCloak = /* #__PURE__*/ makeLazy(() => import("https://cdn.jsdelivr.net/npm/stegcloak-dist@1.0.0/index.js"));
|
|
||||||
|
|
|
||||||
|
|
@ -16,11 +16,12 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { MessageObject } from "@api/MessageEvents";
|
import type { MessageObject } from "@api/MessageEvents";
|
||||||
import { Channel, CloudUpload, Guild, GuildFeatures, Message, User } from "@vencord/discord-types";
|
import type { Channel, CloudUpload, Guild, GuildFeatures, Message, User } from "@vencord/discord-types";
|
||||||
import { ChannelActionCreators, ChannelStore, ComponentDispatch, Constants, FluxDispatcher, GuildStore, i18n, IconUtils, InviteActions, MessageActions, RestAPI, SelectedChannelStore, SelectedGuildStore, UserProfileActions, UserProfileStore, UserSettingsActionCreators, UserUtils } from "@webpack/common";
|
import { ChannelActionCreators, ChannelStore, ComponentDispatch, Constants, FluxDispatcher, GuildStore, i18n, IconUtils, InviteActions, MessageActions, RestAPI, SelectedChannelStore, SelectedGuildStore, Toasts, UserProfileActions, UserProfileStore, UserSettingsActionCreators, UserUtils } from "@webpack/common";
|
||||||
import { Except } from "type-fest";
|
import { Except } from "type-fest";
|
||||||
|
|
||||||
|
import { copyToClipboard } from "./clipboard";
|
||||||
import { runtimeHashMessageKey, runtimeHashMessageKeyLegacy } from "./intlHash";
|
import { runtimeHashMessageKey, runtimeHashMessageKeyLegacy } from "./intlHash";
|
||||||
import { Logger } from "./Logger";
|
import { Logger } from "./Logger";
|
||||||
import { MediaModalItem, MediaModalProps, openMediaModal } from "./modal";
|
import { MediaModalItem, MediaModalProps, openMediaModal } from "./modal";
|
||||||
|
|
@ -116,6 +117,15 @@ export function insertTextIntoChatInputBox(text: string) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function copyWithToast(text: string, toastMessage = "Copied to clipboard!") {
|
||||||
|
await copyToClipboard(text);
|
||||||
|
Toasts.show({
|
||||||
|
message: toastMessage,
|
||||||
|
id: Toasts.genId(),
|
||||||
|
type: Toasts.Type.SUCCESS
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
interface MessageOptions {
|
interface MessageOptions {
|
||||||
messageReference: Message["messageReference"];
|
messageReference: Message["messageReference"];
|
||||||
allowedMentions: {
|
allowedMentions: {
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ export * from "./ChangeList";
|
||||||
export * from "./clipboard";
|
export * from "./clipboard";
|
||||||
export * from "./constants";
|
export * from "./constants";
|
||||||
export * from "./cspViolations";
|
export * from "./cspViolations";
|
||||||
|
export * from "./css";
|
||||||
export * from "./discord";
|
export * from "./discord";
|
||||||
export * from "./guards";
|
export * from "./guards";
|
||||||
export * from "./intlHash";
|
export * from "./intlHash";
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,6 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Toasts } from "@webpack/common";
|
|
||||||
|
|
||||||
import { copyToClipboard } from "./clipboard";
|
|
||||||
import { DevsById } from "./constants";
|
import { DevsById } from "./constants";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -36,15 +33,6 @@ export function sleep(ms: number): Promise<void> {
|
||||||
return new Promise(r => setTimeout(r, ms));
|
return new Promise(r => setTimeout(r, ms));
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function copyWithToast(text: string, toastMessage = "Copied to clipboard!") {
|
|
||||||
await copyToClipboard(text);
|
|
||||||
Toasts.show({
|
|
||||||
message: toastMessage,
|
|
||||||
id: Toasts.genId(),
|
|
||||||
type: Toasts.Type.SUCCESS
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if obj is a true object: of type "object" and not null or array
|
* Check if obj is a true object: of type "object" and not null or array
|
||||||
*/
|
*/
|
||||||
|
|
@ -87,10 +75,6 @@ export function identity<T>(value: T): T {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent#mobile_tablet_or_desktop
|
|
||||||
// "In summary, we recommend looking for the string Mobi anywhere in the User Agent to detect a mobile device."
|
|
||||||
export const isMobile = navigator.userAgent.includes("Mobi");
|
|
||||||
|
|
||||||
export const isPluginDev = (id: string) => Object.hasOwn(DevsById, id);
|
export const isPluginDev = (id: string) => Object.hasOwn(DevsById, id);
|
||||||
export const shouldShowContributorBadge = (id: string) => isPluginDev(id) && DevsById[id].badge !== false;
|
export const shouldShowContributorBadge = (id: string) => isPluginDev(id) && DevsById[id].badge !== false;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,13 +19,8 @@
|
||||||
export function relaunch() {
|
export function relaunch() {
|
||||||
if (IS_DISCORD_DESKTOP)
|
if (IS_DISCORD_DESKTOP)
|
||||||
window.DiscordNative.app.relaunch();
|
window.DiscordNative.app.relaunch();
|
||||||
else
|
else if (IS_VESKTOP)
|
||||||
window.VesktopNative.app.relaunch();
|
window.VesktopNative.app.relaunch();
|
||||||
}
|
|
||||||
|
|
||||||
export function showItemInFolder(path: string) {
|
|
||||||
if (IS_DISCORD_DESKTOP)
|
|
||||||
window.DiscordNative.fileManager.showItemInFolder(path);
|
|
||||||
else
|
else
|
||||||
window.VesktopNative.fileManager.showItemInFolder(path);
|
location.reload();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { React, useEffect, useMemo, useReducer, useState } from "@webpack/common";
|
import { React, useEffect, useMemo, useReducer, useState } from "@webpack/common";
|
||||||
import { ActionDispatch, ReactNode } from "react";
|
import type { ActionDispatch, ReactNode } from "react";
|
||||||
|
|
||||||
import { checkIntersecting } from "./misc";
|
import { checkIntersecting } from "./misc";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,6 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { moment } from "@webpack/common";
|
|
||||||
|
|
||||||
// Utils for readable text transformations eg: `toTitle(fromKebab())`
|
// Utils for readable text transformations eg: `toTitle(fromKebab())`
|
||||||
|
|
||||||
// Case style to words
|
// Case style to words
|
||||||
|
|
@ -54,6 +52,7 @@ function getUnitStr(unit: Units, isOne: boolean, short: boolean) {
|
||||||
* @param short Whether to use short units like "d" instead of "days"
|
* @param short Whether to use short units like "d" instead of "days"
|
||||||
*/
|
*/
|
||||||
export function formatDuration(time: number, unit: Units, short: boolean = false) {
|
export function formatDuration(time: number, unit: Units, short: boolean = false) {
|
||||||
|
const { moment } = require("@webpack/common") as typeof import("@webpack/common");
|
||||||
const dur = moment.duration(time, unit);
|
const dur = moment.duration(time, unit);
|
||||||
|
|
||||||
let unitsAmounts = units.map(unit => ({ amount: dur[unit](), unit }));
|
let unitsAmounts = units.map(unit => ({ amount: dur[unit](), unit }));
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue