diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0d7d4d27b..bd826a2eb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -23,10 +23,10 @@ jobs: - uses: pnpm/action-setup@v3 - - name: Use Node.js 20 + - name: Use Node.js 24 uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 24 cache: "pnpm" - name: Install dependencies @@ -72,6 +72,7 @@ jobs: gh release upload latest --clobber dist/release/* - name: Upload Plugin JSONs to Equibored repo + if: github.repository == 'Equicord/Equicord' run: | git config --global user.name "GitHub-Actions" git config --global user.email actions@github.com diff --git a/.github/workflows/buildDev.yml b/.github/workflows/buildBranches.yml similarity index 96% rename from .github/workflows/buildDev.yml rename to .github/workflows/buildBranches.yml index 6ae23fef9..f4e98b2ac 100644 --- a/.github/workflows/buildDev.yml +++ b/.github/workflows/buildBranches.yml @@ -1,4 +1,4 @@ -name: Build +name: Build Branches on: push: @@ -28,6 +28,7 @@ jobs: Build: name: Build Equicord runs-on: ubuntu-latest + if: github.repository == 'Equicord/Equicord' steps: - uses: actions/checkout@v4 @@ -37,11 +38,11 @@ jobs: - uses: pnpm/action-setup@v3 if: github.ref_name != 'bun' - - name: Use Node.js 20 + - name: Use Node.js 24 if: github.ref_name != 'bun' uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 24 cache: "pnpm" - name: Install dependencies @@ -64,9 +65,8 @@ jobs: pnpm generateVencordPluginJson dist/vencordplugins.json pnpm generateDevsList dist/devs.json - - uses: actions/checkout@v4 - if: github.ref_name == 'bun' - uses: oven-sh/setup-bun@v2 + if: github.ref_name == 'bun' with: bun-version: latest - name: Install dependencies diff --git a/.github/workflows/nixosBuild.yml b/.github/workflows/nixosBuild.yml index 2ea5a91b9..bd2c85c8a 100644 --- a/.github/workflows/nixosBuild.yml +++ b/.github/workflows/nixosBuild.yml @@ -20,10 +20,10 @@ jobs: - uses: pnpm/action-setup@v3 - - name: Use Node.js 20 + - name: Use Node.js 24 uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 24 cache: "pnpm" - name: Install dependencies @@ -50,7 +50,7 @@ jobs: cp browser/browser.* release cp Equicord.user.{js,js.LEGAL.txt} release - # copy the plugin data jsons, the extension zips and the desktop/vesktop asars + # copy the plugin data jsons, the extension zips and the desktop/equibop asars cp *.{json,zip,asar} release # legacy un-asared files diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 2452e5fc8..694368312 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -62,11 +62,11 @@ jobs: if: steps.check.outputs.release == 'true' uses: pnpm/action-setup@v3 - - name: Use Node.js 20 + - name: Use Node.js 24 if: steps.check.outputs.release == 'true' uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 24 cache: "pnpm" - name: Install dependencies diff --git a/.github/workflows/reportBrokenPlugins.yml b/.github/workflows/reportBrokenPlugins.yml index 117a9a70c..ef0225a1f 100644 --- a/.github/workflows/reportBrokenPlugins.yml +++ b/.github/workflows/reportBrokenPlugins.yml @@ -33,10 +33,10 @@ jobs: - uses: pnpm/action-setup@v3 # Install pnpm using packageManager key in package.json - - name: Use Node.js 20 + - name: Use Node.js 24 uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 24 cache: "pnpm" - name: Install dependencies diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 708974e68..21d7e8b6c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -18,10 +18,10 @@ jobs: - uses: actions/checkout@v4 - uses: pnpm/action-setup@v3 # Install pnpm using packageManager key in package.json - - name: Use Node.js 20 + - name: Use Node.js 24 uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 24 cache: "pnpm" - name: Install dependencies diff --git a/package.json b/package.json index 9d4210c45..e7af19996 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "equicord", "private": "true", - "version": "1.14.6.2", + "version": "1.14.7.1", "description": "The other cutest Discord client mod", "homepage": "https://github.com/Equicord/Equicord#readme", "bugs": { @@ -55,47 +55,47 @@ "gifenc": "github:mattdesl/gifenc#64842fca317b112a8590f8fef2bf3825da8f6fe3", "idb": "8.0.3", "jsqr": "1.4.0", - "monaco-editor": "^0.54.0", + "monaco-editor": "^0.55.1", "nanoid": "^5.1.6", "native-file-system-adapter": "^3.0.1", "usercss-meta": "^0.12.0", - "virtual-merge": "^1.0.1" + "virtual-merge": "^1.0.1", + "yaml-js": "^0.3.1" }, "devDependencies": { - "@electron/asar": "^4.0.1", - "@stylistic/eslint-plugin": "^5.6.0", - "@types/adm-zip": "^0.5.7", - "@types/chrome": "^0.1.30", - "@types/diff": "^7.0.2", - "@types/lodash": "^4.17.20", - "@types/node": "^24.10.1", + "@electron/asar": "^4.2.0", + "@stylistic/eslint-plugin": "^5.10.0", + "@types/chrome": "^0.1.40", + "@types/lodash": "^4.17.24", + "@types/node": "^25.6.0", "@types/react": "^19.0.10", "@types/react-dom": "^19.0.4", - "@types/yazl": "^3.3.0", + "@types/yazl": "^3.3.1", "@vencord/discord-types": "link:packages/discord-types", - "diff": "^8.0.2", - "esbuild": "^0.27.0", - "eslint": "9.39.1", + "diff": "^9.0.0", + "esbuild": "^0.28.0", + "eslint": "10.2.0", "eslint-import-resolver-alias": "^1.1.2", "eslint-plugin-react": "^7.37.5", "eslint-plugin-simple-header": "^1.2.1", - "eslint-plugin-simple-import-sort": "^12.1.1", - "eslint-plugin-unused-imports": "^4.3.0", + "eslint-plugin-simple-import-sort": "^13.0.0", + "eslint-plugin-unused-imports": "^4.4.1", "highlight.js": "11.11.1", "html-minifier-terser": "^7.2.0", "moment": "^2.22.2", "p-limit": "^7.3.0", - "puppeteer-core": "^24.30.0", - "standalone-electron-types": "^34.2.0", - "stylelint": "^16.25.0", - "stylelint-config-standard": "^39.0.1", + "puppeteer-core": "^24.41.0", + "standalone-electron-types": "^41.2.1", + "stylelint": "^17.8.0", + "stylelint-config-standard": "^40.0.0", + "svgo": "^4.0.1", "ts-patch": "^3.3.0", - "ts-pattern": "^5.6.0", - "tsx": "^4.20.6", - "type-fest": "^5.2.0", - "typescript": "^5.9.3", - "typescript-eslint": "^8.47.0", - "typescript-transform-paths": "^3.5.5", + "ts-pattern": "^5.9.0", + "tsx": "^4.21.0", + "type-fest": "^5.5.0", + "typescript": "^6.0.2", + "typescript-eslint": "^8.58.2", + "typescript-transform-paths": "^3.5.6", "zip-local": "^0.3.5" }, "packageManager": "pnpm@10.33.0", @@ -126,4 +126,4 @@ "engines": { "node": ">=18" } -} +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index caabc7003..13a10510a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -30,7 +30,7 @@ importers: version: 0.1.2 '@song-spotlight/api': specifier: ^2.1.3 - version: 2.1.3(typescript@5.9.3) + version: 2.1.3(typescript@6.0.2) '@streamparser/json': specifier: ^0.0.22 version: 0.0.22 @@ -62,8 +62,8 @@ importers: specifier: 1.4.0 version: 1.4.0 monaco-editor: - specifier: ^0.54.0 - version: 0.54.0 + specifier: ^0.55.1 + version: 0.55.1 nanoid: specifier: ^5.1.6 version: 5.1.6 @@ -76,28 +76,25 @@ importers: virtual-merge: specifier: ^1.0.1 version: 1.0.2 + yaml-js: + specifier: ^0.3.1 + version: 0.3.1 devDependencies: '@electron/asar': - specifier: ^4.0.1 - version: 4.0.1 + specifier: ^4.2.0 + version: 4.2.0 '@stylistic/eslint-plugin': - specifier: ^5.6.0 - version: 5.6.0(eslint@9.39.1) - '@types/adm-zip': - specifier: ^0.5.7 - version: 0.5.7 + specifier: ^5.10.0 + version: 5.10.0(eslint@10.2.0) '@types/chrome': - specifier: ^0.1.30 - version: 0.1.30 - '@types/diff': - specifier: ^7.0.2 - version: 7.0.2 + specifier: ^0.1.40 + version: 0.1.40 '@types/lodash': - specifier: ^4.17.20 - version: 4.17.20 + specifier: ^4.17.24 + version: 4.17.24 '@types/node': - specifier: ^24.10.1 - version: 24.10.1 + specifier: ^25.6.0 + version: 25.6.0 '@types/react': specifier: ^19.0.10 version: 19.0.12 @@ -105,35 +102,35 @@ importers: specifier: ^19.0.4 version: 19.0.4(@types/react@19.0.12) '@types/yazl': - specifier: ^3.3.0 - version: 3.3.0 + specifier: ^3.3.1 + version: 3.3.1 '@vencord/discord-types': specifier: link:packages/discord-types version: link:packages/discord-types diff: - specifier: ^8.0.2 - version: 8.0.2 + specifier: ^9.0.0 + version: 9.0.0 esbuild: - specifier: ^0.27.0 - version: 0.27.0 + specifier: ^0.28.0 + version: 0.28.0 eslint: - specifier: 9.39.1 - version: 9.39.1 + specifier: 10.2.0 + version: 10.2.0 eslint-import-resolver-alias: specifier: ^1.1.2 - version: 1.1.2(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.47.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)) + version: 1.1.2(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.58.2(eslint@10.2.0)(typescript@6.0.2))(eslint@10.2.0)) eslint-plugin-react: specifier: ^7.37.5 - version: 7.37.5(eslint@9.39.1) + version: 7.37.5(eslint@10.2.0) eslint-plugin-simple-header: specifier: ^1.2.1 - version: 1.2.2(eslint@9.39.1) + version: 1.2.2(eslint@10.2.0) eslint-plugin-simple-import-sort: - specifier: ^12.1.1 - version: 12.1.1(eslint@9.39.1) + specifier: ^13.0.0 + version: 13.0.0(eslint@10.2.0) eslint-plugin-unused-imports: - specifier: ^4.3.0 - version: 4.3.0(@typescript-eslint/eslint-plugin@8.47.0(@typescript-eslint/parser@8.47.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1) + specifier: ^4.4.1 + version: 4.4.1(@typescript-eslint/eslint-plugin@8.58.2(@typescript-eslint/parser@8.58.2(eslint@10.2.0)(typescript@6.0.2))(eslint@10.2.0)(typescript@6.0.2))(eslint@10.2.0) highlight.js: specifier: 11.11.1 version: 11.11.1 @@ -147,38 +144,41 @@ importers: specifier: ^7.3.0 version: 7.3.0 puppeteer-core: - specifier: ^24.30.0 - version: 24.30.0 + specifier: ^24.41.0 + version: 24.41.0 standalone-electron-types: - specifier: ^34.2.0 - version: 34.2.0 + specifier: ^41.2.1 + version: 41.2.1 stylelint: - specifier: ^16.25.0 - version: 16.25.0(typescript@5.9.3) + specifier: ^17.8.0 + version: 17.8.0(typescript@6.0.2) stylelint-config-standard: - specifier: ^39.0.1 - version: 39.0.1(stylelint@16.25.0(typescript@5.9.3)) + specifier: ^40.0.0 + version: 40.0.0(stylelint@17.8.0(typescript@6.0.2)) + svgo: + specifier: ^4.0.1 + version: 4.0.1 ts-patch: specifier: ^3.3.0 version: 3.3.0 ts-pattern: - specifier: ^5.6.0 - version: 5.6.2 + specifier: ^5.9.0 + version: 5.9.0 tsx: - specifier: ^4.20.6 - version: 4.20.6 + specifier: ^4.21.0 + version: 4.21.0 type-fest: - specifier: ^5.2.0 - version: 5.2.0 + specifier: ^5.5.0 + version: 5.5.0 typescript: - specifier: ^5.9.3 - version: 5.9.3 + specifier: ^6.0.2 + version: 6.0.2 typescript-eslint: - specifier: ^8.47.0 - version: 8.47.0(eslint@9.39.1)(typescript@5.9.3) + specifier: ^8.58.2 + version: 8.58.2(eslint@10.2.0)(typescript@6.0.2) typescript-transform-paths: - specifier: ^3.5.5 - version: 3.5.5(typescript@5.9.3) + specifier: ^3.5.6 + version: 3.5.6(typescript@6.0.2) zip-local: specifier: ^0.3.5 version: 0.3.5 @@ -249,40 +249,58 @@ packages: resolution: {integrity: sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==} engines: {node: '>=6.9.0'} - '@cacheable/memory@2.0.5': - resolution: {integrity: sha512-fkiAxCvssEyJZ5fxX4tcdZFRmW9JehSTGvvqmXn6rTzG5cH6V/3C4ad8yb01vOjp2xBydHkHrgpW0qeGtzt6VQ==} + '@cacheable/memory@2.0.8': + resolution: {integrity: sha512-FvEb29x5wVwu/Kf93IWwsOOEuhHh6dYCJF3vcKLzXc0KXIW181AOzv6ceT4ZpBHDvAfG60eqb+ekmrnLHIy+jw==} - '@cacheable/utils@2.3.1': - resolution: {integrity: sha512-38NJXjIr4W1Sghun8ju+uYWD8h2c61B4dKwfnQHVDFpAJ9oS28RpfqZQJ6Dgd3RceGkILDY9YT+72HJR3LoeSQ==} + '@cacheable/utils@2.4.1': + resolution: {integrity: sha512-eiFgzCbIneyMlLOmNG4g9xzF7Hv3Mga4LjxjcSC/ues6VYq2+gUbQI8JqNuw/ZM8tJIeIaBGpswAsqV2V7ApgA==} - '@csstools/css-parser-algorithms@3.0.5': - resolution: {integrity: sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==} - engines: {node: '>=18'} + '@csstools/css-calc@3.2.0': + resolution: {integrity: sha512-bR9e6o2BDB12jzN/gIbjHa5wLJ4UjD1CB9pM7ehlc0ddk6EBz+yYS1EV2MF55/HUxrHcB/hehAyt5vhsA3hx7w==} + engines: {node: '>=20.19.0'} peerDependencies: - '@csstools/css-tokenizer': ^3.0.4 + '@csstools/css-parser-algorithms': ^4.0.0 + '@csstools/css-tokenizer': ^4.0.0 - '@csstools/css-tokenizer@3.0.4': - resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==} - engines: {node: '>=18'} - - '@csstools/media-query-list-parser@4.0.3': - resolution: {integrity: sha512-HAYH7d3TLRHDOUQK4mZKf9k9Ph/m8Akstg66ywKR4SFAigjs3yBiUeZtFxywiTm5moZMAp/5W/ZuFnNXXYLuuQ==} - engines: {node: '>=18'} + '@csstools/css-parser-algorithms@4.0.0': + resolution: {integrity: sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==} + engines: {node: '>=20.19.0'} peerDependencies: - '@csstools/css-parser-algorithms': ^3.0.5 - '@csstools/css-tokenizer': ^3.0.4 + '@csstools/css-tokenizer': ^4.0.0 - '@csstools/selector-specificity@5.0.0': - resolution: {integrity: sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==} - engines: {node: '>=18'} + '@csstools/css-syntax-patches-for-csstree@1.1.3': + resolution: {integrity: sha512-SH60bMfrRCJF3morcdk57WklujF4Jr/EsQUzqkarfHXEFcAR1gg7fS/chAE922Sehgzc1/+Tz5H3Ypa1HiEKrg==} peerDependencies: - postcss-selector-parser: ^7.0.0 + css-tree: ^3.2.1 + peerDependenciesMeta: + css-tree: + optional: true - '@dual-bundle/import-meta-resolve@4.2.1': - resolution: {integrity: sha512-id+7YRUgoUX6CgV0DtuhirQWodeeA7Lf4i2x71JS/vtA5pRb/hIGWlw+G6MeXvsM+MXrz0VAydTGElX1rAfgPg==} + '@csstools/css-tokenizer@4.0.0': + resolution: {integrity: sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==} + engines: {node: '>=20.19.0'} - '@electron/asar@4.0.1': - resolution: {integrity: sha512-F4Ykm1jiBGY1WV/o8Q8oFW8Nq0u+S2/vPujzNJtdSJ6C4LHC4CiGLn7c17s7SolZ23gcvCebMncmZtNc+MkxPQ==} + '@csstools/media-query-list-parser@5.0.0': + resolution: {integrity: sha512-T9lXmZOfnam3eMERPsszjY5NK0jX8RmThmmm99FZ8b7z8yMaFZWKwLWGZuTwdO3ddRY5fy13GmmEYZXB4I98Eg==} + engines: {node: '>=20.19.0'} + peerDependencies: + '@csstools/css-parser-algorithms': ^4.0.0 + '@csstools/css-tokenizer': ^4.0.0 + + '@csstools/selector-resolve-nested@4.0.0': + resolution: {integrity: sha512-9vAPxmp+Dx3wQBIUwc1v7Mdisw1kbbaGqXUM8QLTgWg7SoPGYtXBsMXvsFs/0Bn5yoFhcktzxNZGNaUt0VjgjA==} + engines: {node: '>=20.19.0'} + peerDependencies: + postcss-selector-parser: ^7.1.1 + + '@csstools/selector-specificity@6.0.0': + resolution: {integrity: sha512-4sSgl78OtOXEX/2d++8A83zHNTgwCJMaR24FvsYL7Uf/VS8HZk9PTwR51elTbGqMuwH3szLvvOXEaVnqn0Z3zA==} + engines: {node: '>=20.19.0'} + peerDependencies: + postcss-selector-parser: ^7.1.1 + + '@electron/asar@4.2.0': + resolution: {integrity: sha512-npW1NW5yy8EB9XY/vEw9sUdgmq0sJEhmSBb6bqyFOAw1CSkrhvAvO6QWlW8CdIMo8VN1lkdF345l/MeW0LrY0Q==} engines: {node: '>=22.12.0'} hasBin: true @@ -298,6 +316,12 @@ packages: cpu: [ppc64] os: [aix] + '@esbuild/aix-ppc64@0.28.0': + resolution: {integrity: sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + '@esbuild/android-arm64@0.25.1': resolution: {integrity: sha512-50tM0zCJW5kGqgG7fQ7IHvQOcAn9TKiVRuQ/lN0xR+T2lzEFvAi1ZcS8DiksFcEpf1t/GYOeOfCAgDHFpkiSmA==} engines: {node: '>=18'} @@ -310,6 +334,12 @@ packages: cpu: [arm64] os: [android] + '@esbuild/android-arm64@0.28.0': + resolution: {integrity: sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + '@esbuild/android-arm@0.25.1': resolution: {integrity: sha512-dp+MshLYux6j/JjdqVLnMglQlFu+MuVeNrmT5nk6q07wNhCdSnB7QZj+7G8VMUGh1q+vj2Bq8kRsuyA00I/k+Q==} engines: {node: '>=18'} @@ -322,6 +352,12 @@ packages: cpu: [arm] os: [android] + '@esbuild/android-arm@0.28.0': + resolution: {integrity: sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + '@esbuild/android-x64@0.25.1': resolution: {integrity: sha512-GCj6WfUtNldqUzYkN/ITtlhwQqGWu9S45vUXs7EIYf+7rCiiqH9bCloatO9VhxsL0Pji+PF4Lz2XXCES+Q8hDw==} engines: {node: '>=18'} @@ -334,6 +370,12 @@ packages: cpu: [x64] os: [android] + '@esbuild/android-x64@0.28.0': + resolution: {integrity: sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + '@esbuild/darwin-arm64@0.25.1': resolution: {integrity: sha512-5hEZKPf+nQjYoSr/elb62U19/l1mZDdqidGfmFutVUjjUZrOazAtwK+Kr+3y0C/oeJfLlxo9fXb1w7L+P7E4FQ==} engines: {node: '>=18'} @@ -346,6 +388,12 @@ packages: cpu: [arm64] os: [darwin] + '@esbuild/darwin-arm64@0.28.0': + resolution: {integrity: sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + '@esbuild/darwin-x64@0.25.1': resolution: {integrity: sha512-hxVnwL2Dqs3fM1IWq8Iezh0cX7ZGdVhbTfnOy5uURtao5OIVCEyj9xIzemDi7sRvKsuSdtCAhMKarxqtlyVyfA==} engines: {node: '>=18'} @@ -358,6 +406,12 @@ packages: cpu: [x64] os: [darwin] + '@esbuild/darwin-x64@0.28.0': + resolution: {integrity: sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + '@esbuild/freebsd-arm64@0.25.1': resolution: {integrity: sha512-1MrCZs0fZa2g8E+FUo2ipw6jw5qqQiH+tERoS5fAfKnRx6NXH31tXBKI3VpmLijLH6yriMZsxJtaXUyFt/8Y4A==} engines: {node: '>=18'} @@ -370,6 +424,12 @@ packages: cpu: [arm64] os: [freebsd] + '@esbuild/freebsd-arm64@0.28.0': + resolution: {integrity: sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + '@esbuild/freebsd-x64@0.25.1': resolution: {integrity: sha512-0IZWLiTyz7nm0xuIs0q1Y3QWJC52R8aSXxe40VUxm6BB1RNmkODtW6LHvWRrGiICulcX7ZvyH6h5fqdLu4gkww==} engines: {node: '>=18'} @@ -382,6 +442,12 @@ packages: cpu: [x64] os: [freebsd] + '@esbuild/freebsd-x64@0.28.0': + resolution: {integrity: sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + '@esbuild/linux-arm64@0.25.1': resolution: {integrity: sha512-jaN3dHi0/DDPelk0nLcXRm1q7DNJpjXy7yWaWvbfkPvI+7XNSc/lDOnCLN7gzsyzgu6qSAmgSvP9oXAhP973uQ==} engines: {node: '>=18'} @@ -394,6 +460,12 @@ packages: cpu: [arm64] os: [linux] + '@esbuild/linux-arm64@0.28.0': + resolution: {integrity: sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + '@esbuild/linux-arm@0.25.1': resolution: {integrity: sha512-NdKOhS4u7JhDKw9G3cY6sWqFcnLITn6SqivVArbzIaf3cemShqfLGHYMx8Xlm/lBit3/5d7kXvriTUGa5YViuQ==} engines: {node: '>=18'} @@ -406,6 +478,12 @@ packages: cpu: [arm] os: [linux] + '@esbuild/linux-arm@0.28.0': + resolution: {integrity: sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + '@esbuild/linux-ia32@0.25.1': resolution: {integrity: sha512-OJykPaF4v8JidKNGz8c/q1lBO44sQNUQtq1KktJXdBLn1hPod5rE/Hko5ugKKZd+D2+o1a9MFGUEIUwO2YfgkQ==} engines: {node: '>=18'} @@ -418,6 +496,12 @@ packages: cpu: [ia32] os: [linux] + '@esbuild/linux-ia32@0.28.0': + resolution: {integrity: sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + '@esbuild/linux-loong64@0.25.1': resolution: {integrity: sha512-nGfornQj4dzcq5Vp835oM/o21UMlXzn79KobKlcs3Wz9smwiifknLy4xDCLUU0BWp7b/houtdrgUz7nOGnfIYg==} engines: {node: '>=18'} @@ -430,6 +514,12 @@ packages: cpu: [loong64] os: [linux] + '@esbuild/linux-loong64@0.28.0': + resolution: {integrity: sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + '@esbuild/linux-mips64el@0.25.1': resolution: {integrity: sha512-1osBbPEFYwIE5IVB/0g2X6i1qInZa1aIoj1TdL4AaAb55xIIgbg8Doq6a5BzYWgr+tEcDzYH67XVnTmUzL+nXg==} engines: {node: '>=18'} @@ -442,6 +532,12 @@ packages: cpu: [mips64el] os: [linux] + '@esbuild/linux-mips64el@0.28.0': + resolution: {integrity: sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + '@esbuild/linux-ppc64@0.25.1': resolution: {integrity: sha512-/6VBJOwUf3TdTvJZ82qF3tbLuWsscd7/1w+D9LH0W/SqUgM5/JJD0lrJ1fVIfZsqB6RFmLCe0Xz3fmZc3WtyVg==} engines: {node: '>=18'} @@ -454,6 +550,12 @@ packages: cpu: [ppc64] os: [linux] + '@esbuild/linux-ppc64@0.28.0': + resolution: {integrity: sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + '@esbuild/linux-riscv64@0.25.1': resolution: {integrity: sha512-nSut/Mx5gnilhcq2yIMLMe3Wl4FK5wx/o0QuuCLMtmJn+WeWYoEGDN1ipcN72g1WHsnIbxGXd4i/MF0gTcuAjQ==} engines: {node: '>=18'} @@ -466,6 +568,12 @@ packages: cpu: [riscv64] os: [linux] + '@esbuild/linux-riscv64@0.28.0': + resolution: {integrity: sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + '@esbuild/linux-s390x@0.25.1': resolution: {integrity: sha512-cEECeLlJNfT8kZHqLarDBQso9a27o2Zd2AQ8USAEoGtejOrCYHNtKP8XQhMDJMtthdF4GBmjR2au3x1udADQQQ==} engines: {node: '>=18'} @@ -478,6 +586,12 @@ packages: cpu: [s390x] os: [linux] + '@esbuild/linux-s390x@0.28.0': + resolution: {integrity: sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + '@esbuild/linux-x64@0.25.1': resolution: {integrity: sha512-xbfUhu/gnvSEg+EGovRc+kjBAkrvtk38RlerAzQxvMzlB4fXpCFCeUAYzJvrnhFtdeyVCDANSjJvOvGYoeKzFA==} engines: {node: '>=18'} @@ -490,6 +604,12 @@ packages: cpu: [x64] os: [linux] + '@esbuild/linux-x64@0.28.0': + resolution: {integrity: sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + '@esbuild/netbsd-arm64@0.25.1': resolution: {integrity: sha512-O96poM2XGhLtpTh+s4+nP7YCCAfb4tJNRVZHfIE7dgmax+yMP2WgMd2OecBuaATHKTHsLWHQeuaxMRnCsH8+5g==} engines: {node: '>=18'} @@ -502,6 +622,12 @@ packages: cpu: [arm64] os: [netbsd] + '@esbuild/netbsd-arm64@0.28.0': + resolution: {integrity: sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + '@esbuild/netbsd-x64@0.25.1': resolution: {integrity: sha512-X53z6uXip6KFXBQ+Krbx25XHV/NCbzryM6ehOAeAil7X7oa4XIq+394PWGnwaSQ2WRA0KI6PUO6hTO5zeF5ijA==} engines: {node: '>=18'} @@ -514,6 +640,12 @@ packages: cpu: [x64] os: [netbsd] + '@esbuild/netbsd-x64@0.28.0': + resolution: {integrity: sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + '@esbuild/openbsd-arm64@0.25.1': resolution: {integrity: sha512-Na9T3szbXezdzM/Kfs3GcRQNjHzM6GzFBeU1/6IV/npKP5ORtp9zbQjvkDJ47s6BCgaAZnnnu/cY1x342+MvZg==} engines: {node: '>=18'} @@ -526,6 +658,12 @@ packages: cpu: [arm64] os: [openbsd] + '@esbuild/openbsd-arm64@0.28.0': + resolution: {integrity: sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + '@esbuild/openbsd-x64@0.25.1': resolution: {integrity: sha512-T3H78X2h1tszfRSf+txbt5aOp/e7TAz3ptVKu9Oyir3IAOFPGV6O9c2naym5TOriy1l0nNf6a4X5UXRZSGX/dw==} engines: {node: '>=18'} @@ -538,12 +676,24 @@ packages: cpu: [x64] os: [openbsd] + '@esbuild/openbsd-x64@0.28.0': + resolution: {integrity: sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + '@esbuild/openharmony-arm64@0.27.0': resolution: {integrity: sha512-nyvsBccxNAsNYz2jVFYwEGuRRomqZ149A39SHWk4hV0jWxKM0hjBPm3AmdxcbHiFLbBSwG6SbpIcUbXjgyECfA==} engines: {node: '>=18'} cpu: [arm64] os: [openharmony] + '@esbuild/openharmony-arm64@0.28.0': + resolution: {integrity: sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + '@esbuild/sunos-x64@0.25.1': resolution: {integrity: sha512-2H3RUvcmULO7dIE5EWJH8eubZAI4xw54H1ilJnRNZdeo8dTADEZ21w6J22XBkXqGJbe0+wnNJtw3UXRoLJnFEg==} engines: {node: '>=18'} @@ -556,6 +706,12 @@ packages: cpu: [x64] os: [sunos] + '@esbuild/sunos-x64@0.28.0': + resolution: {integrity: sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + '@esbuild/win32-arm64@0.25.1': resolution: {integrity: sha512-GE7XvrdOzrb+yVKB9KsRMq+7a2U/K5Cf/8grVFRAGJmfADr/e/ODQ134RK2/eeHqYV5eQRFxb1hY7Nr15fv1NQ==} engines: {node: '>=18'} @@ -568,6 +724,12 @@ packages: cpu: [arm64] os: [win32] + '@esbuild/win32-arm64@0.28.0': + resolution: {integrity: sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + '@esbuild/win32-ia32@0.25.1': resolution: {integrity: sha512-uOxSJCIcavSiT6UnBhBzE8wy3n0hOkJsBOzy7HDAuTDE++1DJMRRVCPGisULScHL+a/ZwdXPpXD3IyFKjA7K8A==} engines: {node: '>=18'} @@ -580,6 +742,12 @@ packages: cpu: [ia32] os: [win32] + '@esbuild/win32-ia32@0.28.0': + resolution: {integrity: sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + '@esbuild/win32-x64@0.25.1': resolution: {integrity: sha512-Y1EQdcfwMSeQN/ujR5VayLOJ1BHaK+ssyk0AEzPjC+t1lITgsnccPqFjb6V+LsTp/9Iov4ysfjxLaGJ9RPtkVg==} engines: {node: '>=18'} @@ -592,43 +760,47 @@ packages: cpu: [x64] os: [win32] + '@esbuild/win32-x64@0.28.0': + resolution: {integrity: sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + '@eslint-community/eslint-utils@4.9.0': resolution: {integrity: sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - '@eslint-community/regexpp@4.12.1': - resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} + '@eslint-community/eslint-utils@4.9.1': + resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.12.2': + resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@eslint/config-array@0.21.1': - resolution: {integrity: sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/config-array@0.23.5': + resolution: {integrity: sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} - '@eslint/config-helpers@0.4.2': - resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/config-helpers@0.5.5': + resolution: {integrity: sha512-eIJYKTCECbP/nsKaaruF6LW967mtbQbsw4JTtSVkUQc9MneSkbrgPJAbKl9nWr0ZeowV8BfsarBmPpBzGelA2w==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} - '@eslint/core@0.17.0': - resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/core@1.2.1': + resolution: {integrity: sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} - '@eslint/eslintrc@3.3.1': - resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/object-schema@3.0.5': + resolution: {integrity: sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} - '@eslint/js@9.39.1': - resolution: {integrity: sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/object-schema@2.1.7': - resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/plugin-kit@0.4.1': - resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/plugin-kit@0.7.1': + resolution: {integrity: sha512-rZAP3aVgB9ds9KOeUSL+zZ21hPmo8dh6fnIFwRQj5EAZl9gzR7wxYbYXYysAM8CTqGmUGyp2S4kUdV17MnGuWQ==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} '@ffmpeg/ffmpeg@0.12.10': resolution: {integrity: sha512-lVtk8PW8e+NUzGZhPTWj2P1J4/NyuCrbDD3O9IGpSeLYtUZKBqZO8CNj1WYGghep/MXoM8e1qVY1GztTkf8YYQ==} @@ -669,18 +841,6 @@ packages: '@intrnl/xxhash64@0.1.2': resolution: {integrity: sha512-1+lx7j99fdph+uy3EnjQyr39KQZ7LP56+aWOr6finJWpgYpvb7XrhFUqDwnEk/wpPC98nCjAT6RulpW3crWjlg==} - '@isaacs/balanced-match@4.0.1': - resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==} - engines: {node: 20 || >=22} - - '@isaacs/brace-expansion@5.0.0': - resolution: {integrity: sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==} - engines: {node: 20 || >=22} - - '@isaacs/cliui@8.0.2': - resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} - engines: {node: '>=12'} - '@jridgewell/gen-mapping@0.3.5': resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} engines: {node: '>=6.0.0'} @@ -702,11 +862,11 @@ packages: '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} - '@keyv/bigmap@1.3.0': - resolution: {integrity: sha512-KT01GjzV6AQD5+IYrcpoYLkCu1Jod3nau1Z7EsEuViO3TZGRacSbO9MfHmbJ1WaOXFtWLxPVj169cn2WNKPkIg==} + '@keyv/bigmap@1.3.1': + resolution: {integrity: sha512-WbzE9sdmQtKy8vrNPa9BRnwZh5UF4s1KTmSK0KUVLo3eff5BlQNNWDnFOouNpKfPKDnms9xynJjsMYjMaT/aFQ==} engines: {node: '>= 18'} peerDependencies: - keyv: ^5.5.4 + keyv: ^5.6.0 '@keyv/serialize@1.1.1': resolution: {integrity: sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==} @@ -723,14 +883,18 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} - '@puppeteer/browsers@2.10.13': - resolution: {integrity: sha512-a9Ruw3j3qlnB5a/zHRTkruppynxqaeE4H9WNj5eYGRWqw0ZauZ23f4W2ARf3hghF5doozyD+CRtt7XSYuYRI/Q==} + '@puppeteer/browsers@2.13.0': + resolution: {integrity: sha512-46BZJYJjc/WwmKjsvDFykHtXrtomsCIrwYQPOP7VfMJoZY2bsDF9oROBABR3paDjDcmkUye1Pb1BqdcdiipaWA==} engines: {node: '>=18'} hasBin: true '@rtsao/scc@1.1.0': resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} + '@sindresorhus/merge-streams@4.0.0': + resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==} + engines: {node: '>=18'} + '@song-spotlight/api@2.1.3': resolution: {integrity: sha512-Wai7JHd9lrHtM/lkhfWQIFjIWKtP8iD+zj4Lnwbs/ykELR0MB2k56TDnQaRAelvu8XOygt27wfDBDQSEepPqdA==} peerDependencies: @@ -739,27 +903,27 @@ packages: '@streamparser/json@0.0.22': resolution: {integrity: sha512-b6gTSBjJ8G8SuO3Gbbj+zXbVx8NSs1EbpbMKpzGLWMdkR+98McH9bEjSz3+0mPJf68c5nxa3CrJHp5EQNXM6zQ==} - '@stylistic/eslint-plugin@5.6.0': - resolution: {integrity: sha512-owEc4B8ME+O/xyZOkLVyLqPMsUgJXIM4XzCm5Vt3WvRXpyoOfYxgA+JkEiFqXPCI8+Nc2BzAT+KGAK7QleGs8Q==} + '@stylistic/eslint-plugin@5.10.0': + resolution: {integrity: sha512-nPK52ZHvot8Ju/0A4ucSX1dcPV2/1clx0kLcH5wDmrE4naKso7TUC/voUyU1O9OTKTrR6MYip6LP0ogEMQ9jPQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: '>=9.0.0' + eslint: ^9.0.0 || ^10.0.0 '@tootallnate/quickjs-emscripten@0.23.0': resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==} - '@types/adm-zip@0.5.7': - resolution: {integrity: sha512-DNEs/QvmyRLurdQPChqq0Md4zGvPwHerAJYWk9l2jCbD1VPpnzRJorOdiq4zsw09NFbYnhfsoEhWtxIzXpn2yw==} + '@types/chrome@0.1.40': + resolution: {integrity: sha512-UnfyRAe8ORu9HSuTH0EqyOEUin3JrWW9Nl/gDXezNfTUrfIoxw+WRZgKOxGz0t5BnjbfXBnS2eCYfW2PxH1wcA==} - '@types/chrome@0.1.30': - resolution: {integrity: sha512-rcP14i+ip4s3SLG6JzNOWIDd+0i8Bg+kBslHl8d4g6m/e2kEbWnR90AtlOPUZj9ONVRbKxnQUqsInxFzXyqLdA==} - - '@types/diff@7.0.2': - resolution: {integrity: sha512-JSWRMozjFKsGlEjiiKajUjIJVKuKdE3oVy2DNtK+fUo8q82nhFZ2CPQwicAIkXrofahDXrWJ7mjelvZphMS98Q==} + '@types/esrecurse@4.3.1': + resolution: {integrity: sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==} '@types/estree@1.0.7': resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==} + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + '@types/filesystem@0.0.36': resolution: {integrity: sha512-vPDXOZuannb9FZdxgHnqSwAG/jvdGM8Wq+6N4D/d80z+D4HWH+bItqsZaVRQykAn6WEVeEkLm2oQigyHtgb0RA==} @@ -787,14 +951,14 @@ packages: '@types/lodash@4.17.15': resolution: {integrity: sha512-w/P33JFeySuhN6JLkysYUK2gEmy9kHHFN7E8ro0tkfmlDOgxBDzWEZ/J8cWA+fHqFevpswDTFZnDx+R9lbL6xw==} - '@types/lodash@4.17.20': - resolution: {integrity: sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA==} + '@types/lodash@4.17.24': + resolution: {integrity: sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==} '@types/node@22.13.13': resolution: {integrity: sha512-ClsL5nMwKaBRwPcCvH8E7+nU4GxHVx1axNvMZTFHMEfNI7oahimt26P5zjVCRrjiIWj6YFXfE1v3dEp94wLcGQ==} - '@types/node@24.10.1': - resolution: {integrity: sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==} + '@types/node@25.6.0': + resolution: {integrity: sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==} '@types/react-dom@19.0.4': resolution: {integrity: sha512-4fSQ8vWFkg+TGhePfUzVmat3eC14TXYSsiiDSLI0dVLsrm9gZFABjPy/Qu6TKgl1tq1Bu1yDsuQgY3A3DOjCcg==} @@ -810,69 +974,72 @@ packages: '@types/tinycolor2@1.4.6': resolution: {integrity: sha512-iEN8J0BoMnsWBqjVbWH/c0G0Hh7O21lpR2/+PrvAVgWdzL7eexIFm4JN/Wn10PTcmNdtS6U67r499mlWMXOxNw==} + '@types/trusted-types@2.0.7': + resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} + '@types/yauzl@2.10.3': resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} - '@types/yazl@3.3.0': - resolution: {integrity: sha512-mFL6lGkk2N5u5nIxpNV/K5LW3qVSbxhJrMxYGOOxZndWxMgCamr/iCsq/1t9kd8pEwhuNP91LC5qZm/qS9pOEw==} + '@types/yazl@3.3.1': + resolution: {integrity: sha512-DIWfCKpsTp6hE5BDBHV3+fIL/bLUF9Bv13iDrWnMlmhQpH67buNvI291ZauQ1xcccxK3FqQ9honnXpq4R8NMuQ==} - '@typescript-eslint/eslint-plugin@8.47.0': - resolution: {integrity: sha512-fe0rz9WJQ5t2iaLfdbDc9T80GJy0AeO453q8C3YCilnGozvOyCG5t+EZtg7j7D88+c3FipfP/x+wzGnh1xp8ZA==} + '@typescript-eslint/eslint-plugin@8.58.2': + resolution: {integrity: sha512-aC2qc5thQahutKjP+cl8cgN9DWe3ZUqVko30CMSZHnFEHyhOYoZSzkGtAI2mcwZ38xeImDucI4dnqsHiOYuuCw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.47.0 - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/parser': ^8.58.2 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/parser@8.47.0': - resolution: {integrity: sha512-lJi3PfxVmo0AkEY93ecfN+r8SofEqZNGByvHAI3GBLrvt1Cw6H5k1IM02nSzu0RfUafr2EvFSw0wAsZgubNplQ==} + '@typescript-eslint/parser@8.58.2': + resolution: {integrity: sha512-/Zb/xaIDfxeJnvishjGdcR4jmr7S+bda8PKNhRGdljDM+elXhlvN0FyPSsMnLmJUrVG9aPO6dof80wjMawsASg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <6.0.0' + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/project-service@8.47.0': - resolution: {integrity: sha512-2X4BX8hUeB5JcA1TQJ7GjcgulXQ+5UkNb0DL8gHsHUHdFoiCTJoYLTpib3LtSDPZsRET5ygN4qqIWrHyYIKERA==} + '@typescript-eslint/project-service@8.58.2': + resolution: {integrity: sha512-Cq6UfpZZk15+r87BkIh5rDpi38W4b+Sjnb8wQCPPDDweS/LRCFjCyViEbzHk5Ck3f2QDfgmlxqSa7S7clDtlfg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: '>=4.8.4 <6.0.0' + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/scope-manager@8.47.0': - resolution: {integrity: sha512-a0TTJk4HXMkfpFkL9/WaGTNuv7JWfFTQFJd6zS9dVAjKsojmv9HT55xzbEpnZoY+VUb+YXLMp+ihMLz/UlZfDg==} + '@typescript-eslint/scope-manager@8.58.2': + resolution: {integrity: sha512-SgmyvDPexWETQek+qzZnrG6844IaO02UVyOLhI4wpo82dpZJY9+6YZCKAMFzXb7qhx37mFK1QcPQ18tud+vo6Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.47.0': - resolution: {integrity: sha512-ybUAvjy4ZCL11uryalkKxuT3w3sXJAuWhOoGS3T/Wu+iUu1tGJmk5ytSY8gbdACNARmcYEB0COksD2j6hfGK2g==} + '@typescript-eslint/tsconfig-utils@8.58.2': + resolution: {integrity: sha512-3SR+RukipDvkkKp/d0jP0dyzuls3DbGmwDpVEc5wqk5f38KFThakqAAO0XMirWAE+kT00oTauTbzMFGPoAzB0A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: '>=4.8.4 <6.0.0' + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/type-utils@8.47.0': - resolution: {integrity: sha512-QC9RiCmZ2HmIdCEvhd1aJELBlD93ErziOXXlHEZyuBo3tBiAZieya0HLIxp+DoDWlsQqDawyKuNEhORyku+P8A==} + '@typescript-eslint/type-utils@8.58.2': + resolution: {integrity: sha512-Z7EloNR/B389FvabdGeTo2XMs4W9TjtPiO9DAsmT0yom0bwlPyRjkJ1uCdW1DvrrrYP50AJZ9Xc3sByZA9+dcg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <6.0.0' + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/types@8.47.0': - resolution: {integrity: sha512-nHAE6bMKsizhA2uuYZbEbmp5z2UpffNrPEqiKIeN7VsV6UY/roxanWfoRrf6x/k9+Obf+GQdkm0nPU+vnMXo9A==} + '@typescript-eslint/types@8.58.2': + resolution: {integrity: sha512-9TukXyATBQf/Jq9AMQXfvurk+G5R2MwfqQGDR2GzGz28HvY/lXNKGhkY+6IOubwcquikWk5cjlgPvD2uAA7htQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.47.0': - resolution: {integrity: sha512-k6ti9UepJf5NpzCjH31hQNLHQWupTRPhZ+KFF8WtTuTpy7uHPfeg2NM7cP27aCGajoEplxJDFVCEm9TGPYyiVg==} + '@typescript-eslint/typescript-estree@8.58.2': + resolution: {integrity: sha512-ELGuoofuhhoCvNbQjFFiobFcGgcDCEm0ThWdmO4Z0UzLqPXS3KFvnEZ+SHewwOYHjM09tkzOWXNTv9u6Gqtyuw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: '>=4.8.4 <6.0.0' + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/utils@8.47.0': - resolution: {integrity: sha512-g7XrNf25iL4TJOiPqatNuaChyqt49a/onq5YsJ9+hXeugK+41LVg7AxikMfM02PC6jbNtZLCJj6AUcQXJS/jGQ==} + '@typescript-eslint/utils@8.58.2': + resolution: {integrity: sha512-QZfjHNEzPY8+l0+fIXMvuQ2sJlplB4zgDZvA+NmvZsZv3EQwOcc1DuIU1VJUTWZ/RKouBMhDyNaBMx4sWvrzRA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <6.0.0' + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/visitor-keys@8.47.0': - resolution: {integrity: sha512-SIV3/6eftCy1bNzCQoPmbWsRLujS8t5iDIZ4spZOBHqrM+yfX2ogg8Tt3PDTAVKw3sSCiUgg30uOAvK2r9zGjQ==} + '@typescript-eslint/visitor-keys@8.58.2': + resolution: {integrity: sha512-f1WO2Lx8a9t8DARmcWAUPJbu0G20bJlj8L4z72K00TMeJAoyLr/tHhI/pzYBLrR4dXWkcxO1cWYZEOX8DKHTqA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@vap/core@0.0.12': @@ -901,12 +1068,17 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + acorn@8.16.0: + resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==} + engines: {node: '>=0.4.0'} + hasBin: true + agent-base@7.1.3: resolution: {integrity: sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==} engines: {node: '>= 14'} - ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + ajv@6.14.0: + resolution: {integrity: sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==} ajv@8.17.1: resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} @@ -927,10 +1099,6 @@ packages: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} - ansi-styles@6.2.3: - resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} - engines: {node: '>=12'} - argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} @@ -946,10 +1114,6 @@ packages: resolution: {integrity: sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==} engines: {node: '>= 0.4'} - array-union@2.1.0: - resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} - engines: {node: '>=8'} - array.prototype.findlast@1.2.5: resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} engines: {node: '>= 0.4'} @@ -1003,8 +1167,9 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - balanced-match@2.0.0: - resolution: {integrity: sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==} + balanced-match@4.0.4: + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} + engines: {node: 18 || 20 || >=22} bare-events@2.5.4: resolution: {integrity: sha512-+gFfDkR8pj4/TrWCGUGWmJIkBwuxPS5F+a5yWjOHQt2hHvNZd5YLzadjmDUtFmMM4y429bnKLa8bYBMHcYdnQA==} @@ -1039,7 +1204,10 @@ packages: basic-ftp@5.0.5: resolution: {integrity: sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==} engines: {node: '>=10.0.0'} - deprecated: Security vulnerability fixed in 5.2.0, please upgrade + deprecated: Security vulnerability fixed in 5.2.1, please upgrade + + boolbase@1.0.0: + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} brace-expansion@1.1.12: resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} @@ -1047,6 +1215,10 @@ packages: brace-expansion@2.0.2: resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} + brace-expansion@5.0.5: + resolution: {integrity: sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==} + engines: {node: 18 || 20 || >=22} + braces@3.0.3: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} @@ -1057,8 +1229,8 @@ packages: buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - cacheable@2.2.0: - resolution: {integrity: sha512-LEJxRqfeomiiRd2t0uON6hxAtgOoWDfY3fugebbz+J3vDLO+SkdfFChQcOHTZhj9SYa9iwE9MGYNX72dKiOE4w==} + cacheable@2.3.4: + resolution: {integrity: sha512-djgxybDbw9fL/ZWMI3+CE8ZilNxcwFkVtDc1gJ+IlOSSWkSMPQabhV/XCHTQ6pwwN6aivXPZ43omTooZiX06Ew==} call-bind-apply-helpers@1.0.2: resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} @@ -1087,8 +1259,8 @@ packages: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} - chromium-bidi@11.0.0: - resolution: {integrity: sha512-cM3DI+OOb89T3wO8cpPSro80Q9eKYJ7hGVXoGS3GkDPxnYSqiv+6xwpIf6XERyJ9Tdsl09hmNmY94BkgZdVekw==} + chromium-bidi@14.0.0: + resolution: {integrity: sha512-9gYlLtS6tStdRWzrtXaTMnqcM4dudNegMXJxkR0I/CXObHalYeYcAMPrL19eroNZHtJ8DQmu1E+ZNOYu/IXMXw==} peerDependencies: devtools-protocol: '*' @@ -1120,6 +1292,10 @@ packages: resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} engines: {node: '>=14'} + commander@11.1.0: + resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} + engines: {node: '>=16'} + commander@13.1.0: resolution: {integrity: sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==} engines: {node: '>=18'} @@ -1130,8 +1306,8 @@ packages: concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - cosmiconfig@9.0.0: - resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==} + cosmiconfig@9.0.1: + resolution: {integrity: sha512-hr4ihw+DBqcvrsEDioRO31Z17x71pUYoNe/4h6Z0wB72p7MU7/9gH8Q3s12NFhHPfYBBOV3qyfUxmr/Yn3shnQ==} engines: {node: '>=14'} peerDependencies: typescript: '>=4.9.5' @@ -1143,19 +1319,38 @@ packages: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} - css-functions-list@3.2.3: - resolution: {integrity: sha512-IQOkD3hbR5KrN93MtcYuad6YPuTSUhntLHDuLEbFWE+ff2/XSZNdZG+LcbbIW5AXKg/WFIfYItIzVoHngHXZzA==} - engines: {node: '>=12 || >=16'} + css-functions-list@3.3.3: + resolution: {integrity: sha512-8HFEBPKhOpJPEPu70wJJetjKta86Gw9+CCyCnB3sui2qQfOvRyqBy4IKLKKAwdMpWb2lHXWk9Wb4Z6AmaUT1Pg==} + engines: {node: '>=12'} + + css-select@5.2.2: + resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==} + + css-tree@2.2.1: + resolution: {integrity: sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} css-tree@3.1.0: resolution: {integrity: sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==} engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + css-tree@3.2.1: + resolution: {integrity: sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + + css-what@6.2.2: + resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==} + engines: {node: '>= 6'} + cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} hasBin: true + csso@5.0.5: + resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} + csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} @@ -1183,15 +1378,6 @@ packages: supports-color: optional: true - debug@4.4.1: - resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - debug@4.4.3: resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} engines: {node: '>=6.0'} @@ -1216,23 +1402,32 @@ packages: resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==} engines: {node: '>= 14'} - devtools-protocol@0.0.1521046: - resolution: {integrity: sha512-vhE6eymDQSKWUXwwA37NtTTVEzjtGVfDr3pRbsWEQ5onH/Snp2c+2xZHWJJawG/0hCCJLRGt4xVtEVUVILol4w==} + devtools-protocol@0.0.1595872: + resolution: {integrity: sha512-kRfgp8vWVjBu/fbYCiVFiOqsCk3CrMKEo3WbgGT2NXK2dG7vawWPBljixajVgGK9II8rDO9G0oD0zLt3I1daRg==} - diff@8.0.2: - resolution: {integrity: sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg==} + diff@9.0.0: + resolution: {integrity: sha512-svtcdpS8CgJyqAjEQIXdb3OjhFVVYjzGAPO8WGCmRbrml64SPw/jJD4GoE98aR7r25A0XcgrK3F02yw9R/vhQw==} engines: {node: '>=0.3.1'} - dir-glob@3.0.1: - resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} - engines: {node: '>=8'} - doctrine@2.1.0: resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} engines: {node: '>=0.10.0'} - dompurify@3.1.7: - resolution: {integrity: sha512-VaTstWtsneJY8xzy7DekmYWEOZcmzIe3Qb3zPd4STve1OBTa+e+WmS1ITQec1fZYXI3HCsOZZiSMpG6oxoWMWQ==} + dom-serializer@2.0.0: + resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + + domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + + domhandler@5.0.3: + resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} + engines: {node: '>= 4'} + + dompurify@3.2.7: + resolution: {integrity: sha512-WhL/YuveyGXJaerVlMYGWhvQswa7myDG17P7Vu65EWC05o8vfeNbvNf4d/BOvH99+ZW+LlQsc1GDKMa1vNK6dw==} + + domutils@3.2.2: + resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} dot-case@3.0.4: resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} @@ -1241,15 +1436,9 @@ packages: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} - eastasianwidth@0.2.0: - resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - emoji-regex@9.2.2: - resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - end-of-stream@1.4.4: resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} @@ -1310,6 +1499,11 @@ packages: engines: {node: '>=18'} hasBin: true + esbuild@0.28.0: + resolution: {integrity: sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw==} + engines: {node: '>=18'} + hasBin: true + escalade@3.1.2: resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} engines: {node: '>=6'} @@ -1378,23 +1572,23 @@ packages: peerDependencies: eslint: '>=8.41.0' - eslint-plugin-simple-import-sort@12.1.1: - resolution: {integrity: sha512-6nuzu4xwQtE3332Uz0to+TxDQYRLTKRESSc2hefVT48Zc8JthmN23Gx9lnYhu0FtkRSL1oxny3kJ2aveVhmOVA==} + eslint-plugin-simple-import-sort@13.0.0: + resolution: {integrity: sha512-McAc+/Nlvcg4byY/CABGH8kqnefWBj8s3JA2okEtz8ixbECQgU46p0HkTUKa4YS7wvgGceimlc34p1nXqbWqtA==} peerDependencies: eslint: '>=5.0.0' - eslint-plugin-unused-imports@4.3.0: - resolution: {integrity: sha512-ZFBmXMGBYfHttdRtOG9nFFpmUvMtbHSjsKrS20vdWdbfiVYsO3yA2SGYy9i9XmZJDfMGBflZGBCm70SEnFQtOA==} + eslint-plugin-unused-imports@4.4.1: + resolution: {integrity: sha512-oZGYUz1X3sRMGUB+0cZyK2VcvRX5lm/vB56PgNNcU+7ficUCKm66oZWKUubXWnOuPjQ8PvmXtCViXBMONPe7tQ==} peerDependencies: '@typescript-eslint/eslint-plugin': ^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0 - eslint: ^9.0.0 || ^8.0.0 + eslint: ^10.0.0 || ^9.0.0 || ^8.0.0 peerDependenciesMeta: '@typescript-eslint/eslint-plugin': optional: true - eslint-scope@8.4.0: - resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + eslint-scope@9.1.2: + resolution: {integrity: sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} eslint-visitor-keys@3.4.3: resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} @@ -1404,9 +1598,13 @@ packages: resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@9.39.1: - resolution: {integrity: sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + eslint-visitor-keys@5.0.1: + resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + eslint@10.2.0: + resolution: {integrity: sha512-+L0vBFYGIpSNIt/KWTpFonPrqYvgKw1eUI5Vn7mEogrQcWtWYtNQ7dNqC+px/J0idT3BAkiWrhfS7k+Tum8TUA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} hasBin: true peerDependencies: jiti: '*' @@ -1418,13 +1616,17 @@ packages: resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + espree@11.2.0: + resolution: {integrity: sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + esprima@4.0.1: resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} engines: {node: '>=4'} hasBin: true - esquery@1.6.0: - resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} + esquery@1.7.0: + resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} engines: {node: '>=0.10'} esrecurse@4.3.0: @@ -1476,6 +1678,15 @@ packages: fd-slicer@1.1.0: resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + fetch-blob@3.2.0: resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} engines: {node: ^12.20 || >= 14.13} @@ -1483,8 +1694,8 @@ packages: fflate@0.8.2: resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==} - file-entry-cache@10.1.4: - resolution: {integrity: sha512-5XRUFc0WTtUbjfGzEwXc42tiGxQHBmtbUG1h9L2apu4SulCGN3Hqm//9D6FAolf8MYNL7f/YlJl9vy08pj5JuA==} + file-entry-cache@11.1.2: + resolution: {integrity: sha512-N2WFfK12gmrK1c1GXOqiAJ1tc5YE+R53zvQ+t5P8S5XhnmKYVB5eZEiLNZKDSmoG8wqqbF9EXYBBW/nef19log==} file-entry-cache@8.0.0: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} @@ -1502,20 +1713,19 @@ packages: resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} engines: {node: '>=16'} - flat-cache@6.1.19: - resolution: {integrity: sha512-l/K33newPTZMTGAnnzaiqSl6NnH7Namh8jBNjrgjprWxGmZUuxx/sJNIRaijOh3n7q7ESbhNZC+pvVZMFdeU4A==} + flat-cache@6.1.22: + resolution: {integrity: sha512-N2dnzVJIphnNsjHcrxGW7DePckJ6haPrSFqpsBUhHYgwtKGVq4JrBGielEGD2fCVnsGm1zlBVZ8wGhkyuetgug==} flatted@3.3.3: resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} + flatted@3.4.2: + resolution: {integrity: sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==} + for-each@0.3.5: resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} engines: {node: '>= 0.4'} - foreground-child@3.3.1: - resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} - engines: {node: '>=14'} - fs-extra@11.3.0: resolution: {integrity: sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==} engines: {node: '>=14.14'} @@ -1539,6 +1749,10 @@ packages: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} + get-east-asian-width@1.5.0: + resolution: {integrity: sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==} + engines: {node: '>=18'} + get-intrinsic@1.3.0: resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} engines: {node: '>= 0.4'} @@ -1574,10 +1788,9 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} - glob@11.0.3: - resolution: {integrity: sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==} - engines: {node: 20 || >=22} - hasBin: true + glob@13.0.6: + resolution: {integrity: sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==} + engines: {node: 18 || 20 || >=22} global-modules@2.0.0: resolution: {integrity: sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==} @@ -1591,17 +1804,13 @@ packages: resolution: {integrity: sha512-w0Uf9Y9/nyHinEk5vMJKRie+wa4kR5hmDbEhGGds/kG1PwGLLHKRoNMeJOyCQjjBkANlnScqgzcFwGHgmgLkVA==} engines: {node: '>=16'} - globals@14.0.0: - resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} - engines: {node: '>=18'} - globalthis@1.0.4: resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} engines: {node: '>= 0.4'} - globby@11.1.0: - resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} - engines: {node: '>=10'} + globby@16.2.0: + resolution: {integrity: sha512-QrJia2qDf5BB/V6HYlDTs0I0lBahyjLzpGQg3KT7FnCdTonAyPy2RtY802m2k4ALx6Dp752f82WsOczEVr3l6Q==} + engines: {node: '>=20'} globjoin@0.1.4: resolution: {integrity: sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==} @@ -1613,9 +1822,6 @@ packages: graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - graphemer@1.4.0: - resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - has-bigints@1.0.2: resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} @@ -1627,6 +1833,10 @@ packages: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} + has-flag@5.0.1: + resolution: {integrity: sha512-CsNUt5x9LUdx6hnk/E2SZLsDyvfqANZSUq4+D3D8RzDJ2M+HDTIkF60ibS1vHaK55vzgiZw1bEPFG9yH7l33wA==} + engines: {node: '>=12'} + has-property-descriptors@1.0.2: resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} @@ -1642,8 +1852,8 @@ packages: resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} engines: {node: '>= 0.4'} - hashery@1.2.0: - resolution: {integrity: sha512-43XJKpwle72Ik5Zpam7MuzRWyNdwwdf6XHlh8wCj2PggvWf+v/Dm5B0dxGZOmddidgeO6Ofu9As/o231Ti/9PA==} + hashery@1.5.1: + resolution: {integrity: sha512-iZyKG96/JwPz1N55vj2Ie2vXbhu440zfUfJvSwEqEbeLluk7NnapfGqa7LH0mOsnDxTF85Mx8/dyR6HfqcbmbQ==} engines: {node: '>=20'} hasown@2.0.2: @@ -1654,17 +1864,20 @@ packages: resolution: {integrity: sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==} engines: {node: '>=12.0.0'} - hookified@1.13.0: - resolution: {integrity: sha512-6sPYUY8olshgM/1LDNW4QZQN0IqgKhtl/1C8koNZBJrKLBk3AZl6chQtNwpNztvfiApHMEwMHek5rv993PRbWw==} + hookified@1.15.1: + resolution: {integrity: sha512-MvG/clsADq1GPM2KGo2nyfaWVyn9naPiXrqIe4jYjXNZQt238kWyOGrsyc/DmRAQ+Re6yeo6yX/yoNCG5KAEVg==} + + hookified@2.1.1: + resolution: {integrity: sha512-AHb76R16GB5EsPBE2J7Ko5kiEyXwviB9P5SMrAKcuAu4vJPZttViAbj9+tZeaQE5zjDme+1vcHP78Yj/WoAveA==} html-minifier-terser@7.2.0: resolution: {integrity: sha512-tXgn3QfqPIpGl9o+K5tpcj3/MN4SfLtsx2GWwBC3SSd0tXQGyF3gsSqad8loJgKZGM3ZxbYDd5yhiBIdWpmvLA==} engines: {node: ^14.13.1 || >=16.0.0} hasBin: true - html-tags@3.3.1: - resolution: {integrity: sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==} - engines: {node: '>=8'} + html-tags@5.1.0: + resolution: {integrity: sha512-n6l5uca7/y5joxZ3LUePhzmBFUJ+U2YWzhMa8XUTecSeSlQiZdF5XAd/Q3/WUl0VsXgUwWi8I7CNIwdI5WN1SQ==} + engines: {node: '>=20.10'} http-proxy-agent@7.0.2: resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} @@ -1681,10 +1894,6 @@ packages: resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} engines: {node: '>= 4'} - ignore@7.0.3: - resolution: {integrity: sha512-bAH5jbK/F3T3Jls4I0SO1hmPR0dKU0a7+SY6n1yzRtG54FLO8d6w/nxLFX2Nb7dBu6cCWXPaAME6cYqFUMmuCA==} - engines: {node: '>= 4'} - ignore@7.0.5: resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} engines: {node: '>= 4'} @@ -1693,6 +1902,9 @@ packages: resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} engines: {node: '>=6'} + import-meta-resolve@4.2.0: + resolution: {integrity: sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==} + imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} @@ -1783,6 +1995,10 @@ packages: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} + is-path-inside@4.0.0: + resolution: {integrity: sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==} + engines: {node: '>=12'} + is-plain-object@5.0.0: resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==} engines: {node: '>=0.10.0'} @@ -1837,10 +2053,6 @@ packages: resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==} engines: {node: '>= 0.4'} - jackspeak@4.1.1: - resolution: {integrity: sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==} - engines: {node: 20 || >=22} - js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -1889,16 +2101,13 @@ packages: keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - keyv@5.5.4: - resolution: {integrity: sha512-eohl3hKTiVyD1ilYdw9T0OiB4hnjef89e3dMYKz+mVKDzj+5IteTseASUsOB+EU9Tf6VNTCjDePcP6wkDGmLKQ==} + keyv@5.6.0: + resolution: {integrity: sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==} kind-of@6.0.3: resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} engines: {node: '>=0.10.0'} - known-css-properties@0.37.0: - resolution: {integrity: sha512-JCDrsP4Z1Sb9JwG0aJ8Eo2r7k4Ou5MwmThS/6lcIe1ICyb7UBJKGRIUUdqc2ASdE/42lgz6zFUnzAIhtXnBVrQ==} - levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} @@ -1910,9 +2119,6 @@ packages: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} - lodash.merge@4.6.2: - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - lodash.truncate@4.4.2: resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} @@ -1923,8 +2129,8 @@ packages: lower-case@2.0.2: resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} - lru-cache@11.2.1: - resolution: {integrity: sha512-r8LA6i4LP4EeWOhqBaZZjDWwehd1xUJPCJd9Sv300H0ZmcUER4+JPh7bqqZeqs1o5pgtgvXm+d9UGrB5zZGDiQ==} + lru-cache@11.3.5: + resolution: {integrity: sha512-NxVFwLAnrd9i7KUBxC4DrUhmgjzOs+1Qm50D3oF1/oL+r1NpZ4gA7xvG0/zJ8evR7zIKn4vLf7qTNduWFtCrRw==} engines: {node: 20 || >=22} lru-cache@7.18.3: @@ -1940,15 +2146,21 @@ packages: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} - mathml-tag-names@2.1.3: - resolution: {integrity: sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==} + mathml-tag-names@4.0.0: + resolution: {integrity: sha512-aa6AU2Pcx0VP/XWnh8IGL0SYSgQHDT6Ucror2j2mXeFAlN3ahaNs8EZtG1YiticMkSLj3Gt6VPFfZogt7G5iFQ==} + + mdn-data@2.0.28: + resolution: {integrity: sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==} mdn-data@2.12.2: resolution: {integrity: sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==} - meow@13.2.0: - resolution: {integrity: sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==} - engines: {node: '>=18'} + mdn-data@2.27.1: + resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==} + + meow@14.1.0: + resolution: {integrity: sha512-EDYo6VlmtnumlcBCbh1gLJ//9jvM/ndXHfVXIFrZVr6fGcwTUyCTFNTLCKuY3ffbK8L/+3Mzqnd58RojiZqHVw==} + engines: {node: '>=20'} merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} @@ -1958,9 +2170,9 @@ packages: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} - minimatch@10.0.3: - resolution: {integrity: sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==} - engines: {node: 20 || >=22} + minimatch@10.2.5: + resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==} + engines: {node: 18 || 20 || >=22} minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} @@ -1975,8 +2187,8 @@ packages: minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - minipass@7.1.2: - resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + minipass@7.1.3: + resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} engines: {node: '>=16 || 14 >=14.17'} mitt@3.0.1: @@ -1985,8 +2197,8 @@ packages: moment@2.30.1: resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==} - monaco-editor@0.54.0: - resolution: {integrity: sha512-hx45SEUoLatgWxHKCmlLJH81xBo0uXP4sRkESUpmDQevfi+e7K1VuiSprK6UpQ8u4zOcKNiH0pMvHvlMWA/4cw==} + monaco-editor@0.55.1: + resolution: {integrity: sha512-jz4x+TJNFHwHtwuV9vA9rMujcZRb0CEilTEwG2rRSpe/A7Jdkuj8xPKttCgOh+v/lkHy7HsZ64oj+q3xoAFl9A==} ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -2024,6 +2236,9 @@ packages: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} + nth-check@2.1.1: + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -2087,9 +2302,6 @@ packages: resolution: {integrity: sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==} engines: {node: '>= 14'} - package-json-from-dist@1.0.1: - resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} - pako@1.0.11: resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} @@ -2118,13 +2330,9 @@ packages: path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - path-scurry@2.0.0: - resolution: {integrity: sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==} - engines: {node: 20 || >=22} - - path-type@4.0.0: - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} - engines: {node: '>=8'} + path-scurry@2.0.2: + resolution: {integrity: sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==} + engines: {node: 18 || 20 || >=22} pend@1.2.0: resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} @@ -2140,28 +2348,29 @@ packages: resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} engines: {node: '>=12'} + picomatch@4.0.4: + resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} + engines: {node: '>=12'} + possible-typed-array-names@1.1.0: resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} engines: {node: '>= 0.4'} - postcss-resolve-nested-selector@0.1.6: - resolution: {integrity: sha512-0sglIs9Wmkzbr8lQwEyIzlDOOC9bGmfVKcJTaxv3vMmd3uo4o4DerC3En0bnmgceeql9BfC8hRkp7cg0fjdVqw==} - postcss-safe-parser@7.0.1: resolution: {integrity: sha512-0AioNCJZ2DPYz5ABT6bddIqlhgwhpHZ/l65YAYo0BCIn0xiDpsnTHz0gnoTGk0OXZW0JRs+cDwL8u/teRdz+8A==} engines: {node: '>=18.0'} peerDependencies: postcss: ^8.4.31 - postcss-selector-parser@7.1.0: - resolution: {integrity: sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==} + postcss-selector-parser@7.1.1: + resolution: {integrity: sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==} engines: {node: '>=4'} postcss-value-parser@4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - postcss@8.5.6: - resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} + postcss@8.5.10: + resolution: {integrity: sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==} engines: {node: ^10 || ^12 || >=14} prelude-ls@1.2.1: @@ -2189,8 +2398,8 @@ packages: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} - puppeteer-core@24.30.0: - resolution: {integrity: sha512-2S3Smy0t0W4wJnNvDe7W0bE7wDmZjfZ3ljfMgJd6hn2Hq/f0jgN+x9PULZo2U3fu5UUIJ+JP8cNUGllu8P91Pg==} + puppeteer-core@24.41.0: + resolution: {integrity: sha512-rLIUri7E/NQ3APSEYCCozaSJx0u8Tu9wxO6BJwnvXmIgILSK3L0TombaVh3izp1njAGrO6H2ru0hcIrLF+gWLw==} engines: {node: '>=18'} q@1.5.1: @@ -2201,8 +2410,8 @@ packages: (For a CapTP with native promises, see @endo/eventual-send and @endo/captp) - qified@0.5.2: - resolution: {integrity: sha512-7gJ6mxcQb9vUBOtbKm5mDevbe2uRcOEVp1g4gb/Q+oLntB3HY8eBhOYRxFI2mlDFlY1e4DOSCptzxarXRvzxCA==} + qified@0.9.1: + resolution: {integrity: sha512-n7mar4T0xQ+39dE2vGTAlbxUEpndwPANH0kDef1/MYsB8Bba9wshkybIRx74qgcvKQPEWErf9AqAdYjhzY2Ilg==} engines: {node: '>=20'} queue-microtask@1.2.3: @@ -2235,10 +2444,6 @@ packages: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} - resolve-from@5.0.0: - resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} - engines: {node: '>=8'} - resolve-pkg-maps@1.0.0: resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} @@ -2274,6 +2479,10 @@ packages: resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} engines: {node: '>= 0.4'} + sax@1.6.0: + resolution: {integrity: sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==} + engines: {node: '>=11.0.0'} + semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true @@ -2283,13 +2492,13 @@ packages: engines: {node: '>=10'} hasBin: true - semver@7.7.2: - resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} + semver@7.7.3: + resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} engines: {node: '>=10'} hasBin: true - semver@7.7.3: - resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} + semver@7.7.4: + resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==} engines: {node: '>=10'} hasBin: true @@ -2333,9 +2542,9 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} - slash@3.0.0: - resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} - engines: {node: '>=8'} + slash@5.1.0: + resolution: {integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==} + engines: {node: '>=14.16'} slice-ansi@4.0.0: resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} @@ -2367,8 +2576,8 @@ packages: sprintf-js@1.1.3: resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} - standalone-electron-types@34.2.0: - resolution: {integrity: sha512-+BIrNe0TdZBBBRS3G/F7cPbuBipSZylSjSrJu9+sjw84+vz36a5oZ7l9NeH7aXgMWmPzPZKsTm+K0nOIvhENJQ==} + standalone-electron-types@41.2.1: + resolution: {integrity: sha512-0NAQpGYvxpqZ87SNaWyJhmgmIZ3vkPkES01j3etqSoRepINU/LpNy9bk4Pyp/4me6rCs11jPoWqzQCEn+e+d6Q==} stop-iteration-iterator@1.1.0: resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} @@ -2381,9 +2590,9 @@ packages: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} - string-width@5.1.2: - resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} - engines: {node: '>=12'} + string-width@8.2.0: + resolution: {integrity: sha512-6hJPQ8N0V0P3SNmP6h2J99RLuzrWz2gvT7VnK5tKvrNqJoyS9W4/Fb8mo31UiPvy00z7DQXkP2hnKBVav76thw==} + engines: {node: '>=20'} string.prototype.matchall@4.0.12: resolution: {integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==} @@ -2416,27 +2625,27 @@ packages: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} - strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} - - stylelint-config-recommended@17.0.0: - resolution: {integrity: sha512-WaMSdEiPfZTSFVoYmJbxorJfA610O0tlYuU2aEwY33UQhSPgFbClrVJYWvy3jGJx+XW37O+LyNLiZOEXhKhJmA==} - engines: {node: '>=18.12.0'} + stylelint-config-recommended@18.0.0: + resolution: {integrity: sha512-mxgT2XY6YZ3HWWe3Di8umG6aBmWmHTblTgu/f10rqFXnyWxjKWwNdjSWkgkwCtxIKnqjSJzvFmPT5yabVIRxZg==} + engines: {node: '>=20.19.0'} peerDependencies: - stylelint: ^16.23.0 + stylelint: ^17.0.0 - stylelint-config-standard@39.0.1: - resolution: {integrity: sha512-b7Fja59EYHRNOTa3aXiuWnhUWXFU2Nfg6h61bLfAb5GS5fX3LMUD0U5t4S8N/4tpHQg3Acs2UVPR9jy2l1g/3A==} - engines: {node: '>=18.12.0'} + stylelint-config-standard@40.0.0: + resolution: {integrity: sha512-EznGJxOUhtWck2r6dJpbgAdPATIzvpLdK9+i5qPd4Lx70es66TkBPljSg4wN3Qnc6c4h2n+WbUrUynQ3fanjHw==} + engines: {node: '>=20.19.0'} peerDependencies: - stylelint: ^16.23.0 + stylelint: ^17.0.0 - stylelint@16.25.0: - resolution: {integrity: sha512-Li0avYWV4nfv1zPbdnxLYBGq4z8DVZxbRgx4Kn6V+Uftz1rMoF1qiEI3oL4kgWqyYgCgs7gT5maHNZ82Gk03vQ==} - engines: {node: '>=18.12.0'} + stylelint@17.8.0: + resolution: {integrity: sha512-oHkld9T60LDSaUQ4CSVc+tlt9eUoDlxhaGWShsUCKyIL14boZfmK5bSphZqx64aiC5tCqX+BsQMTMoSz8D1zIg==} + engines: {node: '>=20.19.0'} hasBin: true + supports-color@10.2.2: + resolution: {integrity: sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==} + engines: {node: '>=18'} + supports-color@5.5.0: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} engines: {node: '>=4'} @@ -2445,9 +2654,9 @@ packages: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} - supports-hyperlinks@3.2.0: - resolution: {integrity: sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig==} - engines: {node: '>=14.18'} + supports-hyperlinks@4.4.0: + resolution: {integrity: sha512-UKbpT93hN5Nr9go5UY7bopIB9YQlMz9nm/ct4IXt/irb5YRkn9WaqrOBJGZ5Pwvsd5FQzSVeYlGdXoCAPQZrPg==} + engines: {node: '>=20'} supports-preserve-symlinks-flag@1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} @@ -2456,6 +2665,11 @@ packages: svg-tags@1.0.0: resolution: {integrity: sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==} + svgo@4.0.1: + resolution: {integrity: sha512-XDpWUOPC6FEibaLzjfe0ucaV0YrOjYotGJO1WpF0Zd+n6ZGEQUsSugaoLq9QkEZtAfQIxT42UChcssDVPP3+/w==} + engines: {node: '>=16'} + hasBin: true + table@6.9.0: resolution: {integrity: sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==} engines: {node: '>=10.0.0'} @@ -2478,12 +2692,16 @@ packages: text-decoder@1.1.1: resolution: {integrity: sha512-8zll7REEv4GDD3x4/0pW+ppIxSNs7H1J10IKFZsuOMscumCdM2a+toDGLPA3T+1+fLBql4zbt5z83GEQGGV5VA==} + tinyglobby@0.2.16: + resolution: {integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==} + engines: {node: '>=12.0.0'} + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} - ts-api-utils@2.1.0: - resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} + ts-api-utils@2.5.0: + resolution: {integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==} engines: {node: '>=18.12'} peerDependencies: typescript: '>=4.8.4' @@ -2495,6 +2713,9 @@ packages: ts-pattern@5.6.2: resolution: {integrity: sha512-d4IxJUXROL5NCa3amvMg6VQW2HVtZYmUTPfvVtO7zJWGYLJ+mry9v2OmYm+z67aniQoQ8/yFNadiEwtNS9qQiw==} + ts-pattern@5.9.0: + resolution: {integrity: sha512-6s5V71mX8qBUmlgbrfL33xDUwO0fq48rxAu2LBE11WBeGdpCPOsXksQbZJHvHwhrd3QjUusd3mAOM5Gg0mFBLg==} + tsconfig-paths@3.15.0: resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} @@ -2509,8 +2730,8 @@ packages: engines: {node: '>=18.0.0'} hasBin: true - tsx@4.20.6: - resolution: {integrity: sha512-ytQKuwgmrrkDTFP4LjR0ToE2nqgy886GpvRSpU0JAnrdBYppuY5rLkRUYPU1yCryb24SsKBTL/hlDQAEFVwtZg==} + tsx@4.21.0: + resolution: {integrity: sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==} engines: {node: '>=18.0.0'} hasBin: true @@ -2526,8 +2747,8 @@ packages: resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} engines: {node: '>=16'} - type-fest@5.2.0: - resolution: {integrity: sha512-xxCJm+Bckc6kQBknN7i9fnP/xobQRsRQxR01CztFkp/h++yfVxUUcmMgfR2HttJx/dpWjS9ubVuyspJv24Q9DA==} + type-fest@5.5.0: + resolution: {integrity: sha512-PlBfpQwiUvGViBNX84Yxwjsdhd1TUlXr6zjX7eoirtCPIr08NAmxwa+fcYBTeRQxHo9YC9wwF3m9i700sHma8g==} engines: {node: '>=20'} typed-array-buffer@1.0.3: @@ -2546,23 +2767,23 @@ packages: resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} engines: {node: '>= 0.4'} - typed-query-selector@2.12.0: - resolution: {integrity: sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg==} + typed-query-selector@2.12.1: + resolution: {integrity: sha512-uzR+FzI8qrUEIu96oaeBJmd9E7CFEiQ3goA5qCVgc4s5llSubcfGHq9yUstZx/k4s9dXHVKsE35YWoFyvEqEHA==} - typescript-eslint@8.47.0: - resolution: {integrity: sha512-Lwe8i2XQ3WoMjua/r1PHrCTpkubPYJCAfOurtn+mtTzqB6jNd+14n9UN1bJ4s3F49x9ixAm0FLflB/JzQ57M8Q==} + typescript-eslint@8.58.2: + resolution: {integrity: sha512-V8iSng9mRbdZjl54VJ9NKr6ZB+dW0J3TzRXRGcSbLIej9jV86ZRtlYeTKDR/QLxXykocJ5icNzbsl2+5TzIvcQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <6.0.0' + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' - typescript-transform-paths@3.5.5: - resolution: {integrity: sha512-RMK86wKe/4+ad+3kMT9SKAs3K0tUHLe7hF+MLbD6VpC9VUmFuKorhf3pHz+qO5GdS4mUp2ncNUo14j6ws9UvBQ==} + typescript-transform-paths@3.5.6: + resolution: {integrity: sha512-3eQTG6Ogt+pgPEh45uX2s9OwcfAVjWnyNO+osjYcOqYaWDVMIFUkqW8e0O1cOaVwdMqQFQf6alDT+76xmeS2Ag==} peerDependencies: typescript: '>=3.6.5' - typescript@5.9.3: - resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + typescript@6.0.2: + resolution: {integrity: sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ==} engines: {node: '>=14.17'} hasBin: true @@ -2573,8 +2794,12 @@ packages: undici-types@6.20.0: resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} - undici-types@7.16.0: - resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} + undici-types@7.19.2: + resolution: {integrity: sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==} + + unicorn-magic@0.4.0: + resolution: {integrity: sha512-wH590V9VNgYH9g3lH9wWjTrUoKsjLF6sGLjhR4sH1LWpLmCOH0Zf7PukhDA8BiS7KHe4oPNkcTHqYkj7SOGUOw==} + engines: {node: '>=20'} universalify@2.0.1: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} @@ -2603,8 +2828,8 @@ packages: resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} engines: {node: '>= 8'} - webdriver-bidi-protocol@0.3.8: - resolution: {integrity: sha512-21Yi2GhGntMc671vNBCjiAeEVknXjVRoyu+k+9xOMShu+ZQfpGQwnBqbNz/Sv4GXZ6JmutlPAi2nIJcrymAWuQ==} + webdriver-bidi-protocol@0.4.1: + resolution: {integrity: sha512-ARrjNjtWRRs2w4Tk7nqrf2gBI0QXWuOmMCx2hU+1jUt6d00MjMxURrhxhGbrsoiZKJrhTSTzbIrc554iKI10qw==} which-boxed-primitive@1.1.1: resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} @@ -2648,19 +2873,15 @@ packages: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} - wrap-ansi@8.1.0: - resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} - engines: {node: '>=12'} - wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - write-file-atomic@5.0.1: - resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + write-file-atomic@7.0.1: + resolution: {integrity: sha512-OTIk8iR8/aCRWBqvxrzxR0hgxWpnYBblY1S5hDWBQfk/VFmJwzmJgQFN3WsoUKHISv2eAwe+PpbUzyL1CKTLXg==} + engines: {node: ^20.17.0 || >=22.9.0} - ws@8.18.3: - resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==} + ws@8.20.0: + resolution: {integrity: sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==} engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 @@ -2675,6 +2896,10 @@ packages: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} + yaml-js@0.3.1: + resolution: {integrity: sha512-LjoIFHCtSfkGzPsmYmfDsW+TShtQBcY7lwH1yLQ5brJHXRhjteUnVE2ThCbz1madq8JUZIAjFiavfnIFeTO8CQ==} + engines: {node: '>=8'} + yargs-parser@21.1.1: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} @@ -2719,40 +2944,51 @@ snapshots: js-tokens: 4.0.0 picocolors: 1.1.1 - '@cacheable/memory@2.0.5': + '@cacheable/memory@2.0.8': dependencies: - '@cacheable/utils': 2.3.1 - '@keyv/bigmap': 1.3.0(keyv@5.5.4) - hookified: 1.13.0 - keyv: 5.5.4 + '@cacheable/utils': 2.4.1 + '@keyv/bigmap': 1.3.1(keyv@5.6.0) + hookified: 1.15.1 + keyv: 5.6.0 - '@cacheable/utils@2.3.1': + '@cacheable/utils@2.4.1': dependencies: - hashery: 1.2.0 - keyv: 5.5.4 + hashery: 1.5.1 + keyv: 5.6.0 - '@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4)': + '@csstools/css-calc@3.2.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': dependencies: - '@csstools/css-tokenizer': 3.0.4 + '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) + '@csstools/css-tokenizer': 4.0.0 - '@csstools/css-tokenizer@3.0.4': {} - - '@csstools/media-query-list-parser@4.0.3(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': + '@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0)': dependencies: - '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) - '@csstools/css-tokenizer': 3.0.4 + '@csstools/css-tokenizer': 4.0.0 - '@csstools/selector-specificity@5.0.0(postcss-selector-parser@7.1.0)': + '@csstools/css-syntax-patches-for-csstree@1.1.3(css-tree@3.2.1)': + optionalDependencies: + css-tree: 3.2.1 + + '@csstools/css-tokenizer@4.0.0': {} + + '@csstools/media-query-list-parser@5.0.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': dependencies: - postcss-selector-parser: 7.1.0 + '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) + '@csstools/css-tokenizer': 4.0.0 - '@dual-bundle/import-meta-resolve@4.2.1': {} + '@csstools/selector-resolve-nested@4.0.0(postcss-selector-parser@7.1.1)': + dependencies: + postcss-selector-parser: 7.1.1 - '@electron/asar@4.0.1': + '@csstools/selector-specificity@6.0.0(postcss-selector-parser@7.1.1)': + dependencies: + postcss-selector-parser: 7.1.1 + + '@electron/asar@4.2.0': dependencies: commander: 13.1.0 - glob: 11.0.3 - minimatch: 10.0.3 + glob: 13.0.6 + minimatch: 10.2.5 '@esbuild/aix-ppc64@0.25.1': optional: true @@ -2760,197 +2996,264 @@ snapshots: '@esbuild/aix-ppc64@0.27.0': optional: true + '@esbuild/aix-ppc64@0.28.0': + optional: true + '@esbuild/android-arm64@0.25.1': optional: true '@esbuild/android-arm64@0.27.0': optional: true + '@esbuild/android-arm64@0.28.0': + optional: true + '@esbuild/android-arm@0.25.1': optional: true '@esbuild/android-arm@0.27.0': optional: true + '@esbuild/android-arm@0.28.0': + optional: true + '@esbuild/android-x64@0.25.1': optional: true '@esbuild/android-x64@0.27.0': optional: true + '@esbuild/android-x64@0.28.0': + optional: true + '@esbuild/darwin-arm64@0.25.1': optional: true '@esbuild/darwin-arm64@0.27.0': optional: true + '@esbuild/darwin-arm64@0.28.0': + optional: true + '@esbuild/darwin-x64@0.25.1': optional: true '@esbuild/darwin-x64@0.27.0': optional: true + '@esbuild/darwin-x64@0.28.0': + optional: true + '@esbuild/freebsd-arm64@0.25.1': optional: true '@esbuild/freebsd-arm64@0.27.0': optional: true + '@esbuild/freebsd-arm64@0.28.0': + optional: true + '@esbuild/freebsd-x64@0.25.1': optional: true '@esbuild/freebsd-x64@0.27.0': optional: true + '@esbuild/freebsd-x64@0.28.0': + optional: true + '@esbuild/linux-arm64@0.25.1': optional: true '@esbuild/linux-arm64@0.27.0': optional: true + '@esbuild/linux-arm64@0.28.0': + optional: true + '@esbuild/linux-arm@0.25.1': optional: true '@esbuild/linux-arm@0.27.0': optional: true + '@esbuild/linux-arm@0.28.0': + optional: true + '@esbuild/linux-ia32@0.25.1': optional: true '@esbuild/linux-ia32@0.27.0': optional: true + '@esbuild/linux-ia32@0.28.0': + optional: true + '@esbuild/linux-loong64@0.25.1': optional: true '@esbuild/linux-loong64@0.27.0': optional: true + '@esbuild/linux-loong64@0.28.0': + optional: true + '@esbuild/linux-mips64el@0.25.1': optional: true '@esbuild/linux-mips64el@0.27.0': optional: true + '@esbuild/linux-mips64el@0.28.0': + optional: true + '@esbuild/linux-ppc64@0.25.1': optional: true '@esbuild/linux-ppc64@0.27.0': optional: true + '@esbuild/linux-ppc64@0.28.0': + optional: true + '@esbuild/linux-riscv64@0.25.1': optional: true '@esbuild/linux-riscv64@0.27.0': optional: true + '@esbuild/linux-riscv64@0.28.0': + optional: true + '@esbuild/linux-s390x@0.25.1': optional: true '@esbuild/linux-s390x@0.27.0': optional: true + '@esbuild/linux-s390x@0.28.0': + optional: true + '@esbuild/linux-x64@0.25.1': optional: true '@esbuild/linux-x64@0.27.0': optional: true + '@esbuild/linux-x64@0.28.0': + optional: true + '@esbuild/netbsd-arm64@0.25.1': optional: true '@esbuild/netbsd-arm64@0.27.0': optional: true + '@esbuild/netbsd-arm64@0.28.0': + optional: true + '@esbuild/netbsd-x64@0.25.1': optional: true '@esbuild/netbsd-x64@0.27.0': optional: true + '@esbuild/netbsd-x64@0.28.0': + optional: true + '@esbuild/openbsd-arm64@0.25.1': optional: true '@esbuild/openbsd-arm64@0.27.0': optional: true + '@esbuild/openbsd-arm64@0.28.0': + optional: true + '@esbuild/openbsd-x64@0.25.1': optional: true '@esbuild/openbsd-x64@0.27.0': optional: true + '@esbuild/openbsd-x64@0.28.0': + optional: true + '@esbuild/openharmony-arm64@0.27.0': optional: true + '@esbuild/openharmony-arm64@0.28.0': + optional: true + '@esbuild/sunos-x64@0.25.1': optional: true '@esbuild/sunos-x64@0.27.0': optional: true + '@esbuild/sunos-x64@0.28.0': + optional: true + '@esbuild/win32-arm64@0.25.1': optional: true '@esbuild/win32-arm64@0.27.0': optional: true + '@esbuild/win32-arm64@0.28.0': + optional: true + '@esbuild/win32-ia32@0.25.1': optional: true '@esbuild/win32-ia32@0.27.0': optional: true + '@esbuild/win32-ia32@0.28.0': + optional: true + '@esbuild/win32-x64@0.25.1': optional: true '@esbuild/win32-x64@0.27.0': optional: true - '@eslint-community/eslint-utils@4.9.0(eslint@9.39.1)': + '@esbuild/win32-x64@0.28.0': + optional: true + + '@eslint-community/eslint-utils@4.9.0(eslint@10.2.0)': dependencies: - eslint: 9.39.1 + eslint: 10.2.0 eslint-visitor-keys: 3.4.3 - '@eslint-community/regexpp@4.12.1': {} - - '@eslint/config-array@0.21.1': + '@eslint-community/eslint-utils@4.9.1(eslint@10.2.0)': dependencies: - '@eslint/object-schema': 2.1.7 - debug: 4.4.1 - minimatch: 3.1.2 + eslint: 10.2.0 + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.12.2': {} + + '@eslint/config-array@0.23.5': + dependencies: + '@eslint/object-schema': 3.0.5 + debug: 4.4.3 + minimatch: 10.2.5 transitivePeerDependencies: - supports-color - '@eslint/config-helpers@0.4.2': + '@eslint/config-helpers@0.5.5': dependencies: - '@eslint/core': 0.17.0 + '@eslint/core': 1.2.1 - '@eslint/core@0.17.0': + '@eslint/core@1.2.1': dependencies: '@types/json-schema': 7.0.15 - '@eslint/eslintrc@3.3.1': + '@eslint/object-schema@3.0.5': {} + + '@eslint/plugin-kit@0.7.1': dependencies: - ajv: 6.12.6 - debug: 4.4.1 - espree: 10.4.0 - globals: 14.0.0 - ignore: 5.3.1 - import-fresh: 3.3.1 - js-yaml: 4.1.0 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - - '@eslint/js@9.39.1': {} - - '@eslint/object-schema@2.1.7': {} - - '@eslint/plugin-kit@0.4.1': - dependencies: - '@eslint/core': 0.17.0 + '@eslint/core': 1.2.1 levn: 0.4.1 '@ffmpeg/ffmpeg@0.12.10': @@ -2978,21 +3281,6 @@ snapshots: '@intrnl/xxhash64@0.1.2': {} - '@isaacs/balanced-match@4.0.1': {} - - '@isaacs/brace-expansion@5.0.0': - dependencies: - '@isaacs/balanced-match': 4.0.1 - - '@isaacs/cliui@8.0.2': - dependencies: - string-width: 5.1.2 - string-width-cjs: string-width@4.2.3 - strip-ansi: 7.1.2 - strip-ansi-cjs: strip-ansi@6.0.1 - wrap-ansi: 8.1.0 - wrap-ansi-cjs: wrap-ansi@7.0.0 - '@jridgewell/gen-mapping@0.3.5': dependencies: '@jridgewell/set-array': 1.2.1 @@ -3015,11 +3303,11 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.4.15 - '@keyv/bigmap@1.3.0(keyv@5.5.4)': + '@keyv/bigmap@1.3.1(keyv@5.6.0)': dependencies: - hashery: 1.2.0 - hookified: 1.13.0 - keyv: 5.5.4 + hashery: 1.5.1 + hookified: 1.15.1 + keyv: 5.6.0 '@keyv/serialize@1.1.1': {} @@ -3035,13 +3323,13 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.19.1 - '@puppeteer/browsers@2.10.13': + '@puppeteer/browsers@2.13.0': dependencies: debug: 4.4.3 extract-zip: 2.0.1 progress: 2.0.3 proxy-agent: 6.5.0 - semver: 7.7.3 + semver: 7.7.4 tar-fs: 3.1.1 yargs: 17.7.2 transitivePeerDependencies: @@ -3050,19 +3338,21 @@ snapshots: '@rtsao/scc@1.1.0': {} - '@song-spotlight/api@2.1.3(typescript@5.9.3)': + '@sindresorhus/merge-streams@4.0.0': {} + + '@song-spotlight/api@2.1.3(typescript@6.0.2)': dependencies: - typescript: 5.9.3 + typescript: 6.0.2 optionalDependencies: zod: 4.3.6 '@streamparser/json@0.0.22': {} - '@stylistic/eslint-plugin@5.6.0(eslint@9.39.1)': + '@stylistic/eslint-plugin@5.10.0(eslint@10.2.0)': dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1) - '@typescript-eslint/types': 8.47.0 - eslint: 9.39.1 + '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.0) + '@typescript-eslint/types': 8.58.2 + eslint: 10.2.0 eslint-visitor-keys: 4.2.1 espree: 10.4.0 estraverse: 5.3.0 @@ -3070,19 +3360,17 @@ snapshots: '@tootallnate/quickjs-emscripten@0.23.0': {} - '@types/adm-zip@0.5.7': - dependencies: - '@types/node': 24.10.1 - - '@types/chrome@0.1.30': + '@types/chrome@0.1.40': dependencies: '@types/filesystem': 0.0.36 '@types/har-format': 1.2.15 - '@types/diff@7.0.2': {} + '@types/esrecurse@4.3.1': {} '@types/estree@1.0.7': {} + '@types/estree@1.0.8': {} + '@types/filesystem@0.0.36': dependencies: '@types/filewriter': 0.0.33 @@ -3108,15 +3396,15 @@ snapshots: '@types/lodash@4.17.15': {} - '@types/lodash@4.17.20': {} + '@types/lodash@4.17.24': {} '@types/node@22.13.13': dependencies: undici-types: 6.20.0 - '@types/node@24.10.1': + '@types/node@25.6.0': dependencies: - undici-types: 7.16.0 + undici-types: 7.19.2 '@types/react-dom@19.0.4(@types/react@19.0.12)': dependencies: @@ -3128,111 +3416,112 @@ snapshots: '@types/stylus@0.48.42': dependencies: - '@types/node': 24.10.1 + '@types/node': 25.6.0 '@types/tinycolor2@1.4.6': {} - '@types/yauzl@2.10.3': - dependencies: - '@types/node': 24.10.1 + '@types/trusted-types@2.0.7': optional: true - '@types/yazl@3.3.0': + '@types/yauzl@2.10.3': dependencies: - '@types/node': 24.10.1 + '@types/node': 25.6.0 + optional: true - '@typescript-eslint/eslint-plugin@8.47.0(@typescript-eslint/parser@8.47.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3)': + '@types/yazl@3.3.1': dependencies: - '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.47.0(eslint@9.39.1)(typescript@5.9.3) - '@typescript-eslint/scope-manager': 8.47.0 - '@typescript-eslint/type-utils': 8.47.0(eslint@9.39.1)(typescript@5.9.3) - '@typescript-eslint/utils': 8.47.0(eslint@9.39.1)(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.47.0 - eslint: 9.39.1 - graphemer: 1.4.0 - ignore: 7.0.3 + '@types/node': 25.6.0 + + '@typescript-eslint/eslint-plugin@8.58.2(@typescript-eslint/parser@8.58.2(eslint@10.2.0)(typescript@6.0.2))(eslint@10.2.0)(typescript@6.0.2)': + dependencies: + '@eslint-community/regexpp': 4.12.2 + '@typescript-eslint/parser': 8.58.2(eslint@10.2.0)(typescript@6.0.2) + '@typescript-eslint/scope-manager': 8.58.2 + '@typescript-eslint/type-utils': 8.58.2(eslint@10.2.0)(typescript@6.0.2) + '@typescript-eslint/utils': 8.58.2(eslint@10.2.0)(typescript@6.0.2) + '@typescript-eslint/visitor-keys': 8.58.2 + eslint: 10.2.0 + ignore: 7.0.5 natural-compare: 1.4.0 - ts-api-utils: 2.1.0(typescript@5.9.3) - typescript: 5.9.3 + ts-api-utils: 2.5.0(typescript@6.0.2) + typescript: 6.0.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.47.0(eslint@9.39.1)(typescript@5.9.3)': + '@typescript-eslint/parser@8.58.2(eslint@10.2.0)(typescript@6.0.2)': dependencies: - '@typescript-eslint/scope-manager': 8.47.0 - '@typescript-eslint/types': 8.47.0 - '@typescript-eslint/typescript-estree': 8.47.0(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.47.0 - debug: 4.4.1 - eslint: 9.39.1 - typescript: 5.9.3 + '@typescript-eslint/scope-manager': 8.58.2 + '@typescript-eslint/types': 8.58.2 + '@typescript-eslint/typescript-estree': 8.58.2(typescript@6.0.2) + '@typescript-eslint/visitor-keys': 8.58.2 + debug: 4.4.3 + eslint: 10.2.0 + typescript: 6.0.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.47.0(typescript@5.9.3)': + '@typescript-eslint/project-service@8.58.2(typescript@6.0.2)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.47.0(typescript@5.9.3) - '@typescript-eslint/types': 8.47.0 - debug: 4.4.1 - typescript: 5.9.3 + '@typescript-eslint/tsconfig-utils': 8.58.2(typescript@6.0.2) + '@typescript-eslint/types': 8.58.2 + debug: 4.4.3 + typescript: 6.0.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.47.0': + '@typescript-eslint/scope-manager@8.58.2': dependencies: - '@typescript-eslint/types': 8.47.0 - '@typescript-eslint/visitor-keys': 8.47.0 + '@typescript-eslint/types': 8.58.2 + '@typescript-eslint/visitor-keys': 8.58.2 - '@typescript-eslint/tsconfig-utils@8.47.0(typescript@5.9.3)': + '@typescript-eslint/tsconfig-utils@8.58.2(typescript@6.0.2)': dependencies: - typescript: 5.9.3 + typescript: 6.0.2 - '@typescript-eslint/type-utils@8.47.0(eslint@9.39.1)(typescript@5.9.3)': + '@typescript-eslint/type-utils@8.58.2(eslint@10.2.0)(typescript@6.0.2)': dependencies: - '@typescript-eslint/types': 8.47.0 - '@typescript-eslint/typescript-estree': 8.47.0(typescript@5.9.3) - '@typescript-eslint/utils': 8.47.0(eslint@9.39.1)(typescript@5.9.3) - debug: 4.4.1 - eslint: 9.39.1 - ts-api-utils: 2.1.0(typescript@5.9.3) - typescript: 5.9.3 + '@typescript-eslint/types': 8.58.2 + '@typescript-eslint/typescript-estree': 8.58.2(typescript@6.0.2) + '@typescript-eslint/utils': 8.58.2(eslint@10.2.0)(typescript@6.0.2) + debug: 4.4.3 + eslint: 10.2.0 + ts-api-utils: 2.5.0(typescript@6.0.2) + typescript: 6.0.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.47.0': {} + '@typescript-eslint/types@8.58.2': {} - '@typescript-eslint/typescript-estree@8.47.0(typescript@5.9.3)': + '@typescript-eslint/typescript-estree@8.58.2(typescript@6.0.2)': dependencies: - '@typescript-eslint/project-service': 8.47.0(typescript@5.9.3) - '@typescript-eslint/tsconfig-utils': 8.47.0(typescript@5.9.3) - '@typescript-eslint/types': 8.47.0 - '@typescript-eslint/visitor-keys': 8.47.0 - debug: 4.4.1 - fast-glob: 3.3.3 - is-glob: 4.0.3 - minimatch: 9.0.5 - semver: 7.7.2 - ts-api-utils: 2.1.0(typescript@5.9.3) - typescript: 5.9.3 + '@typescript-eslint/project-service': 8.58.2(typescript@6.0.2) + '@typescript-eslint/tsconfig-utils': 8.58.2(typescript@6.0.2) + '@typescript-eslint/types': 8.58.2 + '@typescript-eslint/visitor-keys': 8.58.2 + debug: 4.4.3 + minimatch: 10.2.5 + semver: 7.7.3 + tinyglobby: 0.2.16 + ts-api-utils: 2.5.0(typescript@6.0.2) + typescript: 6.0.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.47.0(eslint@9.39.1)(typescript@5.9.3)': + '@typescript-eslint/utils@8.58.2(eslint@10.2.0)(typescript@6.0.2)': dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1) - '@typescript-eslint/scope-manager': 8.47.0 - '@typescript-eslint/types': 8.47.0 - '@typescript-eslint/typescript-estree': 8.47.0(typescript@5.9.3) - eslint: 9.39.1 - typescript: 5.9.3 + '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.0) + '@typescript-eslint/scope-manager': 8.58.2 + '@typescript-eslint/types': 8.58.2 + '@typescript-eslint/typescript-estree': 8.58.2(typescript@6.0.2) + eslint: 10.2.0 + typescript: 6.0.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.47.0': + '@typescript-eslint/visitor-keys@8.58.2': dependencies: - '@typescript-eslint/types': 8.47.0 - eslint-visitor-keys: 4.2.1 + '@typescript-eslint/types': 8.58.2 + eslint-visitor-keys: 5.0.1 '@vap/core@0.0.12': dependencies: @@ -3254,13 +3543,19 @@ snapshots: dependencies: acorn: 8.15.0 + acorn-jsx@5.3.2(acorn@8.16.0): + dependencies: + acorn: 8.16.0 + acorn@8.14.1: {} acorn@8.15.0: {} + acorn@8.16.0: {} + agent-base@7.1.3: {} - ajv@6.12.6: + ajv@6.14.0: dependencies: fast-deep-equal: 3.1.3 fast-json-stable-stringify: 2.1.0 @@ -3286,8 +3581,6 @@ snapshots: dependencies: color-convert: 2.0.1 - ansi-styles@6.2.3: {} - argparse@2.0.1: {} array-buffer-byte-length@1.0.2: @@ -3315,8 +3608,6 @@ snapshots: is-string: 1.1.1 math-intrinsics: 1.1.0 - array-union@2.1.0: {} - array.prototype.findlast@1.2.5: dependencies: call-bind: 1.0.8 @@ -3393,7 +3684,7 @@ snapshots: balanced-match@1.0.2: {} - balanced-match@2.0.0: {} + balanced-match@4.0.4: {} bare-events@2.5.4: optional: true @@ -3422,6 +3713,8 @@ snapshots: basic-ftp@5.0.5: {} + boolbase@1.0.0: {} + brace-expansion@1.1.12: dependencies: balanced-match: 1.0.2 @@ -3431,6 +3724,10 @@ snapshots: dependencies: balanced-match: 1.0.2 + brace-expansion@5.0.5: + dependencies: + balanced-match: 4.0.4 + braces@3.0.3: dependencies: fill-range: 7.1.1 @@ -3439,13 +3736,13 @@ snapshots: buffer-from@1.1.2: {} - cacheable@2.2.0: + cacheable@2.3.4: dependencies: - '@cacheable/memory': 2.0.5 - '@cacheable/utils': 2.3.1 - hookified: 1.13.0 - keyv: 5.5.4 - qified: 0.5.2 + '@cacheable/memory': 2.0.8 + '@cacheable/utils': 2.4.1 + hookified: 1.15.1 + keyv: 5.6.0 + qified: 0.9.1 call-bind-apply-helpers@1.0.2: dependencies: @@ -3482,9 +3779,9 @@ snapshots: ansi-styles: 4.3.0 supports-color: 7.2.0 - chromium-bidi@11.0.0(devtools-protocol@0.0.1521046): + chromium-bidi@14.0.0(devtools-protocol@0.0.1595872): dependencies: - devtools-protocol: 0.0.1521046 + devtools-protocol: 0.0.1595872 mitt: 3.0.1 zod: 3.24.2 @@ -3514,20 +3811,22 @@ snapshots: commander@10.0.1: {} + commander@11.1.0: {} + commander@13.1.0: {} commander@2.20.3: {} concat-map@0.0.1: {} - cosmiconfig@9.0.0(typescript@5.9.3): + cosmiconfig@9.0.1(typescript@6.0.2): dependencies: env-paths: 2.2.1 import-fresh: 3.3.1 js-yaml: 4.1.0 parse-json: 5.2.0 optionalDependencies: - typescript: 5.9.3 + typescript: 6.0.2 cross-spawn@7.0.6: dependencies: @@ -3535,15 +3834,39 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 - css-functions-list@3.2.3: {} + css-functions-list@3.3.3: {} + + css-select@5.2.2: + dependencies: + boolbase: 1.0.0 + css-what: 6.2.2 + domhandler: 5.0.3 + domutils: 3.2.2 + nth-check: 2.1.1 + + css-tree@2.2.1: + dependencies: + mdn-data: 2.0.28 + source-map-js: 1.2.1 css-tree@3.1.0: dependencies: mdn-data: 2.12.2 source-map-js: 1.2.1 + css-tree@3.2.1: + dependencies: + mdn-data: 2.27.1 + source-map-js: 1.2.1 + + css-what@6.2.2: {} + cssesc@3.0.0: {} + csso@5.0.5: + dependencies: + css-tree: 2.2.1 + csstype@3.1.3: {} data-uri-to-buffer@6.0.2: {} @@ -3570,10 +3893,6 @@ snapshots: dependencies: ms: 2.1.3 - debug@4.4.1: - dependencies: - ms: 2.1.3 - debug@4.4.3: dependencies: ms: 2.1.3 @@ -3598,19 +3917,35 @@ snapshots: escodegen: 2.1.0 esprima: 4.0.1 - devtools-protocol@0.0.1521046: {} + devtools-protocol@0.0.1595872: {} - diff@8.0.2: {} - - dir-glob@3.0.1: - dependencies: - path-type: 4.0.0 + diff@9.0.0: {} doctrine@2.1.0: dependencies: esutils: 2.0.3 - dompurify@3.1.7: {} + dom-serializer@2.0.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + entities: 4.5.0 + + domelementtype@2.3.0: {} + + domhandler@5.0.3: + dependencies: + domelementtype: 2.3.0 + + dompurify@3.2.7: + optionalDependencies: + '@types/trusted-types': 2.0.7 + + domutils@3.2.2: + dependencies: + dom-serializer: 2.0.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 dot-case@3.0.4: dependencies: @@ -3623,12 +3958,8 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 - eastasianwidth@0.2.0: {} - emoji-regex@8.0.0: {} - emoji-regex@9.2.2: {} - end-of-stream@1.4.4: dependencies: once: 1.4.0 @@ -3853,6 +4184,35 @@ snapshots: '@esbuild/win32-ia32': 0.27.0 '@esbuild/win32-x64': 0.27.0 + esbuild@0.28.0: + optionalDependencies: + '@esbuild/aix-ppc64': 0.28.0 + '@esbuild/android-arm': 0.28.0 + '@esbuild/android-arm64': 0.28.0 + '@esbuild/android-x64': 0.28.0 + '@esbuild/darwin-arm64': 0.28.0 + '@esbuild/darwin-x64': 0.28.0 + '@esbuild/freebsd-arm64': 0.28.0 + '@esbuild/freebsd-x64': 0.28.0 + '@esbuild/linux-arm': 0.28.0 + '@esbuild/linux-arm64': 0.28.0 + '@esbuild/linux-ia32': 0.28.0 + '@esbuild/linux-loong64': 0.28.0 + '@esbuild/linux-mips64el': 0.28.0 + '@esbuild/linux-ppc64': 0.28.0 + '@esbuild/linux-riscv64': 0.28.0 + '@esbuild/linux-s390x': 0.28.0 + '@esbuild/linux-x64': 0.28.0 + '@esbuild/netbsd-arm64': 0.28.0 + '@esbuild/netbsd-x64': 0.28.0 + '@esbuild/openbsd-arm64': 0.28.0 + '@esbuild/openbsd-x64': 0.28.0 + '@esbuild/openharmony-arm64': 0.28.0 + '@esbuild/sunos-x64': 0.28.0 + '@esbuild/win32-arm64': 0.28.0 + '@esbuild/win32-ia32': 0.28.0 + '@esbuild/win32-x64': 0.28.0 + escalade@3.1.2: {} escape-string-regexp@1.0.5: {} @@ -3867,9 +4227,9 @@ snapshots: optionalDependencies: source-map: 0.6.1 - eslint-import-resolver-alias@1.1.2(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.47.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)): + eslint-import-resolver-alias@1.1.2(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.58.2(eslint@10.2.0)(typescript@6.0.2))(eslint@10.2.0)): dependencies: - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.47.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.58.2(eslint@10.2.0)(typescript@6.0.2))(eslint@10.2.0) eslint-import-resolver-node@0.3.9: dependencies: @@ -3879,17 +4239,17 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.47.0(eslint@9.39.1)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.39.1): + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.58.2(eslint@10.2.0)(typescript@6.0.2))(eslint-import-resolver-node@0.3.9)(eslint@10.2.0): dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 8.47.0(eslint@9.39.1)(typescript@5.9.3) - eslint: 9.39.1 + '@typescript-eslint/parser': 8.58.2(eslint@10.2.0)(typescript@6.0.2) + eslint: 10.2.0 eslint-import-resolver-node: 0.3.9 transitivePeerDependencies: - supports-color - eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.47.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1): + eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.58.2(eslint@10.2.0)(typescript@6.0.2))(eslint@10.2.0): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -3898,9 +4258,9 @@ snapshots: array.prototype.flatmap: 1.3.3 debug: 3.2.7 doctrine: 2.1.0 - eslint: 9.39.1 + eslint: 10.2.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.47.0(eslint@9.39.1)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.39.1) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.58.2(eslint@10.2.0)(typescript@6.0.2))(eslint-import-resolver-node@0.3.9)(eslint@10.2.0) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -3912,13 +4272,13 @@ snapshots: string.prototype.trimend: 1.0.9 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 8.47.0(eslint@9.39.1)(typescript@5.9.3) + '@typescript-eslint/parser': 8.58.2(eslint@10.2.0)(typescript@6.0.2) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack - supports-color - eslint-plugin-react@7.37.5(eslint@9.39.1): + eslint-plugin-react@7.37.5(eslint@10.2.0): dependencies: array-includes: 3.1.8 array.prototype.findlast: 1.2.5 @@ -3926,7 +4286,7 @@ snapshots: array.prototype.tosorted: 1.1.4 doctrine: 2.1.0 es-iterator-helpers: 1.2.1 - eslint: 9.39.1 + eslint: 10.2.0 estraverse: 5.3.0 hasown: 2.0.2 jsx-ast-utils: 3.3.5 @@ -3940,22 +4300,24 @@ snapshots: string.prototype.matchall: 4.0.12 string.prototype.repeat: 1.0.0 - eslint-plugin-simple-header@1.2.2(eslint@9.39.1): + eslint-plugin-simple-header@1.2.2(eslint@10.2.0): dependencies: - eslint: 9.39.1 + eslint: 10.2.0 - eslint-plugin-simple-import-sort@12.1.1(eslint@9.39.1): + eslint-plugin-simple-import-sort@13.0.0(eslint@10.2.0): dependencies: - eslint: 9.39.1 + eslint: 10.2.0 - eslint-plugin-unused-imports@4.3.0(@typescript-eslint/eslint-plugin@8.47.0(@typescript-eslint/parser@8.47.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1): + eslint-plugin-unused-imports@4.4.1(@typescript-eslint/eslint-plugin@8.58.2(@typescript-eslint/parser@8.58.2(eslint@10.2.0)(typescript@6.0.2))(eslint@10.2.0)(typescript@6.0.2))(eslint@10.2.0): dependencies: - eslint: 9.39.1 + eslint: 10.2.0 optionalDependencies: - '@typescript-eslint/eslint-plugin': 8.47.0(@typescript-eslint/parser@8.47.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3) + '@typescript-eslint/eslint-plugin': 8.58.2(@typescript-eslint/parser@8.58.2(eslint@10.2.0)(typescript@6.0.2))(eslint@10.2.0)(typescript@6.0.2) - eslint-scope@8.4.0: + eslint-scope@9.1.2: dependencies: + '@types/esrecurse': 4.3.1 + '@types/estree': 1.0.8 esrecurse: 4.3.0 estraverse: 5.3.0 @@ -3963,29 +4325,28 @@ snapshots: eslint-visitor-keys@4.2.1: {} - eslint@9.39.1: + eslint-visitor-keys@5.0.1: {} + + eslint@10.2.0: dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1) - '@eslint-community/regexpp': 4.12.1 - '@eslint/config-array': 0.21.1 - '@eslint/config-helpers': 0.4.2 - '@eslint/core': 0.17.0 - '@eslint/eslintrc': 3.3.1 - '@eslint/js': 9.39.1 - '@eslint/plugin-kit': 0.4.1 + '@eslint-community/eslint-utils': 4.9.0(eslint@10.2.0) + '@eslint-community/regexpp': 4.12.2 + '@eslint/config-array': 0.23.5 + '@eslint/config-helpers': 0.5.5 + '@eslint/core': 1.2.1 + '@eslint/plugin-kit': 0.7.1 '@humanfs/node': 0.16.6 '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.4.2 '@types/estree': 1.0.7 - ajv: 6.12.6 - chalk: 4.1.2 + ajv: 6.14.0 cross-spawn: 7.0.6 - debug: 4.4.1 + debug: 4.4.3 escape-string-regexp: 4.0.0 - eslint-scope: 8.4.0 - eslint-visitor-keys: 4.2.1 - espree: 10.4.0 - esquery: 1.6.0 + eslint-scope: 9.1.2 + eslint-visitor-keys: 5.0.1 + espree: 11.2.0 + esquery: 1.7.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 file-entry-cache: 8.0.0 @@ -3995,8 +4356,7 @@ snapshots: imurmurhash: 0.1.4 is-glob: 4.0.3 json-stable-stringify-without-jsonify: 1.0.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 + minimatch: 10.2.5 natural-compare: 1.4.0 optionator: 0.9.4 transitivePeerDependencies: @@ -4008,9 +4368,15 @@ snapshots: acorn-jsx: 5.3.2(acorn@8.15.0) eslint-visitor-keys: 4.2.1 + espree@11.2.0: + dependencies: + acorn: 8.16.0 + acorn-jsx: 5.3.2(acorn@8.16.0) + eslint-visitor-keys: 5.0.1 + esprima@4.0.1: {} - esquery@1.6.0: + esquery@1.7.0: dependencies: estraverse: 5.3.0 @@ -4062,6 +4428,10 @@ snapshots: dependencies: pend: 1.2.0 + fdir@6.5.0(picomatch@4.0.4): + optionalDependencies: + picomatch: 4.0.4 + fetch-blob@3.2.0: dependencies: node-domexception: 1.0.0 @@ -4070,9 +4440,9 @@ snapshots: fflate@0.8.2: {} - file-entry-cache@10.1.4: + file-entry-cache@11.1.2: dependencies: - flat-cache: 6.1.19 + flat-cache: 6.1.22 file-entry-cache@8.0.0: dependencies: @@ -4092,23 +4462,20 @@ snapshots: flatted: 3.3.3 keyv: 4.5.4 - flat-cache@6.1.19: + flat-cache@6.1.22: dependencies: - cacheable: 2.2.0 - flatted: 3.3.3 - hookified: 1.13.0 + cacheable: 2.3.4 + flatted: 3.4.2 + hookified: 1.15.1 flatted@3.3.3: {} + flatted@3.4.2: {} + for-each@0.3.5: dependencies: is-callable: 1.2.7 - foreground-child@3.3.1: - dependencies: - cross-spawn: 7.0.6 - signal-exit: 4.1.0 - fs-extra@11.3.0: dependencies: graceful-fs: 4.2.11 @@ -4133,6 +4500,8 @@ snapshots: get-caller-file@2.0.5: {} + get-east-asian-width@1.5.0: {} + get-intrinsic@1.3.0: dependencies: call-bind-apply-helpers: 1.0.2 @@ -4184,14 +4553,11 @@ snapshots: dependencies: is-glob: 4.0.3 - glob@11.0.3: + glob@13.0.6: dependencies: - foreground-child: 3.3.1 - jackspeak: 4.1.1 - minimatch: 10.0.3 - minipass: 7.1.2 - package-json-from-dist: 1.0.1 - path-scurry: 2.0.0 + minimatch: 10.2.5 + minipass: 7.1.3 + path-scurry: 2.0.2 global-modules@2.0.0: dependencies: @@ -4209,21 +4575,19 @@ snapshots: kind-of: 6.0.3 which: 4.0.0 - globals@14.0.0: {} - globalthis@1.0.4: dependencies: define-properties: 1.2.1 gopd: 1.2.0 - globby@11.1.0: + globby@16.2.0: dependencies: - array-union: 2.1.0 - dir-glob: 3.0.1 + '@sindresorhus/merge-streams': 4.0.0 fast-glob: 3.3.3 - ignore: 5.3.1 - merge2: 1.4.1 - slash: 3.0.0 + ignore: 7.0.5 + is-path-inside: 4.0.0 + slash: 5.1.0 + unicorn-magic: 0.4.0 globjoin@0.1.4: {} @@ -4231,14 +4595,14 @@ snapshots: graceful-fs@4.2.11: {} - graphemer@1.4.0: {} - has-bigints@1.0.2: {} has-flag@3.0.0: {} has-flag@4.0.0: {} + has-flag@5.0.1: {} + has-property-descriptors@1.0.2: dependencies: es-define-property: 1.0.1 @@ -4253,9 +4617,9 @@ snapshots: dependencies: has-symbols: 1.1.0 - hashery@1.2.0: + hashery@1.5.1: dependencies: - hookified: 1.13.0 + hookified: 1.15.1 hasown@2.0.2: dependencies: @@ -4263,7 +4627,9 @@ snapshots: highlight.js@11.11.1: {} - hookified@1.13.0: {} + hookified@1.15.1: {} + + hookified@2.1.1: {} html-minifier-terser@7.2.0: dependencies: @@ -4275,7 +4641,7 @@ snapshots: relateurl: 0.2.7 terser: 5.39.0 - html-tags@3.3.1: {} + html-tags@5.1.0: {} http-proxy-agent@7.0.2: dependencies: @@ -4295,8 +4661,6 @@ snapshots: ignore@5.3.1: {} - ignore@7.0.3: {} - ignore@7.0.5: {} import-fresh@3.3.1: @@ -4304,6 +4668,8 @@ snapshots: parent-module: 1.0.1 resolve-from: 4.0.0 + import-meta-resolve@4.2.0: {} + imurmurhash@0.1.4: {} ini@1.3.8: {} @@ -4393,6 +4759,8 @@ snapshots: is-number@7.0.0: {} + is-path-inside@4.0.0: {} + is-plain-object@5.0.0: {} is-regex@1.2.1: @@ -4449,10 +4817,6 @@ snapshots: has-symbols: 1.1.0 set-function-name: 2.0.2 - jackspeak@4.1.1: - dependencies: - '@isaacs/cliui': 8.0.2 - js-tokens@4.0.0: {} js-yaml@4.1.0: @@ -4500,14 +4864,12 @@ snapshots: dependencies: json-buffer: 3.0.1 - keyv@5.5.4: + keyv@5.6.0: dependencies: '@keyv/serialize': 1.1.1 kind-of@6.0.3: {} - known-css-properties@0.37.0: {} - levn@0.4.1: dependencies: prelude-ls: 1.2.1 @@ -4519,8 +4881,6 @@ snapshots: dependencies: p-locate: 5.0.0 - lodash.merge@4.6.2: {} - lodash.truncate@4.4.2: {} loose-envify@1.4.0: @@ -4531,7 +4891,7 @@ snapshots: dependencies: tslib: 2.6.2 - lru-cache@11.2.1: {} + lru-cache@11.3.5: {} lru-cache@7.18.3: {} @@ -4539,11 +4899,15 @@ snapshots: math-intrinsics@1.1.0: {} - mathml-tag-names@2.1.3: {} + mathml-tag-names@4.0.0: {} + + mdn-data@2.0.28: {} mdn-data@2.12.2: {} - meow@13.2.0: {} + mdn-data@2.27.1: {} + + meow@14.1.0: {} merge2@1.4.1: {} @@ -4552,9 +4916,9 @@ snapshots: braces: 3.0.3 picomatch: 2.3.1 - minimatch@10.0.3: + minimatch@10.2.5: dependencies: - '@isaacs/brace-expansion': 5.0.0 + brace-expansion: 5.0.5 minimatch@3.1.2: dependencies: @@ -4570,15 +4934,15 @@ snapshots: minimist@1.2.8: {} - minipass@7.1.2: {} + minipass@7.1.3: {} mitt@3.0.1: {} moment@2.30.1: {} - monaco-editor@0.54.0: + monaco-editor@0.55.1: dependencies: - dompurify: 3.1.7 + dompurify: 3.2.7 marked: 14.0.0 ms@2.1.3: {} @@ -4605,6 +4969,10 @@ snapshots: normalize-path@3.0.0: {} + nth-check@2.1.1: + dependencies: + boolbase: 1.0.0 + object-assign@4.1.1: {} object-inspect@1.13.4: {} @@ -4696,8 +5064,6 @@ snapshots: degenerator: 5.0.1 netmask: 2.0.2 - package-json-from-dist@1.0.1: {} - pako@1.0.11: {} param-case@3.0.4: @@ -4727,12 +5093,10 @@ snapshots: path-parse@1.0.7: {} - path-scurry@2.0.0: + path-scurry@2.0.2: dependencies: - lru-cache: 11.2.1 - minipass: 7.1.2 - - path-type@4.0.0: {} + lru-cache: 11.3.5 + minipass: 7.1.3 pend@1.2.0: {} @@ -4742,22 +5106,22 @@ snapshots: picomatch@4.0.3: {} + picomatch@4.0.4: {} + possible-typed-array-names@1.1.0: {} - postcss-resolve-nested-selector@0.1.6: {} - - postcss-safe-parser@7.0.1(postcss@8.5.6): + postcss-safe-parser@7.0.1(postcss@8.5.10): dependencies: - postcss: 8.5.6 + postcss: 8.5.10 - postcss-selector-parser@7.1.0: + postcss-selector-parser@7.1.1: dependencies: cssesc: 3.0.0 util-deprecate: 1.0.2 postcss-value-parser@4.2.0: {} - postcss@8.5.6: + postcss@8.5.10: dependencies: nanoid: 3.3.11 picocolors: 1.1.1 @@ -4795,15 +5159,15 @@ snapshots: punycode@2.3.1: {} - puppeteer-core@24.30.0: + puppeteer-core@24.41.0: dependencies: - '@puppeteer/browsers': 2.10.13 - chromium-bidi: 11.0.0(devtools-protocol@0.0.1521046) + '@puppeteer/browsers': 2.13.0 + chromium-bidi: 14.0.0(devtools-protocol@0.0.1595872) debug: 4.4.3 - devtools-protocol: 0.0.1521046 - typed-query-selector: 2.12.0 - webdriver-bidi-protocol: 0.3.8 - ws: 8.18.3 + devtools-protocol: 0.0.1595872 + typed-query-selector: 2.12.1 + webdriver-bidi-protocol: 0.4.1 + ws: 8.20.0 transitivePeerDependencies: - bare-buffer - bufferutil @@ -4812,9 +5176,9 @@ snapshots: q@1.5.1: {} - qified@0.5.2: + qified@0.9.1: dependencies: - hookified: 1.13.0 + hookified: 2.1.1 queue-microtask@1.2.3: {} @@ -4848,8 +5212,6 @@ snapshots: resolve-from@4.0.0: {} - resolve-from@5.0.0: {} - resolve-pkg-maps@1.0.0: {} resolve@1.22.11: @@ -4895,14 +5257,16 @@ snapshots: es-errors: 1.3.0 is-regex: 1.2.1 + sax@1.6.0: {} + semver@6.3.1: {} semver@7.7.1: {} - semver@7.7.2: {} - semver@7.7.3: {} + semver@7.7.4: {} + set-function-length@1.2.2: dependencies: define-data-property: 1.1.4 @@ -4961,7 +5325,7 @@ snapshots: signal-exit@4.1.0: {} - slash@3.0.0: {} + slash@5.1.0: {} slice-ansi@4.0.0: dependencies: @@ -4995,7 +5359,7 @@ snapshots: sprintf-js@1.1.3: {} - standalone-electron-types@34.2.0: + standalone-electron-types@41.2.1: dependencies: '@types/node': 22.13.13 @@ -5017,10 +5381,9 @@ snapshots: is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 - string-width@5.1.2: + string-width@8.2.0: dependencies: - eastasianwidth: 0.2.0 - emoji-regex: 9.2.2 + get-east-asian-width: 1.5.0 strip-ansi: 7.1.2 string.prototype.matchall@4.0.12: @@ -5077,61 +5440,59 @@ snapshots: strip-bom@3.0.0: {} - strip-json-comments@3.1.1: {} - - stylelint-config-recommended@17.0.0(stylelint@16.25.0(typescript@5.9.3)): + stylelint-config-recommended@18.0.0(stylelint@17.8.0(typescript@6.0.2)): dependencies: - stylelint: 16.25.0(typescript@5.9.3) + stylelint: 17.8.0(typescript@6.0.2) - stylelint-config-standard@39.0.1(stylelint@16.25.0(typescript@5.9.3)): + stylelint-config-standard@40.0.0(stylelint@17.8.0(typescript@6.0.2)): dependencies: - stylelint: 16.25.0(typescript@5.9.3) - stylelint-config-recommended: 17.0.0(stylelint@16.25.0(typescript@5.9.3)) + stylelint: 17.8.0(typescript@6.0.2) + stylelint-config-recommended: 18.0.0(stylelint@17.8.0(typescript@6.0.2)) - stylelint@16.25.0(typescript@5.9.3): + stylelint@17.8.0(typescript@6.0.2): dependencies: - '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) - '@csstools/css-tokenizer': 3.0.4 - '@csstools/media-query-list-parser': 4.0.3(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - '@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.1.0) - '@dual-bundle/import-meta-resolve': 4.2.1 - balanced-match: 2.0.0 + '@csstools/css-calc': 3.2.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) + '@csstools/css-syntax-patches-for-csstree': 1.1.3(css-tree@3.2.1) + '@csstools/css-tokenizer': 4.0.0 + '@csstools/media-query-list-parser': 5.0.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + '@csstools/selector-resolve-nested': 4.0.0(postcss-selector-parser@7.1.1) + '@csstools/selector-specificity': 6.0.0(postcss-selector-parser@7.1.1) colord: 2.9.3 - cosmiconfig: 9.0.0(typescript@5.9.3) - css-functions-list: 3.2.3 - css-tree: 3.1.0 + cosmiconfig: 9.0.1(typescript@6.0.2) + css-functions-list: 3.3.3 + css-tree: 3.2.1 debug: 4.4.3 fast-glob: 3.3.3 fastest-levenshtein: 1.0.16 - file-entry-cache: 10.1.4 + file-entry-cache: 11.1.2 global-modules: 2.0.0 - globby: 11.1.0 + globby: 16.2.0 globjoin: 0.1.4 - html-tags: 3.3.1 + html-tags: 5.1.0 ignore: 7.0.5 - imurmurhash: 0.1.4 + import-meta-resolve: 4.2.0 is-plain-object: 5.0.0 - known-css-properties: 0.37.0 - mathml-tag-names: 2.1.3 - meow: 13.2.0 + mathml-tag-names: 4.0.0 + meow: 14.1.0 micromatch: 4.0.8 normalize-path: 3.0.0 picocolors: 1.1.1 - postcss: 8.5.6 - postcss-resolve-nested-selector: 0.1.6 - postcss-safe-parser: 7.0.1(postcss@8.5.6) - postcss-selector-parser: 7.1.0 + postcss: 8.5.10 + postcss-safe-parser: 7.0.1(postcss@8.5.10) + postcss-selector-parser: 7.1.1 postcss-value-parser: 4.2.0 - resolve-from: 5.0.0 - string-width: 4.2.3 - supports-hyperlinks: 3.2.0 + string-width: 8.2.0 + supports-hyperlinks: 4.4.0 svg-tags: 1.0.0 table: 6.9.0 - write-file-atomic: 5.0.1 + write-file-atomic: 7.0.1 transitivePeerDependencies: - supports-color - typescript + supports-color@10.2.2: {} + supports-color@5.5.0: dependencies: has-flag: 3.0.0 @@ -5140,15 +5501,25 @@ snapshots: dependencies: has-flag: 4.0.0 - supports-hyperlinks@3.2.0: + supports-hyperlinks@4.4.0: dependencies: - has-flag: 4.0.0 - supports-color: 7.2.0 + has-flag: 5.0.1 + supports-color: 10.2.2 supports-preserve-symlinks-flag@1.0.0: {} svg-tags@1.0.0: {} + svgo@4.0.1: + dependencies: + commander: 11.1.0 + css-select: 5.2.2 + css-tree: 3.1.0 + css-what: 6.2.2 + csso: 5.0.5 + picocolors: 1.1.1 + sax: 1.6.0 + table@6.9.0: dependencies: ajv: 8.17.1 @@ -5186,13 +5557,18 @@ snapshots: dependencies: b4a: 1.6.6 + tinyglobby@0.2.16: + dependencies: + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 - ts-api-utils@2.1.0(typescript@5.9.3): + ts-api-utils@2.5.0(typescript@6.0.2): dependencies: - typescript: 5.9.3 + typescript: 6.0.2 ts-patch@3.3.0: dependencies: @@ -5205,6 +5581,8 @@ snapshots: ts-pattern@5.6.2: {} + ts-pattern@5.9.0: {} + tsconfig-paths@3.15.0: dependencies: '@types/json5': 0.0.29 @@ -5223,9 +5601,9 @@ snapshots: optionalDependencies: fsevents: 2.3.3 - tsx@4.20.6: + tsx@4.21.0: dependencies: - esbuild: 0.25.1 + esbuild: 0.27.0 get-tsconfig: 4.10.0 optionalDependencies: fsevents: 2.3.3 @@ -5238,7 +5616,7 @@ snapshots: type-fest@4.41.0: {} - type-fest@5.2.0: + type-fest@5.5.0: dependencies: tagged-tag: 1.0.0 @@ -5275,25 +5653,25 @@ snapshots: possible-typed-array-names: 1.1.0 reflect.getprototypeof: 1.0.10 - typed-query-selector@2.12.0: {} + typed-query-selector@2.12.1: {} - typescript-eslint@8.47.0(eslint@9.39.1)(typescript@5.9.3): + typescript-eslint@8.58.2(eslint@10.2.0)(typescript@6.0.2): dependencies: - '@typescript-eslint/eslint-plugin': 8.47.0(@typescript-eslint/parser@8.47.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3) - '@typescript-eslint/parser': 8.47.0(eslint@9.39.1)(typescript@5.9.3) - '@typescript-eslint/typescript-estree': 8.47.0(typescript@5.9.3) - '@typescript-eslint/utils': 8.47.0(eslint@9.39.1)(typescript@5.9.3) - eslint: 9.39.1 - typescript: 5.9.3 + '@typescript-eslint/eslint-plugin': 8.58.2(@typescript-eslint/parser@8.58.2(eslint@10.2.0)(typescript@6.0.2))(eslint@10.2.0)(typescript@6.0.2) + '@typescript-eslint/parser': 8.58.2(eslint@10.2.0)(typescript@6.0.2) + '@typescript-eslint/typescript-estree': 8.58.2(typescript@6.0.2) + '@typescript-eslint/utils': 8.58.2(eslint@10.2.0)(typescript@6.0.2) + eslint: 10.2.0 + typescript: 6.0.2 transitivePeerDependencies: - supports-color - typescript-transform-paths@3.5.5(typescript@5.9.3): + typescript-transform-paths@3.5.6(typescript@6.0.2): dependencies: minimatch: 9.0.5 - typescript: 5.9.3 + typescript: 6.0.2 - typescript@5.9.3: {} + typescript@6.0.2: {} unbox-primitive@1.1.0: dependencies: @@ -5304,7 +5682,9 @@ snapshots: undici-types@6.20.0: {} - undici-types@7.16.0: {} + undici-types@7.19.2: {} + + unicorn-magic@0.4.0: {} universalify@2.0.1: {} @@ -5325,7 +5705,7 @@ snapshots: web-streams-polyfill@3.3.3: optional: true - webdriver-bidi-protocol@0.3.8: {} + webdriver-bidi-protocol@0.4.1: {} which-boxed-primitive@1.1.1: dependencies: @@ -5398,23 +5778,18 @@ snapshots: string-width: 4.2.3 strip-ansi: 6.0.1 - wrap-ansi@8.1.0: - dependencies: - ansi-styles: 6.2.3 - string-width: 5.1.2 - strip-ansi: 7.1.2 - wrappy@1.0.2: {} - write-file-atomic@5.0.1: + write-file-atomic@7.0.1: dependencies: - imurmurhash: 0.1.4 signal-exit: 4.1.0 - ws@8.18.3: {} + ws@8.20.0: {} y18n@5.0.8: {} + yaml-js@0.3.1: {} + yargs-parser@21.1.1: {} yargs@17.7.2: diff --git a/scripts/build/build.mjs b/scripts/build/build.mjs index 748553645..b722e5837 100644 --- a/scripts/build/build.mjs +++ b/scripts/build/build.mjs @@ -77,7 +77,7 @@ const globNativesPlugin = { }); build.onLoad({ filter, namespace: "import-natives" }, async () => { - const pluginDirs = ["plugins", "userplugins", "equicordplugins"]; + const pluginDirs = ["plugins", "equicordplugins", "userplugins"]; let code = ""; let natives = "\n"; let i = 0; diff --git a/scripts/build/common.mjs b/scripts/build/common.mjs index 3db6ba7ac..159404783 100644 --- a/scripts/build/common.mjs +++ b/scripts/build/common.mjs @@ -147,7 +147,7 @@ export const globPlugins = kind => ({ }); build.onLoad({ filter, namespace: "import-plugins" }, async () => { - const pluginDirs = ["plugins/_api", "plugins/_core", "plugins", "userplugins", "equicordplugins", "equicordplugins/_api"]; + const pluginDirs = ["plugins/_api", "plugins/_core", "plugins", "equicordplugins", "equicordplugins/_api", "userplugins"]; let code = ""; let pluginsCode = "\n"; let metaCode = "\n"; diff --git a/scripts/utils.ts b/scripts/utils.ts index 0d2357ed9..1e1dbd863 100644 --- a/scripts/utils.ts +++ b/scripts/utils.ts @@ -38,6 +38,7 @@ export interface PluginData { name: string; description: string; tags: string[]; + searchTerms: string[]; authors: Dev[]; dependencies: string[]; hasPatches: boolean; @@ -185,7 +186,8 @@ export async function parseFile(fileName: string) { enabledByDefault: false, required: false, isModified: false, - tags: [] as string[] + tags: [] as string[], + searchTerms: [] as string[], } as PluginData; for (const prop of pluginObj.properties) { @@ -244,9 +246,10 @@ export async function parseFile(fileName: string) { }); break; case "tags": - if (!isArrayLiteralExpression(value)) throw fail("tags is not an array literal"); - data.tags = value.elements.map(e => { - if (!isStringLiteral(e)) throw fail("tags array contains non-string literals"); + case "searchTerms": + if (!isArrayLiteralExpression(value)) throw fail(`${key} is not an array literal`); + data[key] = value.elements.map(e => { + if (!isStringLiteral(e)) throw fail(`${key} array contains non-string literals`); return e.text; }); break; diff --git a/src/api/AudioPlayer.ts b/src/api/AudioPlayer.ts index 53d6c0614..d106d26b8 100644 --- a/src/api/AudioPlayer.ts +++ b/src/api/AudioPlayer.ts @@ -4,7 +4,7 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -import { findByCodeLazy, findLazy } from "webpack"; +import { findByCodeLazy, findLazy } from "@webpack"; let defaultSounds: null | string[] = null; const findDefaultSounds = findLazy(module => module.resolve && module.id && module.keys().some(key => key.endsWith(".mp3")), false); diff --git a/src/api/DataStore/index.ts b/src/api/DataStore/index.ts index 3cdb50c7e..80ebb065f 100644 --- a/src/api/DataStore/index.ts +++ b/src/api/DataStore/index.ts @@ -18,97 +18,31 @@ * limitations under the License. */ -import { Logger } from "@utils/Logger"; - -const logger = new Logger("DataStore"); -let loggedFailure = false; -const memoryDatabases = new Map>>(); - -interface MemoryStore { - __memoryStore: true; - get(key: IDBValidKey): T | undefined; - put(value: unknown, key: IDBValidKey): void; - delete(key: IDBValidKey): void; - clear(): void; - getAllKeys(): KeyType[]; - getAll(): T[]; - entries(): [KeyType, ValueType][]; -} - -type StoreLike = IDBObjectStore | MemoryStore; - -function handleFailure(error: unknown) { - if (loggedFailure) return; - loggedFailure = true; - logger.error("IndexedDB unavailable, using empty storage.", error); -} - -function withFailureFallback(promise: Promise, fallback: T): Promise { - return promise.catch(error => { - handleFailure(error); - return fallback; - }); -} - -function getMemoryStore(dbName: string, storeName: string): MemoryStore { - let database = memoryDatabases.get(dbName); - if (!database) { - database = new Map(); - memoryDatabases.set(dbName, database); - } - - let data = database.get(storeName); - if (!data) { - data = new Map(); - database.set(storeName, data); - } - - return { - __memoryStore: true, - get: (key: IDBValidKey) => data.get(key) as T | undefined, - put: (value, key) => { data.set(key, value); }, - delete: key => { data.delete(key); }, - clear: () => { data.clear(); }, - getAllKeys: () => Array.from(data.keys()) as KeyType[], - getAll: () => Array.from(data.values()) as T[], - entries: () => Array.from(data.entries()) as [KeyType, ValueType][] - }; -} - -function isMemoryStore(store: StoreLike): store is MemoryStore { - return "__memoryStore" in store; -} - export function promisifyRequest( request: IDBRequest | IDBTransaction, ): Promise { return new Promise((resolve, reject) => { - const target = request as IDBRequest & IDBTransaction; - target.oncomplete = target.onsuccess = () => resolve(target.result); - target.onabort = target.onerror = () => reject(target.error); + // @ts-expect-error - file size hacks + request.oncomplete = request.onsuccess = () => resolve(request.result); + // @ts-expect-error - file size hacks + request.onabort = request.onerror = () => reject(request.error); }); } export function createStore(dbName: string, storeName: string): UseStore { const request = indexedDB.open(dbName); request.onupgradeneeded = () => request.result.createObjectStore(storeName); - const dbp = promisifyRequest(request).catch(error => { - handleFailure(error); - return null; - }); - const memoryStore = getMemoryStore(dbName, storeName); + const dbp = promisifyRequest(request); - return async (txMode, callback) => { - const db = await dbp; - if (!db) return callback(memoryStore); - - return callback(db.transaction(storeName, txMode).objectStore(storeName)); - }; + return (txMode, callback) => + dbp.then(db => + callback(db.transaction(storeName, txMode).objectStore(storeName)), + ); } export type UseStore = ( txMode: IDBTransactionMode, - callback: (store: StoreLike) => T | PromiseLike, + callback: (store: IDBObjectStore) => T | PromiseLike, ) => Promise; let defaultGetStoreFunc: UseStore | undefined; @@ -120,68 +54,88 @@ function defaultGetStore() { return defaultGetStoreFunc; } +/** + * Get a value by its key. + * + * @param key + * @param customStore Method to get a custom store. Use with caution (see the docs). + */ export function get( key: IDBValidKey, customStore = defaultGetStore(), ): Promise { - return withFailureFallback(customStore("readonly", store => { - if (isMemoryStore(store)) return store.get(key) as T | undefined; - return promisifyRequest(store.get(key)); - }), undefined); + return customStore("readonly", store => promisifyRequest(store.get(key))); } +/** + * Set a value with a key. + * + * @param key + * @param value + * @param customStore Method to get a custom store. Use with caution (see the docs). + */ export function set( key: IDBValidKey, value: any, customStore = defaultGetStore(), ): Promise { - return withFailureFallback(customStore("readwrite", store => { + return customStore("readwrite", store => { store.put(value, key); - if (isMemoryStore(store)) return; - return promisifyRequest(store.transaction); - }), undefined); + }); } +/** + * Set multiple values at once. This is faster than calling set() multiple times. + * It's also atomic – if one of the pairs can't be added, none will be added. + * + * @param entries Array of entries, where each entry is an array of `[key, value]`. + * @param customStore Method to get a custom store. Use with caution (see the docs). + */ export function setMany( entries: [IDBValidKey, any][], customStore = defaultGetStore(), ): Promise { - return withFailureFallback(customStore("readwrite", store => { + return customStore("readwrite", store => { entries.forEach(entry => store.put(entry[1], entry[0])); - if (isMemoryStore(store)) return; - return promisifyRequest(store.transaction); - }), undefined); + }); } +/** + * Get multiple values by their keys + * + * @param keys + * @param customStore Method to get a custom store. Use with caution (see the docs). + */ export function getMany( keys: IDBValidKey[], customStore = defaultGetStore(), ): Promise { - return withFailureFallback(customStore("readonly", store => { - if (isMemoryStore(store)) { - return keys.map(key => store.get(key) as T | undefined); - } - - return Promise.all(keys.map(key => promisifyRequest(store.get(key)))); - }), []); + return customStore("readonly", store => + Promise.all(keys.map(key => promisifyRequest(store.get(key)))), + ); } +/** + * Update a value. This lets you see the old value and update it as an atomic operation. + * + * @param key + * @param updater A callback that takes the old value and returns a new value. + * @param customStore Method to get a custom store. Use with caution (see the docs). + */ export function update( key: IDBValidKey, updater: (oldValue: T | undefined) => T, customStore = defaultGetStore(), ): Promise { - return withFailureFallback(customStore( + return customStore( "readwrite", - store => { - if (isMemoryStore(store)) { - store.put(updater(store.get(key) as T | undefined), key); - return; - } - - return new Promise((resolve, reject) => { + store => + // Need to create the promise manually. + // If I try to chain promises, the transaction closes in browsers + // that use a promise polyfill (IE10/11). + new Promise((resolve, reject) => { store.get(key).onsuccess = function () { try { store.put(updater(this.result), key); @@ -190,42 +144,52 @@ export function update( reject(err); } }; - }); - }, - ), undefined); + }), + ); } +/** + * Delete a particular key from the store. + * + * @param key + * @param customStore Method to get a custom store. Use with caution (see the docs). + */ export function del( key: IDBValidKey, customStore = defaultGetStore(), ): Promise { - return withFailureFallback(customStore("readwrite", store => { + return customStore("readwrite", store => { store.delete(key); - if (isMemoryStore(store)) return; - return promisifyRequest(store.transaction); - }), undefined); + }); } +/** + * Delete multiple keys at once. + * + * @param keys List of keys to delete. + * @param customStore Method to get a custom store. Use with caution (see the docs). + */ export function delMany( keys: IDBValidKey[], customStore = defaultGetStore(), ): Promise { - return withFailureFallback(customStore("readwrite", store => { - keys.forEach(key => store.delete(key)); - if (isMemoryStore(store)) return; - + return customStore("readwrite", (store: IDBObjectStore) => { + keys.forEach((key: IDBValidKey) => store.delete(key)); return promisifyRequest(store.transaction); - }), undefined); + }); } +/** + * Clear all values in the store. + * + * @param customStore Method to get a custom store. Use with caution (see the docs). + */ export function clear(customStore = defaultGetStore()): Promise { - return withFailureFallback(customStore("readwrite", store => { + return customStore("readwrite", store => { store.clear(); - if (isMemoryStore(store)) return; - return promisifyRequest(store.transaction); - }), undefined); + }); } function eachCursor( @@ -240,12 +204,16 @@ function eachCursor( return promisifyRequest(store.transaction); } +/** + * Get all keys in the store. + * + * @param customStore Method to get a custom store. Use with caution (see the docs). + */ export function keys( customStore = defaultGetStore(), ): Promise { - return withFailureFallback(customStore("readonly", store => { - if (isMemoryStore(store)) return store.getAllKeys(); - + return customStore("readonly", store => { + // Fast path for modern browsers if (store.getAllKeys) { return promisifyRequest( store.getAllKeys() as unknown as IDBRequest, @@ -253,45 +221,59 @@ export function keys( } const items: KeyType[] = []; + return eachCursor(store, cursor => items.push(cursor.key as KeyType), ).then(() => items); - }), [] as KeyType[]); + }); } +/** + * Get all values in the store. + * + * @param customStore Method to get a custom store. Use with caution (see the docs). + */ export function values(customStore = defaultGetStore()): Promise { - return withFailureFallback(customStore("readonly", store => { - if (isMemoryStore(store)) return store.getAll(); - + return customStore("readonly", store => { + // Fast path for modern browsers if (store.getAll) { return promisifyRequest(store.getAll() as IDBRequest); } const items: T[] = []; + return eachCursor(store, cursor => items.push(cursor.value as T)).then( () => items, ); - }), [] as T[]); + }); } +/** + * Get all entries in the store. Each entry is an array of `[key, value]`. + * + * @param customStore Method to get a custom store. Use with caution (see the docs). + */ export function entries( customStore = defaultGetStore(), ): Promise<[KeyType, ValueType][]> { - return withFailureFallback(customStore("readonly", store => { - if (isMemoryStore(store)) return store.entries(); - + return customStore("readonly", store => { + // Fast path for modern browsers + // (although, hopefully we'll get a simpler path some day) if (store.getAll && store.getAllKeys) { return Promise.all([ promisifyRequest( store.getAllKeys() as unknown as IDBRequest, ), promisifyRequest(store.getAll() as IDBRequest), - ]).then(([keys, values]) => keys.map((key, i) => [key, values[i]] as [KeyType, ValueType])); + ]).then(([keys, values]) => keys.map((key, i) => [key, values[i]])); } const items: [KeyType, ValueType][] = []; - return eachCursor(store, cursor => - items.push([cursor.key as KeyType, cursor.value]), - ).then(() => items); - }), [] as [KeyType, ValueType][]); + + return customStore("readonly", store => + eachCursor(store, cursor => + items.push([cursor.key as KeyType, cursor.value]), + ).then(() => items), + ); + }); } diff --git a/src/api/PluginManager.ts b/src/api/PluginManager.ts index 4e60323b9..e7c245ca5 100644 --- a/src/api/PluginManager.ts +++ b/src/api/PluginManager.ts @@ -28,6 +28,7 @@ import { addMessagePopoverButton, removeMessagePopoverButton } from "@api/Messag import { addNicknameIcon, removeNicknameIcon } from "@api/NicknameIcons"; import { Settings, SettingsStore } from "@api/Settings"; import { disableStyle, enableStyle } from "@api/Styles"; +import { traceFunction } from "@debug/Tracer"; import { Logger } from "@utils/Logger"; import { onlyOnce } from "@utils/onlyOnce"; import { canonicalizeFind, canonicalizeReplacement } from "@utils/patches"; @@ -39,7 +40,6 @@ import { patches } from "@webpack/patcher"; import Plugins from "~plugins"; export { Plugins as plugins }; -import { traceFunction } from "../debug/Tracer"; import { addAudioProcessor, removeAudioProcessor } from "./AudioPlayer"; import { addChannelToolbarButton, addHeaderBarButton, removeChannelToolbarButton, removeHeaderBarButton } from "./HeaderBar"; import { addProfileCollection, removeProfileCollection } from "./ProfileCollections"; diff --git a/src/components/CheckedTextInput.tsx b/src/components/CheckedTextInput.tsx index 027dd51fa..cb2015f94 100644 --- a/src/components/CheckedTextInput.tsx +++ b/src/components/CheckedTextInput.tsx @@ -16,13 +16,13 @@ * along with this program. If not, see . */ -import { React, TextInput } from "@webpack/common"; +import { React, TextInput, useState } from "@webpack/common"; interface TextInputProps { /** * WARNING: Changing this between renders will have no effect! */ - value: string; + initialValue: string; /** * This will only be called if the new value passed validate() */ @@ -41,13 +41,15 @@ interface TextInputProps { * A very simple wrapper around Discord's TextInput that validates input and shows * the user an error message and only calls your onChange when the input is valid */ -export function CheckedTextInput({ value: initialValue, onChange, validate, placeholder }: TextInputProps) { - const [value, setValue] = React.useState(initialValue); - const [error, setError] = React.useState(); +export function CheckedTextInput({ initialValue, onChange, validate, placeholder }: TextInputProps) { + const [value, setValue] = useState(initialValue); + const [error, setError] = useState(); function handleChange(v: string) { setValue(v); + const res = validate(v); + if (res === true) { setError(void 0); onChange(v); diff --git a/src/components/ThemeSettings/components/SettingColorComponent.tsx b/src/components/ThemeSettings/components/SettingColorComponent.tsx index e01228c5f..9f3e00fd2 100644 --- a/src/components/ThemeSettings/components/SettingColorComponent.tsx +++ b/src/components/ThemeSettings/components/SettingColorComponent.tsx @@ -9,6 +9,7 @@ import "./colorStyles.css"; import { classNameFactory } from "@utils/css"; import { findByCodeLazy } from "@webpack"; import { ColorPicker, useMemo } from "@webpack/common"; +import type tinycolor from "tinycolor2"; // TinyColor is completely unmangled and it's duplicated in two modules! Fun! const TinyColor: tinycolor.Constructor = findByCodeLazy("this._gradientType="); diff --git a/src/components/settings/tabs/plugins/PluginCard.tsx b/src/components/settings/tabs/plugins/PluginCard.tsx index 140498249..96d1cb788 100644 --- a/src/components/settings/tabs/plugins/PluginCard.tsx +++ b/src/components/settings/tabs/plugins/PluginCard.tsx @@ -6,13 +6,13 @@ import { showNotice } from "@api/Notices"; import { isPluginEnabled, pluginRequiresRestart, startDependenciesRecursive, startPlugin, stopPlugin } from "@api/PluginManager"; +import { Settings } from "@api/Settings"; import { CogWheel, InfoIcon } from "@components/Icons"; import { AddonCard } from "@components/settings/AddonCard"; import { classNameFactory } from "@utils/css"; import { Logger } from "@utils/Logger"; import { OptionType, Plugin } from "@utils/types"; import { React, showToast, Toasts } from "@webpack/common"; -import { Settings } from "Vencord"; import { PluginMeta } from "~plugins"; diff --git a/src/components/settings/tabs/plugins/PluginModal.css b/src/components/settings/tabs/plugins/PluginModal.css index 90620c665..bdd35c80c 100644 --- a/src/components/settings/tabs/plugins/PluginModal.css +++ b/src/components/settings/tabs/plugins/PluginModal.css @@ -60,5 +60,25 @@ } .vc-plugin-modal-info { + display: flex; + gap: 1em; + justify-content: space-between; + align-items: start; +} + +.vc-plugin-modal-tags { + display: flex; + flex-wrap: wrap; + gap: 4px; + margin-block: 8px 16px; +} + +.vc-plugin-modal-tag { align-items: center; -} \ No newline at end of file + border: 1px solid var(--border-normal); + border-radius: 9999px; + display: flex; + justify-content: center; + padding: 6px 12px; + color: var(--text-default); +} diff --git a/src/components/settings/tabs/plugins/PluginModal.tsx b/src/components/settings/tabs/plugins/PluginModal.tsx index cf3379ee9..177fce95d 100644 --- a/src/components/settings/tabs/plugins/PluginModal.tsx +++ b/src/components/settings/tabs/plugins/PluginModal.tsx @@ -32,7 +32,7 @@ import { proxyLazy } from "@utils/lazy"; import { Margins } from "@utils/margins"; import { classes, isObjectEmpty } from "@utils/misc"; import { ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal"; -import { OptionType, Plugin } from "@utils/types"; +import { OptionType, Plugin, PluginTag } from "@utils/types"; import { User } from "@vencord/discord-types"; import { findComponentByCodeLazy, findCssClassesLazy } from "@webpack"; import { Clickable, FluxDispatcher, React, Toasts, Tooltip, useEffect, useMemo, UserStore, UserSummaryItem, UserUtils, useState } from "@webpack/common"; @@ -74,6 +74,16 @@ export function makeDummyUser(user: { username: string; id?: string; avatar?: st return newUser; } +function PluginTags({ tags }: { tags: PluginTag[]; }) { + return ( +
+ {tags.map(tag => ( +
{tag}
+ ))} +
+ ); +} + export default function PluginModal({ plugin, onRestartNeeded, onClose, transitionState }: PluginModalProps) { const pluginSettings = useSettings([`plugins.${plugin.name}.*`]).plugins[plugin.name]; const hasSettings = Boolean(pluginSettings && plugin.options && !isObjectEmpty(plugin.options)); @@ -167,6 +177,7 @@ export default function PluginModal({ plugin, onRestartNeeded, onClose, transiti
{plugin.name} {plugin.description} + {!!plugin.tags?.length && } {!!plugin.settingsAboutComponent && (
diff --git a/src/components/settings/tabs/plugins/index.tsx b/src/components/settings/tabs/plugins/index.tsx index 877ff18c3..708c46cf6 100644 --- a/src/components/settings/tabs/plugins/index.tsx +++ b/src/components/settings/tabs/plugins/index.tsx @@ -37,7 +37,8 @@ import { Margins } from "@utils/margins"; import { classes } from "@utils/misc"; import { useAwaiter, useIntersection } from "@utils/react"; import { t } from "@utils/translation"; -import { Alerts, lodash, Parser, React, Select, TextInput, Toasts, Tooltip, useCallback, useMemo, useState } from "@webpack/common"; +import { PluginTag, PluginTags } from "@utils/types"; +import { Alerts, lodash, Parser, React, SearchableSelect, Select, TextInput, Toasts, Tooltip, useCallback, useMemo, useRef, useState } from "@webpack/common"; import { JSX } from "react"; import Plugins, { ExcludedPlugins, PluginMeta } from "~plugins"; @@ -144,7 +145,8 @@ function ExcludedPluginsList({ search }: { search: string; }) { export default function PluginSettings() { const settings = useSettings(); - const changes = React.useMemo(() => new ChangeList(), []); + const changeRef = useRef>(null); + const changes = changeRef.current ??= new ChangeList(); React.useEffect(() => { return () => { @@ -195,25 +197,13 @@ export default function PluginSettings() { const hasUserPlugins = useMemo(() => !IS_STANDALONE && Object.values(PluginMeta).some(m => m.userPlugin), []); - const [searchValue, setSearchValue] = useState({ value: "", status: SearchStatus.ALL }); - const [searchInput, setSearchInput] = useState(""); - - const debouncedSetSearch = useMemo( - () => debounce((query: string) => setSearchValue(prev => ({ ...prev, value: query })), 150), - [] - ); + const [searchValue, setSearchValue] = useState({ value: "", tags: [] as PluginTag[], status: SearchStatus.ALL }); const search = searchValue.value.toLowerCase(); - const onSearch = useCallback((query: string) => { - setSearchInput(query); - debouncedSetSearch(query); - }, [debouncedSetSearch]); - const onStatusChange = useCallback((status: SearchStatus) => { - setSearchValue(prev => ({ ...prev, status })); - }, []); + const onSearch = (query: string) => setSearchValue(prev => ({ ...prev, value: query })); const pluginFilter = useCallback((plugin: typeof Plugins[keyof typeof Plugins], newPluginsSet: Set | null) => { - const { status } = searchValue; + const { status, tags } = searchValue; const enabled = isPluginEnabled(plugin.name); switch (status) { @@ -240,12 +230,14 @@ export default function PluginSettings() { break; } + if (tags.length && tags.some(t => !plugin.tags?.includes(t))) return false; + if (!search.length) return true; return ( plugin.name.toLowerCase().includes(search.replace(/\s+/g, "")) || plugin.description.toLowerCase().includes(search) || - plugin.tags?.some(t => t.toLowerCase().includes(search)) + plugin.searchTerms?.some(t => t.toLowerCase().includes(search)) ); }, [searchValue, search]); @@ -407,31 +399,45 @@ export default function PluginSettings() { Filters -
- - - -
- - setSearchValue(prev => ({ ...prev, status }))} + isSelected={v => v === searchValue.status} + closeOnSelect={true} + placeholder="Filter by Type" + /> + ({ label: tag, value: tag }))} + value={searchValue.tags} + onChange={tags => setSearchValue(prev => ({ ...prev, tags }))} + closeOnSelect={false} + placeholder="Filter by Tags" + multi + />
-
+
Plugins @@ -457,6 +463,7 @@ export default function PluginSettings() { Required Plugins +
{requiredPlugins.length ? requiredPlugins diff --git a/src/components/settings/tabs/plugins/styles.css b/src/components/settings/tabs/plugins/styles.css index 27e512395..0f531b126 100644 --- a/src/components/settings/tabs/plugins/styles.css +++ b/src/components/settings/tabs/plugins/styles.css @@ -45,7 +45,12 @@ display: grid; height: 40px; gap: 10px; - grid-template-columns: 1fr 150px; + grid-template-columns: 1fr 1fr; + align-items: center; +} + +.vc-plugins-filter-control { + height: 40px; } .vc-plugins-dep-name { diff --git a/src/components/settings/tabs/sync/CloudTab.tsx b/src/components/settings/tabs/sync/CloudTab.tsx index e848106c8..c66fde69a 100644 --- a/src/components/settings/tabs/sync/CloudTab.tsx +++ b/src/components/settings/tabs/sync/CloudTab.tsx @@ -137,7 +137,7 @@ function CloudTab() {
{ cloud.url = v; cloud.authenticated = false; diff --git a/src/components/settings/tabs/vencord/index.tsx b/src/components/settings/tabs/vencord/index.tsx index 23fde219c..7ef1bf048 100644 --- a/src/components/settings/tabs/vencord/index.tsx +++ b/src/components/settings/tabs/vencord/index.tsx @@ -20,6 +20,7 @@ import { Paragraph } from "@components/Paragraph"; import { openContributorModal, openPluginModal, SettingsTab, wrapTab } from "@components/settings"; import { QuickAction, QuickActionCard } from "@components/settings/QuickAction"; import { SpecialCard } from "@components/settings/SpecialCard"; +import BadgeAPI from "@plugins/_api/badges"; import { gitRemote } from "@shared/vencordUserAgent"; import { DONOR_ROLE_ID, GUILD_ID, IS_MAC, IS_WINDOWS, VC_DONOR_ROLE_ID, VC_GUILD_ID } from "@utils/constants"; import { classNameFactory } from "@utils/css"; @@ -27,8 +28,7 @@ import { Margins } from "@utils/margins"; import { identity, isAnyPluginDev } from "@utils/misc"; import { relaunch } from "@utils/native"; import { t } from "@utils/translation"; -import { GuildMemberStore, React, Select, UserStore } from "@webpack/common"; -import BadgeAPI from "plugins/_api/badges"; +import { Alerts, GuildMemberStore, React, Select, UserStore } from "@webpack/common"; import { DonateButtonComponent } from "./DonateButton"; import { openNotificationSettingsModal } from "./NotificationSettings"; @@ -68,28 +68,28 @@ function EquicordSettings() { warning: { enabled: boolean; message?: string; }; } > = [ - { - key: "useQuickCss", - title: t("vencord.settings.useQuickCss.title"), - description: t("vencord.settings.useQuickCss.description"), - restartRequired: true, - warning: { enabled: false }, - }, - !IS_WEB && { - key: "enableReactDevtools", - title: t("vencord.settings.enableReactDevtools.title"), - description: t("vencord.settings.enableReactDevtools.description"), - restartRequired: true, - warning: { enabled: false }, - }, - (!IS_WEB && !IS_DISCORD_DESKTOP || !IS_WINDOWS) && { - key: "mainWindowFrameless", - title: t("equicord.mainWindowFrameless.title"), - description: t("equicord.mainWindowFrameless.description"), - restartRequired: true, - warning: { enabled: false }, - }, - !IS_WEB && + { + key: "useQuickCss", + title: t("vencord.settings.useQuickCss.title"), + description: t("vencord.settings.useQuickCss.description"), + restartRequired: true, + warning: { enabled: false }, + }, + !IS_WEB && { + key: "enableReactDevtools", + title: t("vencord.settings.enableReactDevtools.title"), + description: t("vencord.settings.enableReactDevtools.description"), + restartRequired: true, + warning: { enabled: false }, + }, + (!IS_WEB && !IS_DISCORD_DESKTOP || !IS_WINDOWS) && { + key: "mainWindowFrameless", + title: t("equicord.mainWindowFrameless.title"), + description: t("equicord.mainWindowFrameless.description"), + restartRequired: true, + warning: { enabled: false }, + }, + !IS_WEB && (!IS_DISCORD_DESKTOP || !IS_WINDOWS ? { key: "frameless", @@ -106,34 +106,34 @@ function EquicordSettings() { warning: { enabled: false }, } ), - !IS_WEB && { - key: "transparent", - title: t("vencord.settings.transparent.title"), - description: t("vencord.settings.transparent.description"), - restartRequired: true, - warning: { - enabled: true, - message: IS_WINDOWS - ? t("vencord.settings.transparent.noteWindows") - : t("vencord.settings.transparent.note"), - }, + !IS_WEB && { + key: "transparent", + title: t("vencord.settings.transparent.title"), + description: t("vencord.settings.transparent.description"), + restartRequired: true, + warning: { + enabled: true, + message: IS_WINDOWS + ? t("vencord.settings.transparent.noteWindows") + : t("vencord.settings.transparent.note"), }, - IS_DISCORD_DESKTOP && { - key: "disableMinSize", - title: t("vencord.settings.disableMinSize.title"), - description: t("vencord.settings.disableMinSize.description"), - restartRequired: true, - warning: { enabled: false }, - }, - !IS_WEB && + }, + IS_DISCORD_DESKTOP && { + key: "disableMinSize", + title: t("vencord.settings.disableMinSize.title"), + description: t("vencord.settings.disableMinSize.description"), + restartRequired: true, + warning: { enabled: false }, + }, + !IS_WEB && IS_WINDOWS && { - key: "winCtrlQ", - title: t("vencord.settings.winCtrlQ.title"), - description: t("vencord.settings.winCtrlQ.description"), - restartRequired: true, - warning: { enabled: false }, - }, - ]; + key: "winCtrlQ", + title: t("vencord.settings.winCtrlQ.title"), + description: t("vencord.settings.winCtrlQ.description"), + restartRequired: true, + warning: { enabled: false }, + }, + ]; return ( @@ -250,7 +250,19 @@ function EquicordSettings() { (settings[s.key] = v)} + onChange={v => { + settings[s.key] = v; + + if (s.restartRequired) { + Alerts.show({ + title: "Restart Required", + body: "A restart is required to apply this change", + confirmText: "Restart now", + cancelText: "Later!", + onConfirm: relaunch + }); + } + }} title={s.title} description={ s.warning.enabled ? ( diff --git a/src/debug/loadLazyChunks.ts b/src/debug/loadLazyChunks.ts index 44e483faf..997e69fa2 100644 --- a/src/debug/loadLazyChunks.ts +++ b/src/debug/loadLazyChunks.ts @@ -9,8 +9,8 @@ import { canonicalizeMatch } from "@utils/patches"; import { ModuleFactory } from "@vencord/discord-types/webpack"; import * as Webpack from "@webpack"; import { wreq } from "@webpack"; +import { AnyModuleFactory } from "@webpack/types"; import pLimit from "p-limit"; -import { AnyModuleFactory } from "webpack"; function getWebpackChunkMap() { const sym = Symbol(); diff --git a/src/debug/reporterData.ts b/src/debug/reporterData.ts index 0fd261c0f..e713521e5 100644 --- a/src/debug/reporterData.ts +++ b/src/debug/reporterData.ts @@ -26,6 +26,7 @@ export interface ReporterData { }; failedWebpack: Record; } + export const reporterData: ReporterData = { failedPatches: { foundNoModule: [], diff --git a/src/equicordplugins/_api/userArea.ts b/src/equicordplugins/_api/userArea.ts index 2db25b8e6..9519f2efc 100644 --- a/src/equicordplugins/_api/userArea.ts +++ b/src/equicordplugins/_api/userArea.ts @@ -23,8 +23,8 @@ export default definePlugin({ find: ".DISPLAY_NAME_STYLES_COACHMARK)", replacement: [ { - match: /(?<=className:(\i)\.\i,style:\i,)children:\[/, - replace: "children:[...$self.renderButtons(arguments[0],$1)," + match: /children:\[(?=.{0,50}accountContainerRef:\i)/, + replace: "children:[...$self.renderButtons(arguments[0])," }, // fix discord weird shrink with extra buttons { diff --git a/src/equicordplugins/altKrispSwitch/index.tsx b/src/equicordplugins/altKrispSwitch/index.tsx index 03ce33068..7c42c3989 100644 --- a/src/equicordplugins/altKrispSwitch/index.tsx +++ b/src/equicordplugins/altKrispSwitch/index.tsx @@ -11,6 +11,7 @@ import definePlugin from "@utils/types"; export default definePlugin({ name: "AltKrispSwitch", description: t("equicord.altKrispSwitch.description"), + tags: ["Customisation", "Voice"], authors: [Devs.newwares], patches: [ { diff --git a/src/equicordplugins/alwaysExpandProfiles/index.ts b/src/equicordplugins/alwaysExpandProfiles/index.ts index 49b3a744c..479590776 100644 --- a/src/equicordplugins/alwaysExpandProfiles/index.ts +++ b/src/equicordplugins/alwaysExpandProfiles/index.ts @@ -12,6 +12,7 @@ import definePlugin from "@utils/types"; export default definePlugin({ name: "AlwaysExpandProfiles", description: t("equicord.alwaysExpandProfiles.description"), + tags: ["Appearance", "Utility"], authors: [Devs.thororen], patches: [ { diff --git a/src/equicordplugins/animalese/index.ts b/src/equicordplugins/animalese/index.ts index 3b299139b..66e401443 100644 --- a/src/equicordplugins/animalese/index.ts +++ b/src/equicordplugins/animalese/index.ts @@ -194,6 +194,7 @@ async function playSound(buffer: AudioBuffer, volume: number) { export default definePlugin({ name: "Animalese", description: t("equicord.animalese.description"), + tags: ["Customisation", "Fun"], authors: [EquicordDevs.ryanamay, EquicordDevs.Mocha], settings, diff --git a/src/equicordplugins/atSomeone/index.ts b/src/equicordplugins/atSomeone/index.ts index 75c830f3d..87f8dde27 100644 --- a/src/equicordplugins/atSomeone/index.ts +++ b/src/equicordplugins/atSomeone/index.ts @@ -14,6 +14,7 @@ export default definePlugin({ name: "AtSomeone", authors: [Devs.Joona], description: t("equicord.atSomeone.description"), + tags: ["Chat", "Fun"], patches: [ { find: ".LAUNCHABLE_APPLICATIONS;", diff --git a/src/equicordplugins/autoZipper/index.ts b/src/equicordplugins/autoZipper/index.ts index 1283d190b..2f8cd0160 100644 --- a/src/equicordplugins/autoZipper/index.ts +++ b/src/equicordplugins/autoZipper/index.ts @@ -210,6 +210,7 @@ function handlePaste(event: ClipboardEvent) { export default definePlugin({ name: "AutoZipper", description: t("equicord.autoZipper.description"), + tags: ["Chat", "Organisation"], authors: [EquicordDevs.SSnowly], settings, diff --git a/src/equicordplugins/bannersEverywhere/index.tsx b/src/equicordplugins/bannersEverywhere/index.tsx index 49aba8199..ba5a83f40 100644 --- a/src/equicordplugins/bannersEverywhere/index.tsx +++ b/src/equicordplugins/bannersEverywhere/index.tsx @@ -45,6 +45,7 @@ const DATASTORE_KEY = "bannersEverywhere"; export default definePlugin({ name: "BannersEverywhere", description: t("equicord.bannersEverywhere.description"), + tags: ["Appearance", "Customisation"], authors: [Devs.ImLvna, Devs.AutumnVN], settings, patches: [ diff --git a/src/equicordplugins/baseDecoder/index.tsx b/src/equicordplugins/baseDecoder/index.tsx index afc4ddf07..41233369d 100644 --- a/src/equicordplugins/baseDecoder/index.tsx +++ b/src/equicordplugins/baseDecoder/index.tsx @@ -108,6 +108,8 @@ const settings = definePluginSettings({ export default definePlugin({ name: "DecodeBase64", description: t("equicord.baseDecoder.description"), + dependencies: ["MessagePopoverAPI"], + tags: ["Appearance", "Customisation", "Chat"], authors: [EquicordDevs.ThePirateStoner], settings, messagePopoverButton: { diff --git a/src/equicordplugins/betterActivities/index.tsx b/src/equicordplugins/betterActivities/index.tsx index 5577441ba..e819d44d9 100644 --- a/src/equicordplugins/betterActivities/index.tsx +++ b/src/equicordplugins/betterActivities/index.tsx @@ -21,7 +21,7 @@ export default definePlugin({ name: "BetterActivities", description: t("equicord.betterActivities.description"), authors: [Devs.D3SOX, Devs.Arjix, Devs.AutumnVN, Devs.thororen], - tags: ["activity"], + tags: ["Activity"], settings, patchActivityList, showAllActivitiesComponent, @@ -46,7 +46,7 @@ export default definePlugin({ // Show all activities in the user popout/sidebar find: /onOpenUserProfileModal:\i,onClose:\i\}\),null/, replacement: { - match: /((\i)=.{0,10}(\i)\.id\).*?,onInteraction:\i\}\),).{0,250}onClose:\i\}\)/, + match: /((\i)=.{0,10}(\i)\.id\).*?,onOpenUserProfileModal:\i\}\),).{0,250}onClose:\i\}\)/, replace: "$1$self.showAllActivitiesComponent({ activity: $2, user: $3 })" }, predicate: () => settings.store.userPopout diff --git a/src/equicordplugins/betterAudioPlayer/index.tsx b/src/equicordplugins/betterAudioPlayer/index.tsx index 7c91c142d..8270e4163 100644 --- a/src/equicordplugins/betterAudioPlayer/index.tsx +++ b/src/equicordplugins/betterAudioPlayer/index.tsx @@ -275,6 +275,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "BetterAudioPlayer", description: t("equicord.betterAudioPlayer.description"), + tags: ["Appearance", "Media", "Voice"], authors: [EquicordDevs.creations], settings, diff --git a/src/equicordplugins/betterBanReasons/index.tsx b/src/equicordplugins/betterBanReasons/index.tsx index 30b257183..a86da0f1a 100644 --- a/src/equicordplugins/betterBanReasons/index.tsx +++ b/src/equicordplugins/betterBanReasons/index.tsx @@ -75,6 +75,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "BetterBanReasons", description: t("equicord.betterBanReasons.description"), + tags: ["Appearance", "Customisation"], authors: [Devs.Inbestigator], patches: [ { diff --git a/src/equicordplugins/betterBlockedUsers/index.tsx b/src/equicordplugins/betterBlockedUsers/index.tsx index 7b1361846..873ecec25 100644 --- a/src/equicordplugins/betterBlockedUsers/index.tsx +++ b/src/equicordplugins/betterBlockedUsers/index.tsx @@ -18,6 +18,7 @@ let updateFunc = (v: any) => { }; export default definePlugin({ name: "BetterBlockedUsers", description: t("equicord.betterBlockedUsers.description"), + tags: ["Appearance", "Shortcuts"], authors: [EquicordDevs.TheArmagan], patches: [ { diff --git a/src/equicordplugins/betterCommands/index.ts b/src/equicordplugins/betterCommands/index.ts index fa1eb4919..315590b6b 100644 --- a/src/equicordplugins/betterCommands/index.ts +++ b/src/equicordplugins/betterCommands/index.ts @@ -34,6 +34,8 @@ function fetchIndex(target: object) { export default definePlugin({ name: "BetterCommands", description: t("equicord.betterCommands.description"), + dependencies: ["CommandsAPI"], + tags: ["Appearance", "Commands", "Shortcuts"], authors: [Devs.thororen], settings, patches: [ diff --git a/src/equicordplugins/betterInvites/index.tsx b/src/equicordplugins/betterInvites/index.tsx index 0c902b6aa..bff8fb6c1 100644 --- a/src/equicordplugins/betterInvites/index.tsx +++ b/src/equicordplugins/betterInvites/index.tsx @@ -35,6 +35,7 @@ function lurk(id: string) { export default definePlugin({ name: "BetterInvites", description: t("equicord.betterInvites.description"), + tags: ["Appearance", "Customisation", "Chat", "Servers"], authors: [EquicordDevs.iamme, Devs.thororen], patches: [ { diff --git a/src/equicordplugins/betterPlusReacts/index.ts b/src/equicordplugins/betterPlusReacts/index.ts index d0f42a5a1..60df1cd97 100644 --- a/src/equicordplugins/betterPlusReacts/index.ts +++ b/src/equicordplugins/betterPlusReacts/index.ts @@ -13,6 +13,7 @@ export default definePlugin({ name: "BetterPlusReacts", authors: [Devs.Joona], description: t("equicord.betterPlusReacts.description"), + tags: ["Chat", "Emotes"], patches: [ { find: ".SLASH_COMMAND_USED,", diff --git a/src/equicordplugins/blockKeywords/index.ts b/src/equicordplugins/blockKeywords/index.ts index 26c5a9906..d4923ba37 100644 --- a/src/equicordplugins/blockKeywords/index.ts +++ b/src/equicordplugins/blockKeywords/index.ts @@ -71,6 +71,7 @@ export function containsBlockedKeywords(message: Message) { export default definePlugin({ name: "BlockKeywords", description: t("equicord.blockKeywords.description"), + tags: ["Appearance", "Customisation", "Privacy"], authors: [EquicordDevs.catcraft], patches: [ { diff --git a/src/equicordplugins/blockKrisp/index.ts b/src/equicordplugins/blockKrisp/index.ts index 7ff05e068..42dbfb6d0 100644 --- a/src/equicordplugins/blockKrisp/index.ts +++ b/src/equicordplugins/blockKrisp/index.ts @@ -11,6 +11,7 @@ import definePlugin from "@utils/types"; export default definePlugin({ name: "BlockKrisp", description: t("equicord.blockKrisp.description"), + tags: ["Privacy", "Utility", "Voice"], authors: [Devs.D3SOX], patches: [ // Block loading modules on Desktop diff --git a/src/equicordplugins/bypassPinPrompt/index.ts b/src/equicordplugins/bypassPinPrompt/index.ts index 867d2d041..755168f3c 100644 --- a/src/equicordplugins/bypassPinPrompt/index.ts +++ b/src/equicordplugins/bypassPinPrompt/index.ts @@ -11,6 +11,7 @@ import definePlugin from "@utils/types"; export default definePlugin({ name: "BypassPinPrompt", description: t("equicord.bypassPinPrompt.description"), + tags: ["Shortcuts"], authors: [Devs.thororen], patches: [ ...[ diff --git a/src/equicordplugins/bypassStatus/index.tsx b/src/equicordplugins/bypassStatus/index.tsx index 3c049491e..be0908789 100644 --- a/src/equicordplugins/bypassStatus/index.tsx +++ b/src/equicordplugins/bypassStatus/index.tsx @@ -158,6 +158,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "BypassStatus", description: t("equicord.bypassStatus.description"), + tags: ["Activity", "Customisation", "Notifications", "Servers"], authors: [Devs.Inbestigator], dependencies: ["AudioPlayerAPI"], flux: { diff --git a/src/equicordplugins/channelBadges/index.tsx b/src/equicordplugins/channelBadges/index.tsx index 4fba2fd6a..ea3a68e15 100644 --- a/src/equicordplugins/channelBadges/index.tsx +++ b/src/equicordplugins/channelBadges/index.tsx @@ -33,6 +33,7 @@ function renderBadge(id: number, title: string) { export default definePlugin({ name: "ChannelBadges", description: t("equicord.channelBadges.description"), + tags: ["Appearance", "Customisation", "Servers"], authors: [EquicordDevs.creations, Devs.thororen], settings, patches: [ diff --git a/src/equicordplugins/channelTabs/index.tsx b/src/equicordplugins/channelTabs/index.tsx index 731c19175..25747e671 100644 --- a/src/equicordplugins/channelTabs/index.tsx +++ b/src/equicordplugins/channelTabs/index.tsx @@ -16,8 +16,8 @@ import { ChannelStore, Menu } from "@webpack/common"; import { JSX } from "react"; import ChannelsTabsContainer from "./components/ChannelTabsContainer"; -import { BasicChannelTabsProps, createTab, handleChannelSwitch, settings } from "./util"; import * as ChannelTabsUtils from "./util"; +import { BasicChannelTabsProps, createTab, handleChannelSwitch, settings } from "./util"; const contextMenuPatch: NavContextMenuPatchCallback = (children, props: { channel: Channel, messageId?: string; }) => { const { channel, messageId } = props; @@ -48,6 +48,7 @@ const contextMenuPatch: NavContextMenuPatchCallback = (children, props: { channe export default definePlugin({ name: "ChannelTabs", description: t("equicord.channelTabs.description"), + tags: ["Appearance", "Customisation", "Organisation", "Servers"], authors: [Devs.TheSun, Devs.TheKodeToad, EquicordDevs.keifufu, Devs.Nickyux, EquicordDevs.DiabeloDEV, EquicordDevs.justjxke], dependencies: ["ContextMenuAPI"], contextMenus: { diff --git a/src/equicordplugins/cleanChannelName/index.ts b/src/equicordplugins/cleanChannelName/index.ts index 35cf48b67..c930fa1a0 100644 --- a/src/equicordplugins/cleanChannelName/index.ts +++ b/src/equicordplugins/cleanChannelName/index.ts @@ -13,6 +13,7 @@ export default definePlugin({ name: "CleanChannelName", authors: [Devs.AutumnVN], description: t("equicord.cleanChannelName.description"), + tags: ["Appearance", "Customisation", "Chat", "Emotes", "Servers"], patches: [ { find: "loadAllGuildAndPrivateChannelsFromDisk(){", diff --git a/src/equicordplugins/cleanerChannelGroups/index.ts b/src/equicordplugins/cleanerChannelGroups/index.ts index fd19fdb0c..23679ad11 100644 --- a/src/equicordplugins/cleanerChannelGroups/index.ts +++ b/src/equicordplugins/cleanerChannelGroups/index.ts @@ -11,6 +11,7 @@ import definePlugin from "@utils/types"; export default definePlugin({ name: "CleanerChannelGroups", description: t("equicord.cleanerChannelGroups.description"), + tags: ["Appearance", "Customisation", "Chat", "Organisation", "Servers"], authors: [EquicordDevs.justjxke], patches: [ { diff --git a/src/equicordplugins/clickableRoles/index.tsx b/src/equicordplugins/clickableRoles/index.tsx index 4e7eb6548..4eacc108e 100644 --- a/src/equicordplugins/clickableRoles/index.tsx +++ b/src/equicordplugins/clickableRoles/index.tsx @@ -159,6 +159,7 @@ const WrappedClickableRole = ErrorBoundary.wrap(ClickableRole, { noop: true }); export default definePlugin({ name: "ClickableRoles", description: t("equicord.clickableRoles.description"), + tags: ["Appearance", "Roles"], authors: [Devs.prism], patches: [ diff --git a/src/equicordplugins/clientSideBlock/index.tsx b/src/equicordplugins/clientSideBlock/index.tsx index 89b6d168d..cae0edd87 100644 --- a/src/equicordplugins/clientSideBlock/index.tsx +++ b/src/equicordplugins/clientSideBlock/index.tsx @@ -143,7 +143,7 @@ function activeNowView(cards) { export default definePlugin({ name: "ClientSideBlock", description: t("equicord.clientSideBlock.description"), - tags: ["blocked", "block", "hide", "hidden", "noblockedmessages"], + tags: ["Utility"], authors: [Devs.Samwich, EquicordDevs.KamiRu], settings, activeNowView, diff --git a/src/equicordplugins/clipsEnhancements.discordDesktop/index.tsx b/src/equicordplugins/clipsEnhancements.discordDesktop/index.tsx index dbdee64cd..5e8c6ae76 100644 --- a/src/equicordplugins/clipsEnhancements.discordDesktop/index.tsx +++ b/src/equicordplugins/clipsEnhancements.discordDesktop/index.tsx @@ -73,6 +73,7 @@ migratePluginSettings("ClipsEnhancements", "TimelessClips"); export default definePlugin({ name: "ClipsEnhancements", description: t("equicord.clipsEnhancements.description"), + tags: ["Activity", "Media", "Utility"], authors: [Devs.niko, Devs.Joona, EquicordDevs.keircn], settings, patches: [ diff --git a/src/equicordplugins/collapsibleUi/index.tsx b/src/equicordplugins/collapsibleUi/index.tsx new file mode 100644 index 000000000..d6c7d709c --- /dev/null +++ b/src/equicordplugins/collapsibleUi/index.tsx @@ -0,0 +1,150 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2026 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import { ChannelToolbarButton } from "@api/HeaderBar"; +import ErrorBoundary from "@components/ErrorBoundary"; +import { EquicordDevs } from "@utils/constants"; +import { classNameFactory } from "@utils/css"; +import { classes } from "@utils/misc"; +import definePlugin from "@utils/types"; +import { ContextMenuApi, Menu } from "@webpack/common"; +import type { ReactNode, SVGProps } from "react"; + +import { PanelId, panelRegistry, settings, toolbarPanelOrder } from "./settings"; +import managedStyle from "./style.css?managed"; + +const cl = classNameFactory("vc-collapsible-ui-"); + +type StateStore = ReturnType; + +function PanelsIcon(props: SVGProps) { + return ( + + + + ); +} + +function getStateClasses(store: StateStore) { + const classNames = [cl("state"), cl(`transition-${store.transitionMs}`)]; + + for (const panelId of toolbarPanelOrder) { + const panel = panelRegistry[panelId]; + if (store[panel.collapsedKey]) classNames.push(cl(`${panel.classId}-collapsed`)); + } + + return classes(...classNames); +} + +function togglePanel(panelId: PanelId) { + const key = panelRegistry[panelId].collapsedKey; + settings.store[key] = !settings.store[key]; +} + +const ToolbarMenu = ErrorBoundary.wrap(({ onClose }: { onClose(): void; }) => { + const store = settings.use(); + + return ( + + {toolbarPanelOrder.map(panelId => { + const panel = panelRegistry[panelId]; + const collapsed = store[panel.collapsedKey]; + + return ( + togglePanel(panelId)} + /> + ); + })} + + ); +}, { noop: true }); + +const ToolbarButtons = ErrorBoundary.wrap(() => { + const store = settings.use(); + const anyCollapsed = toolbarPanelOrder.some(panelId => store[panelRegistry[panelId].collapsedKey]); + + return ( + <> + + ContextMenuApi.openContextMenu(event, () => )} + onContextMenu={event => ContextMenuApi.openContextMenu(event, () => )} + /> + + ); +}, { noop: true }); + +const ChatButtonsRow = ErrorBoundary.wrap(({ buttons }: { buttons: ReactNode[]; }) => { + const { chatButtonsCollapsed } = settings.use(); + + if (buttons.length === 0) return <>{buttons}; + + return ( +
+
+ {buttons} +
+
+ ); +}, { noop: true }); + +export default definePlugin({ + name: "CollapsibleUI", + description: "Native collapsible channel, member, chat button, and user area surfaces.", + tags: ["Appearance", "Customisation", "Chat", "Servers"], + dependencies: ["HeaderBarAPI"], + authors: [EquicordDevs.benjii], + searchTerms: ["ui", "sidebar", "layout"], + managedStyle, + settings, + + headerBarButton: { + icon: PanelsIcon, + location: "channeltoolbar", + priority: 25, + render: () => , + }, + + patches: [ + { + find: ".DISPLAY_NAME_STYLES_COACHMARK)", + replacement: { + match: /className:(\i\.\i),(?=style:(\i),children:\[)/, + replace: "className:$self.userAreaControlsClass($1)," + } + }, + { + find: '"sticker")', + replacement: { + match: /(?<="div",\{.{0,15}children:)(.+?)\}/, + replace: "$self.wrapChatButtons($1)}" + } + } + ], + + wrapChatButtons(buttons: ReactNode[]) { + if (!Array.isArray(buttons) || buttons.length === 0) return buttons; + return ; + }, + + userAreaControlsClass(className: string) { + return classes(className, cl("user-area-controls")); + }, +}); diff --git a/src/equicordplugins/collapsibleUi/settings.ts b/src/equicordplugins/collapsibleUi/settings.ts new file mode 100644 index 000000000..dce2485b2 --- /dev/null +++ b/src/equicordplugins/collapsibleUi/settings.ts @@ -0,0 +1,70 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2026 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import { definePluginSettings } from "@api/Settings"; +import { OptionType } from "@utils/types"; + +export const transitionMarkers = [0, 80, 120, 160, 200, 260, 320]; + +export const panelRegistry = { + channelList: { + id: "channelList", + classId: "channel-list", + label: "Channel List", + collapsedKey: "channelListCollapsed", + }, + membersList: { + id: "membersList", + classId: "members-list", + label: "Members List", + collapsedKey: "membersListCollapsed", + }, + chatButtons: { + id: "chatButtons", + classId: "chat-buttons", + label: "Message Buttons", + collapsedKey: "chatButtonsCollapsed", + }, + userArea: { + id: "userArea", + classId: "user-area", + label: "User Area", + collapsedKey: "userAreaCollapsed", + }, +} as const; + +export type PanelId = keyof typeof panelRegistry; + +export const toolbarPanelOrder = ["channelList", "membersList", "chatButtons", "userArea"] as const satisfies readonly PanelId[]; + +export const settings = definePluginSettings({ + transitionMs: { + type: OptionType.SLIDER, + description: "Panel transition speed in milliseconds.", + default: 160, + markers: transitionMarkers, + }, + channelListCollapsed: { + type: OptionType.BOOLEAN, + description: "Persist the channel list as collapsed.", + default: false, + }, + membersListCollapsed: { + type: OptionType.BOOLEAN, + description: "Persist the members list as collapsed.", + default: false, + }, + chatButtonsCollapsed: { + type: OptionType.BOOLEAN, + description: "Persist the message button row as collapsed.", + default: false, + }, + userAreaCollapsed: { + type: OptionType.BOOLEAN, + description: "Persist the user area as collapsed.", + default: false, + }, +}); diff --git a/src/equicordplugins/collapsibleUi/style.css b/src/equicordplugins/collapsibleUi/style.css new file mode 100644 index 000000000..0ff9d8cc3 --- /dev/null +++ b/src/equicordplugins/collapsibleUi/style.css @@ -0,0 +1,213 @@ +body:has(.vc-collapsible-ui-state) { + --vc-cui-chat-buttons-width: min(320px, 36vw); + --vc-cui-collapsed-size: 12px; + --vc-cui-hover-peek: 18px; + --vc-cui-hover-delay: 120ms; + --vc-cui-user-area-collapsed-width: 52px; + --vc-cui-transition: 160ms; + --vc-cui-ease: cubic-bezier(.2, 0, 0, 1); +} + +body:has(.vc-collapsible-ui-transition-0) { + --vc-cui-transition: 0ms; +} + +body:has(.vc-collapsible-ui-transition-80) { + --vc-cui-transition: 80ms; +} + +body:has(.vc-collapsible-ui-transition-120) { + --vc-cui-transition: 120ms; +} + +body:has(.vc-collapsible-ui-transition-160) { + --vc-cui-transition: 160ms; +} + +body:has(.vc-collapsible-ui-transition-200) { + --vc-cui-transition: 200ms; +} + +body:has(.vc-collapsible-ui-transition-260) { + --vc-cui-transition: 260ms; +} + +body:has(.vc-collapsible-ui-transition-320) { + --vc-cui-transition: 320ms; +} + +body:has(.vc-collapsible-ui-channel-list-collapsed):has([class*="sidebarList_"]:hover) [class*="sidebarList_"] { + transition-delay: var(--vc-cui-hover-delay); +} + +body:has(.vc-collapsible-ui-channel-list-collapsed):has([class*="sidebarList_"]:hover) [class*="sidebarList_"] > * { + opacity: 1; + pointer-events: auto; + transition: opacity var(--vc-cui-transition) var(--vc-cui-ease); + transition-delay: var(--vc-cui-hover-delay); +} + +body:has(.vc-collapsible-ui-channel-list-collapsed):not(:has([class*="sidebarList_"]:hover), :has([class*="sidebar_"] > [class*="panels_"]:hover)) [class*="sidebarList_"] { + width: var(--vc-cui-collapsed-size) !important; + inline-size: var(--vc-cui-collapsed-size) !important; + min-width: var(--vc-cui-collapsed-size) !important; + min-inline-size: var(--vc-cui-collapsed-size) !important; + max-width: var(--vc-cui-collapsed-size) !important; + max-inline-size: var(--vc-cui-collapsed-size) !important; + flex: 0 0 var(--vc-cui-collapsed-size) !important; + overflow: hidden !important; + transition: + width var(--vc-cui-transition) var(--vc-cui-ease), + inline-size var(--vc-cui-transition) var(--vc-cui-ease), + min-width var(--vc-cui-transition) var(--vc-cui-ease), + min-inline-size var(--vc-cui-transition) var(--vc-cui-ease), + max-width var(--vc-cui-transition) var(--vc-cui-ease), + max-inline-size var(--vc-cui-transition) var(--vc-cui-ease), + flex-basis var(--vc-cui-transition) var(--vc-cui-ease) !important; +} + +body:has(.vc-collapsible-ui-channel-list-collapsed):not(:has([class*="sidebarList_"]:hover), :has([class*="sidebar_"] > [class*="panels_"]:hover)) [class*="sidebarList_"] > * { + opacity: 0; + pointer-events: none; + transition: opacity var(--vc-cui-transition) var(--vc-cui-ease); +} + +body:has(.vc-collapsible-ui-channel-list-collapsed):not(:has([class*="sidebar_"] > [class*="panels_"]:hover)) [class*="sidebar_"] > [class*="panels_"] { + width: var(--vc-cui-user-area-collapsed-width) !important; + inline-size: var(--vc-cui-user-area-collapsed-width) !important; + min-width: var(--vc-cui-user-area-collapsed-width) !important; + min-inline-size: var(--vc-cui-user-area-collapsed-width) !important; + max-width: var(--vc-cui-user-area-collapsed-width) !important; + max-inline-size: var(--vc-cui-user-area-collapsed-width) !important; + overflow: hidden !important; + transition: + width var(--vc-cui-transition) var(--vc-cui-ease), + inline-size var(--vc-cui-transition) var(--vc-cui-ease), + min-width var(--vc-cui-transition) var(--vc-cui-ease), + min-inline-size var(--vc-cui-transition) var(--vc-cui-ease), + max-width var(--vc-cui-transition) var(--vc-cui-ease), + max-inline-size var(--vc-cui-transition) var(--vc-cui-ease) !important; +} + +body:has(.vc-collapsible-ui-channel-list-collapsed):not(:has([class*="sidebar_"] > [class*="panels_"]:hover)) .vc-collapsible-ui-user-area-controls { + max-width: 0 !important; + min-width: 0 !important; + overflow: hidden !important; + opacity: 0; + pointer-events: none; + transition: + max-width var(--vc-cui-transition) var(--vc-cui-ease), + opacity var(--vc-cui-transition) var(--vc-cui-ease) !important; +} + +body:has(.vc-collapsible-ui-channel-list-collapsed):has([class*="sidebar_"] > [class*="panels_"]:hover) .vc-collapsible-ui-user-area-controls { + opacity: 1; + pointer-events: auto; +} + +body:has(.vc-collapsible-ui-members-list-collapsed) [class*="membersWrap"] { + overflow: hidden !important; + transition: + width var(--vc-cui-transition) var(--vc-cui-ease), + min-width var(--vc-cui-transition) var(--vc-cui-ease), + max-width var(--vc-cui-transition) var(--vc-cui-ease) !important; +} + +body:has(.vc-collapsible-ui-members-list-collapsed):has([class*="membersWrap"]:hover) [class*="membersWrap"], +body:has(.vc-collapsible-ui-members-list-collapsed):has([class*="membersWrap"]:focus-within) [class*="membersWrap"] { + transition-delay: var(--vc-cui-hover-delay); +} + +body:has(.vc-collapsible-ui-members-list-collapsed):has([class*="membersWrap"]:hover) [class*="membersWrap"] > :where(*), +body:has(.vc-collapsible-ui-members-list-collapsed):has([class*="membersWrap"]:focus-within) [class*="membersWrap"] > :where(*) { + opacity: 1; + pointer-events: auto; + transition: opacity var(--vc-cui-transition) var(--vc-cui-ease); + transition-delay: var(--vc-cui-hover-delay); +} + +body:has(.vc-collapsible-ui-members-list-collapsed):not(:has([class*="membersWrap"]:hover), :has([class*="membersWrap"]:focus-within)) [class*="membersWrap"] { + width: var(--vc-cui-collapsed-size) !important; + min-width: var(--vc-cui-collapsed-size) !important; + max-width: var(--vc-cui-collapsed-size) !important; +} + +body:has(.vc-collapsible-ui-members-list-collapsed):not(:has([class*="membersWrap"]:hover), :has([class*="membersWrap"]:focus-within)) [class*="membersWrap"] > :where(*) { + opacity: 0; + pointer-events: none; + transition: opacity var(--vc-cui-transition) var(--vc-cui-ease); +} + +body:has(.vc-collapsible-ui-user-area-collapsed):has([class*="sidebar_"] > [class*="panels_"]:hover) [class*="sidebar_"] > [class*="panels_"] > :where(*), +body:has(.vc-collapsible-ui-user-area-collapsed):has([class*="sidebar_"] > [class*="panels_"]:focus-within) [class*="sidebar_"] > [class*="panels_"] > :where(*) { + opacity: 1; + pointer-events: auto; + transition: opacity var(--vc-cui-transition) var(--vc-cui-ease); +} + +body:has(.vc-collapsible-ui-user-area-collapsed):not(:has([class*="sidebar_"] > [class*="panels_"]:hover), :has([class*="sidebar_"] > [class*="panels_"]:focus-within)) [class*="sidebar_"] > [class*="panels_"] { + height: var(--vc-cui-hover-peek) !important; + block-size: var(--vc-cui-hover-peek) !important; + min-height: var(--vc-cui-hover-peek) !important; + min-block-size: var(--vc-cui-hover-peek) !important; + max-height: var(--vc-cui-hover-peek) !important; + max-block-size: var(--vc-cui-hover-peek) !important; + overflow: hidden !important; + border-top-width: 0 !important; + padding-block: 0 !important; + transition: + height var(--vc-cui-transition) var(--vc-cui-ease), + block-size var(--vc-cui-transition) var(--vc-cui-ease), + min-height var(--vc-cui-transition) var(--vc-cui-ease), + min-block-size var(--vc-cui-transition) var(--vc-cui-ease), + max-height var(--vc-cui-transition) var(--vc-cui-ease), + max-block-size var(--vc-cui-transition) var(--vc-cui-ease), + padding var(--vc-cui-transition) var(--vc-cui-ease) !important; +} + +body:has(.vc-collapsible-ui-user-area-collapsed):not(:has([class*="sidebar_"] > [class*="panels_"]:hover), :has([class*="sidebar_"] > [class*="panels_"]:focus-within)) [class*="sidebar_"] > [class*="panels_"] > :where(*) { + opacity: 0; + pointer-events: none; + transition: opacity var(--vc-cui-transition) var(--vc-cui-ease); +} + +.vc-collapsible-ui-chat-buttons { + display: flex; + align-items: center; + min-inline-size: 0; +} + +.vc-collapsible-ui-chat-buttons-collapsed { + min-inline-size: var(--vc-cui-hover-peek); +} + +.vc-collapsible-ui-chat-buttons-items { + display: flex; + align-items: center; + min-inline-size: 0; + max-inline-size: var(--vc-cui-chat-buttons-width); + overflow: hidden; + transition: + max-inline-size var(--vc-cui-transition) var(--vc-cui-ease), + opacity var(--vc-cui-transition) var(--vc-cui-ease), + margin var(--vc-cui-transition) var(--vc-cui-ease); +} + +.vc-collapsible-ui-chat-buttons-collapsed .vc-collapsible-ui-chat-buttons-items { + max-inline-size: 0; + opacity: 0; + pointer-events: none; +} + +.vc-collapsible-ui-chat-buttons-collapsed:hover .vc-collapsible-ui-chat-buttons-items { + max-inline-size: var(--vc-cui-chat-buttons-width); + opacity: 1; + pointer-events: auto; + transition-delay: var(--vc-cui-hover-delay); +} + +@media (prefers-reduced-motion: reduce) { + body:has(.vc-collapsible-ui-state) { + --vc-cui-transition: 0ms; + } +} diff --git a/src/equicordplugins/commandPalette/index.tsx b/src/equicordplugins/commandPalette/index.tsx index 1d75830f8..b97abb85d 100644 --- a/src/equicordplugins/commandPalette/index.tsx +++ b/src/equicordplugins/commandPalette/index.tsx @@ -203,6 +203,7 @@ export default definePlugin({ name: "CommandPalette", description: t("equicord.commandPalette.description"), authors: [EquicordDevs.justjxke, EquicordDevs.Ethan], + tags: ["Appearance", "Customisation", "Commands", "Shortcuts"], settings, patches: [ { diff --git a/src/equicordplugins/commandPalette/registry.tsx b/src/equicordplugins/commandPalette/registry.tsx index ea1616940..8c7c87cf9 100644 --- a/src/equicordplugins/commandPalette/registry.tsx +++ b/src/equicordplugins/commandPalette/registry.tsx @@ -6,7 +6,7 @@ import { DataStore } from "@api/index"; import { isPluginEnabled, plugins, startPlugin, stopPlugin } from "@api/PluginManager"; -import { SettingsStore } from "@api/Settings"; +import { Settings, SettingsStore } from "@api/Settings"; import { getUserSettingLazy } from "@api/UserSettings"; import { openPluginModal } from "@components/settings/tabs"; import { toggleEnabled } from "@equicordplugins/equicordHelper/utils"; @@ -18,7 +18,6 @@ import { Guild } from "@vencord/discord-types"; import { findByPropsLazy, findExportedComponentLazy, findStoreLazy } from "@webpack"; import { Alerts, ChannelActionCreators, ChannelRouter, ChannelStore, ComponentDispatch, FluxDispatcher, GuildStore, IconUtils, MediaEngineStore, MessageStore, NavigationRouter, React, ReadStateStore, ReadStateUtils, SelectedChannelStore, SelectedGuildStore, SettingsRouter, StreamerModeStore, Toasts, useEffect, UserStore, VoiceActions } from "@webpack/common"; import type { FC, ReactElement, ReactNode } from "react"; -import { Settings } from "Vencord"; import commandPalette from "."; import { diff --git a/src/equicordplugins/components.dev/index.tsx b/src/equicordplugins/components.dev/index.tsx index b841e7091..2ba245a3c 100644 --- a/src/equicordplugins/components.dev/index.tsx +++ b/src/equicordplugins/components.dev/index.tsx @@ -19,6 +19,7 @@ import ComponentsTab from "./components/ComponentsTab"; export default definePlugin({ name: "Components", description: t("equicord.components.description"), + tags: ["Appearance", "Customisation", "Console", "Developers", "Organisation"], authors: [Devs.prism], dependencies: ["Settings"], startAt: StartAt.WebpackReady, diff --git a/src/equicordplugins/contentWarning/index.tsx b/src/equicordplugins/contentWarning/index.tsx index 3e51e5af9..a6f13c091 100644 --- a/src/equicordplugins/contentWarning/index.tsx +++ b/src/equicordplugins/contentWarning/index.tsx @@ -153,6 +153,7 @@ export default definePlugin({ name: "ContentWarning", authors: [EquicordDevs.camila314], description: t("equicord.contentWarning.description"), + tags: ["Appearance", "Utility"], settings, patches: [ { diff --git a/src/equicordplugins/copyProfileColors/index.tsx b/src/equicordplugins/copyProfileColors/index.tsx index c0390a39d..0dc06875d 100644 --- a/src/equicordplugins/copyProfileColors/index.tsx +++ b/src/equicordplugins/copyProfileColors/index.tsx @@ -91,6 +91,7 @@ const userContextMenuPatch: NavContextMenuPatchCallback = (children, { user }) = export default definePlugin({ name: "CopyProfileColors", description: t("equicord.copyProfileColors.description"), + tags: ["Appearance", "Customisation"], authors: [EquicordDevs.Crxa, EquicordDevs.Cortex], contextMenus: { "user-context": userContextMenuPatch, diff --git a/src/equicordplugins/copyStatusUrls/index.ts b/src/equicordplugins/copyStatusUrls/index.ts index ff1f0977a..266fcbba4 100644 --- a/src/equicordplugins/copyStatusUrls/index.ts +++ b/src/equicordplugins/copyStatusUrls/index.ts @@ -24,6 +24,7 @@ const getMetadataFromApi: (activity: any, userId: string) => Promise = find export default definePlugin({ name: "CopyStatusUrls", description: t("equicord.copyStatusUrls.description"), + tags: ["Activity", "Utility"], authors: [Devs.sadan], patches: [ diff --git a/src/equicordplugins/copyUserMention/index.tsx b/src/equicordplugins/copyUserMention/index.tsx index e8fd1f5ca..07931bd8e 100644 --- a/src/equicordplugins/copyUserMention/index.tsx +++ b/src/equicordplugins/copyUserMention/index.tsx @@ -49,6 +49,7 @@ export default definePlugin({ name: "CopyUserMention", authors: [EquicordDevs.Cortex, Devs.castdrian], description: t("equicord.copyUserMention.description"), + tags: ["Chat", "Utility"], contextMenus: { "user-context": UserContextMenuPatch } diff --git a/src/equicordplugins/cursorBuddy/index.tsx b/src/equicordplugins/cursorBuddy/index.tsx index c21cbb93f..f3d4f2b05 100644 --- a/src/equicordplugins/cursorBuddy/index.tsx +++ b/src/equicordplugins/cursorBuddy/index.tsx @@ -236,8 +236,9 @@ migratePluginSettings("CursorBuddy", "Oneko", "oneko"); export default definePlugin({ name: "CursorBuddy", description: t("equicord.cursorBuddy.description"), + tags: ["Appearance", "Customisation", "Fun"], authors: [Devs.Ven, Devs.adryd, EquicordDevs.nexpid, EquicordDevs.ZcraftElite], - tags: ["Oneko", "FatassHorse", "Pet"], + searchTerms: ["Oneko", "FatassHorse", "Pet"], settings, isModified: true, diff --git a/src/equicordplugins/customFolderIcons/index.tsx b/src/equicordplugins/customFolderIcons/index.tsx index b9f08673e..712c4cea8 100644 --- a/src/equicordplugins/customFolderIcons/index.tsx +++ b/src/equicordplugins/customFolderIcons/index.tsx @@ -15,6 +15,7 @@ import { folderProp, int2rgba } from "./util"; export default definePlugin({ name: "CustomFolderIcons", description: t("equicord.customFolderIcons.description"), + tags: ["Appearance", "Customisation", "Organisation"], authors: [EquicordDevs.sadan], settings, patches: [ diff --git a/src/equicordplugins/customSounds/index.tsx b/src/equicordplugins/customSounds/index.tsx index 835d230ca..90f6e4c75 100644 --- a/src/equicordplugins/customSounds/index.tsx +++ b/src/equicordplugins/customSounds/index.tsx @@ -394,6 +394,8 @@ export function findOverride(id: string): SoundOverride | null { export default definePlugin({ name: "CustomSounds", description: t("equicord.customSounds.description"), + dependencies: ["AudioPlayerAPI"], + tags: ["Customisation", "Notifications", "Voice"], authors: [Devs.ScattrdBlade, Devs.TheKodeToad], settings, startAt: StartAt.Init, diff --git a/src/equicordplugins/customStatusTimeouts/index.tsx b/src/equicordplugins/customStatusTimeouts/index.tsx new file mode 100644 index 000000000..d76f258a1 --- /dev/null +++ b/src/equicordplugins/customStatusTimeouts/index.tsx @@ -0,0 +1,116 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2026 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import { definePluginSettings } from "@api/Settings"; +import { EquicordDevs } from "@utils/constants"; +import definePlugin, { OptionType } from "@utils/types"; + +const Millis = { + HALF_SECOND: 500, + SECOND: 1e3, + MINUTE: 6e4, + HOUR: 36e5, + DAY: 864e5, + WEEK: 6048e5, + DAYS_30: 2592e6 +}; + +const settings = definePluginSettings({ + showForeverOnTop: { + type: OptionType.BOOLEAN, + description: "Show the Forever option at the top of the list instead of the bottom.", + restartNeeded: true, + default: true + }, + extraSeconds: { + type: OptionType.STRING, + description: "Extra seconds to add, separated by a comma (e.g. 5, 10, 30)", + restartNeeded: true, + default: "15, 30, 45" + }, + extraMinutes: { + type: OptionType.STRING, + description: "Extra minutes to add, separated by a comma (e.g. 5, 10, 30)", + restartNeeded: true, + default: "5, 10, 30" + }, + extraHours: { + type: OptionType.STRING, + description: "Extra hours to add, separated by a comma (e.g. 2, 4, 6, 12)", + restartNeeded: true, + default: "2, 4, 6, 12" + }, + extraDays: { + type: OptionType.STRING, + description: "Extra days to add, separated by a comma (e.g. 1, 2)", + restartNeeded: true, + default: "1, 2" + }, +}); + +export default definePlugin({ + name: "CustomStatusTimeouts", + description: "Adds configurable timeout presets to the status (presence) menu.", + tags: ["Activity", "Utility"], + authors: [EquicordDevs.Kiri, EquicordDevs.thororen], + settings, + patches: [ + { + find: "#{intl::DURATION_FOREVER}", + replacement: { + match: /\[\{duration.*?#{intl::DURATION_FOREVER}\)\}\]/, + replace: "$self.buildTimeouts($&)" + } + } + ], + buildTimeouts(existing) { + const parse = (str: string) => str.split(",").map(s => Number(s.trim())).filter(Boolean); + + const seconds = parse(settings.store.extraSeconds); + const minutes = parse(settings.store.extraMinutes); + const hours = parse(settings.store.extraHours); + const days = parse(settings.store.extraDays); + // I was testing weeks and months and for some reason random ones didnt apply look below for the working ones + // tested weeks between 1-12 working weeks were 1, 2, 3, 8, 9, 10 the rest didnt work + // tested months between 1-12 working months were 2, 4, 10, 12 the rest didnt work + // for months I only tested evens except for 1 so I hardcoded them to avoid user complaints + const weeks = [1, 2, 3]; + const months = [2, 4]; + + const extra = [ + ...seconds.map(s => ({ + duration: s * Millis.SECOND, + label: () => `For ${s} ${s === 1 ? "Second" : "Seconds"}` + })), + ...minutes.map(m => ({ + duration: m * Millis.MINUTE, + label: () => `For ${m} ${m === 1 ? "Minute" : "Minutes"}` + })), + ...hours.map(h => ({ + duration: h * Millis.HOUR, + label: () => `For ${h} ${h === 1 ? "Hour" : "Hours"}` + })), + ...days.map(d => ({ + duration: d * Millis.DAY, + label: () => `For ${d} ${d === 1 ? "Day" : "Days"}` + })), + ...weeks.map(w => ({ + duration: w * Millis.WEEK, + label: () => `For ${w} ${w === 1 ? "Week" : "Weeks"}` + })), + ...months.map(m => ({ + duration: m * Millis.DAYS_30, + label: () => `For ${m} ${m === 1 ? "Month" : "Months"}` + })), + ]; + + return [...existing, ...extra].sort((a, b) => { + if (a.duration === undefined) return settings.store.showForeverOnTop ? -1 : 1; + if (b.duration === undefined) return settings.store.showForeverOnTop ? 1 : -1; + return a.duration - b.duration; + }); + } +}); diff --git a/src/equicordplugins/customTimestamps/index.tsx b/src/equicordplugins/customTimestamps/index.tsx index 4bd845810..36b806b9e 100644 --- a/src/equicordplugins/customTimestamps/index.tsx +++ b/src/equicordplugins/customTimestamps/index.tsx @@ -126,6 +126,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "CustomTimestamps", description: t("equicord.customTimestamps.description"), + tags: ["Appearance", "Customisation"], authors: [Devs.Rini, EquicordDevs.nvhhr, EquicordDevs.Suffocate, Devs.Obsidian], settings, settingsAboutComponent: () => ( diff --git a/src/equicordplugins/customUserColors/index.tsx b/src/equicordplugins/customUserColors/index.tsx index b3c8a56c6..41df07dcb 100644 --- a/src/equicordplugins/customUserColors/index.tsx +++ b/src/equicordplugins/customUserColors/index.tsx @@ -101,6 +101,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "CustomUserColors", description: t("equicord.customUserColors.description"), + tags: ["Appearance", "Customisation", "Chat"], authors: [EquicordDevs.mochienya], contextMenus: { "user-context": userContextMenuPatch, diff --git a/src/equicordplugins/declutter/index.tsx b/src/equicordplugins/declutter/index.tsx index dbed13c86..c5ce2a9d7 100644 --- a/src/equicordplugins/declutter/index.tsx +++ b/src/equicordplugins/declutter/index.tsx @@ -144,15 +144,16 @@ function SectionSeparator(title: string) { export default definePlugin({ name: "Declutter", description: t("equicord.declutter.description"), + tags: ["Appearance", "Customisation"], authors: [EquicordDevs.Leon135, Devs.prism, Devs.Kyuuhachi], settings, patches: [ { // Nameplate - find: "#{intl::AVATAR_MALLOW}", + find: ".MINI_PREVIEW,[", replacement: { - match: /function \i\(\i\)\{(?=.{0,25}skuId:)/, - replace: "$&return null;" + match: /function \i\((\i)\)\{(?=let\{nameplate:\i,hovered:\i,selected:\i,content:\i,placement:\i\}=)/, + replace: '$&if($1.placement!=="preview"&&$1.placement!=="mini_preview")return null;' }, predicate: () => settings.store.removeNameplate, }, @@ -160,8 +161,8 @@ export default definePlugin({ // Profile banner animation effect find: "bannerAdjustment,isHovering", replacement: { - match: /\i=\i=>\{(?=.{0,50}\.useReducedMotion\))/, - replace: "$&return null;" + match: /\i=(\i)=>\{(?=.{0,50}\.useReducedMotion\))/, + replace: "$&if(!$1.shopPreview)return null;" }, predicate: () => settings.store.removeProfileEffect, }, diff --git a/src/equicordplugins/disableCameras/index.tsx b/src/equicordplugins/disableCameras/index.tsx index 829b36357..16425a6f2 100644 --- a/src/equicordplugins/disableCameras/index.tsx +++ b/src/equicordplugins/disableCameras/index.tsx @@ -11,6 +11,7 @@ import definePlugin from "@utils/types"; export default definePlugin({ name: "DisableCameras", description: t("equicord.disableCameras.description"), + tags: ["Appearance", "Customisation", "Media", "Privacy"], authors: [Devs.Joona], patches: [ { diff --git a/src/equicordplugins/discordDevBanner/components/makeDevBanner.tsx b/src/equicordplugins/discordDevBanner/components/makeDevBanner.tsx index 48ef55064..10642d7e0 100644 --- a/src/equicordplugins/discordDevBanner/components/makeDevBanner.tsx +++ b/src/equicordplugins/discordDevBanner/components/makeDevBanner.tsx @@ -4,10 +4,10 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ +import SettingsPlugin from "@plugins/_core/settings"; import { detectClient } from "@plugins/_core/supportHelper"; import { gitHashShort } from "@shared/vencordUserAgent"; import { React } from "@webpack/common"; -import SettingsPlugin from "plugins/_core/settings"; import { JSX } from "react"; import { ChromiumIcon, ClientIcon, DevBannerIcon, DiscordIcon, ElectronIcon, EquicordIcon, names, settings } from "."; diff --git a/src/equicordplugins/discordDevBanner/index.tsx b/src/equicordplugins/discordDevBanner/index.tsx index 3cf923ed7..6f7fcb8ea 100644 --- a/src/equicordplugins/discordDevBanner/index.tsx +++ b/src/equicordplugins/discordDevBanner/index.tsx @@ -15,6 +15,7 @@ import { makeDevBanner, settings } from "./components"; export default definePlugin({ name: "DiscordDevBanner", description: t("equicord.discordDevBanner.description"), + tags: ["Appearance", "Console", "Developers"], authors: [EquicordDevs.KrystalSkull, Devs.thororen], settings, patches: [ diff --git a/src/equicordplugins/dragFavoriteEmotes/index.tsx b/src/equicordplugins/dragFavoriteEmotes/index.tsx index 7bb14787c..28546defc 100644 --- a/src/equicordplugins/dragFavoriteEmotes/index.tsx +++ b/src/equicordplugins/dragFavoriteEmotes/index.tsx @@ -34,6 +34,7 @@ export default definePlugin({ name: "DragFavoriteEmotes", authors: [EquicordDevs.PWall], description: t("equicord.dragFavoriteEmotes.description"), + tags: ["Customisation", "Chat", "Emotes"], patches: [ { find: "#{intl::EMOJI_FAVORITE_TOOLTIP}", diff --git a/src/equicordplugins/dragify/index.tsx b/src/equicordplugins/dragify/index.tsx index 08d5944b3..d1d28969e 100644 --- a/src/equicordplugins/dragify/index.tsx +++ b/src/equicordplugins/dragify/index.tsx @@ -150,13 +150,14 @@ const settings = definePluginSettings({ export default definePlugin({ name: "Dragify", description: t("equicord.dragify.description"), + tags: ["Chat", "Servers", "Utility", "Voice"], authors: [EquicordDevs.justjxke], settings, patches: [ // Voice user rows (voice channel sidebar list) { - find: '"system:click_outside","user:escape"', + find: ".VOICE_USER],shouldShow:", replacement: { match: /(?<=GuildChannelUserContextMenu.{0,150})"data-dnd-name":\i/, replace: "\"data-dragify-user\":!0,\"data-user-id\":arguments[0].user?.id,draggable:!0,onDragStart:e=>$self.onUserDragStart(e,arguments[0].user),$&" diff --git a/src/equicordplugins/elementHighlighter.dev/index.tsx b/src/equicordplugins/elementHighlighter.dev/index.tsx index 943609e1f..f5c782c35 100644 --- a/src/equicordplugins/elementHighlighter.dev/index.tsx +++ b/src/equicordplugins/elementHighlighter.dev/index.tsx @@ -450,6 +450,7 @@ function onToggle(e: KeyboardEvent) { export default definePlugin({ name: "ElementHighlighter", description: t("equicord.elementHighlighter.description"), + tags: ["Developers"], authors: [Devs.prism], settings, diff --git a/src/equicordplugins/equibopStreamFixes.equibop/index.tsx b/src/equicordplugins/equibopStreamFixes.equibop/index.tsx index fb9a99b3f..2f6341ca1 100644 --- a/src/equicordplugins/equibopStreamFixes.equibop/index.tsx +++ b/src/equicordplugins/equibopStreamFixes.equibop/index.tsx @@ -89,6 +89,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "EquibopStreamFixes", description: "Tries to fix stream quality on Equibop by patching Discord's encoder and quality restrictions.", + tags: ["Voice"], authors: [EquicordDevs.creations], settings, diff --git a/src/equicordplugins/equicordHelper/index.tsx b/src/equicordplugins/equicordHelper/index.tsx index 93fef6c56..52c98e078 100644 --- a/src/equicordplugins/equicordHelper/index.tsx +++ b/src/equicordplugins/equicordHelper/index.tsx @@ -8,7 +8,7 @@ import { ApplicationCommandInputType, sendBotMessage } from "@api/Commands"; import { HeaderBarButton } from "@api/HeaderBar"; import { addMessagePreSendListener, removeMessagePreSendListener } from "@api/MessageEvents"; import { isPluginEnabled } from "@api/PluginManager"; -import { definePluginSettings, migratePluginToSettings } from "@api/Settings"; +import { definePluginSettings, migratePluginToSettings, Settings } from "@api/Settings"; import customRPC from "@plugins/customRPC"; import { Devs, EquicordDevs, GUILD_ID, SUPPORT_CHANNEL_ID, SUPPORT_CHANNEL_IDS, VC_SUPPORT_CHANNEL_IDS } from "@utils/constants"; import { isAnyPluginDev } from "@utils/misc"; @@ -126,14 +126,22 @@ const settings = definePluginSettings({ disableAdoptTagPrompt: { type: OptionType.BOOLEAN, description: "Disable the prompt to adopt tags", - default: true, - restartNeeded: true + restartNeeded: true, + default: false, }, + jsonGateway: { + type: OptionType.BOOLEAN, + description: "Forces JSON on gateway reconnect", + restartNeeded: true, + default: false, + } }); export default definePlugin({ name: "EquicordHelper", description: t("equicord.equicordHelper.description"), + dependencies: ["CommandsAPI", "HeaderBarAPI", "MessageAccessoriesAPI"], + tags: ["Appearance", "Commands", "Utility"], authors: [ Devs.thororen, EquicordDevs.nyx, @@ -273,6 +281,36 @@ export default definePlugin({ replace: "return null;$&" }, predicate: () => settings.store.disableAdoptTagPrompt + }, + { + find: "JSONEncoding", + replacement: { + match: /void 0!==\i\?\i:/, + replace: "" + }, + predicate: () => settings.store.jsonGateway + }, + { + find: ".USE_OSX_NATIVE_TRAFFIC_LIGHTS", + predicate: () => Settings.winNativeTitleBar, + replacement: { + match: /case \i\.\i\.WINDOWS:/, + replace: 'case "WEB":' + }, + }, + { + find: '"refresh-title-bar-small"', + predicate: () => Settings.winNativeTitleBar, + replacement: [ + { + match: /\i===\i\.PlatformTypes\.WINDOWS/g, + replace: "false" + }, + { + match: /\i===\i\.PlatformTypes\.WEB/g, + replace: "true" + } + ] } ], renderMessageAccessory(props) { diff --git a/src/equicordplugins/equicordToolbox/index.tsx b/src/equicordplugins/equicordToolbox/index.tsx index 21730e05e..3def6d948 100644 --- a/src/equicordplugins/equicordToolbox/index.tsx +++ b/src/equicordplugins/equicordToolbox/index.tsx @@ -78,11 +78,10 @@ migratePluginSettings("EquicordToolbox", "VencordToolbox"); export default definePlugin({ name: "EquicordToolbox", description: t("equicord.equicordToolbox.description"), + tags: ["Voice", "Accessibility"], authors: [Devs.Ven, Devs.AutumnVN], dependencies: ["HeaderBarAPI"], - settings, - headerBarButton: { icon: Icon, render: VencordPopoutButton, diff --git a/src/equicordplugins/equissant/index.ts b/src/equicordplugins/equissant/index.ts index 0c198bb79..c1e8680bb 100644 --- a/src/equicordplugins/equissant/index.ts +++ b/src/equicordplugins/equissant/index.ts @@ -34,6 +34,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "Equissant", description: t("equicord.equissant.description"), + tags: ["Fun"], authors: [EquicordDevs.SomeAspy, Devs.thororen], dependencies: ["AudioPlayerAPI"], settings, diff --git a/src/equicordplugins/exitSounds/index.tsx b/src/equicordplugins/exitSounds/index.tsx index 73cc8d841..e93a51144 100644 --- a/src/equicordplugins/exitSounds/index.tsx +++ b/src/equicordplugins/exitSounds/index.tsx @@ -105,6 +105,7 @@ let original: typeof ChannelActions.selectVoiceChannel; export default definePlugin({ name: "ExitSounds", description: t("equicord.exitSounds.description"), + tags: ["Fun", "Voice"], authors: [Devs.prism], dependencies: ["AudioPlayerAPI"], settings, diff --git a/src/equicordplugins/exportMessages/index.tsx b/src/equicordplugins/exportMessages/index.tsx index 133be45f6..0d9b63f72 100644 --- a/src/equicordplugins/exportMessages/index.tsx +++ b/src/equicordplugins/exportMessages/index.tsx @@ -130,6 +130,7 @@ function getUsernames(contacts: ContactsList[], type: number): string[] { export default definePlugin({ name: "ExportMessages", description: t("equicord.exportMessages.description"), + tags: ["Chat", "Utility"], authors: [EquicordDevs.veygax, EquicordDevs.dat_insanity], settings, contextMenus: { diff --git a/src/equicordplugins/fastDeleteChannels/index.tsx b/src/equicordplugins/fastDeleteChannels/index.tsx index beb20f343..efa027e7d 100644 --- a/src/equicordplugins/fastDeleteChannels/index.tsx +++ b/src/equicordplugins/fastDeleteChannels/index.tsx @@ -75,6 +75,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "FastDeleteChannels", description: t("equicord.fastDeleteChannels.description"), + tags: ["Servers", "Utility"], authors: [Devs.thororen], settings, patches: [ diff --git a/src/equicordplugins/favouriteAnything/index.tsx b/src/equicordplugins/favouriteAnything/index.tsx index 126c1d549..c9d8d526a 100644 --- a/src/equicordplugins/favouriteAnything/index.tsx +++ b/src/equicordplugins/favouriteAnything/index.tsx @@ -26,8 +26,9 @@ export const AttachmentContext = proxyLazyWebpack(() => React.createContext; } -function supportsToBase64(array: Uint8Array): array is Uint8ArrayExtended { +function supportsToBase64(array: Uint8Array): boolean { return "toBase64" in array && typeof array.toBase64 === "function"; } diff --git a/src/equicordplugins/fileUpload/index.tsx b/src/equicordplugins/fileUpload/index.tsx index 4fbf30b49..34b405f05 100644 --- a/src/equicordplugins/fileUpload/index.tsx +++ b/src/equicordplugins/fileUpload/index.tsx @@ -217,6 +217,7 @@ const channelAttachMenuPatch: NavContextMenuPatchCallback = (children, props) => export default definePlugin({ name: "FileUpload", description: t("equicord.fileUpload.description"), + tags: ["Media"], authors: [EquicordDevs.creations, EquicordDevs.keircn, Devs.ScattrdBlade], settings, patches: [ diff --git a/src/equicordplugins/fileUpload/settings.tsx b/src/equicordplugins/fileUpload/settings.tsx index b1aceb041..ab697c3fa 100644 --- a/src/equicordplugins/fileUpload/settings.tsx +++ b/src/equicordplugins/fileUpload/settings.tsx @@ -209,6 +209,12 @@ export const settings = definePluginSettings({ default: false, hidden: true }, + preserveOriginalFilename: { + type: OptionType.BOOLEAN, + description: "Preserve the original filename when uploading.", + default: true, + hidden: true + }, autoCopy: { type: OptionType.BOOLEAN, description: "Auto copy upload URL", @@ -508,6 +514,13 @@ export function SettingsComponent() { /> + + (store as { preserveOriginalFilename?: boolean; }).preserveOriginalFilename = v} + /> + + ( diff --git a/src/equicordplugins/fontLoader/index.tsx b/src/equicordplugins/fontLoader/index.tsx index 63d26e5e4..1f474e476 100644 --- a/src/equicordplugins/fontLoader/index.tsx +++ b/src/equicordplugins/fontLoader/index.tsx @@ -201,6 +201,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "FontLoader", description: t("equicord.fontLoader.description"), + tags: ["Appearance", "Customisation"], authors: [EquicordDevs.vmohammad], settings, diff --git a/src/equicordplugins/forwardAnywhere/index.ts b/src/equicordplugins/forwardAnywhere/index.ts index 6959bc6ac..9b8701c25 100644 --- a/src/equicordplugins/forwardAnywhere/index.ts +++ b/src/equicordplugins/forwardAnywhere/index.ts @@ -26,6 +26,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "ForwardAnywhere", description: t("equicord.forwardAnywhere.description"), + tags: ["Chat", "Utility"], authors: [Devs.thororen], settings, patches: [ diff --git a/src/equicordplugins/frequentQuickSwitcher/index.tsx b/src/equicordplugins/frequentQuickSwitcher/index.tsx index eb40ece47..284053eec 100644 --- a/src/equicordplugins/frequentQuickSwitcher/index.tsx +++ b/src/equicordplugins/frequentQuickSwitcher/index.tsx @@ -38,6 +38,7 @@ function generateSearchResults(query) { export default definePlugin({ name: "FrequentQuickSwitcher", description: t("equicord.frequentQuickSwitcher.description"), + tags: ["Shortcuts", "Servers"], authors: [Devs.Samwich], generateSearchResults: generateSearchResults, patches: [ diff --git a/src/equicordplugins/friendCodes/index.tsx b/src/equicordplugins/friendCodes/index.tsx index 8168cfe04..9997a8347 100644 --- a/src/equicordplugins/friendCodes/index.tsx +++ b/src/equicordplugins/friendCodes/index.tsx @@ -12,6 +12,7 @@ import FriendCodesPanel from "./FriendCodesPanel"; export default definePlugin({ name: "FriendCodes", description: "Generate FriendCodes to easily add friends", + tags: ["Friends", "Utility"], authors: [Devs.HypedDomi], patches: [ { diff --git a/src/equicordplugins/friendTags/index.tsx b/src/equicordplugins/friendTags/index.tsx index c1a673227..69d6d5eb3 100644 --- a/src/equicordplugins/friendTags/index.tsx +++ b/src/equicordplugins/friendTags/index.tsx @@ -210,6 +210,7 @@ const userPatch: NavContextMenuPatchCallback = (children, { user }) => { export default definePlugin({ name: "FriendTags", description: t("equicord.friendTags.description"), + tags: ["Shortcuts"], authors: [Devs.Samwich], settings, contextMenus: { diff --git a/src/equicordplugins/friendshipRanks/index.tsx b/src/equicordplugins/friendshipRanks/index.tsx index 3c6574d0c..8d0a64eba 100644 --- a/src/equicordplugins/friendshipRanks/index.tsx +++ b/src/equicordplugins/friendshipRanks/index.tsx @@ -144,6 +144,7 @@ function getBadgesToApply() { export default definePlugin({ name: "FriendshipRanks", description: t("equicord.friendshipRanks.description"), + tags: ["Friends"], authors: [Devs.Samwich], start() { getBadgesToApply().forEach(b => Badges.addProfileBadge(b)); diff --git a/src/equicordplugins/fullVcPfp/index.tsx b/src/equicordplugins/fullVcPfp/index.tsx index 3a0485427..ce8040e9f 100644 --- a/src/equicordplugins/fullVcPfp/index.tsx +++ b/src/equicordplugins/fullVcPfp/index.tsx @@ -15,6 +15,7 @@ import style from "./style.css?managed"; export default definePlugin({ name: "FullVCPFP", description: t("equicord.fullVcPfp.description"), + tags: ["Appearance", "Voice"], authors: [EquicordDevs.mochienya], patches: [ { diff --git a/src/equicordplugins/ghosted/index.tsx b/src/equicordplugins/ghosted/index.tsx index c919a9d84..bf974f891 100644 --- a/src/equicordplugins/ghosted/index.tsx +++ b/src/equicordplugins/ghosted/index.tsx @@ -148,6 +148,7 @@ function makeContextItem(props) { export default definePlugin({ name: "Ghosted", description: t("equicord.ghosted.description"), + tags: ["Chat", "Utility"], authors: [EquicordDevs.vei, Devs.sadan, EquicordDevs.justjxke, EquicordDevs.iamme], settings, dependencies: ["AudioPlayerAPI", "ServerListAPI"], diff --git a/src/equicordplugins/gifCollections/index.tsx b/src/equicordplugins/gifCollections/index.tsx index 355009c6f..819fa9e01 100644 --- a/src/equicordplugins/gifCollections/index.tsx +++ b/src/equicordplugins/gifCollections/index.tsx @@ -7,6 +7,7 @@ import "./style.css"; import { Devs, EquicordDevs } from "@utils/constants"; +import { t } from "@utils/translation"; import definePlugin from "@utils/types"; import { FluxDispatcher } from "@webpack/common"; @@ -17,7 +18,6 @@ import { cache_collections, refreshCacheCollection, updateGif } from "./utils/co import { getFormat } from "./utils/getFormat"; import { logger, stripPrefix } from "./utils/misc"; import { batchRefreshAttachmentUrls, isCdnUrlExpired } from "./utils/refreshUrl"; -import { t } from "@utils/translation"; let GIF_COLLECTION_PREFIX: string; let GIF_ITEM_PREFIX: string; @@ -28,6 +28,7 @@ export default definePlugin({ name: "GifCollections", description: t("equicord.gifCollections.description"), authors: [Devs.Aria, EquicordDevs.creations], + tags: ["Chat", "Emotes"], settings, contextMenus: { "message": addCollectionContextMenuPatch, @@ -158,7 +159,7 @@ export default definePlugin({ oldTrendingCat = instance.props.trendingCategories; } if (settings.store.onlyShowCollections) { - instance.props.trendingCategories = [...this.sortedCollections(), ...instance.props.favorites]; + instance.props.trendingCategories = this.sortedCollections(); } else if (oldTrendingCat != null) { instance.props.trendingCategories = [...this.sortedCollections(), ...oldTrendingCat]; } diff --git a/src/equicordplugins/githubRepos/index.tsx b/src/equicordplugins/githubRepos/index.tsx index cb6ef7e17..13956a3ce 100644 --- a/src/equicordplugins/githubRepos/index.tsx +++ b/src/equicordplugins/githubRepos/index.tsx @@ -39,6 +39,8 @@ export const settings = definePluginSettings({ export default definePlugin({ name: "GitHubRepos", description: t("equicord.githubRepos.description"), + dependencies: ["ProfileCollectionsAPI"], + tags: ["Appearance"], authors: [EquicordDevs.talhakf, EquicordDevs.Panniku, EquicordDevs.benjii], settings, diff --git a/src/equicordplugins/globalBadges/index.tsx b/src/equicordplugins/globalBadges/index.tsx index 5efdb7a99..59e1b8c2c 100644 --- a/src/equicordplugins/globalBadges/index.tsx +++ b/src/equicordplugins/globalBadges/index.tsx @@ -26,6 +26,7 @@ migratePluginSetting("GlobalBadges", "showRaincord", "showRa1ncord"); export default definePlugin({ name: "GlobalBadges", description: t("equicord.globalBadges.description"), + tags: ["Appearance"], authors: [Devs.HypedDomi, EquicordDevs.Wolfie, Devs.thororen], settings, settingsAboutComponent: () => ( diff --git a/src/equicordplugins/googleThat/index.tsx b/src/equicordplugins/googleThat/index.tsx index 9792b3abc..2812468ef 100644 --- a/src/equicordplugins/googleThat/index.tsx +++ b/src/equicordplugins/googleThat/index.tsx @@ -76,8 +76,10 @@ const settings = definePluginSettings({ export default definePlugin({ name: "GoogleThat", description: t("equicord.googleThat.description"), + dependencies: ["CommandsAPI"], + tags: ["Commands", "Utility"], authors: [Devs.Samwich, EquicordDevs.KrystalSkull], - tags: ["search", "google", "query", "duckduckgo", "command"], + searchTerms: ["search", "google", "query", "duckduckgo", "command"], settings, commands: [ { diff --git a/src/equicordplugins/guildPickerDumper/index.tsx b/src/equicordplugins/guildPickerDumper/index.tsx index 98116edb9..ff956e4a1 100644 --- a/src/equicordplugins/guildPickerDumper/index.tsx +++ b/src/equicordplugins/guildPickerDumper/index.tsx @@ -95,6 +95,7 @@ async function zipGuildAssets(guild: Guild, type: "emojis" | "stickers") { export default definePlugin({ name: "GuildPickerDumper", description: t("equicord.guildPickerDumper.description"), + tags: ["Emotes", "Servers", "Utility"], authors: [EquicordDevs.Cortex, Devs.Samwich, EquicordDevs.Synth, Devs.thororen], contextMenus: { "guild-context": Patch, diff --git a/src/equicordplugins/hideChatButtons/index.tsx b/src/equicordplugins/hideChatButtons/index.tsx index 7b37a7d33..6f8bf0a5d 100644 --- a/src/equicordplugins/hideChatButtons/index.tsx +++ b/src/equicordplugins/hideChatButtons/index.tsx @@ -9,7 +9,7 @@ import { definePluginSettings } from "@api/Settings"; import { EquicordDevs } from "@utils/constants"; import { t } from "@utils/translation"; import definePlugin, { OptionType, StartAt } from "@utils/types"; -import { React, useEffect, useState } from "@webpack/common"; +import { useEffect, useState } from "@webpack/common"; import type { MouseEventHandler, ReactNode } from "react"; let hidechatbuttonsopen: boolean | undefined; @@ -51,8 +51,14 @@ function HideToggleButton(props: { open: boolean | undefined, onClick: MouseEven ); } -function ButtonsInnerComponent({ buttons }: { buttons: ReactNode[]; }) { - if (!buttons || buttons.every(x => (x as any)?.props?.disabled === true)) return null; +function ButtonsInnerComponent({ buttons }: { buttons: ReactNode; }) { + const buttonItems = Array.isArray(buttons) + ? buttons + : buttons == null + ? [] + : [buttons]; + + if (buttonItems.length === 0 || buttonItems.every(button => (button as any)?.props?.disabled === true)) return null; const [open, setOpen] = useState(hidechatbuttonsopen); @@ -67,7 +73,7 @@ function ButtonsInnerComponent({ buttons }: { buttons: ReactNode[]; }) { overflowX: "auto", overflowY: "hidden" }}> - {open && buttons.map((b, i) => {b})} + {open && buttons} setOpen(!open)} open={open} />
); @@ -76,6 +82,7 @@ function ButtonsInnerComponent({ buttons }: { buttons: ReactNode[]; }) { export default definePlugin({ name: "HideChatButtons", description: t("equicord.hideChatButtons.description"), + tags: ["Chat", "Utility"], settings: settings, authors: [EquicordDevs.iamme], patches: [ @@ -88,7 +95,7 @@ export default definePlugin({ } ], startAt: StartAt.Init, - buttonsInner(buttons: ReactNode[]) { + buttonsInner(buttons: ReactNode) { return ; }, start() { diff --git a/src/equicordplugins/hideMessages/index.tsx b/src/equicordplugins/hideMessages/index.tsx index 09cc8e2ba..c5b468507 100644 --- a/src/equicordplugins/hideMessages/index.tsx +++ b/src/equicordplugins/hideMessages/index.tsx @@ -50,6 +50,8 @@ const settings = definePluginSettings({ export default definePlugin({ name: "HideMessages", description: t("equicord.hideMessages.description"), + dependencies: ["MessagePopoverAPI"], + tags: ["Chat", "Utility"], authors: [EquicordDevs.yash], contextMenus: { "message": messageCtxPatch diff --git a/src/equicordplugins/hideServers/index.tsx b/src/equicordplugins/hideServers/index.tsx index 552cc5769..ffdcee812 100644 --- a/src/equicordplugins/hideServers/index.tsx +++ b/src/equicordplugins/hideServers/index.tsx @@ -77,8 +77,9 @@ export function removeIndicator() { export default definePlugin({ name: "HideServers", description: t("equicord.hideServers.description"), + tags: ["Servers", "Utility"], authors: [EquicordDevs.bep], - tags: ["guild", "server", "hide", "folder"], + searchTerms: ["guild", "server", "hide", "folder"], dependencies: ["ServerListAPI"], contextMenus: { diff --git a/src/equicordplugins/holyNotes/index.tsx b/src/equicordplugins/holyNotes/index.tsx index b8d7bd342..080856e11 100644 --- a/src/equicordplugins/holyNotes/index.tsx +++ b/src/equicordplugins/holyNotes/index.tsx @@ -73,6 +73,8 @@ function ToolBarHeader() { export default definePlugin({ name: "HolyNotes", description: t("equicord.holyNotes.description"), + dependencies: ["MessagePopoverAPI", "HeaderBarAPI"], + tags: ["Chat", "Organisation"], authors: [EquicordDevs.Wolfie], toolboxActions: { diff --git a/src/equicordplugins/homeTyping/index.tsx b/src/equicordplugins/homeTyping/index.tsx index ce83a1aa5..da2e80659 100644 --- a/src/equicordplugins/homeTyping/index.tsx +++ b/src/equicordplugins/homeTyping/index.tsx @@ -19,6 +19,7 @@ const PrivateChannelSortStore = findStoreLazy("PrivateChannelSortStore") as { ge export default definePlugin({ name: "HomeTyping", description: t("equicord.homeTyping.description"), + tags: ["Chat"], authors: [Devs.Samwich], TypingIcon() { return ; diff --git a/src/equicordplugins/hopOn/index.tsx b/src/equicordplugins/hopOn/index.tsx index a3c105cd0..2f9ff4d16 100644 --- a/src/equicordplugins/hopOn/index.tsx +++ b/src/equicordplugins/hopOn/index.tsx @@ -33,6 +33,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "HopOn", description: t("equicord.hopOn.description"), + tags: ["Fun"], authors: [Devs.ImLvna], settings, flux: { diff --git a/src/equicordplugins/husk/index.tsx b/src/equicordplugins/husk/index.tsx index 26539d567..85c9d33ae 100644 --- a/src/equicordplugins/husk/index.tsx +++ b/src/equicordplugins/husk/index.tsx @@ -100,6 +100,8 @@ function getEmojiIdThatShouldBeUsed(guildId: string) { export default definePlugin({ name: "Husk", description: t("equicord.husk.description"), + dependencies: ["MessagePopoverAPI"], + tags: ["Emotes", "Fun"], authors: [Devs.nin0dev], settings, messagePopoverButton: { diff --git a/src/equicordplugins/iRememberYou/components/data.tsx b/src/equicordplugins/iRememberYou/components/data.tsx index 4d75730bb..6d5250f7e 100644 --- a/src/equicordplugins/iRememberYou/components/data.tsx +++ b/src/equicordplugins/iRememberYou/components/data.tsx @@ -6,7 +6,7 @@ import { DataStore } from "@api/index"; import { Guild, User } from "@vencord/discord-types"; -import { ChannelStore, GuildMemberStore, GuildStore, InviteActions, MessageStore, PermissionsBits, PermissionStore, UserStore, } from "@webpack/common"; +import { ChannelStore, GuildMemberStore, GuildStore, MessageStore, UserStore, } from "@webpack/common"; export interface IUserExtra { isOwner?: boolean; @@ -104,9 +104,7 @@ export class Data { extra: { ...previouExtra, ...extra }, iconURL: user.getAvatarURL(), }; - - if (source && !processedGuilds.has(source.id) && this.hasInvitePermissions(source.id)) { - this.collectInviteLink(source.id); + if (source && !processedGuilds.has(source.id)) { processedGuilds.add(source.id); } } @@ -148,10 +146,6 @@ export class Data { } this.processUsersToCollection([...target]); - - if (guild && this.hasInvitePermissions(guild.id)) { - this.collectInviteLink(guild.id); - } } } @@ -176,38 +170,6 @@ export class Data { this.processUsersToCollection([...target]); } - hasInvitePermissions(guildId: string): boolean { - const guild = GuildStore.getGuild(guildId); - if (!guild) return false; - - const currentUser = UserStore.getCurrentUser(); - if (!currentUser) return false; - - if (guild.ownerId === currentUser.id) return true; - - const member = GuildMemberStore.getMember(guildId, currentUser.id); - if (!member) return false; - - return PermissionStore.can(PermissionsBits.CREATE_INSTANT_INVITE, guild); - } - - async collectInviteLink(guildId: string) { - try { - const invites = await InviteActions.getInvites(guildId); - if (invites && invites.length > 0) { - const invite = invites[0]; - const inviteCode = invite.code; - const inviteLink = `https://discord.gg/${inviteCode}`; - - if (this.usersCollection[guildId]) { - this.usersCollection[guildId].inviteLink = inviteLink; - } - } - } catch (error) { - console.warn("Failed to collect invite link for guild:", guildId, error); - } - } - storageAutoSaveProtocol() { this._storageAutoSaveProtocol_interval = setInterval( this.updateStorage.bind(this), diff --git a/src/equicordplugins/iRememberYou/index.tsx b/src/equicordplugins/iRememberYou/index.tsx index 1c53de15f..f4186d4df 100644 --- a/src/equicordplugins/iRememberYou/index.tsx +++ b/src/equicordplugins/iRememberYou/index.tsx @@ -20,6 +20,7 @@ import DataUI from "./components/ui"; export default definePlugin({ name: "IRememberYou", description: t("equicord.iRememberYou.description"), + tags: ["Chat", "Servers"], authors: [EquicordDevs.zoodogood, EquicordDevs.keircn], dependencies: ["MessageEventsAPI"], diff --git a/src/equicordplugins/iconViewer/index.tsx b/src/equicordplugins/iconViewer/index.tsx index 0c48cb568..7a75f35d5 100644 --- a/src/equicordplugins/iconViewer/index.tsx +++ b/src/equicordplugins/iconViewer/index.tsx @@ -20,6 +20,7 @@ import { SettingsAbout } from "./components/Modals"; export default definePlugin({ name: "IconViewer", description: t("equicord.iconViewer.description"), + tags: ["Developers"], authors: [EquicordDevs.iamme], dependencies: ["Settings"], startAt: StartAt.WebpackReady, diff --git a/src/equicordplugins/idleAutoRestart/index.tsx b/src/equicordplugins/idleAutoRestart/index.tsx index 0ce7e4f0e..70420b48b 100644 --- a/src/equicordplugins/idleAutoRestart/index.tsx +++ b/src/equicordplugins/idleAutoRestart/index.tsx @@ -37,6 +37,7 @@ function onActivity() { export default definePlugin({ name: "IdleAutoRestart", description: t("equicord.idleAutoRestart.description"), + tags: ["Utility"], authors: [EquicordDevs.SteelTech], settings, diff --git a/src/equicordplugins/ignoreCalls/index.tsx b/src/equicordplugins/ignoreCalls/index.tsx index f0bbc9b51..8e508c40f 100644 --- a/src/equicordplugins/ignoreCalls/index.tsx +++ b/src/equicordplugins/ignoreCalls/index.tsx @@ -94,6 +94,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "IgnoreCalls", description: t("equicord.ignoreCalls.description"), + tags: ["Voice"], authors: [EquicordDevs.TheArmagan, Devs.thororen], settings, patches: [ diff --git a/src/equicordplugins/inRole/index.tsx b/src/equicordplugins/inRole/index.tsx index e60629fb9..a36415eb8 100644 --- a/src/equicordplugins/inRole/index.tsx +++ b/src/equicordplugins/inRole/index.tsx @@ -35,8 +35,9 @@ function getMembersInRole(roleId: string, guildId: string) { export default definePlugin({ name: "InRole", description: t("equicord.inRole.description"), + tags: ["Commands", "Roles"], authors: [Devs.nin0dev], - dependencies: ["UserSettingsAPI"], + dependencies: ["UserSettingsAPI", "CommandsAPI"], start() { DeveloperMode.updateSetting(true); }, diff --git a/src/equicordplugins/ingtoninator/index.tsx b/src/equicordplugins/ingtoninator/index.tsx index fddb11065..6956f4cd3 100644 --- a/src/equicordplugins/ingtoninator/index.tsx +++ b/src/equicordplugins/ingtoninator/index.tsx @@ -147,6 +147,8 @@ function disabledIcon() { export default definePlugin({ name: "Ingtoninator", description: t("equicord.ingtoninator.description"), + dependencies: ["ChatInputButtonAPI"], + tags: ["Fun"], authors: [EquicordDevs.zyqunix, EquicordDevs.BioTomateDE], settings, chatBarButton: { diff --git a/src/equicordplugins/instantScreenshare/index.tsx b/src/equicordplugins/instantScreenshare/index.tsx index 8049f78ce..368f26e5a 100644 --- a/src/equicordplugins/instantScreenshare/index.tsx +++ b/src/equicordplugins/instantScreenshare/index.tsx @@ -63,9 +63,10 @@ async function autoStartStream(instant = true) { export default definePlugin({ name: "InstantScreenshare", description: t("equicord.instantScreenshare.description"), + tags: ["Media", "Voice"], authors: [Devs.HAHALOSAH, Devs.thororen, EquicordDevs.mart], dependencies: ["EquicordToolbox"], - tags: ["ScreenshareKeybind"], + searchTerms: ["ScreenshareKeybind"], autoStartStream, settings, diff --git a/src/equicordplugins/invisibleChat.desktop/index.tsx b/src/equicordplugins/invisibleChat.desktop/index.tsx index 52288800a..3a9c198c4 100644 --- a/src/equicordplugins/invisibleChat.desktop/index.tsx +++ b/src/equicordplugins/invisibleChat.desktop/index.tsx @@ -150,8 +150,9 @@ export async function buildEmbed(message: any, revealed: string): Promise export default definePlugin({ name: "InvisibleChat", description: t("equicord.invisibleChat.description"), + tags: ["Chat"], authors: [Devs.SammCheese], - dependencies: ["MessageUpdaterAPI"], + dependencies: ["MessageUpdaterAPI", "ChatInputButtonAPI", "MessagePopoverAPI"], reporterTestable: ReporterTestable.Patches, settings, diff --git a/src/equicordplugins/inviteDefaults/index.ts b/src/equicordplugins/inviteDefaults/index.ts index 7991c1291..a638acf01 100644 --- a/src/equicordplugins/inviteDefaults/index.ts +++ b/src/equicordplugins/inviteDefaults/index.ts @@ -46,6 +46,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "InviteDefaults", description: t("equicord.inviteDefaults.description"), + tags: ["Servers"], authors: [EquicordDevs.VillainsRule], settings, patches: [ diff --git a/src/equicordplugins/jumpTo/index.tsx b/src/equicordplugins/jumpTo/index.tsx index 6021c83bb..8ae949a1d 100644 --- a/src/equicordplugins/jumpTo/index.tsx +++ b/src/equicordplugins/jumpTo/index.tsx @@ -122,6 +122,7 @@ const MessageMenuPatch: NavContextMenuPatchCallback = (children, { message }: { export default definePlugin({ name: "JumpTo", description: t("equicord.jumpTo.description"), + tags: ["Chat", "Utility"], authors: [Devs.Samwich, Devs.thororen], contextMenus: { "channel-context": ChannelMenuPatch, diff --git a/src/equicordplugins/jumpscare/index.tsx b/src/equicordplugins/jumpscare/index.tsx index bca209552..dae41391c 100644 --- a/src/equicordplugins/jumpscare/index.tsx +++ b/src/equicordplugins/jumpscare/index.tsx @@ -49,6 +49,7 @@ function getJumpscareRoot(): Root { export default definePlugin({ name: "Jumpscare", description: t("equicord.jumpscare.description"), + tags: ["Fun"], authors: [Devs.surgedevs], dependencies: ["AudioPlayerAPI"], settings, diff --git a/src/equicordplugins/keyboardNavigation/index.tsx b/src/equicordplugins/keyboardNavigation/index.tsx index f3ae45339..9fb8534f3 100644 --- a/src/equicordplugins/keyboardNavigation/index.tsx +++ b/src/equicordplugins/keyboardNavigation/index.tsx @@ -88,6 +88,7 @@ export const settings = definePluginSettings({ export default definePlugin({ name: "KeyboardNavigation", description: t("equicord.keyboardNavigation.description"), + tags: ["Accessibility", "Shortcuts"], authors: [Devs.Ethan], settings, diff --git a/src/equicordplugins/keyboardSounds/index.ts b/src/equicordplugins/keyboardSounds/index.ts index 17454c209..f299b4c14 100644 --- a/src/equicordplugins/keyboardSounds/index.ts +++ b/src/equicordplugins/keyboardSounds/index.ts @@ -127,6 +127,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "KeyboardSounds", description: t("equicord.keyboardSounds.description"), + tags: ["Fun"], authors: [Devs.HypedDomi, EquicordDevs.Etorix], dependencies: ["AudioPlayerAPI"], settings, diff --git a/src/equicordplugins/keywordNotify/index.tsx b/src/equicordplugins/keywordNotify/index.tsx index d69baf504..241eb4203 100644 --- a/src/equicordplugins/keywordNotify/index.tsx +++ b/src/equicordplugins/keywordNotify/index.tsx @@ -319,6 +319,7 @@ export default definePlugin({ name: "KeywordNotify", authors: [EquicordDevs.camila314, EquicordDevs.x3rt], description: t("equicord.keywordNotify.description"), + tags: ["Chat", "Notifications"], settings, patches: [ { diff --git a/src/equicordplugins/lastActive/index.tsx b/src/equicordplugins/lastActive/index.tsx index 9fe761d2d..589fb46bc 100644 --- a/src/equicordplugins/lastActive/index.tsx +++ b/src/equicordplugins/lastActive/index.tsx @@ -136,6 +136,7 @@ export function LastActiveIcon() { export default definePlugin({ name: "LastActive", description: t("equicord.lastActive.description"), + tags: ["Chat", "Utility"], authors: [EquicordDevs.Crxa], contextMenus: { "channel-context": ChannelContextMenuPatch, diff --git a/src/equicordplugins/loginWithQR/index.tsx b/src/equicordplugins/loginWithQR/index.tsx index 7fb5805a1..37ae448dc 100644 --- a/src/equicordplugins/loginWithQR/index.tsx +++ b/src/equicordplugins/loginWithQR/index.tsx @@ -43,6 +43,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "LoginWithQR", description: t("equicord.loginWithQR.description"), + tags: ["Utility"], authors: [EquicordDevs.nexpid], settings, diff --git a/src/equicordplugins/mediaPlaybackSpeed/index.tsx b/src/equicordplugins/mediaPlaybackSpeed/index.tsx index d8954ed3b..57c377dcc 100644 --- a/src/equicordplugins/mediaPlaybackSpeed/index.tsx +++ b/src/equicordplugins/mediaPlaybackSpeed/index.tsx @@ -49,6 +49,7 @@ type MediaRef = RefObject | undefined; export default definePlugin({ name: "MediaPlaybackSpeed", description: t("equicord.mediaPlaybackSpeed.description"), + tags: ["Chat", "Media"], authors: [Devs.D3SOX], settings, patches: [ diff --git a/src/equicordplugins/messageBurst/index.ts b/src/equicordplugins/messageBurst/index.ts index 0893610e8..15a0a7edf 100644 --- a/src/equicordplugins/messageBurst/index.ts +++ b/src/equicordplugins/messageBurst/index.ts @@ -67,6 +67,8 @@ const settings = definePluginSettings({ export default definePlugin({ name: "MessageBurst", description: t("equicord.messageBurst.description"), + dependencies: ["MessagePopoverAPI"], + tags: ["Chat"], authors: [EquicordDevs.port22exposed], settings, onBeforeMessageSend(channelId, message) { diff --git a/src/equicordplugins/messageColors/index.tsx b/src/equicordplugins/messageColors/index.tsx index a273b90ba..688b22839 100644 --- a/src/equicordplugins/messageColors/index.tsx +++ b/src/equicordplugins/messageColors/index.tsx @@ -28,6 +28,7 @@ export default definePlugin({ authors: [EquicordDevs.Hen], name: "MessageColors", description: t("equicord.messageColors.description"), + tags: ["Appearance", "Chat"], settings, patches: [ // Create a new markdown rule, so it parses just like any other features diff --git a/src/equicordplugins/messageFetchTimer/index.tsx b/src/equicordplugins/messageFetchTimer/index.tsx index bee077e86..21d49c9c7 100644 --- a/src/equicordplugins/messageFetchTimer/index.tsx +++ b/src/equicordplugins/messageFetchTimer/index.tsx @@ -148,6 +148,8 @@ function handleMessageLoad(data: any) { export default definePlugin({ name: "MessageFetchTimer", description: t("equicord.messageFetchTimer.description"), + dependencies: ["ChatInputButtonAPI"], + tags: ["Chat", "Utility"], authors: [EquicordDevs.GroupXyz], settings, diff --git a/src/equicordplugins/messageLinkTooltip/index.tsx b/src/equicordplugins/messageLinkTooltip/index.tsx index 4cc0136aa..2c7498ece 100644 --- a/src/equicordplugins/messageLinkTooltip/index.tsx +++ b/src/equicordplugins/messageLinkTooltip/index.tsx @@ -63,6 +63,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "MessageLinkTooltip", description: "Adds a tooltip with a message preview when hovering over message links, replies, and forwarded messages.", + tags: ["Appearance", "Chat"], authors: [Devs.Kyuuhachi], settings, diff --git a/src/equicordplugins/messageLoggerEnhanced/LoggedMessageManager.ts b/src/equicordplugins/messageLoggerEnhanced/LoggedMessageManager.ts index 7f51572af..5408349e9 100644 --- a/src/equicordplugins/messageLoggerEnhanced/LoggedMessageManager.ts +++ b/src/equicordplugins/messageLoggerEnhanced/LoggedMessageManager.ts @@ -17,7 +17,7 @@ */ import { Flogger, settings } from "."; -import { addMessageIDB, countMessagesIDB, DBMessageStatus, deleteMessagesBulkIDB, getOlderThanTimestampForGuildsIDB, getOldestMessagesIDB } from "./db"; +import { addMessageIDB, db, DBMessageStatus, deleteMessagesBulkIDB, getOlderThanTimestampForGuildsIDB, getOldestMessagesIDB } from "./db"; import { LoggedMessage, LoggedMessageJSON } from "./types"; import { cleanupMessage } from "./utils"; import { cacheMessageImages } from "./utils/saveImage"; @@ -47,7 +47,7 @@ export const addMessage = async (message: LoggedMessage | LoggedMessageJSON, sta } if (settings.store.messageLimit > 0) { - const currentMessageCount = await countMessagesIDB(); + const currentMessageCount = await db.count("messages"); if (currentMessageCount > settings.store.messageLimit) { const messagesToDelete = currentMessageCount - settings.store.messageLimit; if (messagesToDelete <= 0 || messagesToDelete >= settings.store.messageLimit) return; diff --git a/src/equicordplugins/messageLoggerEnhanced/components/LogsModal.tsx b/src/equicordplugins/messageLoggerEnhanced/components/LogsModal.tsx index e6f741313..f2aeab4f7 100644 --- a/src/equicordplugins/messageLoggerEnhanced/components/LogsModal.tsx +++ b/src/equicordplugins/messageLoggerEnhanced/components/LogsModal.tsx @@ -17,8 +17,8 @@ import { type User } from "@vencord/discord-types"; import { find, findByCode, findByCodeLazy } from "@webpack"; import { Alerts, ChannelStore, ContextMenuApi, FluxDispatcher, GuildStore, Menu, NavigationRouter, React, TabBar, TextInput, Tooltip, useMemo, useRef, useState } from "@webpack/common"; -import { clearMessagesIDB, DBMessageRecord, deleteMessageIDB, deleteMessagesBulkIDB } from "../db"; -import { cl, settings } from "../index"; +import { DBMessageRecord, deleteMessageIDB, deleteMessagesBulkIDB } from "../db"; +import { cl, clearLogs, settings } from "../index"; import { LoggedMessage, LoggedMessageJSON } from "../types"; import { messageJsonToMessageClass } from "../utils"; import { importLogs } from "../utils/settingsUtils"; @@ -148,7 +148,7 @@ export function LogsModal({ modalProps, initalQuery }: Props) { confirmVariant: "critical-primary", cancelText: t("vencord.cancel"), onConfirm: async () => { - await clearMessagesIDB(); + await clearLogs(); reset(); } diff --git a/src/equicordplugins/messageLoggerEnhanced/db.ts b/src/equicordplugins/messageLoggerEnhanced/db.ts index 31c34ef45..a9824e3dc 100644 --- a/src/equicordplugins/messageLoggerEnhanced/db.ts +++ b/src/equicordplugins/messageLoggerEnhanced/db.ts @@ -4,7 +4,6 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -import { Logger } from "@utils/Logger"; import { ChannelStore, Toasts } from "@webpack/common"; import { DBSchema, IDBPDatabase, openDB } from "idb"; @@ -38,63 +37,17 @@ export interface MLIDB extends DBSchema { by_timestamp_and_message_id: [string, string]; }; }; + } -const logger = new Logger("MessageLoggerEnhanced"); -let db: IDBPDatabase | null = null; -let dbPromise: Promise | null> | null = null; -let loggedFailure = false; - +export let db: IDBPDatabase; export const cachedMessages = new Map(); -function handleDbFailure(error: unknown) { - if (loggedFailure) return; - loggedFailure = true; - logger.error("Message storage unavailable, using memory only.", error); -} - -async function ensureDb() { - if (db) return db; - if (!dbPromise) { - dbPromise = openDB(DB_NAME, DB_VERSION, { - upgrade(database) { - const messageStore = database.createObjectStore("messages", { keyPath: "message_id" }); - messageStore.createIndex("by_channel_id", "channel_id"); - messageStore.createIndex("by_status", "status"); - messageStore.createIndex("by_timestamp", "message.timestamp"); - messageStore.createIndex("by_timestamp_and_message_id", ["channel_id", "message.timestamp"]); - } - }).then(database => { - db = database; - return database; - }).catch(error => { - handleDbFailure(error); - return null; - }); - } - - db = await dbPromise; - return db; -} - -async function withDb(fallback: T, callback: (database: IDBPDatabase) => Promise): Promise { - const database = await ensureDb(); - if (!database) return fallback; - - try { - return await callback(database); - } catch (error) { - handleDbFailure(error); - return fallback; - } -} - -async function cacheRecords(records: DBMessageRecord[], cacheAttachmentBlobs = true) { +// this is probably not the best way to do this +async function cacheRecords(records: DBMessageRecord[]) { for (const r of records) { cacheRecord(r); - if (!cacheAttachmentBlobs) continue; - for (const att of r.message.attachments) { const blobUrl = await getAttachmentBlobUrl(att); if (blobUrl) { @@ -103,7 +56,6 @@ async function cacheRecords(records: DBMessageRecord[], cacheAttachmentBlobs = t } } } - return records; } @@ -116,56 +68,57 @@ async function cacheRecord(record?: DBMessageRecord | null) { } export async function initIDB() { - await ensureDb(); + if (db) return; + db = await openDB(DB_NAME, DB_VERSION, { + upgrade(db) { + const messageStore = db.createObjectStore("messages", { keyPath: "message_id" }); + messageStore.createIndex("by_channel_id", "channel_id"); + messageStore.createIndex("by_status", "status"); + messageStore.createIndex("by_timestamp", "message.timestamp"); + messageStore.createIndex("by_timestamp_and_message_id", ["channel_id", "message.timestamp"]); + } + }); } -void initIDB(); +initIDB(); export async function hasMessageIDB(message_id: string) { - if (cachedMessages.has(message_id)) return true; - return withDb(false, database => database.count("messages", message_id).then(count => count > 0)); + return cachedMessages.has(message_id) || (await db.count("messages", message_id)) > 0; } export async function countMessagesIDB() { - if (!db) return cachedMessages.size; return db.count("messages"); } export async function countMessagesByStatusIDB(status: DBMessageStatus) { - return withDb(0, database => database.countFromIndex("messages", "by_status", status)); + return db.countFromIndex("messages", "by_status", status); } export async function getAllMessagesIDB() { - return withDb([], async database => cacheRecords(await database.getAll("messages"))); + return cacheRecords(await db.getAll("messages")); } export async function getMessagesForChannelIDB(channel_id: string) { - return withDb([], async database => cacheRecords(await database.getAllFromIndex("messages", "by_channel_id", channel_id))); + return cacheRecords(await db.getAllFromIndex("messages", "by_channel_id", channel_id)); } export async function getMessageIDB(message_id: string) { - return withDb(null, async database => { - const record = await database.get("messages", message_id); - await cacheRecord(record); - return record ?? null; - }); + return cacheRecord(await db.get("messages", message_id)); } export async function getMessagesByStatusIDB(status: DBMessageStatus) { - return withDb([], async database => cacheRecords(await database.getAllFromIndex("messages", "by_status", status))); + return cacheRecords(await db.getAllFromIndex("messages", "by_status", status)); } export async function getOldestMessagesIDB(limit: number) { - return withDb([], async database => cacheRecords(await database.getAllFromIndex("messages", "by_timestamp", undefined, limit))); + return cacheRecords(await db.getAllFromIndex("messages", "by_timestamp", undefined, limit)); } export async function* iterateAllMessagesIDB(batchSize = 100) { - if (!db && !(await ensureDb())) return; - let lastId: string | undefined; while (true) { const batch: DBMessageRecord[] = []; - - const tx = db!.transaction("messages"); + // new transaction for each batch to avoid timeouts during yield + const tx = db.transaction("messages"); const range = lastId ? IDBKeyRange.lowerBound(lastId, true) : undefined; let cursor = await tx.store.openCursor(range); @@ -177,6 +130,7 @@ export async function* iterateAllMessagesIDB(batchSize = 100) { if (batch.length === 0) break; lastId = batch[batch.length - 1].message_id; + yield await cacheRecords(batch); if (batch.length < batchSize) break; @@ -184,20 +138,22 @@ export async function* iterateAllMessagesIDB(batchSize = 100) { } export async function getOlderThanTimestampIDB(timestamp: string) { - return withDb([], async database => { - const tx = database.transaction("messages", "readonly"); - const index = tx.store.index("by_timestamp"); - const cursor = await index.openCursor(IDBKeyRange.upperBound(timestamp)); + const tx = db.transaction("messages", "readonly"); + const { store } = tx; + const index = store.index("by_timestamp"); - if (!cursor) return []; + const cursor = await index.openCursor(IDBKeyRange.upperBound(timestamp)); - const messages: DBMessageRecord[] = []; - for await (const c of cursor) { - messages.push(c.value); - } + if (!cursor) { + return []; + } - return cacheRecords(messages, false); - }); + const messages: DBMessageRecord[] = []; + for await (const c of cursor) { + messages.push(c.value); + } + + return cacheRecords(messages); } export async function getOlderThanTimestampForGuildsIDB(timestamp: string, currentChannelId?: string, preserveCurrentChannel?: boolean) { @@ -212,106 +168,102 @@ export async function getOlderThanTimestampForGuildsIDB(timestamp: string, curre } export async function getDateStortedMessagesByStatusIDB(newest: boolean, limit: number, status: DBMessageStatus) { - return withDb([], async database => { - const tx = database.transaction("messages", "readonly"); - const index = tx.store.index("by_status"); - const direction = newest ? "prev" : "next"; - const cursor = await index.openCursor(IDBKeyRange.only(status), direction); + const tx = db.transaction("messages", "readonly"); + const { store } = tx; + const index = store.index("by_status"); - if (!cursor) { - return []; - } + const direction = newest ? "prev" : "next"; + const cursor = await index.openCursor(IDBKeyRange.only(status), direction); - const messages: DBMessageRecord[] = []; - for await (const c of cursor) { - messages.push(c.value); - if (messages.length >= limit) break; - } + if (!cursor) { + console.log("No messages found"); + return []; + } - return cacheRecords(messages); - }); + const messages: DBMessageRecord[] = []; + for await (const c of cursor) { + messages.push(c.value); + if (messages.length >= limit) break; + } + + return cacheRecords(messages); } export async function getMessagesByChannelAndAfterTimestampIDB(channel_id: string, start: string) { - return withDb([], async database => { - const tx = database.transaction("messages", "readonly"); - const index = tx.store.index("by_timestamp_and_message_id"); - const cursor = await index.openCursor(IDBKeyRange.bound([channel_id, start], [channel_id, "\uffff"])); + const tx = db.transaction("messages", "readonly"); + const { store } = tx; + const index = store.index("by_timestamp_and_message_id"); - if (!cursor) { - return []; - } + const cursor = await index.openCursor(IDBKeyRange.bound([channel_id, start], [channel_id, "\uffff"])); - const messages: DBMessageRecord[] = []; - for await (const c of cursor) { - messages.push(c.value); - } + if (!cursor) { + console.log("No messages found in range"); + return []; + } - return cacheRecords(messages, false); - }); + const messages: DBMessageRecord[] = []; + for await (const c of cursor) { + messages.push(c.value); + } + + return cacheRecords(messages); } export async function addMessageIDB(message: LoggedMessageJSON, status: DBMessageStatus) { stripTransientRenderState(message); - cachedMessages.set(message.id, message); - return withDb(void 0, async database => { - await database.put("messages", { - channel_id: message.channel_id, - message_id: message.id, - status, - message, - }); + if (!db) await initIDB(); + await db.put("messages", { + channel_id: message.channel_id, + message_id: message.id, + status, + message, }); + + cachedMessages.set(message.id, message); } export async function addMessagesBulkIDB(messages: LoggedMessageJSON[], status?: DBMessageStatus) { messages.forEach(stripTransientRenderState); + + const tx = db.transaction("messages", "readwrite"); + const { store } = tx; + + await Promise.all([ + ...messages.map(message => store.add({ + channel_id: message.channel_id, + message_id: message.id, + status: status ?? getMessageStatus(message), + message, + })), + tx.done + ]); + messages.forEach(message => cachedMessages.set(message.id, message)); - - return withDb(void 0, async database => { - const tx = database.transaction("messages", "readwrite"); - const { store } = tx; - - await Promise.all([ - ...messages.map(message => store.add({ - channel_id: message.channel_id, - message_id: message.id, - status: status ?? getMessageStatus(message), - message, - })), - tx.done - ]); - }); } export async function deleteMessageIDB(message_id: string) { - cachedMessages.delete(message_id); + await db.delete("messages", message_id); - return withDb(void 0, database => database.delete("messages", message_id)); + cachedMessages.delete(message_id); } export async function deleteMessagesBulkIDB(message_ids: string[]) { + const tx = db.transaction("messages", "readwrite"); + const { store } = tx; + + await Promise.all([...message_ids.map(id => store.delete(id)), tx.done]); message_ids.forEach(id => cachedMessages.delete(id)); - - return withDb(void 0, async database => { - const tx = database.transaction("messages", "readwrite"); - const { store } = tx; - await Promise.all([ - ...message_ids.map(id => store.delete(id)), - tx.done - ]); - }); } -export async function clearMessagesIDB() { +export async function clearMessagesIDB(showToast = true) { cachedMessages.clear(); + await db.clear("messages"); + if (!showToast) return; - return withDb(void 0, database => database.clear("messages")).then(() => { - Toasts.show({ - type: Toasts.Type.MESSAGE, - message: "Cleared message log database and cache.", - id: Toasts.genId() - }); + Toasts.show({ + type: Toasts.Type.MESSAGE, + message: "Cleared message log database and cache.", + id: Toasts.genId() }); } diff --git a/src/equicordplugins/messageLoggerEnhanced/index.tsx b/src/equicordplugins/messageLoggerEnhanced/index.tsx index cf5a537f8..2abe5c7df 100644 --- a/src/equicordplugins/messageLoggerEnhanced/index.tsx +++ b/src/equicordplugins/messageLoggerEnhanced/index.tsx @@ -18,8 +18,8 @@ import { FluxDispatcher, MessageStore, SelectedChannelStore, UserStore } from "@ import { LogsIcon, OpenLogsButton } from "./components/LogsButton"; import { openLogModal } from "./components/LogsModal"; import * as idb from "./db"; -import { addMessage } from "./LoggedMessageManager"; import * as LoggedMessageManager from "./LoggedMessageManager"; +import { addMessage } from "./LoggedMessageManager"; import { settings } from "./settings"; import { FetchMessagesResponse, LoadMessagePayload, LoggedMessage, LoggedMessageJSON, MessageCreatePayload, MessageDeleteBulkPayload, MessageDeletePayload, MessageUpdatePayload } from "./types"; import { cleanUpCachedMessage, cleanupUserObject, getNative, isGhostPinged, mapTimestamp, messageJsonToMessageClass, reAddDeletedMessages } from "./utils"; @@ -36,8 +36,15 @@ export const Flogger = new Logger("MessageLoggerEnhanced", "#f26c6c"); export const cacheSentMessages = new LimitedMap(); export const cl = classNameFactory("vc-msg-logger-enhanced-"); +let didClearLogsOnStartup = false; + const cacheThing = findByPropsLazy("commit", "getOrCreate"); +export async function clearLogs(showToast = true) { + await idb.clearMessagesIDB(showToast); + cacheSentMessages.clear(); +} + let oldGetMessage: typeof MessageStore.getMessage; const handledMessageIds = new Set(); @@ -251,7 +258,8 @@ export default definePlugin({ name: "MessageLoggerEnhanced", authors: [Devs.Aria, EquicordDevs.keircn], description: "Improves MessageLogger with edited message history, ghost ping detection and more", - dependencies: ["MessageLogger"], + tags: ["Chat", "Servers"], + dependencies: ["MessageLogger", "HeaderBarAPI"], patches: [ { @@ -396,6 +404,15 @@ export default definePlugin({ Native.init(); + if (settings.store.clearLogsOnRestart && !didClearLogsOnStartup) { + try { + await clearLogs(false); + didClearLogsOnStartup = true; + } catch (e) { + Flogger.error("Failed to clear logs on restart", e); + } + } + const { imageCacheDir, logsDir } = await Native.getSettings(); settings.store.imageCacheDir = imageCacheDir; settings.store.logsDir = logsDir; diff --git a/src/equicordplugins/messageLoggerEnhanced/settings.tsx b/src/equicordplugins/messageLoggerEnhanced/settings.tsx index 5c969da97..bb4e523f0 100644 --- a/src/equicordplugins/messageLoggerEnhanced/settings.tsx +++ b/src/equicordplugins/messageLoggerEnhanced/settings.tsx @@ -4,18 +4,16 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -import { definePluginSettings } from "@api/Settings"; +import { definePluginSettings, Settings } from "@api/Settings"; import { Button } from "@components/Button"; import ErrorBoundary from "@components/ErrorBoundary"; import { t } from "@utils/translation"; import { OptionType } from "@utils/types"; import { Alerts, useState } from "@webpack/common"; -import { Settings } from "Vencord"; -import { Native } from "."; +import { clearLogs, Native } from "."; import { ImageCacheDir, LogsDir } from "./components/FolderSelectInput"; import { openLogModal } from "./components/LogsModal"; -import { clearMessagesIDB } from "./db"; import { blockedExts } from "./list"; import { DEFAULT_IMAGE_CACHE_DIR } from "./utils/constants"; import { exportLogs, importLogs } from "./utils/settingsUtils"; @@ -261,6 +259,13 @@ export const settings = definePluginSettings({ component: ExportLogsButton }, + clearLogsOnRestart: { + type: OptionType.BOOLEAN, + description: "Clear logs when Discord restarts.", + default: false, + restartNeeded: true, + }, + openLogs: { type: OptionType.COMPONENT, description: "Open Logs", @@ -299,7 +304,7 @@ export const settings = definePluginSettings({ confirmText: "Clear", cancelText: t("vencord.cancel"), onConfirm: async () => { - await clearMessagesIDB(); + await clearLogs(); }, })} > diff --git a/src/equicordplugins/messageLoggerEnhanced/utils/LimitedMap.ts b/src/equicordplugins/messageLoggerEnhanced/utils/LimitedMap.ts index a0b381e75..c027d3869 100644 --- a/src/equicordplugins/messageLoggerEnhanced/utils/LimitedMap.ts +++ b/src/equicordplugins/messageLoggerEnhanced/utils/LimitedMap.ts @@ -33,4 +33,8 @@ export class LimitedMap { get(key: K) { return this.map.get(key); } + + clear() { + this.map.clear(); + } } diff --git a/src/equicordplugins/messageLoggerEnhanced/utils/misc.ts b/src/equicordplugins/messageLoggerEnhanced/utils/misc.ts index 43c5f4166..66a264abf 100644 --- a/src/equicordplugins/messageLoggerEnhanced/utils/misc.ts +++ b/src/equicordplugins/messageLoggerEnhanced/utils/misc.ts @@ -24,6 +24,7 @@ import { DBMessageStatus } from "../db"; import { LoggedMessageJSON } from "../types"; import { DEFAULT_IMAGE_CACHE_DIR } from "./constants"; import { DISCORD_EPOCH } from "./index"; +import { memoize } from "./memoize"; const MessageClass: any = findLazy(m => m?.prototype?.isEdited); const AuthorClass = findLazy(m => m?.prototype?.getAvatarURL); @@ -92,7 +93,7 @@ export const mapTimestamp = (m: any) => { return m; }; -export const messageJsonToMessageClass = (log: { message: LoggedMessageJSON; }) => { +export const messageJsonToMessageClass = memoize((log: { message: LoggedMessageJSON; }) => { // console.time("message populate"); if (!log?.message) return null; @@ -122,7 +123,7 @@ export const messageJsonToMessageClass = (log: { message: LoggedMessageJSON; }) // console.timeEnd("message populate"); return message; -}; +}); export function parseJSON(json?: string | null) { try { diff --git a/src/equicordplugins/messageLoggerEnhanced/utils/settingsUtils.ts b/src/equicordplugins/messageLoggerEnhanced/utils/settingsUtils.ts index 1f89770c5..0d59e56ab 100644 --- a/src/equicordplugins/messageLoggerEnhanced/utils/settingsUtils.ts +++ b/src/equicordplugins/messageLoggerEnhanced/utils/settingsUtils.ts @@ -21,8 +21,8 @@ import { chooseFile as chooseFileWeb } from "@utils/web"; import { Toasts } from "@webpack/common"; import { showSaveFilePicker } from "native-file-system-adapter"; -import { Native } from ".."; -import { addMessagesBulkIDB, clearMessagesIDB, iterateAllMessagesIDB } from "../db"; +import { clearLogs,Native } from ".."; +import { addMessagesBulkIDB, iterateAllMessagesIDB } from "../db"; import { LoggedMessageJSON } from "../types"; export async function importLogs() { @@ -34,7 +34,7 @@ export async function importLogs() { for await (const logItems of iterateLogItems()) { if (!cleared) { - await clearMessagesIDB(); + await clearLogs(false); cleared = true; } diff --git a/src/equicordplugins/messageNotifier/index.ts b/src/equicordplugins/messageNotifier/index.ts index 756c5d4d4..1b793d8aa 100644 --- a/src/equicordplugins/messageNotifier/index.ts +++ b/src/equicordplugins/messageNotifier/index.ts @@ -39,6 +39,7 @@ export default definePlugin({ authors: [EquicordDevs.cassie, EquicordDevs.mochienya], name: "MessageNotifier", description: t("equicord.messageNotifier.description"), + tags: ["Chat", "Notifications"], settings, flux: { MESSAGE_CREATE({ message, channelId, guildId }: MessageCreatePayload) { diff --git a/src/equicordplugins/messagePeek/index.tsx b/src/equicordplugins/messagePeek/index.tsx index 029d12d77..f9d69882a 100644 --- a/src/equicordplugins/messagePeek/index.tsx +++ b/src/equicordplugins/messagePeek/index.tsx @@ -240,6 +240,8 @@ function shouldShowActivity(lastMessage: Message | undefined, hasActivity: boole export default definePlugin({ name: "MessagePeek", description: t("equicord.messagePeek.description"), + dependencies: ["MemberListDecoratorsAPI"], + tags: ["Appearance", "Chat"], authors: [Devs.prism, EquicordDevs.justjxke], settings, patches: [ diff --git a/src/equicordplugins/messageTranslate/index.tsx b/src/equicordplugins/messageTranslate/index.tsx index 7f10a10ad..b8b1da127 100644 --- a/src/equicordplugins/messageTranslate/index.tsx +++ b/src/equicordplugins/messageTranslate/index.tsx @@ -4,65 +4,111 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -import { definePluginSettings } from "@api/Settings"; -import { Devs } from "@utils/constants"; +import { EquicordDevs } from "@utils/constants"; +import { classNameFactory } from "@utils/css"; import { t } from "@utils/translation"; -import definePlugin, { OptionType } from "@utils/types"; +import definePlugin from "@utils/types"; +import { ChannelStore, FluxDispatcher, MessageStore, UserStore } from "@webpack/common"; -const settings = definePluginSettings( - { - targetLanguage: { - type: OptionType.STRING, - description: t("equicord.messageTranslate.settings.targetLanguage"), - default: "en", - restartNeeded: true - }, - confidenceRequirement: { - type: OptionType.STRING, - description: t("equicord.messageTranslate.settings.confidenceRequirement"), - default: "0.8", - restartNeeded: true - }, - }); +import { getIgnoredChannels, getIgnoredGuilds, getIgnoredUsers, settings } from "./settings"; +import { MessageWithContent } from "./types"; +import { clearCache, getCached, hasFailed, isInProgress, translate } from "./utils/translate"; -async function translateAPI(sourceLang: string, targetLang: string, text: string): Promise { +const cl = classNameFactory("mt-"); +const translatedMessages = new Map(); - const url = `https://translate.googleapis.com/translate_a/single?client=gtx&sl=${sourceLang}&tl=${targetLang}&dt=t&dj=1&q=${encodeURIComponent(text)}`; - const response = await fetch(url); - if (!response.ok) { - throw new Error(`Failed to translate "${text}" from ${sourceLang} to ${targetLang}: ${response.status} ${response.statusText}`); +function shouldTranslate(message: MessageWithContent): boolean { + if (!message.content || typeof message.content !== "string") return false; + if (hasFailed(message.id, message.content)) return false; + + if (settings.store.skipOwnMessages) { + const currentUserId = UserStore.getCurrentUser()?.id; + if (currentUserId && message.author?.id === currentUserId) return false; } - return await response.json(); + if (settings.store.skipBotMessages && message.author?.bot) return false; + + if (message.author && getIgnoredUsers().has(message.author.id)) return false; + if (message.channel_id && getIgnoredChannels().has(message.channel_id)) return false; + + const guildId = message.channel_id ? ChannelStore.getChannel(message.channel_id)?.guild_id : null; + if (guildId && getIgnoredGuilds().has(guildId)) return false; + + return true; } -async function TranslateMessage(string) { - // there may be a better way to do this lmao - if (string.includes("(Translated)")) return string; +function triggerReRender(message: MessageWithContent) { + const current = MessageStore.getMessage(message.channel_id, message.id); + if (!current) return; - const response = await translateAPI("auto", settings.store.targetLanguage, string); - - if (response.src === settings.store.targetLanguage || response.confidence < settings.store.confidenceRequirement) return string; - - const { sentences }: { sentences: { trans?: string; }[]; } = await response; - const translatedText = sentences.map(s => s?.trans).filter(Boolean).join(""); - - return `${translatedText} *(Translated)*`; + FluxDispatcher.dispatch({ + type: "MESSAGE_UPDATE", + message: current, + }); } export default definePlugin({ name: "MessageTranslate", description: t("equicord.messageTranslate.description"), - authors: [Devs.Samwich], + tags: ["Chat", "Utility"], + authors: [EquicordDevs.creations], settings, - TranslateMessage: TranslateMessage, + patches: [ { find: '.CUSTOM_GIFT?""', - replacement: { - match: /renderContentOnly:\i}=\i;/, - replace: "$&$self.TranslateMessage(arguments[0].message.content).then(response => arguments[0].message.content = response);" - } + replacement: [ + { + match: /message:(\i),message:\{id:\i\}.{0,200}renderContentOnly:\i\}=\i;/, + replace: "$&$1=$self.transformMessage($1);", + }, + { + match: /childrenMessageContent:(\i),/g, + replace: "childrenMessageContent:$self.wrapContent($1,arguments[0].message.id),", + }, + ], }, - ] + ], + + transformMessage(message: MessageWithContent): MessageWithContent { + if (!settings.store.autoTranslate || !shouldTranslate(message)) { + translatedMessages.delete(message.id); + return message; + } + + const cached = getCached(message.id); + if (cached) { + if (cached.original !== message.content) { + clearCache(message.id); + translatedMessages.delete(message.id); + return message; + } + translatedMessages.set(message.id, cached.sourceLang); + return Object.assign(Object.create(Object.getPrototypeOf(message)), message, { + content: cached.translated, + }) as MessageWithContent; + } + + translatedMessages.delete(message.id); + if (!isInProgress(message.id)) { + translate(message.id, message.content).then(result => { + if (result) triggerReRender(message); + }); + } + + return message; + }, + + wrapContent(content: any, messageId: string) { + const sourceLang = translatedMessages.get(messageId); + if (!sourceLang) return content; + return ( + <> + {content} + {settings.store.showIndicator && ( +
translated from {sourceLang}
+ )} + + ); + }, }); diff --git a/src/equicordplugins/messageTranslate/settings.ts b/src/equicordplugins/messageTranslate/settings.ts new file mode 100644 index 000000000..491240737 --- /dev/null +++ b/src/equicordplugins/messageTranslate/settings.ts @@ -0,0 +1,72 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2026 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import { definePluginSettings } from "@api/Settings"; +import { OptionType } from "@utils/types"; + +export const settings = definePluginSettings({ + targetLanguage: { + type: OptionType.STRING, + description: "Target language code for translations (e.g. en, es, fr, de, ja).", + default: "en", + }, + confidenceRequirement: { + type: OptionType.NUMBER, + description: "Minimum confidence (0 to 1) required to show a translation.", + default: 0.8, + }, + autoTranslate: { + type: OptionType.BOOLEAN, + description: "Automatically translate messages as they appear.", + default: true, + }, + skipOwnMessages: { + type: OptionType.BOOLEAN, + description: "Do not translate your own messages.", + default: true, + }, + skipBotMessages: { + type: OptionType.BOOLEAN, + description: "Do not translate bot messages.", + default: false, + }, + ignoredGuilds: { + type: OptionType.STRING, + description: "Comma-separated list of server IDs to not translate in.", + default: "", + }, + ignoredChannels: { + type: OptionType.STRING, + description: "Comma-separated list of channel IDs to not translate in.", + default: "", + }, + ignoredUsers: { + type: OptionType.STRING, + description: "Comma-separated list of user IDs to not translate.", + default: "", + }, + showIndicator: { + type: OptionType.BOOLEAN, + description: "Append a small (translated) indicator to translated messages.", + default: true, + }, +}); + +function parseIdList(value: string): Set { + return new Set(value.split(",").map(s => s.trim()).filter(Boolean)); +} + +export function getIgnoredGuilds(): Set { + return parseIdList(settings.store.ignoredGuilds); +} + +export function getIgnoredChannels(): Set { + return parseIdList(settings.store.ignoredChannels); +} + +export function getIgnoredUsers(): Set { + return parseIdList(settings.store.ignoredUsers); +} diff --git a/src/equicordplugins/messageTranslate/styles.css b/src/equicordplugins/messageTranslate/styles.css new file mode 100644 index 000000000..14cd820e6 --- /dev/null +++ b/src/equicordplugins/messageTranslate/styles.css @@ -0,0 +1,9 @@ +.mt-indicator { + color: var(--text-muted); + font-style: italic; + font-weight: 400; + font-size: 0.7rem; + line-height: 1; + margin-top: 0.15em; + opacity: 0.75; +} diff --git a/src/equicordplugins/messageTranslate/types.ts b/src/equicordplugins/messageTranslate/types.ts new file mode 100644 index 000000000..d6cb8f1f5 --- /dev/null +++ b/src/equicordplugins/messageTranslate/types.ts @@ -0,0 +1,21 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2026 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import type { Message } from "@vencord/discord-types"; + +export interface TranslateResponse { + src: string; + confidence: number; + sentences: { trans?: string; }[]; +} + +export interface CachedTranslation { + original: string; + translated: string; + sourceLang: string; +} + +export type MessageWithContent = Message & { content: string; }; diff --git a/src/equicordplugins/messageTranslate/utils/translate.ts b/src/equicordplugins/messageTranslate/utils/translate.ts new file mode 100644 index 000000000..612b26c1a --- /dev/null +++ b/src/equicordplugins/messageTranslate/utils/translate.ts @@ -0,0 +1,81 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2026 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import { Logger } from "@utils/Logger"; + +import { settings } from "../settings"; +import { CachedTranslation, TranslateResponse } from "../types"; + +const logger = new Logger("MessageTranslate"); + +const translationCache = new Map(); +const inProgress = new Set(); +const failed = new Map(); + +export function getCached(messageId: string): CachedTranslation | undefined { + return translationCache.get(messageId); +} + +export function hasFailed(messageId: string, text: string): boolean { + return failed.get(messageId) === text; +} + +export function isInProgress(messageId: string): boolean { + return inProgress.has(messageId); +} + +export function clearCache(messageId: string) { + translationCache.delete(messageId); + failed.delete(messageId); +} + +async function fetchTranslation(text: string, targetLang: string): Promise { + const url = `https://translate.googleapis.com/translate_a/single?client=gtx&sl=auto&tl=${targetLang}&dt=t&dj=1&q=${encodeURIComponent(text)}`; + const response = await fetch(url); + + if (!response.ok) { + throw new Error(`Translation API returned ${response.status} ${response.statusText}`); + } + + return await response.json(); +} + +export async function translate(messageId: string, text: string): Promise { + if (inProgress.has(messageId)) return null; + if (translationCache.has(messageId)) return translationCache.get(messageId)!; + + inProgress.add(messageId); + + try { + const targetLang = settings.store.targetLanguage; + const response = await fetchTranslation(text, targetLang); + + if (response.src === targetLang || response.confidence < settings.store.confidenceRequirement) { + failed.set(messageId, text); + return null; + } + + const translatedText = response.sentences.map(s => s.trans).filter(Boolean).join(""); + if (!translatedText || translatedText === text) { + failed.set(messageId, text); + return null; + } + + const entry: CachedTranslation = { + original: text, + translated: translatedText, + sourceLang: response.src, + }; + translationCache.set(messageId, entry); + return entry; + } catch (e) { + logger.error("Translation failed", e); + failed.set(messageId, text); + return null; + } finally { + inProgress.delete(messageId); + } +} diff --git a/src/equicordplugins/micLoopbackTester/index.tsx b/src/equicordplugins/micLoopbackTester/index.tsx index 740dc9e18..44af1e5ae 100644 --- a/src/equicordplugins/micLoopbackTester/index.tsx +++ b/src/equicordplugins/micLoopbackTester/index.tsx @@ -116,6 +116,7 @@ const MicLoopbackUserAreaButton: UserAreaButtonFactory = props => { flexGrow: 1 }}> { try { diff --git a/src/equicordplugins/moreStickers/index.tsx b/src/equicordplugins/moreStickers/index.tsx index bc90a31a5..1f0770d76 100644 --- a/src/equicordplugins/moreStickers/index.tsx +++ b/src/equicordplugins/moreStickers/index.tsx @@ -35,6 +35,7 @@ export const settings = definePluginSettings({ export default definePlugin({ name: "MoreStickers", description: t("equicord.moreStickers.description"), + tags: ["Chat", "Emotes", "Media"], authors: [EquicordDevs.Leko, Devs.Arjix], settings, diff --git a/src/equicordplugins/moreUserTags/index.tsx b/src/equicordplugins/moreUserTags/index.tsx index ce0f4bcf8..6c7b9f1a8 100644 --- a/src/equicordplugins/moreUserTags/index.tsx +++ b/src/equicordplugins/moreUserTags/index.tsx @@ -38,6 +38,8 @@ migratePluginToSettings(true, "MoreUserTags", "NoAppsAllowed", "noAppsAllowed"); export default definePlugin({ name: "MoreUserTags", description: t("equicord.moreUserTags.description"), + dependencies: ["MemberListDecoratorsAPI", "MessageDecorationsAPI", "NicknameIconsAPI"], + tags: ["Appearance", "Chat"], authors: [Devs.Cyn, Devs.TheSun, Devs.RyanCaoDev, Devs.LordElias, Devs.AutumnVN, EquicordDevs.Hen, EquicordDevs.meowabyte], settings, patches: [ diff --git a/src/equicordplugins/moyai/index.ts b/src/equicordplugins/moyai/index.ts index 841dc23ef..740a6b944 100644 --- a/src/equicordplugins/moyai/index.ts +++ b/src/equicordplugins/moyai/index.ts @@ -92,6 +92,7 @@ export default definePlugin({ name: "Moyai", authors: [Devs.Megu, Devs.Nuckyz], description: t("equicord.moyai.description"), + tags: ["Fun"], settings, flux: { diff --git a/src/equicordplugins/musicControls/index.tsx b/src/equicordplugins/musicControls/index.tsx index b08d86c67..992db1612 100644 --- a/src/equicordplugins/musicControls/index.tsx +++ b/src/equicordplugins/musicControls/index.tsx @@ -35,7 +35,8 @@ export default definePlugin({ description: t("equicord.musicControls.description"), authors: [Devs.Ven, Devs.afn, Devs.KraXen72, Devs.Av32000, Devs.nin0dev, Devs.thororen, EquicordDevs.vmohammad, Devs.Joona], settings, - tags: [ + tags: ["Media", "Activity"], + searchTerms: [ // Spotify "Spotify", "SpotifyControls", diff --git a/src/equicordplugins/musicControls/spotify/spotifyStyles.css b/src/equicordplugins/musicControls/spotify/spotifyStyles.css index 8f54fa623..d33f4fd47 100644 --- a/src/equicordplugins/musicControls/spotify/spotifyStyles.css +++ b/src/equicordplugins/musicControls/spotify/spotifyStyles.css @@ -70,7 +70,7 @@ position: absolute; top: 50%; left: 50%; - transform: translate(-50%, -50%); + transform: translate(-55%, -50%); } .vc-spotify-button-row { diff --git a/src/equicordplugins/musicControls/tidal/tidalStyles.css b/src/equicordplugins/musicControls/tidal/tidalStyles.css index e5e840cb1..746f6c680 100644 --- a/src/equicordplugins/musicControls/tidal/tidalStyles.css +++ b/src/equicordplugins/musicControls/tidal/tidalStyles.css @@ -135,7 +135,7 @@ position: absolute; top: 50%; left: 50%; - transform: translate(-50%, -50%); + transform: translate(-55%, -50%); } #eq-tdl-info-wrapper { diff --git a/src/equicordplugins/neverPausePreviews/index.tsx b/src/equicordplugins/neverPausePreviews/index.tsx index 7d4aee31e..443ce81a5 100644 --- a/src/equicordplugins/neverPausePreviews/index.tsx +++ b/src/equicordplugins/neverPausePreviews/index.tsx @@ -24,6 +24,7 @@ import definePlugin from "@utils/types"; export default definePlugin({ name: "NeverPausePreviews", description: t("equicord.neverPausePreviews.description"), + tags: ["Media"], authors: [EquicordDevs.vappstar], settingsAboutComponent: () => ( diff --git a/src/equicordplugins/newPluginsManager/index.tsx b/src/equicordplugins/newPluginsManager/index.tsx index e34e40975..5a3c5c4ba 100644 --- a/src/equicordplugins/newPluginsManager/index.tsx +++ b/src/equicordplugins/newPluginsManager/index.tsx @@ -15,6 +15,7 @@ import { openNewPluginsModal } from "./NewPluginsModal"; export default definePlugin({ name: "NewPluginsManager", description: t("equicord.newPluginsManager.description"), + tags: ["Utility"], authors: [Devs.Sqaaakoi], enabledByDefault: true, flux: { diff --git a/src/equicordplugins/noNitroUpsell/index.ts b/src/equicordplugins/noNitroUpsell/index.ts index 5c398afc7..1a3a6c35f 100644 --- a/src/equicordplugins/noNitroUpsell/index.ts +++ b/src/equicordplugins/noNitroUpsell/index.ts @@ -12,6 +12,7 @@ import { OverridePremiumTypeStore } from "@webpack/common"; export default definePlugin({ name: "NoNitroUpsell", description: t("equicord.noNitroUpsell.description"), + tags: ["Utility"], authors: [Devs.thororen], flux: { CONNECTION_OPEN() { diff --git a/src/equicordplugins/noPushToTalk/index.ts b/src/equicordplugins/noPushToTalk/index.ts index e1e01458f..465e87779 100644 --- a/src/equicordplugins/noPushToTalk/index.ts +++ b/src/equicordplugins/noPushToTalk/index.ts @@ -11,6 +11,7 @@ import definePlugin from "@utils/types"; export default definePlugin({ name: "NoPushToTalk", description: t("equicord.noPushToTalk.description"), + tags: ["Servers", "Voice"], authors: [EquicordDevs.omaw], patches: [ { diff --git a/src/equicordplugins/noRPC.discordDesktop/index.ts b/src/equicordplugins/noRPC.discordDesktop/index.ts index 4fe655e72..baf7f96a7 100644 --- a/src/equicordplugins/noRPC.discordDesktop/index.ts +++ b/src/equicordplugins/noRPC.discordDesktop/index.ts @@ -11,6 +11,7 @@ import definePlugin from "@utils/types"; export default definePlugin({ name: "NoRPC", description: t("equicord.noRPC.description"), + tags: ["Privacy", "Servers"], authors: [Devs.Cyn], patches: [ { diff --git a/src/equicordplugins/noRoleHeaders/index.ts b/src/equicordplugins/noRoleHeaders/index.ts index 7ceaf67f8..3168ed171 100644 --- a/src/equicordplugins/noRoleHeaders/index.ts +++ b/src/equicordplugins/noRoleHeaders/index.ts @@ -11,6 +11,7 @@ import definePlugin from "@utils/types"; export default definePlugin({ name: "NoRoleHeaders", description: t("equicord.noRoleHeaders.description"), + tags: ["Appearance", "Fun", "Roles"], authors: [Devs.Samwich], patches: [ { diff --git a/src/equicordplugins/normalizeMessageLinks/index.ts b/src/equicordplugins/normalizeMessageLinks/index.ts index 37d359415..abc2faf95 100644 --- a/src/equicordplugins/normalizeMessageLinks/index.ts +++ b/src/equicordplugins/normalizeMessageLinks/index.ts @@ -11,6 +11,7 @@ import definePlugin from "@utils/types"; export default definePlugin({ name: "NormalizeMessageLinks", description: t("equicord.normalizeMessageLinks.description"), + tags: ["Chat"], authors: [Devs.bb010g], patches: [ { diff --git a/src/equicordplugins/notificationTitle.discordDesktop/index.tsx b/src/equicordplugins/notificationTitle.discordDesktop/index.tsx index 66df8b5ff..f49d30ba3 100644 --- a/src/equicordplugins/notificationTitle.discordDesktop/index.tsx +++ b/src/equicordplugins/notificationTitle.discordDesktop/index.tsx @@ -21,6 +21,7 @@ const MessageTypes = findByPropsLazy("REPLY", "STAGE_RAISE_HAND", "CHANNEL_NAME_ export default definePlugin({ name: "NotificationTitle", description: t("equicord.notificationTitle.description"), + tags: ["Appearance", "Notifications"], authors: [Devs.Kyuuhachi], patches: [ diff --git a/src/equicordplugins/orbolayBridge/index.tsx b/src/equicordplugins/orbolayBridge/index.tsx index be3941c3f..6bd4e3b9b 100644 --- a/src/equicordplugins/orbolayBridge/index.tsx +++ b/src/equicordplugins/orbolayBridge/index.tsx @@ -315,6 +315,7 @@ const createWebsocket = () => { export default definePlugin({ name: "OrbolayBridge", description: t("equicord.orbolayBridge.description"), + tags: ["Utility", "Voice"], authors: [EquicordDevs.SpikeHD], settings, flux: { diff --git a/src/equicordplugins/partyMode/index.ts b/src/equicordplugins/partyMode/index.ts index 11957fe76..dbda9c3bd 100644 --- a/src/equicordplugins/partyMode/index.ts +++ b/src/equicordplugins/partyMode/index.ts @@ -45,6 +45,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "PartyMode", description: t("equicord.partyMode.description"), + tags: ["Fun"], authors: [Devs.UwUDev], reporterTestable: ReporterTestable.None, settings, diff --git a/src/equicordplugins/pinIcon/index.tsx b/src/equicordplugins/pinIcon/index.tsx index cc83ebd5a..32252ef1a 100644 --- a/src/equicordplugins/pinIcon/index.tsx +++ b/src/equicordplugins/pinIcon/index.tsx @@ -26,6 +26,7 @@ const PinIcon = findComponentByCodeLazy("1-.06-.63L6.16"); export default definePlugin({ name: "PinIcon", description: t("equicord.pinIcon.description"), + tags: ["Appearance", "Chat"], authors: [EquicordDevs.iamme], patches: [ { diff --git a/src/equicordplugins/pingNotifications/index.tsx b/src/equicordplugins/pingNotifications/index.tsx index 608f9845c..36e7b1d77 100644 --- a/src/equicordplugins/pingNotifications/index.tsx +++ b/src/equicordplugins/pingNotifications/index.tsx @@ -93,6 +93,7 @@ function isUserBlocked(userId) { export default definePlugin({ name: "PingNotifications", description: t("equicord.pingNotifications.description"), + tags: ["Chat", "Friends", "Notifications", "Servers"], authors: [EquicordDevs.smuki], settings, diff --git a/src/equicordplugins/platformSpoofer/index.tsx b/src/equicordplugins/platformSpoofer/index.tsx index f838994f2..0aaa77949 100644 --- a/src/equicordplugins/platformSpoofer/index.tsx +++ b/src/equicordplugins/platformSpoofer/index.tsx @@ -53,6 +53,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "PlatformSpoofer", description: t("equicord.platformSpoofer.description"), + tags: ["Utility"], authors: [EquicordDevs.Drag, EquicordDevs.neoarz], settingsAboutComponent: () => ( @@ -63,18 +64,17 @@ export default definePlugin({ patches: [ { find: "_doIdentify(){", - replacement: { - match: /(\[IDENTIFY\].*let.{0,5}=\{.*properties:)(.*),presence/, - replace: "$1{...$2,...$self.getPlatform(true)},presence" - } + replacement: [ + { + match: /window._ws=null,null!=\i/, + replace: "false" + }, + { + match: /(?<="GatewaySocket"\)\}\),properties:)(\i)/, + replace: "{...$1,...$self.getPlatform(true)}" + }, + ] }, - { - find: '("AppSkeleton");', - replacement: { - match: /(?<=\.isPlatformEmbedded.{0,50}\i\)\)\}.{0,30})\i\?\i\.\i\.set\(.{0,10}:/, - replace: "" - } - } ], getPlatform(bypass, userId?: any) { const platform = settings.store.platform ?? "desktop"; diff --git a/src/equicordplugins/polishWording/index.ts b/src/equicordplugins/polishWording/index.ts index 84b5777e9..f5988314c 100644 --- a/src/equicordplugins/polishWording/index.ts +++ b/src/equicordplugins/polishWording/index.ts @@ -65,6 +65,8 @@ const settings = definePluginSettings({ export default definePlugin({ name: "PolishWording", description: t("equicord.polishWording.description"), + dependencies: ["MessageEventsAPI"], + tags: ["Chat"], authors: [Devs.Samwich, EquicordDevs.WKoA], onBeforeMessageSend: presendObject, settings, diff --git a/src/equicordplugins/profileSets/index.tsx b/src/equicordplugins/profileSets/index.tsx index 2d90719c1..f26e153ee 100644 --- a/src/equicordplugins/profileSets/index.tsx +++ b/src/equicordplugins/profileSets/index.tsx @@ -30,6 +30,7 @@ export const settings = definePluginSettings({ export default definePlugin({ name: "ProfileSets", description: t("equicord.profileSets.description"), + tags: ["Appearance", "Customisation", "Utility"], authors: [EquicordDevs.omaw, EquicordDevs.justjxke], settings, patches: [ diff --git a/src/equicordplugins/questify/index.tsx b/src/equicordplugins/questify/index.tsx index 4995d3325..56d674ef3 100644 --- a/src/equicordplugins/questify/index.tsx +++ b/src/equicordplugins/questify/index.tsx @@ -283,16 +283,24 @@ function QuestTileContextMenu(children: React.ReactNode[], props: { quest: any; clearInterval(interval.progressTimeout); clearTimeout(interval.rerenderTimeout); activeQuestIntervals.delete(props.quest.id); + + if (interval.type === "play") { + void reportPlayGameQuestProgress(refreshQuest(props.quest), true, QuestifyLogger, { + attempts: 3, + delay: 2500, + }); + } + resetQuestsToResume(props.quest); rerenderQuests(); } }} />) : canAutoComplete ? ( - { processQuestForAutoComplete(props.quest, true); }} - />) : null + { processQuestForAutoComplete(props.quest, true); }} + />) : null } { + await reportPlayGameQuestProgress(refreshQuest(quest), true, QuestifyLogger, { + attempts: 3, + delay: 2500, + }); + } + + async function handleQuestComplete(): Promise { clearTrackingTimers(); activeQuestIntervals.delete(quest.id); + + await sendTerminalHeartbeat(); QuestifyLogger.info(`[${getFormattedNow()}] Quest ${questName} completed.`); if (settings.store.notifyOnQuestComplete) { @@ -856,7 +873,7 @@ async function startPlayGameProgressTracking(quest: Quest, target: { raw: number } if (result.completed || result.progress >= questTarget) { - handleQuestComplete(); + await handleQuestComplete(); return; } @@ -900,7 +917,7 @@ async function startPlayGameProgressTracking(quest: Quest, target: { raw: number } if (initial.completed || initial.progress >= questTarget) { - handleQuestComplete(); + await handleQuestComplete(); return; } @@ -1344,6 +1361,7 @@ migratePluginToSettings(true, "Questify", "QuestCompleter", "completeVideoQuests export default definePlugin({ name: "Questify", description: t("equicord.questify.description"), + tags: ["Appearance", "Customisation", "Privacy", "Utility"], authors: [EquicordDevs.Etorix], dependencies: ["AudioPlayerAPI", "ServerListAPI"], startAt: StartAt.Init, // Needed in order to beat Read All Messages to inserting above the server list. @@ -1431,7 +1449,7 @@ export default definePlugin({ group: true, replacement: [ { - match: /(?<=\i\)&&"xs"===\i;)/, + match: /(?<=null&&"xs"===\i;)/, replace: "const shouldHideMembersListActivelyPlayingIcon=$self.shouldHideMembersListActivelyPlayingIcon();" }, { @@ -1989,6 +2007,15 @@ export default definePlugin({ } activeQuestIntervals.forEach((intervalData, questId) => { + const quest = QuestsStore.getQuest(questId); + + if (intervalData.type === "play" && quest) { + void reportPlayGameQuestProgress(refreshQuest(quest), true, QuestifyLogger, { + attempts: 3, + delay: 2500, + }); + } + clearInterval(intervalData.progressTimeout); clearTimeout(intervalData.rerenderTimeout); activeQuestIntervals.delete(questId); diff --git a/src/equicordplugins/questify/styles.css b/src/equicordplugins/questify/styles.css index 38912c83b..c3ebcc613 100644 --- a/src/equicordplugins/questify/styles.css +++ b/src/equicordplugins/questify/styles.css @@ -362,4 +362,9 @@ .questify-quest-item-restyle > :nth-child(2) [class*="container"] { border-bottom-left-radius: 8px; border-bottom-right-radius: 8px; -} \ No newline at end of file +} + +/* Prevent completion confetti from covering quest buttons */ +div[id^="quest-tile-"] div[class^="confetti__"] { + pointer-events: none; +} diff --git a/src/equicordplugins/questify/utils/misc.tsx b/src/equicordplugins/questify/utils/misc.tsx index fa91de5f3..7f7eb1b31 100644 --- a/src/equicordplugins/questify/utils/misc.tsx +++ b/src/equicordplugins/questify/utils/misc.tsx @@ -346,14 +346,14 @@ export async function reportPlayGameQuestProgress(quest: Quest, terminal: boolea if (!quest.userStatus?.enrolledAt) { logger?.warn(`[${getFormattedNow()}] Cannot send heartbeat for unenrolled Quest ${questName}.`); return { progress: null, completed: false }; - } else if (quest.userStatus?.completedAt) { + } else if (quest.userStatus?.completedAt && !terminal) { return { progress: null, completed: true }; } const maxAttempts = options?.attempts ?? 1; const delay = options?.delay ?? 2500; const timeout = options?.timeout ?? 10000; - const streamKey = options?.streamKey ?? `call:${quest.id}:1`; + const streamKey = options?.streamKey; const applicationId = options?.applicationId ?? quest.config.application.id; const questPlayType = quest.config.taskConfigV2?.tasks.PLAY_ON_DESKTOP || quest.config.taskConfigV2?.tasks.PLAY_ON_XBOX || quest.config.taskConfigV2?.tasks.PLAY_ON_PLAYSTATION || quest.config.taskConfigV2?.tasks.PLAY_ACTIVITY; diff --git a/src/equicordplugins/quickThemeSwitcher.discordDesktop/index.tsx b/src/equicordplugins/quickThemeSwitcher.discordDesktop/index.tsx index b12991173..24c4fe895 100644 --- a/src/equicordplugins/quickThemeSwitcher.discordDesktop/index.tsx +++ b/src/equicordplugins/quickThemeSwitcher.discordDesktop/index.tsx @@ -245,6 +245,7 @@ const handleThemeNamesChange = () => settings.store.autoRefresh && debouncedRefr export default definePlugin({ name: "QuickThemeSwitcher", description: t("equicord.quickThemeSwitcher.description"), + tags: ["Appearance", "Utility"], authors: [Devs.prism], settings, startAt: StartAt.DOMContentLoaded, diff --git a/src/equicordplugins/quoter/index.tsx b/src/equicordplugins/quoter/index.tsx index a4e454ee3..2540e7ef9 100644 --- a/src/equicordplugins/quoter/index.tsx +++ b/src/equicordplugins/quoter/index.tsx @@ -59,6 +59,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "Quoter", description: t("equicord.quoter.description"), + tags: ["Chat"], authors: [Devs.Samwich, Devs.thororen, EquicordDevs.neoarz, Devs.prism], settings, diff --git a/src/equicordplugins/randomVoice/index.tsx b/src/equicordplugins/randomVoice/index.tsx index 98a4f71cc..5a0a8c0e1 100644 --- a/src/equicordplugins/randomVoice/index.tsx +++ b/src/equicordplugins/randomVoice/index.tsx @@ -672,6 +672,8 @@ function renderOperationGroup({ export default definePlugin({ name: "RandomVoice", description: t("equicord.randomVoice.description"), + dependencies: ["UserAreaAPI"], + tags: ["Fun", "Voice"], authors: [EquicordDevs.xijexo, EquicordDevs.omaw, Devs.thororen], settings, diff --git a/src/equicordplugins/recentDMSwitcher/index.tsx b/src/equicordplugins/recentDMSwitcher/index.tsx index 53f842070..99e7fcaae 100644 --- a/src/equicordplugins/recentDMSwitcher/index.tsx +++ b/src/equicordplugins/recentDMSwitcher/index.tsx @@ -333,6 +333,7 @@ function showCycleToast() { export default definePlugin({ name: "RecentDMSwitcher", description: t("equicord.recentDMSwitcher.description"), + tags: ["Chat", "Utility"], authors: [EquicordDevs.mmeta], settings, diff --git a/src/equicordplugins/remix/index.tsx b/src/equicordplugins/remix/index.tsx index bffd08131..d0d9066d9 100644 --- a/src/equicordplugins/remix/index.tsx +++ b/src/equicordplugins/remix/index.tsx @@ -72,6 +72,7 @@ export function sendRemix(blob: Blob) { export default definePlugin({ name: "RemixRevived", description: t("equicord.remix.description"), + tags: ["Customisation", "Fun"], authors: [EquicordDevs.MrDiamond, EquicordDevs.meowabyte], contextMenus: { "channel-attach": UploadContextMenuPatch, diff --git a/src/equicordplugins/repeatMessages/index.tsx b/src/equicordplugins/repeatMessages/index.tsx index bbdb9827b..f0ca01d8c 100644 --- a/src/equicordplugins/repeatMessages/index.tsx +++ b/src/equicordplugins/repeatMessages/index.tsx @@ -133,6 +133,8 @@ migratePluginSettings("RepeatMessages", "RepeatMessage"); export default definePlugin({ name: "RepeatMessages", description: t("equicord.repeatMessages.description"), + dependencies: ["MessagePopoverAPI"], + tags: ["Chat"], authors: [EquicordDevs.Tolgchu, Devs.thororen], contextMenus: { "message": messageCtxPatch diff --git a/src/equicordplugins/replyPingControl/index.ts b/src/equicordplugins/replyPingControl/index.ts index bce9d505c..bc246b829 100644 --- a/src/equicordplugins/replyPingControl/index.ts +++ b/src/equicordplugins/replyPingControl/index.ts @@ -28,6 +28,7 @@ export const settings = definePluginSettings({ export default definePlugin({ name: "ReplyPingControl", description: t("equicord.replyPingControl.description"), + tags: ["Chat", "Notifications"], authors: [Devs.ant0n, EquicordDevs.MrDiamond], settings, diff --git a/src/equicordplugins/richMagnetLinks/index.tsx b/src/equicordplugins/richMagnetLinks/index.tsx index db5c11fbd..3a835f069 100644 --- a/src/equicordplugins/richMagnetLinks/index.tsx +++ b/src/equicordplugins/richMagnetLinks/index.tsx @@ -14,6 +14,7 @@ export default definePlugin({ authors: [EquicordDevs.cassie, EquicordDevs.mochienya, EquicordDevs.secp192k1], name: "RichMagnetLinks", description: t("equicord.richMagnetLinks.description"), + tags: ["Appearance", "Chat"], patches: [ { find: "AUTO_MODERATION_SYSTEM_MESSAGE_RULES:", diff --git a/src/equicordplugins/richPresence/index.tsx b/src/equicordplugins/richPresence/index.tsx index 8c0d4874e..d5d90f5bb 100644 --- a/src/equicordplugins/richPresence/index.tsx +++ b/src/equicordplugins/richPresence/index.tsx @@ -22,80 +22,81 @@ type SettingsKey = keyof SettingsStore; const logger = new Logger("RichPresence"); -const services: Record = { - [ServiceTab.AudioBookShelf]: abs, - [ServiceTab.Tosu]: tosu, - [ServiceTab.StatsFm]: statsfm, - [ServiceTab.Jellyfin]: jellyfin, - [ServiceTab.ListenBrainz]: listenbrainz, - [ServiceTab.GensokyoRadio]: gensokyoRadio, +const services: Record = { + [ServiceTab.AudioBookShelf]: abs, + [ServiceTab.Tosu]: tosu, + [ServiceTab.StatsFm]: statsfm, + [ServiceTab.Jellyfin]: jellyfin, + [ServiceTab.ListenBrainz]: listenbrainz, + [ServiceTab.GensokyoRadio]: gensokyoRadio, }; const enableKeys: Record = { - [ServiceTab.AudioBookShelf]: "abs_enabled", - [ServiceTab.Tosu]: "tosu_enabled", - [ServiceTab.StatsFm]: "sfm_enabled", - [ServiceTab.Jellyfin]: "jf_enabled", - [ServiceTab.ListenBrainz]: "lb_enabled", - [ServiceTab.GensokyoRadio]: "gr_enabled", + [ServiceTab.AudioBookShelf]: "abs_enabled", + [ServiceTab.Tosu]: "tosu_enabled", + [ServiceTab.StatsFm]: "sfm_enabled", + [ServiceTab.Jellyfin]: "jf_enabled", + [ServiceTab.ListenBrainz]: "lb_enabled", + [ServiceTab.GensokyoRadio]: "gr_enabled", }; const activeServices = new Set(); function syncServices() { - const globalEnabled = settings.store.enabled; + const globalEnabled = settings.store.enabled; - for (const [id, service] of Object.entries(services)) { - const shouldRun = - globalEnabled && !!settings.store[enableKeys[id]]; - const isRunning = activeServices.has(id); + for (const [id, service] of Object.entries(services)) { + const shouldRun = + globalEnabled && !!settings.store[enableKeys[id]]; + const isRunning = activeServices.has(id); - if (shouldRun && !isRunning) { - logger.info(`Starting ${id} service`); - service.start(); - activeServices.add(id); - } else if (!shouldRun && isRunning) { - logger.info(`Stopping ${id} service`); - service.stop(); - activeServices.delete(id); - } - } + if (shouldRun && !isRunning) { + logger.info(`Starting ${id} service`); + service.start(); + activeServices.add(id); + } else if (!shouldRun && isRunning) { + logger.info(`Stopping ${id} service`); + service.stop(); + activeServices.delete(id); + } + } } function stopAllServices() { - for (const id of activeServices) { - logger.info(`Stopping ${id} service`); - services[id].stop(); - } - activeServices.clear(); + for (const id of activeServices) { + logger.info(`Stopping ${id} service`); + services[id].stop(); + } + activeServices.clear(); } export default definePlugin({ - name: "RichPresence", - description: "Unified rich presence hub for AudioBookShelf, osu!, stats.fm, Jellyfin, ListenBrainz, and Gensokyo Radio.", - authors: [ - EquicordDevs.vmohammad, - Devs.AutumnVN, - EquicordDevs.Crxa, - Devs.SerStars, - EquicordDevs.ZcraftElite, - EquicordDevs.qouesm, - Devs.RyanCaoDev, - EquicordDevs.Prince527, - EquicordDevs.creations, - ], - reporterTestable: ReporterTestable.None, + name: "RichPresence", + description: "Unified rich presence hub for AudioBookShelf, osu!, stats.fm, Jellyfin, ListenBrainz, and Gensokyo Radio.", + tags: ["Activity"], + authors: [ + EquicordDevs.vmohammad, + Devs.AutumnVN, + EquicordDevs.Crxa, + Devs.SerStars, + EquicordDevs.ZcraftElite, + EquicordDevs.qouesm, + Devs.RyanCaoDev, + EquicordDevs.Prince527, + EquicordDevs.creations, + ], + reporterTestable: ReporterTestable.None, - settings, + settings, - start() { - migrateOldSettings(); - syncServices(); - setOnServiceChange(syncServices); - }, + start() { + migrateOldSettings(); + syncServices(); + setOnServiceChange(syncServices); + }, - stop() { - stopAllServices(); - setOnServiceChange(null); - }, + stop() { + stopAllServices(); + setOnServiceChange(null); + }, }); diff --git a/src/equicordplugins/rpcEditor/ReplaceSettings.tsx b/src/equicordplugins/rpcEditor/ReplaceSettings.tsx index b85b0f7c1..81d541bf5 100644 --- a/src/equicordplugins/rpcEditor/ReplaceSettings.tsx +++ b/src/equicordplugins/rpcEditor/ReplaceSettings.tsx @@ -94,7 +94,7 @@ export function ReplaceSettings({ appIds, update, save }: SettingsProps) { } Application ID { onChange(v, i, "appId"); }} @@ -125,7 +125,7 @@ export function ReplaceSettings({ appIds, update, save }: SettingsProps) { <> Stream URL (must be YouTube or Twitch) { onChange(v, i, "newStreamUrl"); }} diff --git a/src/equicordplugins/rpcEditor/index.tsx b/src/equicordplugins/rpcEditor/index.tsx index e87b294a7..ad90bc880 100644 --- a/src/equicordplugins/rpcEditor/index.tsx +++ b/src/equicordplugins/rpcEditor/index.tsx @@ -74,6 +74,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "RPCEditor", description: t("equicord.rpcEditor.description"), + tags: ["Customisation"], authors: [Devs.Nyako, Devs.nin0dev], patches: [ { diff --git a/src/equicordplugins/rpcStats/index.tsx b/src/equicordplugins/rpcStats/index.tsx index d8b321229..e913257b9 100644 --- a/src/equicordplugins/rpcStats/index.tsx +++ b/src/equicordplugins/rpcStats/index.tsx @@ -173,6 +173,7 @@ async function updateData() { export default definePlugin({ name: "RPCStats", description: t("equicord.rpcStats.description"), + tags: ["Utility"], authors: [Devs.Samwich], async start() { updateData(); diff --git a/src/equicordplugins/saveFavoriteGIFs/index.tsx b/src/equicordplugins/saveFavoriteGIFs/index.tsx index 718df9975..cebca5b1a 100644 --- a/src/equicordplugins/saveFavoriteGIFs/index.tsx +++ b/src/equicordplugins/saveFavoriteGIFs/index.tsx @@ -116,6 +116,8 @@ const settings = definePluginSettings({ export default definePlugin({ name: "SaveFavoriteGIFs", description: t("equicord.saveFavoriteGIFs.description"), + dependencies: ["CommandsAPI"], + tags: ["Emotes", "Utility"], authors: [Devs.thororen], settings, commands: [ diff --git a/src/equicordplugins/scheduledMessages/index.tsx b/src/equicordplugins/scheduledMessages/index.tsx index 150f7416d..887502362 100644 --- a/src/equicordplugins/scheduledMessages/index.tsx +++ b/src/equicordplugins/scheduledMessages/index.tsx @@ -87,6 +87,8 @@ function handleReactionEvent(event: FluxReactionEvent): void { export default definePlugin({ name: "ScheduledMessages", description: t("equicord.scheduledMessages.description"), + dependencies: ["ChatInputButtonAPI", "MessageAccessoriesAPI", "MessageEventsAPI"], + tags: ["Chat", "Utility"], authors: [EquicordDevs.mmeta, Devs.prism], settings, diff --git a/src/equicordplugins/screenRecorder.equibop/index.tsx b/src/equicordplugins/screenRecorder.equibop/index.tsx index 0306c7785..7bdc9c2a9 100644 --- a/src/equicordplugins/screenRecorder.equibop/index.tsx +++ b/src/equicordplugins/screenRecorder.equibop/index.tsx @@ -16,6 +16,7 @@ let recoder: MediaRecorder; export default definePlugin({ name: "ScreenRecorder", description: t("equicord.screenRecorder.description"), + tags: ["Chat"], authors: [Devs.AutumnVN], contextMenus: { "channel-attach": startRecording @@ -55,7 +56,7 @@ function stopRecording(children, props) { } action={() => { recoder.addEventListener("dataavailable", e => { - const file = new File([e.data], "watch if cute.webm", { type: "video/webm" }); + const file = new File([e.data], "recording.webm", { type: "video/webm" }); UploadHandler.promptToUpload([file], props.channel, 0); }); recoder.stop(); diff --git a/src/equicordplugins/searchFix/index.tsx b/src/equicordplugins/searchFix/index.tsx index a12b0517e..331216b86 100644 --- a/src/equicordplugins/searchFix/index.tsx +++ b/src/equicordplugins/searchFix/index.tsx @@ -40,6 +40,7 @@ function settingsComponent() { export default definePlugin({ name: "SearchFix", description: t("equicord.searchFix.description"), + tags: ["Utility"], settingsAboutComponent: () => settingsComponent(), authors: [EquicordDevs.Jaxx], patches: [ diff --git a/src/equicordplugins/sekaiStickers/index.tsx b/src/equicordplugins/sekaiStickers/index.tsx index 1a0f29e7e..bea2ed1c7 100644 --- a/src/equicordplugins/sekaiStickers/index.tsx +++ b/src/equicordplugins/sekaiStickers/index.tsx @@ -34,6 +34,8 @@ let IS_FONTS_LOADED = false; export default definePlugin({ name: "SekaiStickers", description: t("equicord.sekaiStickers.description"), + dependencies: ["ChatInputButtonAPI"], + tags: ["Chat", "Emotes"], authors: [Devs.MaiKokain], settings, chatBarButton: { diff --git a/src/equicordplugins/selfForward/index.ts b/src/equicordplugins/selfForward/index.ts index f5dad9363..9c4b8c124 100644 --- a/src/equicordplugins/selfForward/index.ts +++ b/src/equicordplugins/selfForward/index.ts @@ -11,6 +11,7 @@ import definePlugin from "@utils/types"; export default definePlugin({ name: "SelfForward", description: t("equicord.selfForward.description"), + tags: ["Utility"], authors: [EquicordDevs.VillainsRule], patches: [ { diff --git a/src/equicordplugins/serverSearch/index.tsx b/src/equicordplugins/serverSearch/index.tsx index 6c3fddf4d..beb9d45a8 100644 --- a/src/equicordplugins/serverSearch/index.tsx +++ b/src/equicordplugins/serverSearch/index.tsx @@ -11,8 +11,7 @@ import ErrorBoundary from "@components/ErrorBoundary"; import { EquicordDevs } from "@utils/constants"; import { t } from "@utils/translation"; import definePlugin from "@utils/types"; -import { FluxDispatcher } from "@webpack/common"; -import { Tooltip } from "webpack/common/components"; +import { FluxDispatcher, Tooltip } from "@webpack/common"; function SearchIcon() { return ( @@ -30,6 +29,7 @@ export default definePlugin({ name: "ServerSearch", authors: [EquicordDevs.camila314], description: t("equicord.serverSearch.description"), + tags: ["Shortcuts", "Servers"], renderButton() { return diff --git a/src/equicordplugins/showBadgesInChat/index.tsx b/src/equicordplugins/showBadgesInChat/index.tsx index 887325a24..fecfaba9d 100644 --- a/src/equicordplugins/showBadgesInChat/index.tsx +++ b/src/equicordplugins/showBadgesInChat/index.tsx @@ -6,12 +6,12 @@ import "./styles.css"; +import badges from "@plugins/_api/badges"; import { Devs, EquicordDevs } from "@utils/constants"; import { isEquicordPluginDev, isPluginDev } from "@utils/misc"; import { t } from "@utils/translation"; import definePlugin from "@utils/types"; import { findComponentByCodeLazy, findCssClassesLazy } from "@webpack"; -import badges from "plugins/_api/badges"; const { roleIcon } = findCssClassesLazy("roleIcon", "separator"); const RoleIconComponent = findComponentByCodeLazy("#{intl::ROLE_ICON_ALT_TEXT}"); @@ -143,6 +143,8 @@ export default definePlugin({ name: "ShowBadgesInChat", authors: [Devs.Inbestigator, EquicordDevs.KrystalSkull], description: t("equicord.showBadgesInChat.description"), + dependencies: ["MessageDecorationsAPI"], + tags: ["Appearance", "Chat"], settings, renderMessageDecoration(props) { return props.message?.author ? : null; diff --git a/src/equicordplugins/showMessageEmbeds/index.tsx b/src/equicordplugins/showMessageEmbeds/index.tsx index d4223125a..ba7a62b6b 100644 --- a/src/equicordplugins/showMessageEmbeds/index.tsx +++ b/src/equicordplugins/showMessageEmbeds/index.tsx @@ -194,6 +194,7 @@ function showFailureToast(message: string) { export default definePlugin({ name: "ShowMessageEmbeds", description: t("equicord.showMessageEmbeds.description"), + tags: ["Appearance", "Chat"], authors: [EquicordDevs.Suffocate], patches: [ diff --git a/src/equicordplugins/showResourceChannels/index.ts b/src/equicordplugins/showResourceChannels/index.ts index c87c9805f..f7b6e6df1 100644 --- a/src/equicordplugins/showResourceChannels/index.ts +++ b/src/equicordplugins/showResourceChannels/index.ts @@ -11,6 +11,7 @@ import definePlugin from "@utils/types"; export default definePlugin({ name: "ShowResourceChannels", description: t("equicord.showResourceChannels.description"), + tags: ["Servers"], authors: [EquicordDevs.VillainsRule], patches: [ { diff --git a/src/equicordplugins/showSongName/index.tsx b/src/equicordplugins/showSongName/index.tsx index 83436a384..b6972acf0 100644 --- a/src/equicordplugins/showSongName/index.tsx +++ b/src/equicordplugins/showSongName/index.tsx @@ -11,6 +11,7 @@ import definePlugin from "@utils/types"; export default definePlugin({ name: "ShowSongName", description: t("equicord.showSongName.description"), + tags: ["Activity"], authors: [Devs.prism], patches: [ diff --git a/src/equicordplugins/sidebarChat/index.tsx b/src/equicordplugins/sidebarChat/index.tsx index 717b041b6..738eb6e49 100644 --- a/src/equicordplugins/sidebarChat/index.tsx +++ b/src/equicordplugins/sidebarChat/index.tsx @@ -131,6 +131,7 @@ export default definePlugin({ name: "SidebarChat", authors: [Devs.Joona], description: t("equicord.sidebarChat.description"), + tags: ["Appearance", "Chat", "Servers"], patches: [ { find: 'case"pendingFriends":', diff --git a/src/equicordplugins/signature/index.tsx b/src/equicordplugins/signature/index.tsx index 6396f3585..b87e081db 100644 --- a/src/equicordplugins/signature/index.tsx +++ b/src/equicordplugins/signature/index.tsx @@ -101,6 +101,8 @@ const ChatBarContextCheckbox: NavContextMenuPatchCallback = children => { export default definePlugin({ name: "Signature", description: t("equicord.signature.description"), + dependencies: ["CommandsAPI", "ChatInputButtonAPI", "MessagePopoverAPI"], + tags: ["Appearance", "Chat"], authors: [Devs.Ven, Devs.Rini, Devs.ImBanana, EquicordDevs.KrystalSkull], onBeforeMessageSend(channelId, msg) { if (!settings.store.isEnabled) { diff --git a/src/equicordplugins/snowfall/index.tsx b/src/equicordplugins/snowfall/index.tsx index 7664ed16d..276f70f29 100644 --- a/src/equicordplugins/snowfall/index.tsx +++ b/src/equicordplugins/snowfall/index.tsx @@ -164,7 +164,7 @@ class CopleSnow { private static readonly transitionEndEvent = { WebkitTransition: "webkitTransitionEnd", OTransition: "oTransitionEnd", Moztransition: "transitionend", transition: "transitionend" }[ - this.cssPrefixedNames.transition ?? "transition" + this.cssPrefixedNames.transition ?? "transition" ] ?? "transitionend"; private static random(min: number, max: number, deviation?: number): number { @@ -452,6 +452,7 @@ let container: HTMLDivElement | null = null; export default definePlugin({ name: "Snowfall", description: t("equicord.snowfall.description"), + tags: ["Appearance"], authors: [EquicordDevs.ZcraftElite, EquicordDevs.square], settingsAboutComponent: () => ( diff --git a/src/equicordplugins/soggy/index.tsx b/src/equicordplugins/soggy/index.tsx index 605f6027b..133765c71 100644 --- a/src/equicordplugins/soggy/index.tsx +++ b/src/equicordplugins/soggy/index.tsx @@ -138,9 +138,10 @@ const settings = definePluginSettings({ export default definePlugin({ name: "Soggy", description: t("equicord.soggy.description"), + tags: ["Fun"], authors: [EquicordDevs.sliwka], settings, - dependencies: ["AudioPlayerAPI"], + dependencies: ["AudioPlayerAPI", "HeaderBarAPI"], headerBarButton: { icon: () => ( diff --git a/src/equicordplugins/songLink.desktop/index.tsx b/src/equicordplugins/songLink.desktop/index.tsx index e275f9dd7..e81582bdc 100644 --- a/src/equicordplugins/songLink.desktop/index.tsx +++ b/src/equicordplugins/songLink.desktop/index.tsx @@ -52,6 +52,8 @@ export const Native = VencordNative.pluginHelpers.SongLink as PluginNative { export default definePlugin({ name: "StatusPresets", description: t("equicord.statusPresets.description"), + tags: ["Activity", "Utility"], authors: [EquicordDevs.iamme], settings: settings, dependencies: ["UserSettingsAPI"], diff --git a/src/equicordplugins/statusWhileActive.desktop/index.ts b/src/equicordplugins/statusWhileActive.desktop/index.ts index 6ad70e298..dc290dd83 100644 --- a/src/equicordplugins/statusWhileActive.desktop/index.ts +++ b/src/equicordplugins/statusWhileActive.desktop/index.ts @@ -57,6 +57,7 @@ function setStatus(preq, status) { export default definePlugin({ name: "StatusWhileActive", description: t("equicord.statusWhileActive.description"), + tags: ["Activity", "Customisation", "Voice"], authors: [EquicordDevs.smuki], settings, flux: { diff --git a/src/equicordplugins/steamStatusSync/index.tsx b/src/equicordplugins/steamStatusSync/index.tsx index 7bbf3a075..b13bd08d3 100644 --- a/src/equicordplugins/steamStatusSync/index.tsx +++ b/src/equicordplugins/steamStatusSync/index.tsx @@ -86,6 +86,7 @@ export const settings = definePluginSettings({ export default definePlugin({ name: "SteamStatusSync", description: t("equicord.steamStatusSync.description"), + tags: ["Activity", "Appearance", "Customisation"], authors: [EquicordDevs.niko], settings, diff --git a/src/equicordplugins/stickerBlocker/index.tsx b/src/equicordplugins/stickerBlocker/index.tsx index 129e26658..810ed7454 100644 --- a/src/equicordplugins/stickerBlocker/index.tsx +++ b/src/equicordplugins/stickerBlocker/index.tsx @@ -131,6 +131,7 @@ function isStickerBlocked(name) { export default definePlugin({ name: "StickerBlocker", description: t("equicord.stickerBlocker.description"), + tags: ["Chat", "Emotes", "Utility"], authors: [Devs.Samwich], patches: [ { diff --git a/src/equicordplugins/streamingCodecDisabler/index.ts b/src/equicordplugins/streamingCodecDisabler/index.ts index 2877b3d57..c6a845888 100644 --- a/src/equicordplugins/streamingCodecDisabler/index.ts +++ b/src/equicordplugins/streamingCodecDisabler/index.ts @@ -57,6 +57,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "StreamingCodecDisabler", description: t("equicord.streamingCodecDisabler.description"), + tags: ["Utility", "Voice"], authors: [EquicordDevs.davidkra230], settings, diff --git a/src/equicordplugins/talkInReverse/index.tsx b/src/equicordplugins/talkInReverse/index.tsx index 03f5bbf67..18ac98b32 100644 --- a/src/equicordplugins/talkInReverse/index.tsx +++ b/src/equicordplugins/talkInReverse/index.tsx @@ -67,7 +67,8 @@ export default definePlugin({ name: "TalkInReverse", authors: [EquicordDevs.Tolgchu], description: t("equicord.talkInReverse.description"), - dependencies: ["MessageEventsAPI"], + dependencies: ["MessageEventsAPI", "ChatInputButtonAPI"], + tags: ["Chat", "Fun"], chatBarButton: { icon: ReverseMessageIcon, render: ReverseMessageToggle diff --git a/src/equicordplugins/themeLibrary/index.tsx b/src/equicordplugins/themeLibrary/index.tsx index 4b909db38..440864ad4 100644 --- a/src/equicordplugins/themeLibrary/index.tsx +++ b/src/equicordplugins/themeLibrary/index.tsx @@ -17,6 +17,7 @@ import { settings } from "./utils/settings"; export default definePlugin({ name: "ThemeLibrary", description: t("equicord.themeLibrary.description"), + tags: ["Appearance", "Customisation"], authors: [EquicordDevs.Fafa], settings, toolboxActions: { diff --git a/src/equicordplugins/tidalEmbeds/index.tsx b/src/equicordplugins/tidalEmbeds/index.tsx index 8814ee97c..8ef20e487 100644 --- a/src/equicordplugins/tidalEmbeds/index.tsx +++ b/src/equicordplugins/tidalEmbeds/index.tsx @@ -11,8 +11,9 @@ import definePlugin from "@utils/types"; export default definePlugin({ name: "TidalEmbeds", description: t("equicord.tidalEmbeds.description"), + tags: ["Appearance", "Chat", "Media"], authors: [EquicordDevs.vmohammad], - dependencies: ["MessageUpdaterAPI"], + dependencies: ["MessageUpdaterAPI", "MessageAccessoriesAPI"], patches: [ { find: "renderEmbeds(", diff --git a/src/equicordplugins/tiktokTTS/index.ts b/src/equicordplugins/tiktokTTS/index.ts index a342f756b..d5ad24702 100644 --- a/src/equicordplugins/tiktokTTS/index.ts +++ b/src/equicordplugins/tiktokTTS/index.ts @@ -212,6 +212,7 @@ async function processQueue() { export default definePlugin({ name: "TiktokTTS", description: t("equicord.tiktokTTS.description"), + tags: ["Accessibility", "Chat", "Voice"], authors: [EquicordDevs.VillainsRule, EquicordDevs.examplegit], dependencies: ["AudioPlayerAPI"], settings, diff --git a/src/equicordplugins/timezones/index.tsx b/src/equicordplugins/timezones/index.tsx index 9af3281f0..533f9582b 100644 --- a/src/equicordplugins/timezones/index.tsx +++ b/src/equicordplugins/timezones/index.tsx @@ -258,6 +258,7 @@ export default definePlugin({ name: "Timezones", authors: [Devs.Aria, EquicordDevs.creations], description: t("equicord.timezones.description"), + tags: ["Appearance", "Chat", "Utility"], contextMenus: { "user-context": userContextMenuPatch }, diff --git a/src/equicordplugins/title/index.ts b/src/equicordplugins/title/index.ts index 923b27f85..a2fe9fe6f 100644 --- a/src/equicordplugins/title/index.ts +++ b/src/equicordplugins/title/index.ts @@ -30,6 +30,7 @@ function setTitle(v: string) { export default definePlugin({ name: "Title", description: t("equicord.title.description"), + tags: ["Customisation"], authors: [Devs.Kyuuhachi], settings, diff --git a/src/equicordplugins/toastNotifications/index.tsx b/src/equicordplugins/toastNotifications/index.tsx index b8ae3c3a3..8ae294be7 100644 --- a/src/equicordplugins/toastNotifications/index.tsx +++ b/src/equicordplugins/toastNotifications/index.tsx @@ -211,6 +211,7 @@ const addMention = (id: string, type: string, guildId?: string): ReactNode => { export default definePlugin({ name: "ToastNotifications", description: t("equicord.toastNotifications.description"), + tags: ["Appearance", "Customisation", "Notifications"], authors: [EquicordDevs.Skully, EquicordDevs.Ethan, EquicordDevs.Buzzy], settings, flux: { diff --git a/src/equicordplugins/toggleVideoBind/index.ts b/src/equicordplugins/toggleVideoBind/index.ts index 562f7ad5b..ebe3002e1 100644 --- a/src/equicordplugins/toggleVideoBind/index.ts +++ b/src/equicordplugins/toggleVideoBind/index.ts @@ -60,6 +60,7 @@ function handleKeydown({ code, ctrlKey, shiftKey, altKey }: KeyboardEvent) { export default definePlugin({ name: "ToggleVideoBind", description: t("equicord.toggleVideoBind.description"), + tags: ["Utility", "Voice"], authors: [EquicordDevs.mochienya], settings, start() { diff --git a/src/equicordplugins/toneIndicators/index.tsx b/src/equicordplugins/toneIndicators/index.tsx index fdeb87093..bd5a2293a 100644 --- a/src/equicordplugins/toneIndicators/index.tsx +++ b/src/equicordplugins/toneIndicators/index.tsx @@ -164,6 +164,7 @@ function patchChildrenTree(children: any): any { export default definePlugin({ name: "ToneIndicators", description: t("equicord.toneIndicators.description"), + tags: ["Chat", "Utility"], authors: [EquicordDevs.justjxke], settings, diff --git a/src/equicordplugins/translatePlus/index.tsx b/src/equicordplugins/translatePlus/index.tsx index d656053a5..ab3fdde7a 100644 --- a/src/equicordplugins/translatePlus/index.tsx +++ b/src/equicordplugins/translatePlus/index.tsx @@ -47,6 +47,8 @@ const messageCtxPatch: NavContextMenuPatchCallback = (children, { message }) => export default definePlugin({ name: "Translate+", description: t("equicord.translatePlus.description"), + dependencies: ["MessageAccessoriesAPI", "MessagePopoverAPI"], + tags: ["Chat", "Utility"], authors: [Devs.Ven, EquicordDevs.Prince527], settings, contextMenus: { diff --git a/src/equicordplugins/triviaAI/index.tsx b/src/equicordplugins/triviaAI/index.tsx index 5a8e8babb..2ca73fe7d 100644 --- a/src/equicordplugins/triviaAI/index.tsx +++ b/src/equicordplugins/triviaAI/index.tsx @@ -41,6 +41,8 @@ const messageCtxPatch: NavContextMenuPatchCallback = (children, { message }: { m export default definePlugin({ name: "TriviaAI", description: t("equicord.triviaAI.description"), + dependencies: ["MessagePopoverAPI"], + tags: ["Appearance", "Customisation", "Fun"], authors: [EquicordDevs.yash], settings, contextMenus: { diff --git a/src/equicordplugins/unitConverter/index.tsx b/src/equicordplugins/unitConverter/index.tsx index 8ddf8a8ec..ac4496c02 100644 --- a/src/equicordplugins/unitConverter/index.tsx +++ b/src/equicordplugins/unitConverter/index.tsx @@ -49,6 +49,8 @@ export const settings = definePluginSettings({ export default definePlugin({ name: "UnitConverter", description: t("equicord.unitConverter.description"), + dependencies: ["MessagePopoverAPI"], + tags: ["Utility"], authors: [Devs.sadan], messagePopoverButton: { icon: ConvertIcon, diff --git a/src/equicordplugins/universalMention/index.tsx b/src/equicordplugins/universalMention/index.tsx index 14a5cb486..56966b0d9 100644 --- a/src/equicordplugins/universalMention/index.tsx +++ b/src/equicordplugins/universalMention/index.tsx @@ -40,6 +40,7 @@ export default definePlugin({ name: "UniversalMention", authors: [EquicordDevs.justjxke], description: t("equicord.universalMention.description"), + tags: ["Chat", "Servers", "Utility"], settings, settingsAboutComponent: () => ( diff --git a/src/equicordplugins/unlimitedAccounts/index.ts b/src/equicordplugins/unlimitedAccounts/index.ts index d483d0070..0f3857f46 100644 --- a/src/equicordplugins/unlimitedAccounts/index.ts +++ b/src/equicordplugins/unlimitedAccounts/index.ts @@ -33,6 +33,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "UnlimitedAccounts", description: t("equicord.unlimitedAccounts.description"), + tags: ["Utility"], authors: [Devs.thororen], settings, patches: [ diff --git a/src/equicordplugins/unreadBadgeCount/index.tsx b/src/equicordplugins/unreadBadgeCount/index.tsx index 1dc928707..341928a4c 100644 --- a/src/equicordplugins/unreadBadgeCount/index.tsx +++ b/src/equicordplugins/unreadBadgeCount/index.tsx @@ -34,6 +34,7 @@ export default definePlugin({ name: "UnreadCountBadge", authors: [Devs.Joona], description: t("equicord.unreadBadgeCount.description"), + tags: ["Appearance", "Customisation", "Servers"], settings, patches: [ diff --git a/src/equicordplugins/urlHighlighter/index.tsx b/src/equicordplugins/urlHighlighter/index.tsx index 39acb8965..96b8149e3 100644 --- a/src/equicordplugins/urlHighlighter/index.tsx +++ b/src/equicordplugins/urlHighlighter/index.tsx @@ -122,6 +122,7 @@ function getMatchingPattern(url: string): PatternEntry | null { export default definePlugin({ name: "UrlHighlighter", description: t("equicord.urlHighlighter.description"), + tags: ["Appearance", "Customisation"], authors: [Devs.prism], settings, diff --git a/src/equicordplugins/userpfp/index.tsx b/src/equicordplugins/userpfp/index.tsx index 454cf1818..505a102c8 100644 --- a/src/equicordplugins/userpfp/index.tsx +++ b/src/equicordplugins/userpfp/index.tsx @@ -66,6 +66,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "UserPFP", description: t("equicord.userpfp.description"), + tags: ["Appearance", "Customisation", "Servers"], authors: [EquicordDevs.nexpid, Devs.thororen, EquicordDevs.soapphia], settings, data, diff --git a/src/equicordplugins/userpluginInstaller.dev/VariableWithCallbacks.ts b/src/equicordplugins/userpluginInstaller.dev/VariableWithCallbacks.ts new file mode 100644 index 000000000..b87476fe2 --- /dev/null +++ b/src/equicordplugins/userpluginInstaller.dev/VariableWithCallbacks.ts @@ -0,0 +1,40 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2025 nin0 + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +export class VariableWithCallbacks { + #value: T; + #callbacks: { + id: number; + callback: (value: T, id: number) => void; + }[] = []; + + constructor(value: T) { + this.#value = value; + } + + value(newValue?: T): T { + if (newValue !== undefined) { + this.#value = newValue; + this.#callbacks.forEach(c => c.callback(this.#value, c.id)); + } + return this.#value; + } + + registerCallback(callback: (value: T, id: number) => void): number { + const id = Date.now(); + this.#callbacks.push({ + id, + callback + }); + return id; + } + + deregisterCallback(id: number) { + const possibleFallback = this.#callbacks.find(cb => cb.id === id); + if (!possibleFallback) return; + this.#callbacks.splice(this.#callbacks.indexOf(possibleFallback), 1); + } +} diff --git a/src/equicordplugins/userpluginInstaller.dev/components/SettingsTab.tsx b/src/equicordplugins/userpluginInstaller.dev/components/SettingsTab.tsx new file mode 100644 index 000000000..0bc5a1c53 --- /dev/null +++ b/src/equicordplugins/userpluginInstaller.dev/components/SettingsTab.tsx @@ -0,0 +1,340 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2025 nin0 + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import { pluginRequiresRestart, startPlugin, stopPlugin } from "@api/PluginManager"; +import { useSettings } from "@api/Settings"; +import { BaseText } from "@components/BaseText"; +import { Button } from "@components/Button"; +import { Card } from "@components/Card"; +import { CheckedTextInput } from "@components/CheckedTextInput"; +import { HeadingTertiary } from "@components/Heading"; +import { DeleteIcon } from "@components/Icons"; +import { Paragraph } from "@components/Paragraph"; +import { AddonCard } from "@components/settings"; +import { + SettingsTab as STab, + wrapTab, +} from "@components/settings/tabs/BaseTab"; +import { classes, isObjectEmpty } from "@utils/misc"; +import { closeAllModals } from "@utils/modal"; +import { relaunch } from "@utils/native"; +import { Alerts, NavigationRouter, Toasts, useEffect, useState } from "@webpack/common"; + +import userpluginInstaller, { Native } from ".."; +import { + cl, + CLONE_LINK_REGEX, + showInstallFinishedAlert, +} from "../misc/constants"; + +function UserPluginsTab() { + const rs = useSettings(["plugins.*"]); + const [pluginsLoaded, loadPlugins] = useState(false); + const [plugins, setPlugins] = useState< + { + name: string; + description: string; + usesPreSend: boolean; + usesNative: boolean; + directory?: string; + remote: string; + supportChannelID?: string; + }[] + >([]); + const [url, setUrl] = useState(""); + const [valid, setValid] = useState(false); + const [pluginsWithUpdates, setPluginsWithUpdates] = useState< + Record + >({}); + const [updatesLoaded, loadUpdates] = useState(false); + + useEffect(() => { + const { plugins: plgobj, pluginsWithUpdates: pwug } = + userpluginInstaller; + setPlugins(plgobj.value()); + loadPlugins(true); + const cid2 = plgobj.registerCallback(value => setPlugins(value)); + + const setPWU = value => { + const pwu = value.plugins.map(pg => ({ + [pg]: plgobj.value().find(pfjh => pfjh.directory === pg) + ?.name, + })); + setPluginsWithUpdates(Object.assign({}, ...pwu)); + loadUpdates(value.finished); + }; + const cid = pwug.registerCallback(value => { + setPWU(value); + }); + setPWU(pwug.value()); + + return () => { + pwug.deregisterCallback(cid); + plgobj.deregisterCallback(cid2); + }; + }, []); + + return ( + Vencord.Settings.plugins[p.name].enabled).length} enabled)` : ""}`} + > +
+ {isObjectEmpty(pluginsWithUpdates) ? ( + !updatesLoaded && ( + Checking for updates... + ) + ) : ( + + + Plugin Updates Available + + + The following plugins are out-of-date: +
    + {Object.values(pluginsWithUpdates) + .toSorted() + .map(pl => ( +
  • {pl}
  • + ))} +
+ {!updatesLoaded && + "and possibly more, as update checking is not finished. "} + You can update plugins below. +
+
+ )} +
+ + + Install Plugin + + + You can install a plugin from GitHub, GitLab, Codeberg, + git.nin0.dev, or plugins.nin0.dev by pasting its clone URL + here. + +
+ setUrl(t)} + validate={t => { + const match = t.match(CLONE_LINK_REGEX); + if (match) { + const idpl = match.includes("plugins.nin0.dev") + ? 1 + : 0; + const installed = plugins + .map(p => p.directory) + .includes(match[[3, 6][idpl]]); + if (installed) { + setValid(false); + return "Plugin already installed, update below"; + } + setValid(true); + return true; + } else { + setValid(false); + return "Invalid URL, read the notice above"; + } + }} + initialValue={url} + /> +
+
+ +
+
+
+ {pluginsLoaded ? ( +
+ {plugins + .toSorted((a, b) => + a.name.localeCompare(b.name, "en", { + sensitivity: "base", + }), + ) + .toSorted((a, b) => { + const updatePendingNames = + Object.keys(pluginsWithUpdates); + const [aa, bb] = [ + updatePendingNames.includes(a.directory!) + ? 1000 + : 0, + updatePendingNames.includes(b.directory!) + ? 1000 + : 0, + ]; + return bb - aa; + }) + .map(plugin => { + + const pl = Vencord.Plugins.plugins[ + plugin.name + ]; + return { + await Native.rmPlugin( + plugin.directory!, + ); + Alerts.show({ + title: "Done!", + body: `${plugin.name} has been uninstalled. A ${plugin.usesNative ? "restart" : "refresh"} is needed to fully remove the plugin.`, + confirmText: + plugin.usesNative + ? "Restart" + : "Refresh", + cancelText: "Later", + onConfirm() { + plugin.usesNative + ? relaunch() + : window.location.reload(); + }, + }); + }} + className={cl("delete-button")} + > + + } + setEnabled={t => { + Vencord.Settings.plugins[pl.name].enabled = t; + if (pluginRequiresRestart(pl)) { + Toasts.show({ + id: Toasts.genId(), + message: "Restart to apply changes!", + type: Toasts.Type.MESSAGE + }); + } else { + (t ? startPlugin : stopPlugin)(pl); + } + }} + footer={( +
+ {Object.keys( + pluginsWithUpdates, + ).includes(plugin.directory!) && ( + + )} + + {plugin.supportChannelID && } +
+ )} + />; + })} +
+ ) : ( + Loading plugins... + )} +
+
+ ); +} + +export default wrapTab(UserPluginsTab, "UserPlugins"); diff --git a/src/equicordplugins/userpluginInstaller.dev/components/UserpluginInstallButton.tsx b/src/equicordplugins/userpluginInstaller.dev/components/UserpluginInstallButton.tsx new file mode 100644 index 000000000..753a93961 --- /dev/null +++ b/src/equicordplugins/userpluginInstaller.dev/components/UserpluginInstallButton.tsx @@ -0,0 +1,55 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2025 nin0 + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import { Button } from "@components/Button"; +import { Alerts, ChannelStore, useEffect, useState } from "@webpack/common"; + +import userpluginInstaller, { Native, OpenSettingsModule, settings } from ".."; +import { CLONE_LINK_REGEX, showInstallFinishedAlert, WHITELISTED_SHARE_CHANNELS } from "../misc/constants"; + +export default function UserpluginInstallButton({ props }: any) { + const [plugins, setPlugins] = useState<{ + directory?: string; + }[]>([]); + useEffect(() => { + const { plugins } = userpluginInstaller; + + setPlugins(plugins.value()); + const cid = plugins.registerCallback(value => setPlugins(plugins.value())); + return () => plugins.deregisterCallback(cid); + }); + const { message } = props; + if (![...WHITELISTED_SHARE_CHANNELS, ...(settings.store.allowlistedChannels || "").split(",")].includes(ChannelStore.getChannel(message.channel_id).parent_id) && !WHITELISTED_SHARE_CHANNELS.includes(message.channel_id)) + return; + const gitLink = (props.message.content as string).match(CLONE_LINK_REGEX); + if (!gitLink) return; + const idpl = gitLink.includes("plugins.nin0.dev") ? 1 : 0; + const installed = plugins.map(p => p.directory).includes(gitLink[[3, 6][idpl]]); + return <> +
+ +
+ ; +} diff --git a/src/equicordplugins/userpluginInstaller.dev/index.tsx b/src/equicordplugins/userpluginInstaller.dev/index.tsx new file mode 100644 index 000000000..98e884661 --- /dev/null +++ b/src/equicordplugins/userpluginInstaller.dev/index.tsx @@ -0,0 +1,145 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2025 nin0 + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import "./misc/style.css"; + +import { showNotification } from "@api/Notifications"; +import { definePluginSettings } from "@api/Settings"; +import { Button } from "@components/Button"; +import { Notice } from "@components/Notice"; +import plSettings from "@plugins/_core/settings"; +import { Devs } from "@utils/constants"; +import { relaunch } from "@utils/native"; +import definePlugin, { OptionType, PluginNative } from "@utils/types"; +import { findByPropsLazy, findComponentByCodeLazy } from "@webpack"; +import { Alerts } from "@webpack/common"; + +import SettingsTab from "./components/SettingsTab"; +import UserpluginInstallButton from "./components/UserpluginInstallButton"; +import { VariableWithCallbacks } from "./VariableWithCallbacks"; + +// @ts-ignore +export const Native = VencordNative.pluginHelpers.UserpluginInstaller as PluginNative; +export const OpenSettingsModule = findByPropsLazy("openUserSettings"); +const AppsIcon = findComponentByCodeLazy("2.95H20a2 2 0"); + +export const settings = definePluginSettings({ + allowlistedChannels: { + type: OptionType.STRING, + description: "Comma separated list of channels where the Install Plugin button should be displayed. It is always displayed in the Vencord Userplugin channels" + }, + notifyIfUpdate: { + type: OptionType.BOOLEAN, + description: "Show a Vencord notification if UserPlugins need to be updated", + default: true + }, + neverNotifyForPlugins: { + type: OptionType.STRING, + description: "Never show update notifications for these plugins (you can still update them from the UserPlugins tab)", + default: "" + }, + setGitPath: { + type: OptionType.COMPONENT, + component: () => + } +}); + +export default definePlugin({ + name: "UserpluginInstaller", + description: "Install userplugins with a simple button click", + settingsAboutComponent: () => ( + + Equicord does not moderate userplugins and takes no responsibility for anything that may result from installing them. + Only install userplugins from developers you trust. Doing so is entirely at your own risk. + + ), + async checkPluginUpdates() { + for (const p of this.plugins.value()) { + if (await Native.isUpdateAvailableForPlugin(p.directory!)) { + const t = this.pluginsWithUpdates.value().plugins; + t.push(p.directory!); + this.pluginsWithUpdates.value({ + finished: false, + plugins: t + }); + } + } + const t = this.pluginsWithUpdates.value().plugins; + this.pluginsWithUpdates.value({ + finished: true, + plugins: t + }); + }, + section: { + key: "vencord_userplugins", + title: "UserPlugins", + panelTitle: "UserPlugins", + Component: SettingsTab, + Icon: AppsIcon + }, + async start() { + if (!VencordNative.pluginHelpers.UserpluginInstaller) return void Alerts.show({ + title: "UserpluginInstaller not fully loaded", + body: "You need to restart to allow the native to be loaded :)", + confirmText: "Restart now", + onConfirm() { + relaunch(); + }, + cancelText: "Later" + }); + + plSettings.customEntries.push(this.section); + + this.pluginsWithUpdates.registerCallback((value, id) => { + if (value.plugins.length === 0) return; + if (settings.store.neverNotifyForPlugins.split(",").map(t => t.trim().toLowerCase()).includes(value.plugins[value.plugins.length - 1].toLowerCase())) + return; + this.pluginsWithUpdates.deregisterCallback(id); + if (settings.store.notifyIfUpdate) + showNotification({ + title: "Some UserPlugins are out of date!", + body: "Click to open the UserPlugin Updater", + noPersist: true, + permanent: true, + onClick() { + OpenSettingsModule.openUserSettings("vencord_userplugins_panel"); + }, + }); + }); + const pls = await Native.getUserplugins(); + // @ts-ignore :trolley: + this.plugins.value(pls); + await this.checkPluginUpdates(); + }, + stop() { + // @ts-ignore + plSettings.customEntries.splice(plSettings.customEntries.indexOf(this.section), 1); + }, + plugins: new VariableWithCallbacks<{ + name: string; + description: string; + usesPreSend: boolean; + usesNative: boolean; + directory: string; + remote: string; + }[]>([]), + pluginsWithUpdates: new VariableWithCallbacks<{ + finished: boolean; + plugins: string[]; + }>({ + finished: false, + plugins: [] + }), + settings, + authors: [Devs.nin0dev], + renderMessageAccessory: props => { + return ; + } +}); diff --git a/src/equicordplugins/userpluginInstaller.dev/misc/constants.ts b/src/equicordplugins/userpluginInstaller.dev/misc/constants.ts new file mode 100644 index 000000000..b860a82c3 --- /dev/null +++ b/src/equicordplugins/userpluginInstaller.dev/misc/constants.ts @@ -0,0 +1,28 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2025 nin0 + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import { classNameFactory } from "@api/Styles"; +import { relaunch } from "@utils/native"; +import { Alerts } from "@webpack/common"; + +// if edited, also edit in native.ts!!! +export const CLONE_LINK_REGEX = /https:\/\/(?:((?:git(?:hub|lab)\.com|git\.(?:[a-zA-Z0-9]|\.)+|codeberg\.org))\/(?!user-attachments)((?:[a-zA-Z0-9]|-)+)\/((?:[a-zA-Z0-9]|-|\.)+)(?:\.git)?|(plugins\.(nin0)\.dev)\/((?:[a-zA-Z0-9]|-|\.)+))(?:\/)?/; +export const WHITELISTED_SHARE_CHANNELS = ["1256395889354997771", "1032200195582197831", "1301947896601509900", "1322935137591365683"]; +export const cl = classNameFactory("vc-userplugininstaller-"); + +export function showInstallFinishedAlert(pluginToEnable: string, native: boolean) { + Alerts.show({ + title: "Done!", + body: `${pluginToEnable} has been successfully installed.${native ? " However, as it makes use of native functions, a client restart is required." : ""} What now?`, + confirmText: `Enable & ${native ? "restart" : "refresh"}`, + cancelText: native ? "Restart" : "Refresh", + onConfirm() { + !Vencord.Plugins.plugins[pluginToEnable] ? Vencord.Settings.plugins[pluginToEnable] = { enabled: true } : Vencord.Settings.plugins[pluginToEnable].enabled = true; + native ? relaunch() : window.location.reload(); + }, + onCancel: () => native ? relaunch() : window.location.reload() + }); +} diff --git a/src/equicordplugins/userpluginInstaller.dev/misc/pluginValidate.txt b/src/equicordplugins/userpluginInstaller.dev/misc/pluginValidate.txt new file mode 100644 index 000000000..9486605c9 --- /dev/null +++ b/src/equicordplugins/userpluginInstaller.dev/misc/pluginValidate.txt @@ -0,0 +1,158 @@ + + + + + + Review userplugin + + + + %WARNINGHIDER% %NATIVETSHIDER% %PRESENDHIDER% + + + +

Plugin info

+
+

%PLUGINNAME%

+

%PLUGINDESC%

+
+ +

Warnings

+
+

Uses a native.ts file

+

+ Use of this file allows the plugin to escape the browser sandbox + and potentially do anything to your system and data. + ONLY INSTALL THIS PLUGIN AFTER REVIEWING THE CODE AND BEING + 100% SURE THAT NOTHING BAD CAN BE DONE! +

+
+ Acknowledge warning (required to allow + install) +
+
+

Has pre-send listeners

+

+ This allows the plugin to edit your messages before they are + sent. +

+
+

+ Reminder: installing a userplugin can be a destructive action. Make + sure that you know and trust the developer before installing any. +

+
+ + +
+ + diff --git a/src/equicordplugins/userpluginInstaller.dev/misc/setGitPath.txt b/src/equicordplugins/userpluginInstaller.dev/misc/setGitPath.txt new file mode 100644 index 000000000..5e4e6938e --- /dev/null +++ b/src/equicordplugins/userpluginInstaller.dev/misc/setGitPath.txt @@ -0,0 +1,118 @@ + + + + + + + Git Path + + + + + +

Git path

+

+ If you're having issues downloading userplugins because Git isn't properly detected, you can manually set a Git + path + that'll be used instead of + simply looking in PATH. +
+ If you do not specify anything, Git will be called from the PATH variable. Do not set this setting unless you + have issues. +
+
+ On Linux, Flatpak still isn't supported. +

+ +
+ + + +
+ + + diff --git a/src/equicordplugins/userpluginInstaller.dev/misc/style.css b/src/equicordplugins/userpluginInstaller.dev/misc/style.css new file mode 100644 index 000000000..098e37ea6 --- /dev/null +++ b/src/equicordplugins/userpluginInstaller.dev/misc/style.css @@ -0,0 +1,78 @@ +.vc-userplugininstaller-info-card { + padding: 15px 20px; + margin-bottom: 20px; +} + +.vc-userplugininstaller-install-desc { + margin-top: 5px; +} + +.vc-userplugininstaller-install-field, +.vc-userplugininstaller-button-container { + margin-top: 10px; +} + +.vc-userplugininstaller-install-button { + margin-left: auto; +} + +.vc-userplugininstaller-update-check-container { + margin-top: 10px; +} + +.vc-userplugininstaller-plugins-grid { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 10px; + align-items: start; +} + +.vc-userplugininstaller-info-button { + height: 24px; + width: 24px; + padding: 0; + background: transparent; + color: var(--icon-secondary); + transition: background-color 0.2s ease; + + &:hover { + color: var(--interactive-hover); + } +} + +.vc-userplugininstaller-settings-button:hover { + color: var(--interactive-hover); +} + +.vc-userplugininstaller-plugin-footer { + margin-top: 10px; + display: flex; + flex-wrap: wrap; + gap: 5px; + + div { + flex-basis: 100%; + margin-top: 5px; + font-size: 0.9rem; + } +} + +.vc-userplugininstaller-outdated-list { + padding-left: 30px; + margin: 3px 0; + list-style-type: disc; +} + +.vc-userplugininstaller-delete-button { + height: 24px; + width: 24px; + padding: 0; + background: transparent; + margin-right: 8px; + color: var(--icon-muted); + transition: background-color .2s ease; + + &:hover { + color: var(--red-new-46) + } +} diff --git a/src/equicordplugins/userpluginInstaller.dev/misc/updateValidate.txt b/src/equicordplugins/userpluginInstaller.dev/misc/updateValidate.txt new file mode 100644 index 000000000..573200223 --- /dev/null +++ b/src/equicordplugins/userpluginInstaller.dev/misc/updateValidate.txt @@ -0,0 +1,129 @@ + + + + + + Review userplugin + + + + +

Plugin info

+
+

%PLUGINNAME%

+

%PLUGINDESC%

+
+

Update info

+
+

%COMMITMESSAGE%

+
+

+ You may want to review the + source code that will be applied. +

+
+ +

+ Reminder: installing a userplugin can be a destructive action. Make + sure that you know and trust the developer before installing any. +

+
+ + +
+ + diff --git a/src/equicordplugins/userpluginInstaller.dev/native.ts b/src/equicordplugins/userpluginInstaller.dev/native.ts new file mode 100644 index 000000000..1203b4a85 --- /dev/null +++ b/src/equicordplugins/userpluginInstaller.dev/native.ts @@ -0,0 +1,473 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2025 nin0 + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import { NativeSettings } from "@main/settings"; +import { exec, spawn } from "child_process"; +import { BrowserWindow, dialog, shell, WebContentsView } from "electron"; +import { existsSync, readdirSync, readFileSync } from "fs"; +import { readdir, readFile, rm } from "fs/promises"; +import { basename, join } from "path"; +import yaml from "yaml-js"; + +// @ts-ignore fuck off +import pluginValidateContent from "./misc/pluginValidate.txt"; // i would use HTML but esbuild is being whiny +// @ts-ignore fuck off +import setGitPathContent from "./misc/setGitPath.txt"; +// @ts-ignore fuck off +import updateValidateContent from "./misc/updateValidate.txt"; // see above + +const PLUGIN_META_REGEX = /export default definePlugin\((?:\s|\/(?:\/|\*).*)*{\s*(?:\s|\/(?:\/|\*).*)*name:\s*(?:"|'|`)(.*)(?:"|'|`)(?:\s|\/(?:\/|\*).*)*,(?:\s|\/(?:\/|\*).*)*(?:\s|\/(?:\/|\*).*)*description:\s*(?:"|'|`)(.*)(?:"|'|`)(?:\s|\/(?:\/|\*).*)*/; +// if edited, also edit in misc/constants.ts!!! +const CLONE_LINK_REGEX = /https:\/\/(?:((?:git(?:hub|lab)\.com|git\.(?:[a-zA-Z0-9]|\.)+|codeberg\.org))\/(?!user-attachments)((?:[a-zA-Z0-9]|-)+)\/((?:[a-zA-Z0-9]|-|\.)+)(?:\.git)?|(plugins\.(nin0)\.dev)\/((?:[a-zA-Z0-9]|-|\.)+))(?:\/)?/; + +const vencordPath = ["desktop", "equibop"].includes(basename(__dirname)) ? join(__dirname, "../") : __dirname; + +export async function rmPlugin(_, name: string): Promise { + // eslint-disable-next-line + return new Promise(async (resolve, reject) => { + const ups = await getUserplugins(); + const pl = ups.find(p => p.directory! === name); + if (!pl) return; + + const deleteReqDialog = await dialog.showMessageBox({ + title: "Uninstall plugin", + message: `Uninstall ${pl.name}`, + type: "error", + detail: `The uninstall of the userplugin ${pl.name} has been requested. Would you like to do so?\n\nIf you did not initiate this, press No.`, + buttons: ["No", "Yes"] + }); + + if (deleteReqDialog.response !== 1) return reject("User rejected"); + await rm(join(vencordPath, "../src/userplugins", name), { recursive: true }); + + await build(); + resolve("Done"); + }); +} + +export async function isUpdateAvailableForPlugin(_, name: string): Promise { + return new Promise(resolve => { + const pluginDir = join(vencordPath, "../src/userplugins", name); + const otherProc = exec("git fetch", { + cwd: pluginDir + }); + otherProc.once("close", () => { + async function doStuff() { + try { + const head = (await readFile(join(pluginDir, ".git/HEAD"), "utf8")).match(/^ref: (.+)/)![1]; + const remoteHead = (await readFile(join(pluginDir, ".git/refs/remotes/origin/HEAD"), "utf8")).match(/^ref: (.+)/)![1]; + const localCommit = await readFile(join(pluginDir, ".git", head), "utf8"); + const remoteCommit = await readFile(join(pluginDir, ".git", remoteHead), "utf8"); + + resolve(localCommit !== remoteCommit); + } + catch (e) { + resolve(false); + } + } + doStuff(); + }); + }); +} + +export function initPluginInstall(_, link: string, source: string, owner: string, repo: string): Promise { + // eslint-disable-next-line + return new Promise(async (resolve, reject) => { + const verifiedRegex = link.match(CLONE_LINK_REGEX)!; + const idpl = source === "plugins.nin0.dev" ? 1 : 0; + if (![4, 7].includes(verifiedRegex.length) || verifiedRegex[0] !== link || verifiedRegex[[1, 4][idpl]] !== source || verifiedRegex[[2, 5][idpl]] !== owner || verifiedRegex[[3, 6][idpl]] !== repo) return reject("Invalid link"); + + // Ask for clone + const cloneDialog = await dialog.showMessageBox({ + title: "Clone userplugin", + message: `You are about to clone a userplugin from ${source}.`, + type: "question", + detail: `The repository name is "${repo}" and it is owned by "${owner}".\nThe repository URL is ${link}\n\n(If you did not request this intentionally, choose Cancel)`, + buttons: ["Cancel", "Clone repository and continue install", "Open repository in browser"] + }); + switch (cloneDialog.response) { + case 0: { + return reject("Rejected by user"); + } + case 1: { + await cloneRepo(link, repo); + break; + } + case 2: { + await shell.openExternal(link); + return reject("silentStop"); + } + } + + // Get plugin meta + const meta = await getPluginMeta(join(vencordPath, "..", "src", "userplugins", repo)); + + // Review plugin + const win = new BrowserWindow({ + maximizable: false, + minimizable: false, + width: 560, + height: meta.usesNative || meta.usesPreSend ? 650 : 360, + resizable: false, + webPreferences: { + devTools: true + }, + title: "Review userplugin", + modal: true, + parent: BrowserWindow.getAllWindows()[0], + show: false, + autoHideMenuBar: true + }); + const reView /* haha got it */ = new WebContentsView({ + webPreferences: { + devTools: true, + nodeIntegration: true + } + }); + win.contentView.addChildView(reView); + win.loadURL(generateReviewPluginContent(meta)); + win.on("page-title-updated", async e => { + switch (win.webContents.getTitle() as "abortInstall" | "reviewCode" | "install") { + case "abortInstall": { + win.close(); + await rm(join(vencordPath, "..", "src", "userplugins", repo), { + recursive: true + }); + return reject("Rejected by user"); + } + case "install": { + win.close(); + try { + await build(); + } + catch (e) { + reject((e as Error).toString()); + } + resolve(JSON.stringify({ + name: meta.name, + native: meta.usesNative + })); + break; + } + } + }); + win.show(); + }); +} + +async function build(): Promise { + return new Promise((resolve, reject) => { + const proc = exec("pnpm build --dev", { + cwd: join(vencordPath, ".."), + shell: process.env.SHELL || process.env.ComSpec || "/bin/sh" + }); + proc.once("close", () => { + if (proc.exitCode !== 0) { + reject("Failed to build Vencord, try building from console"); + } + resolve("Success"); + }); + }); +} + +async function getPluginMeta(path: string, extra: object = {}): Promise<{ + name: string; + description: string; + usesPreSend: boolean; + usesNative: boolean; + directory?: string; + remote: string; + supportChannelID?: string; +}> { + return new Promise((resolve, reject) => { + const files = readdirSync(path); + let fileToRead: "index.ts" | "index.tsx" | "index.js" | "index.jsx" | undefined; + files.forEach(f => { + if (f === "index.ts") fileToRead = "index.ts"; + if (f === "index.tsx") fileToRead = "index.tsx"; + if (f === "index.js") fileToRead = "index.js"; + if (f === "index.jsx") fileToRead = "index.jsx"; + }); + if (!fileToRead) reject("Invalid plugin"); + + const file = readFileSync(`${path}/${fileToRead}`, "utf8"); + let remoteURL; + try { + const remoteC = readFileSync(join(path, ".git/config"), "utf8"); + remoteURL = remoteC.match(/\[remote "origin"]\s+url = (https:\/\/(?:(?:git(?:hub|lab)\.com|git\.(?:[a-zA-Z0-9]|\.)+|codeberg\.org)\/(?!user-attachments)(?:[a-zA-Z0-9]|-)+\/(?:[a-zA-Z0-9]|-|\.)+(?:\.git)?|(plugins\.(nin0)\.dev)\/((?:[a-zA-Z0-9]|-|\.)+))(?:\/)?)\n/); + } catch { + remoteURL = null; + } + + let supportChannelID; + try { + const meta = readFileSync(join(path, "meta.yml"), "utf8"); + console.log(meta); + const parsed = yaml.load(meta); + if (parsed.thread && typeof parsed.thread === "string" && /^\d+$/.test(parsed.thread)) { + supportChannelID = parsed.thread; + } + } catch { + supportChannelID = null; + } + + const rawMeta = file.match(PLUGIN_META_REGEX); + resolve({ + name: rawMeta![1], + description: rawMeta![2], + usesPreSend: file.includes("PreSendListener") || file.includes("onBeforeMessage"), + usesNative: files.includes("native.ts") || files.includes("native.js"), + remote: remoteURL ? remoteURL[1] : "", + supportChannelID, + ...extra + }); + + }); +} + +async function cloneRepo(link: string, repo: string): Promise { + return new Promise((resolve, reject) => { + const proc = spawn("git", ["clone", link], { + cwd: join(vencordPath, "..", "src", "userplugins") + }); + proc.once("close", async () => { + if (proc.exitCode !== 0) { + if (!existsSync(join(vencordPath, "..", "src", "userplugins", repo))) + return reject("Failed to clone"); + const deleteReqDialog = await dialog.showMessageBox({ + title: "Error", + message: "Plugin already exists", + type: "error", + detail: `The plugin that you tried to clone already exists at ${join(vencordPath, "..", "src", "userplugins")}.\nWould you like to reclone it? Only do this if you want to reinstall or update the plugin.`, + buttons: ["No", "Yes"] + }); + if (deleteReqDialog.response !== 1) return reject("User rejected"); + await rm(join(vencordPath, "..", "src", "userplugins", repo), { + recursive: true + }); + await cloneRepo(link, repo); + } + resolve(); + }); + }); +} + +function generateReviewPluginContent(meta: { + name: string; + description: string; + usesPreSend: boolean; + usesNative: boolean; +}): string { + const template = pluginValidateContent.replace("%PLUGINNAME%", meta.name.replaceAll("<", "<")).replace("%PLUGINDESC%", meta.description.replaceAll("<", "<")).replace("%WARNINGHIDER%", !meta.usesNative && !meta.usesPreSend ? "[data-useless=\"warning\"] { display: none !important; }" : "").replace("%NATIVETSHIDER%", meta.usesNative ? "" : "#native-ts-warning { display: none !important; }").replace("%PRESENDHIDER%", meta.usesPreSend ? "" : "#pre-send-warning { display: none !important; }"); + const buf = Buffer.from(template).toString("base64"); + return `data:text/html;base64,${buf}`; +} + +function generateUpdatePluginContent(meta: { + name: string; + description: string; + remote: string; + commit: string; +}): string { + const template = updateValidateContent.replace("%PLUGINNAME%", meta.name.replaceAll("<", "<")).replace("%PLUGINDESC%", meta.description.replaceAll("<", "<")).replace("%REMOTE%", meta.remote).replace("%COMMITMESSAGE%", meta.commit.replaceAll("\n", "
")); + const buf = Buffer.from(template).toString("base64"); + return `data:text/html;base64,${buf}`; +} + +export async function getUserplugins() { + const folderContents = await readdir(join(vencordPath, "..", "src", "userplugins"), { + withFileTypes: true + }); + const plugins = await Promise.allSettled( + folderContents + .filter(item => item.isDirectory()) + .map(item => ({ + path: join(item.parentPath, item.name), + directory: item.name + })) + .map(({ path, directory }) => getPluginMeta(path, { directory })) + ); + + return plugins + .filter(p => p.status === "fulfilled") + .map(p => p.value); +} + +export async function updatePlugin(_, directory: string) { + return new Promise((resolve, reject) => { + const pluginDir = join(vencordPath, "../src/userplugins", directory); + + async function doStuff() { + const pluginMeta = await getPluginMeta(pluginDir); + + const win = new BrowserWindow({ + maximizable: false, + minimizable: false, + width: 560, + height: 600, + resizable: false, + webPreferences: { + devTools: true + }, + title: "Review userplugin", + modal: true, + parent: BrowserWindow.getAllWindows()[0], + show: false, + autoHideMenuBar: true + }); + const reView /* haha got it */ = new WebContentsView({ + webPreferences: { + devTools: true, + nodeIntegration: true + } + }); + win.contentView.addChildView(reView); + + const commitProc = exec("git log origin/HEAD...HEAD --oneline --pretty=format:%an////////%h////////%H////////%s", { + cwd: pluginDir + }); + let rawOutput = ""; + commitProc.stdout?.on("data", d => { + rawOutput += String(d); + }); + commitProc.once("close", () => { + win.loadURL(generateUpdatePluginContent({ + name: pluginMeta.name, + description: pluginMeta.description, + remote: pluginMeta.remote, + commit: rawOutput.split("\n").map(line => line.split("////////")).map(([user, shortCommit, longCommit, message]) => `${user} (${shortCommit}) ~ ${message}`).join("\n") + })); + win.on("page-title-updated", async e => { + if (win.webContents.getTitle().startsWith("openLink:")) { + await shell.openExternal(win.webContents.getTitle().replace("openLink:", "")); + } + switch (win.webContents.getTitle() as "abortInstall" | "install") { + case "abortInstall": { + win.close(); + return reject("Rejected by user"); + } + case "install": { + win.close(); + try { + const otherProc = exec("git rebase origin/HEAD", { + cwd: pluginDir + }); + let errored = ""; + otherProc.stderr?.on("data", d => { if (String(d).includes("Success")) return; errored += String(d); }); + otherProc.once("close", () => { + if (errored) if (!errored.includes("Success")) return reject(`Failed to apply the update, chances are you have local changes that conflict with your remote. Git errors:\n\n${errored}`); + build().then(() => resolve(JSON.stringify({ + name: pluginMeta.name, + native: pluginMeta.usesNative + }))); + }); + } + catch (e) { + reject((e as Error).toString()); + } + break; + } + } + }); + }); + win.show(); + } + doStuff(); + }); +} + +export async function openGitPathModal(_: any) { + const gitPathSet: string | undefined = NativeSettings.store.plugins.UserpluginInstaller?.gitPath; + const win = new BrowserWindow({ + maximizable: false, + minimizable: false, + width: 560, + height: 400, + resizable: false, + webPreferences: { + devTools: true + }, + title: "Set Git path", + modal: true, + parent: BrowserWindow.getAllWindows()[0], + show: false, + autoHideMenuBar: true + }); + const reView = new WebContentsView({ + webPreferences: { + devTools: true, + nodeIntegration: true + } + }); + win.contentView.addChildView(reView); + win.loadURL(`data:text/html;base64,${Buffer.from(setGitPathContent).toString("base64")}`); + win.on("page-title-updated", async _ => { + const t = win.webContents.getTitle(); + if (t === "abort") win.close(); + if (t.startsWith("ok")) { + if (!NativeSettings.store.plugins.UserpluginInstaller) { + NativeSettings.store.plugins.UserpluginInstaller = { + gitPath: undefined + }; + } + if (t === "ok-") { + NativeSettings.store.plugins.UserpluginInstaller.gitPath = undefined; + } else { + const gitPath2 = t.split("-").toSpliced(0, 1).join("-"); + NativeSettings.store.plugins.UserpluginInstaller.gitPath = gitPath2; + } + win.close(); + } + if (t.startsWith("check")) { + try { + const gitProc = spawn(t === "check-" ? "git" : t.split("-").toSpliced(0, 1).join("-"), ["--version"]); + let rawOutput = ""; + gitProc.stdout?.on("data", d => { + rawOutput += String(d); + }); + gitProc.on("error", e => { + dialog.showMessageBox({ + title: "Error", + message: "Git error", + type: "error", + detail: `${e}\n\nDouble-check the path you entered.`, + buttons: ["OK"] + }); + }); + gitProc.once("close", () => { + if (gitProc.exitCode === 0) { + dialog.showMessageBox({ + title: "Success", + message: "Git works!", + type: "info", + detail: `Successfully called ${rawOutput.trim()}`, + buttons: ["OK"] + }); + } + }); + } catch (e) { + dialog.showMessageBox({ + title: "Error", + message: "Git error", + type: "error", + detail: `${e}\n\nDouble-check the path you entered.`, + buttons: ["OK"] + }); + } + } + }); + win.show(); + if (gitPathSet) { + win.webContents.executeJavaScript(`document.querySelector("input").value = ${JSON.stringify(gitPathSet)};`); + } + + console.log(yaml.load(` + name: test + items: + - a + - b + `)); +} diff --git a/src/equicordplugins/vcNarratorCustom/index.tsx b/src/equicordplugins/vcNarratorCustom/index.tsx index b0212bbf7..5d0f82082 100644 --- a/src/equicordplugins/vcNarratorCustom/index.tsx +++ b/src/equicordplugins/vcNarratorCustom/index.tsx @@ -896,6 +896,7 @@ const UserContextMenuPatch: NavContextMenuPatchCallback = (children, { user }: U export default definePlugin({ name: "VcNarratorCustom", description: t("equicord.vcNarratorCustom.description"), + tags: ["Accessibility", "Voice"], authors: [Devs.Ven, Devs.Nyako, EquicordDevs.Loukios, EquicordDevs.examplegit], settings, contextMenus: { diff --git a/src/equicordplugins/vcNarratorCustom/util.ts b/src/equicordplugins/vcNarratorCustom/util.ts index 476d2d2e0..5d27f5e3e 100644 --- a/src/equicordplugins/vcNarratorCustom/util.ts +++ b/src/equicordplugins/vcNarratorCustom/util.ts @@ -198,9 +198,6 @@ const DB_VERSION = 2; const VOICES_STORE = "voices"; -import { Logger } from "@utils/Logger"; - -const logger = new Logger("VcNarratorCustom"); const META_STORE = "voices_meta"; type VoiceMeta = { @@ -209,76 +206,49 @@ type VoiceMeta = { lastAccess: number; }; -let openDbPromise: Promise | undefined; -let loggedFailure = false; +function openDB(): Promise { + return new Promise((resolve, reject) => { + const request = indexedDB.open(DB_NAME, DB_VERSION); + request.onupgradeneeded = event => { + const db = request.result; + const upgradeTx = request.transaction; + if (!db.objectStoreNames.contains(VOICES_STORE)) { + db.createObjectStore(VOICES_STORE); + } + if (!db.objectStoreNames.contains(META_STORE)) { + const meta = db.createObjectStore(META_STORE); + meta.createIndex("by_lastAccess", "lastAccess"); + } -function handleDbFailure(error: unknown) { - if (loggedFailure) return; - loggedFailure = true; - logger.error("Voice cache storage unavailable, falling back to memory.", error); -} - -function openDB(): Promise { - if (!openDbPromise) { - openDbPromise = new Promise((resolve, reject) => { - const request = indexedDB.open(DB_NAME, DB_VERSION); - request.onupgradeneeded = event => { - const db = request.result; - const upgradeTx = request.transaction; - if (!db.objectStoreNames.contains(VOICES_STORE)) { - db.createObjectStore(VOICES_STORE); - } - if (!db.objectStoreNames.contains(META_STORE)) { - const meta = db.createObjectStore(META_STORE); - meta.createIndex("by_lastAccess", "lastAccess"); - } - - if (upgradeTx && (event?.oldVersion ?? 0) < 2) { - const now = Date.now(); - const voices = upgradeTx.objectStore(VOICES_STORE); - const meta = upgradeTx.objectStore(META_STORE); - const cursorReq = voices.openCursor(); - cursorReq.onsuccess = () => { - const cursor = cursorReq.result; - if (!cursor) return; - const blob = cursor.value as Blob | undefined; - meta.put( - { - size: blob?.size ?? 0, - createdAt: now, - lastAccess: now, - } satisfies VoiceMeta, - String(cursor.key) - ); - cursor.continue(); - }; - } - }; - request.onsuccess = () => resolve(request.result); - request.onerror = () => reject(request.error); - }).then(db => db).catch(error => { - handleDbFailure(error); - return null; - }); - } - - return openDbPromise; -} - -async function withDb(fallback: T, callback: (db: IDBDatabase) => Promise): Promise { - const db = await openDB(); - if (!db) return fallback; - - try { - return await callback(db); - } catch (error) { - handleDbFailure(error); - return fallback; - } + if (upgradeTx && (event?.oldVersion ?? 0) < 2) { + const now = Date.now(); + const voices = upgradeTx.objectStore(VOICES_STORE); + const meta = upgradeTx.objectStore(META_STORE); + const cursorReq = voices.openCursor(); + cursorReq.onsuccess = () => { + const cursor = cursorReq.result; + if (!cursor) return; + const blob = cursor.value as Blob | undefined; + meta.put( + { + size: blob?.size ?? 0, + createdAt: now, + lastAccess: now, + } satisfies VoiceMeta, + String(cursor.key) + ); + cursor.continue(); + }; + } + }; + request.onsuccess = () => resolve(request.result); + request.onerror = () => reject(request.error); + }); } export async function getPersistentTtsCacheStats(): Promise<{ bytes: number; entries: number; }> { - return withDb<{ bytes: number; entries: number; }>({ bytes: 0, entries: 0 }, db => new Promise<{ bytes: number; entries: number; }>((resolve, reject) => { + const db = await openDB(); + return new Promise((resolve, reject) => { const tx = db.transaction(META_STORE, "readonly"); const store = tx.objectStore(META_STORE); @@ -298,7 +268,7 @@ export async function getPersistentTtsCacheStats(): Promise<{ bytes: number; ent cursor.continue(); }; cursorReq.onerror = () => reject(cursorReq.error); - })); + }); } export async function clearTtsCache(): Promise { @@ -309,17 +279,19 @@ export async function clearTtsCache(): Promise { } ttsCache.clear(); - await withDb(void 0, db => new Promise((resolve, reject) => { + const db = await openDB(); + return new Promise((resolve, reject) => { const tx = db.transaction([VOICES_STORE, META_STORE], "readwrite"); tx.objectStore(VOICES_STORE).clear(); tx.objectStore(META_STORE).clear(); tx.oncomplete = () => resolve(); tx.onerror = () => reject(tx.error); - })); + }); } async function trimPersistentCacheToMaxBytes(maxBytes = PERSISTENT_TTS_CACHE_MAX_BYTES): Promise { - await withDb(void 0, db => new Promise((resolve, reject) => { + const db = await openDB(); + return new Promise((resolve, reject) => { const tx = db.transaction([VOICES_STORE, META_STORE], "readwrite"); const voicesStore = tx.objectStore(VOICES_STORE); const metaStore = tx.objectStore(META_STORE); @@ -372,11 +344,12 @@ async function trimPersistentCacheToMaxBytes(maxBytes = PERSISTENT_TTS_CACHE_MAX tx.oncomplete = () => resolve(); tx.onerror = () => reject(tx.error); - })); + }); } export async function getCachedVoiceFromDB(cacheKey: string): Promise { - return withDb(null, db => new Promise((resolve, reject) => { + const db = await openDB(); + return new Promise((resolve, reject) => { const tx = db.transaction([VOICES_STORE, META_STORE], "readwrite"); const voicesStore = tx.objectStore(VOICES_STORE); const metaStore = tx.objectStore(META_STORE); @@ -400,11 +373,12 @@ export async function getCachedVoiceFromDB(cacheKey: string): Promise reject(request.error); - })); + }); } export async function setCachedVoiceInDB(cacheKey: string, blob: Blob): Promise { - await withDb(void 0, db => new Promise((resolve, reject) => { + const db = await openDB(); + await new Promise((resolve, reject) => { const tx = db.transaction([VOICES_STORE, META_STORE], "readwrite"); const voicesStore = tx.objectStore(VOICES_STORE); const metaStore = tx.objectStore(META_STORE); @@ -418,7 +392,7 @@ export async function setCachedVoiceInDB(cacheKey: string, blob: Blob): Promise< tx.oncomplete = () => resolve(); tx.onerror = () => reject(tx.error); - })); + }); await trimPersistentCacheToMaxBytes(); } diff --git a/src/equicordplugins/vcPanelSettings/index.tsx b/src/equicordplugins/vcPanelSettings/index.tsx index 8da9d1c08..5766a77f1 100644 --- a/src/equicordplugins/vcPanelSettings/index.tsx +++ b/src/equicordplugins/vcPanelSettings/index.tsx @@ -147,14 +147,14 @@ function OutputDeviceComponent() { @@ -175,14 +175,14 @@ function InputDeviceComponent() {
@@ -203,14 +203,14 @@ function VideoDeviceComponent() {
@@ -239,6 +239,7 @@ function VoiceSettings() { export default definePlugin({ name: "VCPanelSettings", description: t("equicord.vcPanelSettings.description"), + tags: ["Utility", "Voice"], authors: [Devs.nin0dev], settings, renderVoiceSettings() { return ; }, diff --git a/src/equicordplugins/viewRawVariant/index.tsx b/src/equicordplugins/viewRawVariant/index.tsx index bf40849d4..f8c9466fa 100644 --- a/src/equicordplugins/viewRawVariant/index.tsx +++ b/src/equicordplugins/viewRawVariant/index.tsx @@ -130,6 +130,7 @@ function makeContextCallback( export default definePlugin({ name: "ViewRawVariant", description: t("equicord.viewRawVariant.description"), + tags: ["Appearance", "Customisation", "Chat", "Organisation", "Servers"], authors: [Devs.KingFish, Devs.Ven, Devs.rad, Devs.ImLvna, Devs.Kyuuhachi], contextMenus: { "guild-context": makeContextCallback("guild", val => diff --git a/src/equicordplugins/voiceButtons/index.tsx b/src/equicordplugins/voiceButtons/index.tsx index ecaa2c051..1ca1270d3 100644 --- a/src/equicordplugins/voiceButtons/index.tsx +++ b/src/equicordplugins/voiceButtons/index.tsx @@ -17,6 +17,7 @@ import { UserChatButton, UserDeafenButton, UserMuteButton } from "./utils"; export default definePlugin({ name: "VoiceButtons", description: t("equicord.voiceButtons.description"), + tags: ["Servers", "Utility", "Voice"], authors: [EquicordDevs.nicola02nb, EquicordDevs.omaw], settings, patches: [ diff --git a/src/equicordplugins/voiceChannelLog/index.tsx b/src/equicordplugins/voiceChannelLog/index.tsx index a0e4d1d9c..377ff7503 100644 --- a/src/equicordplugins/voiceChannelLog/index.tsx +++ b/src/equicordplugins/voiceChannelLog/index.tsx @@ -54,8 +54,9 @@ const patchChannelContextMenu: NavContextMenuPatchCallback = (children, { channe export default definePlugin({ name: "VoiceChannelLog", description: "Logs voice channel activity including joins, leaves, soundboard, mute, camera, screenshare, and more.", + tags: ["Servers", "Utility", "Voice"], authors: [Devs.Sqaaakoi, Devs.thororen, EquicordDevs.nyx, Devs.Moxxie, EquicordDevs.Fres, Devs.amy], - dependencies: ["AudioPlayerAPI"], + dependencies: ["AudioPlayerAPI", "HeaderBarAPI"], settings, contextMenus: { "channel-context": patchChannelContextMenu diff --git a/src/equicordplugins/voiceChatUtils/index.tsx b/src/equicordplugins/voiceChatUtils/index.tsx index 91d5348b1..9700b015b 100644 --- a/src/equicordplugins/voiceChatUtils/index.tsx +++ b/src/equicordplugins/voiceChatUtils/index.tsx @@ -175,6 +175,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "VoiceChatUtilities", description: t("equicord.voiceChatUtils.description"), + tags: ["Chat", "Servers", "Voice"], authors: [Devs.D3SOX, EquicordDevs.nickwoah], settings, diff --git a/src/equicordplugins/voiceJoinMessages/index.ts b/src/equicordplugins/voiceJoinMessages/index.ts index f80c5b4f3..edd7364ee 100644 --- a/src/equicordplugins/voiceJoinMessages/index.ts +++ b/src/equicordplugins/voiceJoinMessages/index.ts @@ -112,6 +112,7 @@ let clientOldChannelId: string | undefined; export default definePlugin({ name: "VoiceJoinMessages", description: t("equicord.voiceJoinMessages.description"), + tags: ["Servers", "Utility", "Voice"], authors: [Devs.Sqaaakoi, Devs.thororen], settings, flux: { diff --git a/src/equicordplugins/voiceMessageTranscriber.desktop/index.tsx b/src/equicordplugins/voiceMessageTranscriber.desktop/index.tsx index fb8528bf6..299447459 100644 --- a/src/equicordplugins/voiceMessageTranscriber.desktop/index.tsx +++ b/src/equicordplugins/voiceMessageTranscriber.desktop/index.tsx @@ -315,6 +315,7 @@ export default definePlugin({ name: "VoiceMessageTranscriber", authors: [Devs.TheSun], description: t("equicord.voiceMessageTranscriber.description"), + tags: ["Chat", "Media", "Utility", "Voice"], patches: [ { find: ".VOICE_MESSAGE)),", diff --git a/src/equicordplugins/voiceRejoin/index.tsx b/src/equicordplugins/voiceRejoin/index.tsx index 6c81ea35f..72499ace0 100644 --- a/src/equicordplugins/voiceRejoin/index.tsx +++ b/src/equicordplugins/voiceRejoin/index.tsx @@ -52,6 +52,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "VoiceRejoin", description: t("equicord.voiceRejoin.description"), + tags: ["Servers", "Utility", "Voice"], authors: [EquicordDevs.omaw, EquicordDevs.keircn], settings, diff --git a/src/equicordplugins/waitForSlot/index.tsx b/src/equicordplugins/waitForSlot/index.tsx index 847a3148e..5271b9b2d 100644 --- a/src/equicordplugins/waitForSlot/index.tsx +++ b/src/equicordplugins/waitForSlot/index.tsx @@ -65,6 +65,7 @@ function promptVoiceChannel(channel: Channel | null | undefined): boolean { export default definePlugin({ name: "WaitForSlot", description: t("equicord.waitForSlot.description"), + tags: ["Servers", "Utility", "Voice"], authors: [EquicordDevs.omaw, Devs.prism], settings, patches: [ diff --git a/src/equicordplugins/wallpaperFree/index.tsx b/src/equicordplugins/wallpaperFree/index.tsx index 21b3e452f..b3f4d02dc 100644 --- a/src/equicordplugins/wallpaperFree/index.tsx +++ b/src/equicordplugins/wallpaperFree/index.tsx @@ -34,13 +34,14 @@ export default definePlugin({ name: "WallpaperFree", authors: [Devs.Joona], description: t("equicord.wallpaperFree.description"), + tags: ["Appearance", "Chat", "Customisation"], patches: [ { find: ".handleSendMessage,onResize", group: true, replacement: [ { - match: /return.{1,150},(?=keyboardModeEnabled)/, + match: /return.{1,200},(?=keyboardModeEnabled)/, replace: "const vcWallpaperFreeUrl=$self.WallpaperState(arguments[0].channel);$&vcWallpaperFreeUrl," }, { diff --git a/src/equicordplugins/webpackTarball/index.tsx b/src/equicordplugins/webpackTarball/index.tsx index 8ca0d7aed..acfd907ea 100644 --- a/src/equicordplugins/webpackTarball/index.tsx +++ b/src/equicordplugins/webpackTarball/index.tsx @@ -32,6 +32,7 @@ export const settings = definePluginSettings({ export default definePlugin({ name: "WebpackTarball", description: t("equicord.webpackTarball.description"), + tags: ["Developers", "Utility"], authors: [Devs.Kyuuhachi], settings, diff --git a/src/equicordplugins/whitelistedEmojis/index.tsx b/src/equicordplugins/whitelistedEmojis/index.tsx index 6f023293d..60ecfe76d 100644 --- a/src/equicordplugins/whitelistedEmojis/index.tsx +++ b/src/equicordplugins/whitelistedEmojis/index.tsx @@ -598,6 +598,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "WhitelistedEmojis", description: "Adds the ability to disable all message emojis except for a whitelisted set.", + tags: ["Chat", "Emotes"], authors: [EquicordDevs.creations], patches: [ { diff --git a/src/equicordplugins/whosWatching/index.tsx b/src/equicordplugins/whosWatching/index.tsx index fed5230a0..2fdccf69e 100644 --- a/src/equicordplugins/whosWatching/index.tsx +++ b/src/equicordplugins/whosWatching/index.tsx @@ -83,6 +83,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "WhosWatching", description: t("equicord.whosWatching.description"), + tags: ["Activity"], authors: [EquicordDevs.Fres, Devs.thororen], settings, patches: [ diff --git a/src/equicordplugins/wigglyText/index.tsx b/src/equicordplugins/wigglyText/index.tsx index 65dfb5cb9..33127c2d2 100644 --- a/src/equicordplugins/wigglyText/index.tsx +++ b/src/equicordplugins/wigglyText/index.tsx @@ -113,6 +113,7 @@ const updateStyles = () => { export default definePlugin({ name: "WigglyText", description: t("equicord.wigglyText.description"), + tags: ["Appearance", "Customisation", "Fun"], authors: [EquicordDevs.nexpid], settings, settingsAboutComponent: () => ( diff --git a/src/equicordplugins/writeUpperCase/index.ts b/src/equicordplugins/writeUpperCase/index.ts index 3593a0666..3c3c21da4 100644 --- a/src/equicordplugins/writeUpperCase/index.ts +++ b/src/equicordplugins/writeUpperCase/index.ts @@ -38,6 +38,7 @@ const presendObject: MessageSendListener = (_, msg) => { export default definePlugin({ name: "WriteUpperCase", description: t("equicord.writeUpperCase.description"), + tags: ["Appearance", "Customisation", "Chat"], authors: [Devs.Samwich, EquicordDevs.KrystalSkull], settings, diff --git a/src/main/utils/extensions.ts b/src/main/utils/extensions.ts index 9ecfbfe82..0b19d9286 100644 --- a/src/main/utils/extensions.ts +++ b/src/main/utils/extensions.ts @@ -79,6 +79,6 @@ export async function installExt(id: string) { .catch(err => console.error(`Failed to extract extension ${id}`, err)); } - // @ts-expect-error Electron 36 Deprecates session.defaultSession.loadExtension() + // Electron 36 Deprecates session.defaultSession.loadExtension() session.defaultSession.extensions ? session.defaultSession.extensions.loadExtension(extDir) : session.defaultSession.loadExtension(extDir); } diff --git a/src/plugins/_core/supportHelper.tsx b/src/plugins/_core/supportHelper.tsx index 922166308..712137e78 100644 --- a/src/plugins/_core/supportHelper.tsx +++ b/src/plugins/_core/supportHelper.tsx @@ -290,7 +290,7 @@ export default definePlugin({ required: true, description: t("vencord.supportHelper.description"), authors: [Devs.Ven], - dependencies: ["UserSettingsAPI"], + dependencies: ["UserSettingsAPI", "CommandsAPI", "MessageAccessoriesAPI"], settings, diff --git a/src/plugins/accountPanelServerProfile/index.tsx b/src/plugins/accountPanelServerProfile/index.tsx index f2482b5a7..a55cefa7e 100644 --- a/src/plugins/accountPanelServerProfile/index.tsx +++ b/src/plugins/accountPanelServerProfile/index.tsx @@ -71,6 +71,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "AccountPanelServerProfile", description: t("vencord.accountPanelServerProfile.description"), + tags: ["Appearance", "Servers"], authors: [Devs.Nuckyz, Devs.relitrix], settings, @@ -80,7 +81,7 @@ export default definePlugin({ group: true, replacement: [ { - match: /(\.AVATAR,children:.+?renderPopout:(\i)=>){(.+?)}(?=,position)(?<=currentUser:(\i).+?)/, + match: /(\.AVATAR,children:.+?renderPopout:\(?(\i)(?:,\i\))?=>){(.+?)}(?=,position)(?<=currentUser:(\i).+?)/, replace: (_, rest, popoutProps, originalPopout, currentUser) => `${rest}$self.UserProfile({popoutProps:${popoutProps},currentUser:${currentUser},originalRenderPopout:()=>{${originalPopout}}})` }, { diff --git a/src/plugins/alwaysAnimate/index.ts b/src/plugins/alwaysAnimate/index.ts index 4d29a338a..84f35f9f1 100644 --- a/src/plugins/alwaysAnimate/index.ts +++ b/src/plugins/alwaysAnimate/index.ts @@ -52,6 +52,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "AlwaysAnimate", description: t("vencord.alwaysAnimate.description"), + tags: ["Appearance", "Fun"], authors: [Devs.FieryFlames], settings, patches: [ diff --git a/src/plugins/alwaysExpandRoles/index.ts b/src/plugins/alwaysExpandRoles/index.ts index e09882f1b..8895345c2 100644 --- a/src/plugins/alwaysExpandRoles/index.ts +++ b/src/plugins/alwaysExpandRoles/index.ts @@ -34,6 +34,7 @@ migratePluginSettings("AlwaysExpandRoles", "ShowAllRoles"); export default definePlugin({ name: "AlwaysExpandRoles", description: t("vencord.alwaysExpandRoles.description"), + tags: ["Appearance", "Roles"], authors: [Devs.surgedevs], isModified: true, settings, diff --git a/src/plugins/alwaysTrust/index.tsx b/src/plugins/alwaysTrust/index.tsx index 6601ae5fc..734b81b7c 100644 --- a/src/plugins/alwaysTrust/index.tsx +++ b/src/plugins/alwaysTrust/index.tsx @@ -61,6 +61,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "AlwaysTrust", description: t("vencord.alwaysTrust.description"), + tags: ["Utility"], authors: [Devs.zt, Devs.Trwy], isModified: true, settings, diff --git a/src/plugins/anonymiseFileNames/index.tsx b/src/plugins/anonymiseFileNames/index.tsx index 32cfdc7ef..aa6909086 100644 --- a/src/plugins/anonymiseFileNames/index.tsx +++ b/src/plugins/anonymiseFileNames/index.tsx @@ -76,6 +76,8 @@ export default definePlugin({ name: "AnonymiseFileNames", authors: [Devs.fawn], description: t("vencord.anonymiseFileNames.description"), + dependencies: ["CommandsAPI"], + tags: ["Privacy", "Utility"], isModified: true, settings, diff --git a/src/plugins/appleMusic.desktop/index.tsx b/src/plugins/appleMusic.desktop/index.tsx index ec430fd4e..f219b9268 100644 --- a/src/plugins/appleMusic.desktop/index.tsx +++ b/src/plugins/appleMusic.desktop/index.tsx @@ -158,6 +158,7 @@ function getImageAsset(type: AssetImageType, data: TrackData) { export default definePlugin({ name: "AppleMusicRichPresence", description: t("vencord.appleMusicRichPresence.description"), + tags: ["Activity", "Media"], authors: [Devs.RyanCaoDev], hidden: !IS_MAC, reporterTestable: ReporterTestable.None, diff --git a/src/plugins/arRPC.web/index.tsx b/src/plugins/arRPC.web/index.tsx index 06045ab05..ce0c022b6 100644 --- a/src/plugins/arRPC.web/index.tsx +++ b/src/plugins/arRPC.web/index.tsx @@ -43,6 +43,7 @@ migratePluginSettings("WebRichPresence", "WebRichPresence (arRPC)"); export default definePlugin({ name: "WebRichPresence", description: t("vencord.arRPC.description"), + tags: ["Activity", "Utility"], authors: [Devs.Ducko], reporterTestable: ReporterTestable.None, hidden: !IS_EQUIBOP && !IS_VESKTOP && !("legcord" in window), diff --git a/src/plugins/autoDndWhilePlaying.discordDesktop/index.ts b/src/plugins/autoDndWhilePlaying.discordDesktop/index.ts index 9c93ef484..ef2d4446b 100644 --- a/src/plugins/autoDndWhilePlaying.discordDesktop/index.ts +++ b/src/plugins/autoDndWhilePlaying.discordDesktop/index.ts @@ -49,6 +49,7 @@ migratePluginSettings("AutoDNDWhilePlaying", "StatusWhilePlaying"); export default definePlugin({ name: "AutoDNDWhilePlaying", description: t("vencord.autoDndWhilePlaying.description"), + tags: ["Activity", "Utility"], authors: [Devs.thororen], isModified: true, settings, diff --git a/src/plugins/betterFolders/index.tsx b/src/plugins/betterFolders/index.tsx index 2a7365146..ee8796d0c 100644 --- a/src/plugins/betterFolders/index.tsx +++ b/src/plugins/betterFolders/index.tsx @@ -255,9 +255,9 @@ const GRID_STYLE_NAME = "vc-betterFolders-sidebar-grid"; export default definePlugin({ name: "BetterFolders", description: t("vencord.betterFolders.description"), + tags: ["Organisation", "Servers", "Appearance"], authors: [Devs.juby, Devs.AutumnVN, Devs.Nuckyz], isModified: true, - settings, start() { settings.store.nestedFolders = getNestedFolderMap(); diff --git a/src/plugins/betterGifAltText/index.ts b/src/plugins/betterGifAltText/index.ts index 00e08b475..b4dfae2cc 100644 --- a/src/plugins/betterGifAltText/index.ts +++ b/src/plugins/betterGifAltText/index.ts @@ -24,6 +24,7 @@ export default definePlugin({ name: "BetterGifAltText", authors: [Devs.Ven], description: t("vencord.betterGifAltText.description"), + tags: ["Media", "Accessibility", "Customisation"], patches: [ { find: ".modalContext})};", diff --git a/src/plugins/betterGifPicker/index.ts b/src/plugins/betterGifPicker/index.ts index 61b750126..5918f9661 100644 --- a/src/plugins/betterGifPicker/index.ts +++ b/src/plugins/betterGifPicker/index.ts @@ -21,6 +21,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "BetterGifPicker", description: t("vencord.betterGifPicker.description"), + tags: ["Emotes", "Customisation"], authors: [Devs.Samwich, EquicordDevs.justjxke], isModified: true, settings, diff --git a/src/plugins/betterNotes/index.tsx b/src/plugins/betterNotes/index.tsx index fb28c24eb..632af88f1 100644 --- a/src/plugins/betterNotes/index.tsx +++ b/src/plugins/betterNotes/index.tsx @@ -41,6 +41,7 @@ export default definePlugin({ name: "BetterNotesBox", description: t("vencord.betterNotesBox.description"), authors: [Devs.Ven], + tags: ["Customisation", "Utility"], settings, patches: [ diff --git a/src/plugins/betterRoleContext/index.tsx b/src/plugins/betterRoleContext/index.tsx index 4b226e729..07514e5d0 100644 --- a/src/plugins/betterRoleContext/index.tsx +++ b/src/plugins/betterRoleContext/index.tsx @@ -91,6 +91,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "BetterRoleContext", description: t("vencord.betterRoleContext.description"), + tags: ["Roles", "Appearance"], authors: [Devs.Ven, Devs.goodbee], dependencies: ["UserSettingsAPI"], diff --git a/src/plugins/betterRoleDot/index.ts b/src/plugins/betterRoleDot/index.ts index aed3f3249..ab9dafc12 100644 --- a/src/plugins/betterRoleDot/index.ts +++ b/src/plugins/betterRoleDot/index.ts @@ -41,6 +41,7 @@ export default definePlugin({ name: "BetterRoleDot", authors: [Devs.Ven, Devs.AutumnVN], description: t("vencord.betterRoleDot.description"), + tags: ["Roles", "Appearance"], settings, patches: [ diff --git a/src/plugins/betterSessions/index.tsx b/src/plugins/betterSessions/index.tsx index 6e369507e..a88b55532 100644 --- a/src/plugins/betterSessions/index.tsx +++ b/src/plugins/betterSessions/index.tsx @@ -57,7 +57,7 @@ export default definePlugin({ name: "BetterSessions", description: t("vencord.betterSessions.description"), authors: [Devs.amia], - + tags: ["Notifications", "Customisation", "Utility"], settings: settings, patches: [ diff --git a/src/plugins/betterSessions/styles.css b/src/plugins/betterSessions/styles.css index adfc283f0..fafba1ed0 100644 --- a/src/plugins/betterSessions/styles.css +++ b/src/plugins/betterSessions/styles.css @@ -7,13 +7,11 @@ .vc-betterSessions-rename-btn { margin-left: 4px; translate: 0 -2px; - width: fit-content; } .vc-betterSessions-new-btn { margin-left: 4px; translate: 0 -2px; - width: fit-content; pointer-events: none; padding: 1px 4px; } \ No newline at end of file diff --git a/src/plugins/betterSettings/index.tsx b/src/plugins/betterSettings/index.tsx index 0bfebf086..4b3ba9c46 100644 --- a/src/plugins/betterSettings/index.tsx +++ b/src/plugins/betterSettings/index.tsx @@ -79,6 +79,7 @@ export default definePlugin({ name: "BetterSettings", description: t("vencord.betterSettings.description"), authors: [Devs.Kyuuhachi], + tags: ["Appearance", "Customisation", "Organisation"], settings, start() { diff --git a/src/plugins/betterUploadButton/index.ts b/src/plugins/betterUploadButton/index.ts index 35c041f09..411789123 100644 --- a/src/plugins/betterUploadButton/index.ts +++ b/src/plugins/betterUploadButton/index.ts @@ -24,6 +24,7 @@ export default definePlugin({ name: "BetterUploadButton", authors: [Devs.fawn, Devs.Ven], description: t("vencord.betterUploadButton.description"), + tags: ["Utility", "Shortcuts"], patches: [ { find: ".CHAT_INPUT_BUTTON_NOTIFICATION,", diff --git a/src/plugins/biggerStreamPreview/index.tsx b/src/plugins/biggerStreamPreview/index.tsx index c4063a85d..81254c777 100644 --- a/src/plugins/biggerStreamPreview/index.tsx +++ b/src/plugins/biggerStreamPreview/index.tsx @@ -90,6 +90,7 @@ export const userContextPatch: NavContextMenuPatchCallback = (children, { user } export default definePlugin({ name: "BiggerStreamPreview", description: t("vencord.biggerStreamPreview.description"), + tags: ["Media", "Appearance"], authors: [Devs.phil], contextMenus: { "user-context": userContextPatch, diff --git a/src/plugins/blurNsfw/index.ts b/src/plugins/blurNsfw/index.ts index 21110d80c..2d6af2770 100644 --- a/src/plugins/blurNsfw/index.ts +++ b/src/plugins/blurNsfw/index.ts @@ -44,6 +44,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "BlurNSFW", description: t("vencord.blurNsfw.description"), + tags: ["Privacy", "Appearance"], authors: [Devs.Ven], isModified: true, settings, diff --git a/src/plugins/callTimer/index.tsx b/src/plugins/callTimer/index.tsx index fb12218d3..019091c8a 100644 --- a/src/plugins/callTimer/index.tsx +++ b/src/plugins/callTimer/index.tsx @@ -4,7 +4,7 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -import { definePluginSettings, migratePluginToSettings, migrateSettingsFromPlugin } from "@api/Settings"; +import { definePluginSettings } from "@api/Settings"; import ErrorBoundary from "@components/ErrorBoundary"; import { Devs, EquicordDevs } from "@utils/constants"; import { useTimer } from "@utils/react"; @@ -107,11 +107,10 @@ let myLastChannelId: string | undefined; // Allow user updates on discord first load let runOneTime = true; -migratePluginToSettings(false, "CallTimer", "AllCallTimers", "allCallTimers"); -migrateSettingsFromPlugin("CallTimer", "AllCallTimers", "showWithoutHover", "showRoleColor", "trackSelf", "showSeconds", "watchLargeGuilds"); export default definePlugin({ name: "CallTimer", description: t("vencord.callTimer.description"), + tags: ["Voice", "Utility"], authors: [Devs.Ven, EquicordDevs.MaxHerbold, Devs.D3SOX], managedStyle: alignedChatInputFix, settings, diff --git a/src/plugins/characterCounter/index.tsx b/src/plugins/characterCounter/index.tsx index 209924bc2..ac5d629ec 100644 --- a/src/plugins/characterCounter/index.tsx +++ b/src/plugins/characterCounter/index.tsx @@ -8,12 +8,14 @@ import "./style.css"; import { definePluginSettings } from "@api/Settings"; import ErrorBoundary from "@components/ErrorBoundary"; -import { Devs } from "@utils/constants"; +import { Devs, EquicordDevs } from "@utils/constants"; import { classNameFactory } from "@utils/css"; import definePlugin, { OptionType } from "@utils/types"; -import { UserStore } from "@webpack/common"; +import { findByPropsLazy } from "@webpack"; +import { useEffect, UserStore, useState } from "@webpack/common"; const cl = classNameFactory("vc-charCounter-"); +const SlateUtils = findByPropsLazy("getSelectedText"); const settings = definePluginSettings({ colorEffects: { @@ -34,15 +36,16 @@ function getCounterColor(percentage: number) { export default definePlugin({ name: "CharacterCounter", description: "Adds a character counter to the chat input", - authors: [Devs.thororen], + authors: [Devs.thororen, EquicordDevs.creations], + tags: ["Utility"], settings, patches: [ { find: ".CREATE_FORUM_POST||", replacement: [ { - match: /(?<=textValue:(\i),editorHeight:\i,channelId:\i\.id\}\)),\i/, - replace: ",$self.renderCharCounter({text:$1})" + match: /(?<=,editorRef:(\i),.{0,200}textValue:(\i),editorHeight:\i,channelId:\i\.id\}\)),\i/, + replace: ",$self.renderCharCounter({editorRef:$1,text:$2})" } ] }, @@ -55,7 +58,21 @@ export default definePlugin({ } ], - renderCharCounter: ErrorBoundary.wrap(({ text }: { text: string; }) => { + renderCharCounter: ErrorBoundary.wrap(({ editorRef, text }: { text: string; editorRef: any; }) => { + const [selectedCount, setSelectedCount] = useState(0); + const showSelected = selectedCount > 0 && (editorRef?.current?.state?.focused ?? false); + + useEffect(() => { + const listener = () => { + if (!editorRef?.current) return setSelectedCount(0); + + setTimeout(() => setSelectedCount(SlateUtils.getSelectedText(editorRef.current.getSlateEditor())?.length ?? 0), 50); + }; + + document.addEventListener("selectionchange", listener); + return () => document.removeEventListener("selectionchange", listener); + }, []); + if (!text.length) return null; const premiumType = UserStore.getCurrentUser().premiumType ?? 0; @@ -65,6 +82,12 @@ export default definePlugin({ return (
+ {showSelected && ( + <> + {selectedCount} + / + + )} {text.length} / {charMax} diff --git a/src/plugins/characterCounter/style.css b/src/plugins/characterCounter/style.css index 072d42bef..87f7d775a 100644 --- a/src/plugins/characterCounter/style.css +++ b/src/plugins/characterCounter/style.css @@ -12,4 +12,8 @@ .vc-charCounter-count { transition: color 0.3s ease; +} + +.vc-charCounter-selected { + color: #4285F4 } \ No newline at end of file diff --git a/src/plugins/clearURLs/index.ts b/src/plugins/clearURLs/index.ts index d01fdde9f..362c43a83 100644 --- a/src/plugins/clearURLs/index.ts +++ b/src/plugins/clearURLs/index.ts @@ -51,6 +51,8 @@ interface RuleSet { export default definePlugin({ name: "ClearURLs", description: t("vencord.clearURLs.description"), + dependencies: ["MessageEventsAPI"], + tags: ["Privacy", "Utility"], authors: [Devs.adryd, Devs.thororen], rules: [] as RuleSet[], diff --git a/src/plugins/clientTheme/index.tsx b/src/plugins/clientTheme/index.tsx index 29a257ed2..964f85f96 100644 --- a/src/plugins/clientTheme/index.tsx +++ b/src/plugins/clientTheme/index.tsx @@ -30,6 +30,7 @@ export default definePlugin({ name: "ClientTheme", authors: [Devs.Nuckyz], description: t("vencord.clientTheme.themeColorDescription"), + tags: ["Appearance", "Customisation"], settings, startAt: StartAt.DOMContentLoaded, diff --git a/src/plugins/colorSighted/index.ts b/src/plugins/colorSighted/index.ts index 5aa9d4f4a..2d64b4109 100644 --- a/src/plugins/colorSighted/index.ts +++ b/src/plugins/colorSighted/index.ts @@ -24,6 +24,7 @@ export default definePlugin({ name: "ColorSighted", description: t("vencord.colorSighted.description"), authors: [Devs.lewisakura], + tags: ["Appearance", "Accessibility"], patches: [ { find: "Masks.STATUS_ONLINE", diff --git a/src/plugins/consoleJanitor/index.tsx b/src/plugins/consoleJanitor/index.tsx index b3eafd0d3..0f03f09a4 100644 --- a/src/plugins/consoleJanitor/index.tsx +++ b/src/plugins/consoleJanitor/index.tsx @@ -110,6 +110,7 @@ export default definePlugin({ name: "ConsoleJanitor", description: t("vencord.consoleJanitor.description"), authors: [Devs.Nuckyz, Devs.sadan], + tags: ["Developers", "Console", "Utility"], settings, startAt: StartAt.Init, diff --git a/src/plugins/consoleShortcuts/index.ts b/src/plugins/consoleShortcuts/index.ts index 9135c2fab..66f43beab 100644 --- a/src/plugins/consoleShortcuts/index.ts +++ b/src/plugins/consoleShortcuts/index.ts @@ -16,6 +16,7 @@ * along with this program. If not, see . */ +import { loadLazyChunks } from "@debug/loadLazyChunks"; import { Devs } from "@utils/constants"; import { getCurrentChannel, getCurrentGuild } from "@utils/discord"; import { runtimeHashMessageKey } from "@utils/intlHash"; @@ -29,7 +30,6 @@ import definePlugin, { PluginNative, StartAt } from "@utils/types"; import * as Webpack from "@webpack"; import { extract, filters, findAll, findModuleId, search } from "@webpack"; import * as Common from "@webpack/common"; -import { loadLazyChunks } from "debug/loadLazyChunks"; import type { ComponentType } from "react"; const DESKTOP_ONLY = (f: string) => () => { @@ -246,6 +246,7 @@ export default definePlugin({ name: "ConsoleShortcuts", description: t("vencord.consoleShortcuts.description"), authors: [Devs.Ven], + tags: ["Developers", "Console", "Shortcuts", "Utility"], startAt: StartAt.Init, patches: [ diff --git a/src/plugins/copyEmojiMarkdown/index.tsx b/src/plugins/copyEmojiMarkdown/index.tsx index ae64950b5..670216d67 100644 --- a/src/plugins/copyEmojiMarkdown/index.tsx +++ b/src/plugins/copyEmojiMarkdown/index.tsx @@ -52,6 +52,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "CopyEmojiMarkdown", description: t("vencord.copyEmojiMarkdown.description"), + tags: ["Emotes", "Utility"], authors: [Devs.HappyEnderman, Devs.Vishnya], settings, diff --git a/src/plugins/copyFileContents/index.tsx b/src/plugins/copyFileContents/index.tsx index f429f1b5c..cb10e5e90 100644 --- a/src/plugins/copyFileContents/index.tsx +++ b/src/plugins/copyFileContents/index.tsx @@ -23,6 +23,7 @@ const CheckMarkIcon = () => { export default definePlugin({ name: "CopyFileContents", description: t("vencord.copyFileContents.description"), + tags: ["Utility"], authors: [Devs.Obsidian, Devs.Nuckyz], patches: [ { diff --git a/src/plugins/copyStickerLinks/index.tsx b/src/plugins/copyStickerLinks/index.tsx index de1dbc48e..59e1f8b4b 100644 --- a/src/plugins/copyStickerLinks/index.tsx +++ b/src/plugins/copyStickerLinks/index.tsx @@ -88,6 +88,7 @@ const expressionPickerPatch: NavContextMenuPatchCallback = (children, props: { t export default definePlugin({ name: "CopyStickerLinks", description: t("vencord.copyStickerLinks.description"), + tags: ["Emotes", "Utility"], authors: [Devs.Ven, Devs.Byeoon], contextMenus: { "message": messageContextMenuPatch, diff --git a/src/plugins/copyUserURLs/index.tsx b/src/plugins/copyUserURLs/index.tsx index 66ad1a624..05baece0b 100644 --- a/src/plugins/copyUserURLs/index.tsx +++ b/src/plugins/copyUserURLs/index.tsx @@ -48,6 +48,7 @@ export default definePlugin({ name: "CopyUserURLs", authors: [Devs.castdrian], description: t("vencord.copyUserURLs.description"), + tags: ["Utility", "Friends"], contextMenus: { "user-context": UserContextMenuPatch } diff --git a/src/plugins/crashHandler/index.ts b/src/plugins/crashHandler/index.ts index 4323d46c9..0d471c9e3 100644 --- a/src/plugins/crashHandler/index.ts +++ b/src/plugins/crashHandler/index.ts @@ -62,8 +62,8 @@ export default definePlugin({ name: "CrashHandler", description: t("vencord.crashHandler.description"), authors: [Devs.Nuckyz], + tags: ["Utility", "Developers"], enabledByDefault: true, - settings, patches: [ diff --git a/src/plugins/ctrlEnterSend/index.ts b/src/plugins/ctrlEnterSend/index.ts index 192b7d240..bd8b37ee0 100644 --- a/src/plugins/ctrlEnterSend/index.ts +++ b/src/plugins/ctrlEnterSend/index.ts @@ -13,6 +13,7 @@ export default definePlugin({ name: "CtrlEnterSend", authors: [Devs.UlyssesZhan], description: t("vencord.ctrlEnterSend.description"), + tags: ["Shortcuts", "Chat"], settings: definePluginSettings({ submitRule: { description: t("vencord.ctrlEnterSend.settings.submitRule"), diff --git a/src/plugins/customCommands/index.ts b/src/plugins/customCommands/index.ts index b89e4d958..bc77ab6f6 100644 --- a/src/plugins/customCommands/index.ts +++ b/src/plugins/customCommands/index.ts @@ -90,8 +90,10 @@ migratePluginSettings("CustomCommands", "MessageTags"); export default definePlugin({ name: "CustomCommands", description: "Allows you to create custom slash commands / tags", - tags: ["MessageTags"], + dependencies: ["CommandsAPI"], + searchTerms: ["MessageTags"], authors: [Devs.Ven, Devs.Luna,], + tags: ["Commands", "Customisation", "Utility"], settings, async start() { diff --git a/src/plugins/customIdle/index.ts b/src/plugins/customIdle/index.ts index a31f5b2c5..f98779903 100644 --- a/src/plugins/customIdle/index.ts +++ b/src/plugins/customIdle/index.ts @@ -30,6 +30,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "CustomIdle", description: t("vencord.customIdle.description"), + tags: ["Activity", "Customisation"], authors: [Devs.newwares], settings, patches: [ diff --git a/src/plugins/customRPC/index.tsx b/src/plugins/customRPC/index.tsx index 2efcffb2e..34d4b2f9b 100644 --- a/src/plugins/customRPC/index.tsx +++ b/src/plugins/customRPC/index.tsx @@ -216,6 +216,7 @@ export async function setRpc(disable?: boolean) { export default definePlugin({ name: "CustomRPC", description: t("vencord.customRPC.description"), + tags: ["Activity", "Customisation"], authors: [Devs.captain, Devs.AutumnVN, Devs.nin0dev], dependencies: ["UserSettingsAPI"], // This plugin's patch is not important for functionality, so don't require a restart diff --git a/src/plugins/dearrow/index.tsx b/src/plugins/dearrow/index.tsx index a56d51643..912bcd6d5 100644 --- a/src/plugins/dearrow/index.tsx +++ b/src/plugins/dearrow/index.tsx @@ -171,6 +171,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "Dearrow", description: t("vencord.dearrow.description"), + tags: ["Media", "Utility"], authors: [Devs.Ven], settings, diff --git a/src/plugins/decor/index.tsx b/src/plugins/decor/index.tsx index 40e1abc74..c1039209a 100644 --- a/src/plugins/decor/index.tsx +++ b/src/plugins/decor/index.tsx @@ -28,6 +28,7 @@ export interface AvatarDecoration { export default definePlugin({ name: "Decor", description: t("vencord.decor.description"), + tags: ["Appearance", "Customisation"], authors: [Devs.FieryFlames], patches: [ // Patch MediaResolver to return correct URL for Decor avatar decorations diff --git a/src/plugins/devCompanion.dev/index.tsx b/src/plugins/devCompanion.dev/index.tsx index a1836a3d2..10fbc6c58 100644 --- a/src/plugins/devCompanion.dev/index.tsx +++ b/src/plugins/devCompanion.dev/index.tsx @@ -19,8 +19,8 @@ import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; import { Logger } from "@utils/Logger"; -import definePlugin, { OptionType, ReporterTestable } from "@utils/types"; import { t } from "@utils/translation"; +import definePlugin, { OptionType, ReporterTestable } from "@utils/types"; import { initWs, socket, stopWs } from "./initWs"; export const PORT = 8485; @@ -49,6 +49,7 @@ export const settings = definePluginSettings({ export default definePlugin({ name: "DevCompanion", description: t("vencord.devCompanion.description"), + tags: ["Developers", "Utility"], authors: [Devs.Ven, Devs.sadan], reporterTestable: ReporterTestable.None, isModified: true, diff --git a/src/plugins/devCompanion.dev/initWs.tsx b/src/plugins/devCompanion.dev/initWs.tsx index 89bee1d38..49e931808 100644 --- a/src/plugins/devCompanion.dev/initWs.tsx +++ b/src/plugins/devCompanion.dev/initWs.tsx @@ -5,14 +5,14 @@ */ import { popNotice, showNotice } from "@api/Notices"; +import { Settings } from "@api/Settings"; import ErrorBoundary from "@components/ErrorBoundary"; +import { loadLazyChunks } from "@debug/loadLazyChunks"; +import { reporterData } from "@debug/reporterData"; import { getIntlMessageFromHash } from "@utils/discord"; import { canonicalizeMatch, canonicalizeReplace } from "@utils/patches"; import { filters, findAll, search, wreq } from "@webpack"; import { React, Toasts, useState } from "@webpack/common"; -import { loadLazyChunks } from "debug/loadLazyChunks"; -import { reporterData } from "debug/reporterData"; -import { Settings } from "Vencord"; import { CLIENT_VERSION, logger, PORT, settings } from "."; import { Recieve } from "./types"; diff --git a/src/plugins/devCompanion.dev/types/send.ts b/src/plugins/devCompanion.dev/types/send.ts index 86260a4e3..e9439e631 100644 --- a/src/plugins/devCompanion.dev/types/send.ts +++ b/src/plugins/devCompanion.dev/types/send.ts @@ -4,7 +4,7 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -import { ReporterData } from "debug/reporterData"; +import { ReporterData } from "@debug/reporterData"; export type OutgoingMessage = Base; export type FullOutgoingMessage = OutgoingMessage & Nonce; diff --git a/src/plugins/devCompanion.dev/util.tsx b/src/plugins/devCompanion.dev/util.tsx index 4fda47040..7611b8081 100644 --- a/src/plugins/devCompanion.dev/util.tsx +++ b/src/plugins/devCompanion.dev/util.tsx @@ -10,8 +10,8 @@ import { Settings } from "@api/Settings"; import { canonicalizeMatch } from "@utils/patches"; import { CodeFilter, stringMatches, wreq } from "@webpack"; import { Toasts } from "@webpack/common"; -import { WebpackPatcher } from "Vencord"; +import { WebpackPatcher } from "../../Vencord"; import { logger, settings as companionSettings } from "."; import { FindNode } from "./types/recieve"; diff --git a/src/plugins/disableCallIdle/index.ts b/src/plugins/disableCallIdle/index.ts index 0547a88c8..2b7afbc65 100644 --- a/src/plugins/disableCallIdle/index.ts +++ b/src/plugins/disableCallIdle/index.ts @@ -23,6 +23,7 @@ import definePlugin from "@utils/types"; export default definePlugin({ name: "DisableCallIdle", description: t("vencord.disableCallIdle.description"), + tags: ["Voice", "Utility"], authors: [Devs.Nuckyz], patches: [ { diff --git a/src/plugins/dontRoundMyTimestamps/index.ts b/src/plugins/dontRoundMyTimestamps/index.ts index 98870b8bc..5590a6385 100644 --- a/src/plugins/dontRoundMyTimestamps/index.ts +++ b/src/plugins/dontRoundMyTimestamps/index.ts @@ -25,6 +25,7 @@ export default definePlugin({ name: "DontRoundMyTimestamps", authors: [Devs.Lexi], description: t("vencord.dontRoundMyTimestamps.description"), + tags: ["Appearance", "Utility"], start() { moment.relativeTimeRounding(Math.floor); diff --git a/src/plugins/experiments/index.tsx b/src/plugins/experiments/index.tsx index e1291de58..f4b963dee 100644 --- a/src/plugins/experiments/index.tsx +++ b/src/plugins/experiments/index.tsx @@ -38,6 +38,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "Experiments", description: t("vencord.experiments.description"), + tags: ["Developers", "Utility"], authors: [ Devs.Megu, Devs.Ven, @@ -71,8 +72,10 @@ export default definePlugin({ match: /(?<=children:\[)(?=null!=.{0,150}"Installation ID:)/, replace: "$self.WarningCard()," }, + // for some reason the installation id and copy buttons are on + // different lines so it looks stupid when the card above is added { - match: /(?<=marginBottom:16)(?=\},)/, + match: /(?<=,marginBottom:16)(?=\},children:\[)/, replace: ',flexDirection:"row",alignItems:"center"' } ] diff --git a/src/plugins/expressionCloner/index.tsx b/src/plugins/expressionCloner/index.tsx index ccdbbc5af..827db5234 100644 --- a/src/plugins/expressionCloner/index.tsx +++ b/src/plugins/expressionCloner/index.tsx @@ -233,7 +233,7 @@ function CloneModal({ data }: { data: Sticker | Emoji; }) { <> {t("vencord.expressionCloner.customName")} { data.name = v; setName(v); @@ -412,7 +412,7 @@ migratePluginSettings("ExpressionCloner", "EmoteCloner"); export default definePlugin({ name: "ExpressionCloner", description: t("vencord.expressionCloner.description"), - tags: ["StickerCloner", "EmoteCloner", "EmojiCloner"], + tags: ["Emotes", "Servers"], authors: [Devs.Ven, Devs.Nuckyz], contextMenus: { "message": messageContextMenuPatch, diff --git a/src/plugins/f8break/index.ts b/src/plugins/f8break/index.ts index ff3fae408..e2d2f9916 100644 --- a/src/plugins/f8break/index.ts +++ b/src/plugins/f8break/index.ts @@ -23,6 +23,7 @@ import definePlugin from "@utils/types"; export default definePlugin({ name: "F8Break", description: t("vencord.f8break.description"), + tags: ["Developers", "Shortcuts"], authors: [Devs.lewisakura], start() { diff --git a/src/plugins/fakeNitro/index.tsx b/src/plugins/fakeNitro/index.tsx index 52b4c8011..238b6d298 100644 --- a/src/plugins/fakeNitro/index.tsx +++ b/src/plugins/fakeNitro/index.tsx @@ -181,6 +181,7 @@ export default definePlugin({ name: "FakeNitro", authors: [Devs.Arjix, Devs.D3SOX, Devs.Ven, Devs.fawn, Devs.captain, Devs.Nuckyz, Devs.AutumnVN, Devs.sadan], description: t("vencord.fakeNitro.description"), + tags: ["Emotes", "Appearance", "Customisation", "Chat"], dependencies: ["MessageEventsAPI"], settings, diff --git a/src/plugins/fakeProfileThemes/index.tsx b/src/plugins/fakeProfileThemes/index.tsx index 04b28a22f..40897c563 100644 --- a/src/plugins/fakeProfileThemes/index.tsx +++ b/src/plugins/fakeProfileThemes/index.tsx @@ -200,6 +200,7 @@ function SettingsAboutComponent() { export default definePlugin({ name: "FakeProfileThemes", description: "Allows profile theming by hiding the colors in your bio thanks to invisible 3y3 encoding", + tags: ["Appearance", "Customisation"], authors: [Devs.Alyxia, Devs.Remty], patches: [ { diff --git a/src/plugins/favEmojiFirst/index.tsx b/src/plugins/favEmojiFirst/index.tsx index 32e6eefaf..f3dbbf0e7 100644 --- a/src/plugins/favEmojiFirst/index.tsx +++ b/src/plugins/favEmojiFirst/index.tsx @@ -1102,8 +1102,9 @@ const messageSendListener = (_channelId: string, messageObj: { content: string; export default definePlugin({ name: "FavoriteEmojiFirst", authors: [Devs.Aria, Devs.Ven, EquicordDevs.justjxke], - tags: ["EmojiAlias"], description: t("vencord.favEmojiFirst.description"), + dependencies: ["MessagePopoverAPI"], + tags: ["Emotes", "Customisation"], settings, contextMenus: { "expression-picker": expressionPickerPatch, diff --git a/src/plugins/favGifSearch/index.tsx b/src/plugins/favGifSearch/index.tsx index f086a29e0..06c40bcb2 100644 --- a/src/plugins/favGifSearch/index.tsx +++ b/src/plugins/favGifSearch/index.tsx @@ -85,6 +85,7 @@ export default definePlugin({ name: "FavoriteGifSearch", authors: [Devs.Aria], description: t("vencord.favGifSearch.description"), + tags: ["Media", "Customisation"], patches: [ { diff --git a/src/plugins/fixCodeblockGap/index.ts b/src/plugins/fixCodeblockGap/index.ts index 5810138d5..133a3f2bc 100644 --- a/src/plugins/fixCodeblockGap/index.ts +++ b/src/plugins/fixCodeblockGap/index.ts @@ -11,6 +11,7 @@ import definePlugin from "@utils/types"; export default definePlugin({ name: "FixCodeblockGap", description: t("vencord.fixCodeblockGap.description"), + tags: ["Appearance"], authors: [Devs.Grzesiek11], patches: [ { diff --git a/src/plugins/fixImagesQuality/index.tsx b/src/plugins/fixImagesQuality/index.tsx index 913aead67..8363389ea 100644 --- a/src/plugins/fixImagesQuality/index.tsx +++ b/src/plugins/fixImagesQuality/index.tsx @@ -25,6 +25,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "FixImagesQuality", description: t("vencord.fixImagesQuality.description"), + tags: ["Media", "Appearance"], authors: [Devs.Nuckyz, Devs.Ven], settings, diff --git a/src/plugins/fixSpotifyEmbeds.desktop/index.tsx b/src/plugins/fixSpotifyEmbeds.desktop/index.tsx index 78767bb6d..085d8e3cf 100644 --- a/src/plugins/fixSpotifyEmbeds.desktop/index.tsx +++ b/src/plugins/fixSpotifyEmbeds.desktop/index.tsx @@ -23,5 +23,6 @@ export default definePlugin({ name: "FixSpotifyEmbeds", description: t("vencord.fixSpotifyEmbeds.description"), authors: [Devs.Ven], + tags: ["Media", "Customisation"], settings, }); diff --git a/src/plugins/fixYoutubeEmbeds.desktop/index.tsx b/src/plugins/fixYoutubeEmbeds.desktop/index.tsx index ebb090086..fb35afc31 100644 --- a/src/plugins/fixYoutubeEmbeds.desktop/index.tsx +++ b/src/plugins/fixYoutubeEmbeds.desktop/index.tsx @@ -28,6 +28,7 @@ migratePluginSettings("FixYoutubeEmbeds", "YoutubeDescription"); export default definePlugin({ name: "FixYoutubeEmbeds", description: t("vencord.fixYoutubeEmbeds.description"), + tags: ["Media", "Utility"], authors: [Devs.coolelectronics, Devs.arHSM], settings, patches: [ diff --git a/src/plugins/fixYoutubeEmbeds.desktop/native.ts b/src/plugins/fixYoutubeEmbeds.desktop/native.ts index f865a6566..950940b06 100644 --- a/src/plugins/fixYoutubeEmbeds.desktop/native.ts +++ b/src/plugins/fixYoutubeEmbeds.desktop/native.ts @@ -4,8 +4,8 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ +import { RendererSettings } from "@main/settings"; import { app } from "electron"; -import { RendererSettings } from "main/settings"; app.on("browser-window-created", (_, win) => { win.webContents.on("frame-created", (_, { frame }) => { diff --git a/src/plugins/forceOwnerCrown/index.ts b/src/plugins/forceOwnerCrown/index.ts index b51c3d4fb..21e306c15 100644 --- a/src/plugins/forceOwnerCrown/index.ts +++ b/src/plugins/forceOwnerCrown/index.ts @@ -26,6 +26,7 @@ export default definePlugin({ name: "ForceOwnerCrown", description: t("vencord.forceOwnerCrown.description"), authors: [Devs.D3SOX, Devs.Nickyux], + tags: ["Roles", "Appearance", "Servers"], patches: [ { find: "#{intl::GUILD_OWNER}),children:", diff --git a/src/plugins/friendInvites/index.ts b/src/plugins/friendInvites/index.ts index 6328cd220..d74af5e85 100644 --- a/src/plugins/friendInvites/index.ts +++ b/src/plugins/friendInvites/index.ts @@ -27,6 +27,8 @@ const FriendInvites = findByPropsLazy("createFriendInvite"); export default definePlugin({ name: "FriendInvites", description: t("vencord.friendInvites.description"), + dependencies: ["CommandsAPI"], + tags: ["Friends", "Commands"], authors: [Devs.afn, Devs.Dziurwa], commands: [ { diff --git a/src/plugins/friendsSince/index.tsx b/src/plugins/friendsSince/index.tsx index c97010eb8..18d2fec58 100644 --- a/src/plugins/friendsSince/index.tsx +++ b/src/plugins/friendsSince/index.tsx @@ -24,6 +24,7 @@ const Section = findComponentByCodeLazy("headingVariant:", '"section"', "heading export default definePlugin({ name: "FriendsSince", description: t("vencord.friendsSince.description"), + tags: ["Friends"], authors: [Devs.Elvyra, Devs.Antti], patches: [ // DM User Sidebar diff --git a/src/plugins/fullSearchContext/index.tsx b/src/plugins/fullSearchContext/index.tsx index 2638d51bb..3e0ed30ce 100644 --- a/src/plugins/fullSearchContext/index.tsx +++ b/src/plugins/fullSearchContext/index.tsx @@ -82,6 +82,7 @@ migratePluginSettings("FullSearchContext", "SearchReply"); export default definePlugin({ name: "FullSearchContext", description: t("vencord.fullSearchContext.description"), + tags: ["Utility"], authors: [Devs.Ven, Devs.Aria], patches: [{ diff --git a/src/plugins/fullUserInChatbox/index.tsx b/src/plugins/fullUserInChatbox/index.tsx index 96b4aeb98..217767b53 100644 --- a/src/plugins/fullUserInChatbox/index.tsx +++ b/src/plugins/fullUserInChatbox/index.tsx @@ -24,6 +24,7 @@ interface UserMentionComponentProps { export default definePlugin({ name: "FullUserInChatbox", description: t("vencord.fullUserInChatbox.description"), + tags: ["Shortcuts", "Utility"], authors: [Devs.sadan], patches: [ diff --git a/src/plugins/gameActivityToggle/index.tsx b/src/plugins/gameActivityToggle/index.tsx index 73a45e45a..3524d8ee2 100644 --- a/src/plugins/gameActivityToggle/index.tsx +++ b/src/plugins/gameActivityToggle/index.tsx @@ -99,8 +99,9 @@ function GameActivityToggleButton({ iconForeground, hideTooltips, nameplate }: U export default definePlugin({ name: "GameActivityToggle", description: t("vencord.gameActivityToggle.description"), + tags: ["Activity", "Shortcuts"], authors: [Devs.Nuckyz, Devs.RuukuLada], - dependencies: ["UserSettingsAPI"], + dependencies: ["UserSettingsAPI", "UserAreaAPI"], settings, userAreaButton: { diff --git a/src/plugins/gifPaste/index.ts b/src/plugins/gifPaste/index.ts index e188eb008..82ed6d76b 100644 --- a/src/plugins/gifPaste/index.ts +++ b/src/plugins/gifPaste/index.ts @@ -27,6 +27,7 @@ import { ExpressionPickerStore } from "@webpack/common"; export default definePlugin({ name: "GifPaste", description: t("vencord.gifPaste.description"), + tags: ["Media", "Chat"], authors: [Devs.Ven], patches: [{ diff --git a/src/plugins/greetStickerPicker/index.tsx b/src/plugins/greetStickerPicker/index.tsx index bf81486b0..e369059b5 100644 --- a/src/plugins/greetStickerPicker/index.tsx +++ b/src/plugins/greetStickerPicker/index.tsx @@ -153,6 +153,7 @@ function GreetMenu({ channel, message }: { message: Message, channel: Channel; } export default definePlugin({ name: "GreetStickerPicker", description: t("vencord.greetStickerPicker.description"), + tags: ["Emotes", "Customisation"], authors: [Devs.Ven], settings, diff --git a/src/plugins/hideAttachments/index.tsx b/src/plugins/hideAttachments/index.tsx index 315c555e9..f720c3e78 100644 --- a/src/plugins/hideAttachments/index.tsx +++ b/src/plugins/hideAttachments/index.tsx @@ -57,8 +57,9 @@ async function toggleHide(channelId: string, messageId: string) { export default definePlugin({ name: "HideMedia", description: t("vencord.hideAttachments.description"), + tags: ["Chat", "Appearance"], authors: [Devs.Ven], - dependencies: ["MessageUpdaterAPI"], + dependencies: ["MessageUpdaterAPI", "MessageAccessoriesAPI", "MessagePopoverAPI"], patches: [{ find: "this.renderAttachments(", diff --git a/src/plugins/iLoveSpam/index.ts b/src/plugins/iLoveSpam/index.ts index 8ba8e9dd7..6e03329aa 100644 --- a/src/plugins/iLoveSpam/index.ts +++ b/src/plugins/iLoveSpam/index.ts @@ -25,6 +25,7 @@ migratePluginSettings("IloveSpam", "iLoveSpam"); export default definePlugin({ name: "ILoveSpam", description: t("vencord.iLoveSpam.description"), + tags: ["Utility", "Chat"], authors: [Devs.botato, Devs.Nyako], patches: [ { diff --git a/src/plugins/ignoreActivities/index.tsx b/src/plugins/ignoreActivities/index.tsx index 7a6cc3a9c..6bfd5b26e 100644 --- a/src/plugins/ignoreActivities/index.tsx +++ b/src/plugins/ignoreActivities/index.tsx @@ -233,6 +233,7 @@ export default definePlugin({ name: "IgnoreActivities", authors: [Devs.Nuckyz, Devs.Kylie], description: t("vencord.ignoreActivities.description"), + tags: ["Activity", "Privacy", "Customisation"], dependencies: ["UserSettingsAPI"], settings, diff --git a/src/plugins/imageFilename/index.ts b/src/plugins/imageFilename/index.ts index 1f65121a8..76e3dadf1 100644 --- a/src/plugins/imageFilename/index.ts +++ b/src/plugins/imageFilename/index.ts @@ -6,8 +6,8 @@ import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; -import definePlugin, { OptionType } from "@utils/types"; import { t } from "@utils/translation"; +import definePlugin, { OptionType } from "@utils/types"; const ImageExtensionRe = /\.(png|jpg|jpeg|gif|webp|avif)$/i; const GifHostRegex = /^(.+?\.)?(tenor|giphy|imgur)\.com$/i; @@ -24,6 +24,7 @@ export default definePlugin({ name: "ImageFilename", authors: [Devs.Ven], description: t("vencord.imageFilename.description"), + tags: ["Media", "Utility"], settings, patches: [ diff --git a/src/plugins/imageLink/index.ts b/src/plugins/imageLink/index.ts index 75bd2c167..c6f66329d 100644 --- a/src/plugins/imageLink/index.ts +++ b/src/plugins/imageLink/index.ts @@ -5,12 +5,13 @@ */ import { Devs } from "@utils/constants"; -import definePlugin from "@utils/types"; import { t } from "@utils/translation"; +import definePlugin from "@utils/types"; export default definePlugin({ name: "ImageLink", description: t("vencord.imageLink.description"), + tags: ["Media", "Appearance"], authors: [Devs.Kyuuhachi, Devs.Sqaaakoi], patches: [ diff --git a/src/plugins/imageZoom/index.tsx b/src/plugins/imageZoom/index.tsx index 29184c879..a81594184 100644 --- a/src/plugins/imageZoom/index.tsx +++ b/src/plugins/imageZoom/index.tsx @@ -156,8 +156,9 @@ const imageContextMenuPatch: NavContextMenuPatchCallback = (children, props) => export default definePlugin({ name: "ImageZoom", description: t("vencord.imageZoom.description"), + tags: ["Media", "Utility"], authors: [Devs.Aria], - tags: ["ImageUtilities"], + searchTerms: ["ImageUtilities"], managedStyle, diff --git a/src/plugins/implicitRelationships/index.ts b/src/plugins/implicitRelationships/index.ts index f32fa3fdb..51cc3b2d2 100644 --- a/src/plugins/implicitRelationships/index.ts +++ b/src/plugins/implicitRelationships/index.ts @@ -22,12 +22,25 @@ import { Logger } from "@utils/Logger"; import { t } from "@utils/translation"; import definePlugin, { OptionType } from "@utils/types"; import { Constants, FluxDispatcher, GuildStore, RelationshipStore, SnowflakeUtils, UserAffinitiesStore, UserStore } from "@webpack/common"; -import { Settings } from "Vencord"; + +const settings = definePluginSettings( + { + sortByAffinity: { + type: OptionType.BOOLEAN, + default: true, + description: t("vencord.implicitRelationships.settings.sortByAffinity"), + restartNeeded: true + }, + } +); export default definePlugin({ name: "ImplicitRelationships", description: t("vencord.implicitRelationships.description"), + tags: ["Friends", "Servers"], authors: [Devs.Dolfies], + settings, + patches: [ // Counts header { @@ -74,7 +87,7 @@ export default definePlugin({ { find: "getRelationshipCounts(){", replacement: { - predicate: () => Settings.plugins.ImplicitRelationships.sortByAffinity, + predicate: () => settings.store.sortByAffinity, match: /\}\)\.sortBy\((.+?)\)\.value\(\)/, replace: "}).sortBy(row => $self.wrapSort(($1), row)).value()" } @@ -103,16 +116,6 @@ export default definePlugin({ }, } ], - settings: definePluginSettings( - { - sortByAffinity: { - type: OptionType.BOOLEAN, - default: true, - description: t("vencord.implicitRelationships.settings.sortByAffinity"), - restartNeeded: true - }, - } - ), wrapSort(comparator: Function, row: any) { return row.type === 5 diff --git a/src/plugins/ircColors/index.ts b/src/plugins/ircColors/index.ts index bd3b72e8b..cd405ecfd 100644 --- a/src/plugins/ircColors/index.ts +++ b/src/plugins/ircColors/index.ts @@ -21,7 +21,7 @@ import { getCustomColorString } from "@equicordplugins/customUserColors"; import { hash as h64 } from "@intrnl/xxhash64"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; -import { useMemo } from "@webpack/common"; +import { useMemo, UserStore } from "@webpack/common"; // Calculate a CSS color string based on the user ID function calculateNameColorForUser(id?: string) { @@ -60,6 +60,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "IrcColors", description: "Makes username colors in chat unique, like in IRC clients", + tags: ["Appearance", "Customisation"], authors: [Devs.Grzesiek11, Devs.jamesbt365], settings, @@ -121,9 +122,25 @@ export default definePlugin({ return colorString; } - return (!settings.store.applyColorOnlyToUsersWithoutColor || !colorString) + const dmColor = (!settings.store.applyColorOnlyToUsersWithoutColor || !colorString) ? color : colorString; + + // guarantee minimum difference in dms + if (context?.channel?.isPrivate?.() && dmColor && userId) { + const currentUserId = UserStore.getCurrentUser()?.id; + if (currentUserId && userId !== currentUserId) { + const currentUserColor = Number(h64(currentUserId) % 360n); + const otherUserColor = Number(h64(userId) % 360n); + const colorDiff = Math.min(Math.abs(currentUserColor - otherUserColor), 360 - Math.abs(currentUserColor - otherUserColor)); + if (colorDiff < 45) { + const newColor = (otherUserColor + 180) % 360; + return `hsl(${newColor}, 100%, ${settings.store.lightness}%)`; + } + } + } + + return dmColor; }, calculateNameColorForListContext(context: any) { diff --git a/src/plugins/keepCurrentChannel/index.ts b/src/plugins/keepCurrentChannel/index.ts index 90e702268..adde4dcac 100644 --- a/src/plugins/keepCurrentChannel/index.ts +++ b/src/plugins/keepCurrentChannel/index.ts @@ -44,6 +44,7 @@ let previousCache: PreviousChannel | undefined; export default definePlugin({ name: "KeepCurrentChannel", description: t("vencord.keepCurrentChannel.description"), + tags: ["Utility", "Organisation"], authors: [Devs.Nuckyz], patches: [ diff --git a/src/plugins/lastfmRichPresence/index.tsx b/src/plugins/lastfmRichPresence/index.tsx index 074b614b6..302672968 100644 --- a/src/plugins/lastfmRichPresence/index.tsx +++ b/src/plugins/lastfmRichPresence/index.tsx @@ -187,6 +187,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "LastFMRichPresence", description: t("vencord.lastfmRichPresence.description"), + tags: ["Activity", "Media"], authors: [Devs.dzshn, Devs.RuiNtD, Devs.blahajZip, Devs.archeruwu], settings, diff --git a/src/plugins/loadingQuotes/index.ts b/src/plugins/loadingQuotes/index.ts index 8c63fe5a2..fa0dd55fd 100644 --- a/src/plugins/loadingQuotes/index.ts +++ b/src/plugins/loadingQuotes/index.ts @@ -57,6 +57,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "LoadingQuotes", description: "Replace Discords loading quotes", + tags: ["Appearance", "Fun", "Customisation"], authors: [Devs.Ven, Devs.KraXen72, Devs.UlyssesZhan], settings, diff --git a/src/plugins/memberCount/index.tsx b/src/plugins/memberCount/index.tsx index a2dd1ed8a..e4bf11625 100644 --- a/src/plugins/memberCount/index.tsx +++ b/src/plugins/memberCount/index.tsx @@ -63,6 +63,7 @@ export const cl = classNameFactory("vc-membercount-"); export default definePlugin({ name: "MemberCount", description: t("vencord.memberCount.description"), + tags: ["Servers", "Utility"], authors: [Devs.Ven, Devs.Commandtechno, Devs.Apexo], settings, diff --git a/src/plugins/mentionAvatars/index.tsx b/src/plugins/mentionAvatars/index.tsx index b87995c8b..44b4ec12d 100644 --- a/src/plugins/mentionAvatars/index.tsx +++ b/src/plugins/mentionAvatars/index.tsx @@ -48,6 +48,7 @@ function DefaultRoleIcon() { export default definePlugin({ name: "MentionAvatars", description: "Shows user avatars and role icons inside mentions", + tags: ["Appearance", "Customisation"], authors: [Devs.Ven, Devs.SerStars], patches: [{ // HEY THOR UPDATE SHOW ME YOUR NAME IF THIS SHIT CHANGES TY :) diff --git a/src/plugins/messageClickActions/index.ts b/src/plugins/messageClickActions/index.ts index 42fd83fef..b070db16e 100644 --- a/src/plugins/messageClickActions/index.ts +++ b/src/plugins/messageClickActions/index.ts @@ -577,6 +577,7 @@ async function executeAction( export default definePlugin({ name: "MessageClickActions", description: "Customize click actions on messages.", + tags: ["Chat", "Shortcuts"], authors: [Devs.Ven, EquicordDevs.keircn, EquicordDevs.ZcraftElite, EquicordDevs.omaw], isModified: true, diff --git a/src/plugins/messageLatency/index.tsx b/src/plugins/messageLatency/index.tsx index fbfbf46eb..36a78b6b8 100644 --- a/src/plugins/messageLatency/index.tsx +++ b/src/plugins/messageLatency/index.tsx @@ -30,6 +30,7 @@ const DISCORD_KT_DELAY = 1471228928; export default definePlugin({ name: "MessageLatency", description: t("vencord.messageLatency.description"), + tags: ["Chat", "Utility"], authors: [Devs.arHSM], settings: definePluginSettings({ diff --git a/src/plugins/messageLinkEmbeds/index.tsx b/src/plugins/messageLinkEmbeds/index.tsx index 07f1632f5..cfcf656f2 100644 --- a/src/plugins/messageLinkEmbeds/index.tsx +++ b/src/plugins/messageLinkEmbeds/index.tsx @@ -365,6 +365,7 @@ function AutomodEmbedAccessory(props: MessageEmbedProps): JSX.Element | null { export default definePlugin({ name: "MessageLinkEmbeds", description: t("vencord.messageLinkEmbeds.description"), + tags: ["Chat", "Appearance"], authors: [Devs.TheSun, Devs.Ven, Devs.RyanCaoDev], dependencies: ["MessageAccessoriesAPI", "MessageUpdaterAPI", "UserSettingsAPI"], diff --git a/src/plugins/messageLogger/index.tsx b/src/plugins/messageLogger/index.tsx index 839cbbd57..d29d84c22 100644 --- a/src/plugins/messageLogger/index.tsx +++ b/src/plugins/messageLogger/index.tsx @@ -418,6 +418,7 @@ export const settings = definePluginSettings({ export default definePlugin({ name: "MessageLogger", description: t("vencord.messageLogger.description"), + tags: ["Chat", "Utility"], authors: [Devs.rushii, Devs.Ven, Devs.AutumnVN, Devs.Nickyux, Devs.Kyuuhachi, EquicordDevs.justjxke], dependencies: ["MessageUpdaterAPI"], isModified: true, diff --git a/src/plugins/moreQuickReactions/index.ts b/src/plugins/moreQuickReactions/index.ts index 25e7ff4f7..811b15c1b 100644 --- a/src/plugins/moreQuickReactions/index.ts +++ b/src/plugins/moreQuickReactions/index.ts @@ -52,6 +52,7 @@ migratePluginSettings("MoreQuickReactions", "BetterQuickReact"); export default definePlugin({ name: "MoreQuickReactions", description: "Improves the quick react buttons in the message context menu.", + tags: ["Emotes", "Reactions", "Customisation", "Shortcuts"], authors: [Devs.Ven, Devs.Sqaaakoi, Devs.iamme], isModified: true, settings, diff --git a/src/plugins/mutualGroupDMs/index.tsx b/src/plugins/mutualGroupDMs/index.tsx index af3094ab4..48247df2d 100644 --- a/src/plugins/mutualGroupDMs/index.tsx +++ b/src/plugins/mutualGroupDMs/index.tsx @@ -36,7 +36,7 @@ const UserUtils = findByPropsLazy("getGlobalName"); const ProfileListClasses = findCssClassesLazy("empty", "textContainer", "connectionIcon"); const TabBarClasses = findCssClassesLazy("tabPanelScroller", "tabBarPanel"); const MutualsListClasses = findCssClassesLazy("row", "icon", "name", "details"); -const ExpandableList = findComponentByCodeLazy('action:"PRESS_SECTION"', "section"); +const ExpandableList = findComponentByCodeLazy('action:"PRESS_SECTION"', '"section"'); function getGroupDMName(channel: Channel) { return channel.name || @@ -89,6 +89,7 @@ const IS_PATCHED = Symbol("MutualGroupDMs.Patched"); export default definePlugin({ name: "MutualGroupDMs", description: t("vencord.mutualGroupDMs.description"), + tags: ["Friends", "Appearance"], authors: [Devs.amia], patches: [ diff --git a/src/plugins/newGuildSettings/index.tsx b/src/plugins/newGuildSettings/index.tsx index 7240aef23..dfcbe94be 100644 --- a/src/plugins/newGuildSettings/index.tsx +++ b/src/plugins/newGuildSettings/index.tsx @@ -152,7 +152,7 @@ function applyDefaultSettings(guildId: string | null) { export default definePlugin({ name: "NewGuildSettings", description: t("vencord.newGuildSettings.description"), - tags: ["MuteNewGuild", "mute", "server"], + tags: ["Servers", "Customisation"], authors: [Devs.Glitch, Devs.Nuckyz, Devs.carince, Devs.Mopi, Devs.GabiRP], isModified: true, contextMenus: { diff --git a/src/plugins/noBlockedMessages/index.ts b/src/plugins/noBlockedMessages/index.ts index 3c50240fa..4b6b312e4 100644 --- a/src/plugins/noBlockedMessages/index.ts +++ b/src/plugins/noBlockedMessages/index.ts @@ -90,6 +90,7 @@ export default definePlugin({ name: "NoBlockedMessages", description: "Hide all blocked/ignored messages from chat completely.", authors: [Devs.rushii, Devs.Samu, Devs.jamesbt365, Devs.Elvyra, EquicordDevs.Etorix], + tags: ["Accessibility", "Chat"], isModified: true, settings, patches: [ diff --git a/src/plugins/noDeepLinks.web/index.ts b/src/plugins/noDeepLinks.web/index.ts index 82e739567..02d22290b 100644 --- a/src/plugins/noDeepLinks.web/index.ts +++ b/src/plugins/noDeepLinks.web/index.ts @@ -11,6 +11,7 @@ import definePlugin from "@utils/types"; export default definePlugin({ name: "DisableDeepLinks", description: t("vencord.noDeepLinks.description"), + tags: ["Utility"], authors: [Devs.Ven], required: true, diff --git a/src/plugins/noDefaultHangStatus/README.md b/src/plugins/noDefaultHangStatus/README.md deleted file mode 100644 index e6bc9f83a..000000000 --- a/src/plugins/noDefaultHangStatus/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# NoDefaultHangStatus - -Disable the default hang status when joining voice channels - -![Visualization](https://github.com/Vendicated/Vencord/assets/24937357/329a9742-236f-48f7-94ff-c3510eca505a) diff --git a/src/plugins/noDefaultHangStatus/index.ts b/src/plugins/noDefaultHangStatus/index.ts deleted file mode 100644 index 1301f0d25..000000000 --- a/src/plugins/noDefaultHangStatus/index.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Vencord, a Discord client mod - * Copyright (c) 2024 Vendicated and contributors - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -import { migrateSettingToPlugin } from "@api/Settings"; -import { Devs } from "@utils/constants"; -import definePlugin from "@utils/types"; - -migrateSettingToPlugin("NoDefaultHangStatus", "EquicordHelper", "noDefaultHangStatus"); -export default definePlugin({ - name: "NoDefaultHangStatus", - description: "Disable the default hang status when joining voice channels", - authors: [Devs.D3SOX], - - patches: [ - { - find: ".CHILLING)", - replacement: { - match: /{enableHangStatus:(\i),/, - replace: "{_enableHangStatus:$1=false," - } - } - ] -}); diff --git a/src/plugins/noDevtoolsWarning/index.ts b/src/plugins/noDevtoolsWarning/index.ts index b9db28950..0f24c8ce7 100644 --- a/src/plugins/noDevtoolsWarning/index.ts +++ b/src/plugins/noDevtoolsWarning/index.ts @@ -24,6 +24,7 @@ export default definePlugin({ name: "NoDevtoolsWarning", description: t("vencord.noDevtoolsWarning.description"), authors: [Devs.Ven], + tags: ["Developers", "Console"], patches: [{ find: "setDevtoolsCallbacks", replacement: { diff --git a/src/plugins/noF1/index.ts b/src/plugins/noF1/index.ts index 8ae898977..f39400d34 100644 --- a/src/plugins/noF1/index.ts +++ b/src/plugins/noF1/index.ts @@ -23,6 +23,7 @@ import definePlugin from "@utils/types"; export default definePlugin({ name: "NoF1", description: t("vencord.noF1.description"), + tags: ["Utility"], authors: [Devs.Cyn], patches: [ { diff --git a/src/plugins/noMaskedUrlPaste/index.ts b/src/plugins/noMaskedUrlPaste/index.ts index d6e3c3c2e..4fc0bb707 100644 --- a/src/plugins/noMaskedUrlPaste/index.ts +++ b/src/plugins/noMaskedUrlPaste/index.ts @@ -12,6 +12,7 @@ export default definePlugin({ name: "NoMaskedUrlPaste", authors: [Devs.CatNoir], description: t("vencord.noMaskedUrlPaste.description"), + tags: ["Chat", "Utility"], patches: [ { find: ".selection,preventEmojiSurrogates:", diff --git a/src/plugins/noMosaic/index.ts b/src/plugins/noMosaic/index.ts index f2bddb8fc..f5b26ff43 100644 --- a/src/plugins/noMosaic/index.ts +++ b/src/plugins/noMosaic/index.ts @@ -22,7 +22,7 @@ export default definePlugin({ name: "NoMosaic", authors: [Devs.AutumnVN], description: t("vencord.noMosaic.description"), - tags: ["image", "mosaic", "media"], + tags: ["Media", "Appearance", "Chat"], settings, @@ -30,8 +30,8 @@ export default definePlugin({ { find: '"PLAINTEXT_PREVIEW":"OTHER"', replacement: { - match: /=>"IMAGE"===\i\|\|"VIDEO"===\i(?:\|\|("VISUAL_PLACEHOLDER"===\i))?;/, - replace: (_, visualPlaceholderPred) => visualPlaceholderPred != null ? `=>${visualPlaceholderPred};` : "=>false;" + match: /return"IMAGE"===\i\|\|"VIDEO"===\i(?:\|\|("VISUAL_PLACEHOLDER"===\i)\|\|\i&&"CLIP"===\i)?/, + replace: (_, visualPlaceholderPred) => visualPlaceholderPred != null ? `return ${visualPlaceholderPred}` : "return false" } }, { diff --git a/src/plugins/noOnboardingDelay/index.ts b/src/plugins/noOnboardingDelay/index.ts index efaaec713..b1e1af97e 100644 --- a/src/plugins/noOnboardingDelay/index.ts +++ b/src/plugins/noOnboardingDelay/index.ts @@ -23,6 +23,7 @@ import definePlugin from "@utils/types"; export default definePlugin({ name: "NoOnboardingDelay", description: t("vencord.noOnboardingDelay.description"), + tags: ["Utility", "Servers"], authors: [Devs.nekohaxx], patches: [ { diff --git a/src/plugins/noPendingCount/index.ts b/src/plugins/noPendingCount/index.ts index b1a7ffad8..5bede8b49 100644 --- a/src/plugins/noPendingCount/index.ts +++ b/src/plugins/noPendingCount/index.ts @@ -47,6 +47,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "NoPendingCount", description: "Removes the ping count of incoming friend requests, message requests, and nitro offers.", + tags: ["Notifications", "Appearance"], authors: [Devs.amia], settings: settings, diff --git a/src/plugins/noProfileThemes/index.ts b/src/plugins/noProfileThemes/index.ts index ee2fd1b0e..1f8cb394d 100644 --- a/src/plugins/noProfileThemes/index.ts +++ b/src/plugins/noProfileThemes/index.ts @@ -24,6 +24,7 @@ import { UserStore } from "@webpack/common"; export default definePlugin({ name: "NoProfileThemes", description: t("vencord.noProfileThemes.description"), + tags: ["Appearance"], authors: [Devs.TheKodeToad], patches: [ { diff --git a/src/plugins/noReplyMention/index.tsx b/src/plugins/noReplyMention/index.tsx index 767d665d4..dbb5aa14c 100644 --- a/src/plugins/noReplyMention/index.tsx +++ b/src/plugins/noReplyMention/index.tsx @@ -61,6 +61,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "NoReplyMention", description: t("vencord.noReplyMention.description"), + tags: ["Chat", "Notifications"], authors: [Devs.DustyAngel47, Devs.rae, Devs.pylix, Devs.outfoxxed], settings, diff --git a/src/plugins/noServerEmojis/index.ts b/src/plugins/noServerEmojis/index.ts index 6550dabb8..fd764dbf3 100644 --- a/src/plugins/noServerEmojis/index.ts +++ b/src/plugins/noServerEmojis/index.ts @@ -26,6 +26,7 @@ export default definePlugin({ name: "NoServerEmojis", authors: [Devs.UlyssesZhan], description: "Do not show server emojis in the autocomplete menu.", + tags: ["Emotes", "Servers"], settings, patches: [ diff --git a/src/plugins/noSystemBadge.discordDesktop/index.ts b/src/plugins/noSystemBadge.discordDesktop/index.ts index 51332f45d..9ca63b731 100644 --- a/src/plugins/noSystemBadge.discordDesktop/index.ts +++ b/src/plugins/noSystemBadge.discordDesktop/index.ts @@ -23,6 +23,7 @@ import definePlugin from "@utils/types"; export default definePlugin({ name: "NoSystemBadge", description: t("vencord.noSystemBadge.description"), + tags: ["Notifications", "Appearance"], authors: [Devs.rushii], patches: [ { diff --git a/src/plugins/noTypingAnimation/index.ts b/src/plugins/noTypingAnimation/index.ts index 090311b98..a129f973a 100644 --- a/src/plugins/noTypingAnimation/index.ts +++ b/src/plugins/noTypingAnimation/index.ts @@ -12,6 +12,7 @@ export default definePlugin({ name: "NoTypingAnimation", authors: [Devs.AutumnVN], description: t("vencord.noTypingAnimation.description"), + tags: ["Appearance"], patches: [ { find: "dotCycle", diff --git a/src/plugins/noUnblockToJump/index.ts b/src/plugins/noUnblockToJump/index.ts index bc0fdc565..bd399a7a6 100644 --- a/src/plugins/noUnblockToJump/index.ts +++ b/src/plugins/noUnblockToJump/index.ts @@ -23,6 +23,7 @@ import definePlugin from "@utils/types"; export default definePlugin({ name: "NoUnblockToJump", description: t("vencord.noUnblockToJump.description"), + tags: ["Utility"], authors: [Devs.dzshn], patches: [ { diff --git a/src/plugins/notificationVolume/index.ts b/src/plugins/notificationVolume/index.ts index d320d76f1..5959c0dd1 100644 --- a/src/plugins/notificationVolume/index.ts +++ b/src/plugins/notificationVolume/index.ts @@ -21,6 +21,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "NotificationVolume", description: "Save your ears and set a separate volume for notifications and in-app sounds", + tags: ["Notifications", "Voice"], authors: [Devs.philipbry], settings, patches: [ diff --git a/src/plugins/onePingPerDM/index.ts b/src/plugins/onePingPerDM/index.ts index 05dba7e80..87727fa32 100644 --- a/src/plugins/onePingPerDM/index.ts +++ b/src/plugins/onePingPerDM/index.ts @@ -47,7 +47,8 @@ const settings = definePluginSettings({ export default definePlugin({ name: "OnePingPerDM", - description: "If unread messages are sent by a user in DMs multiple times, you'll only receive one audio ping.", + description: "If unread messages are sent by a user in DMs multiple times, you'll only receive one audio ping. Read the messages to reset the limit", + tags: ["Notifications", "Customisation"], authors: [Devs.ProffDea], isModified: true, settings, diff --git a/src/plugins/openInApp/index.ts b/src/plugins/openInApp/index.ts index 05e5b1c29..60012f735 100644 --- a/src/plugins/openInApp/index.ts +++ b/src/plugins/openInApp/index.ts @@ -84,6 +84,7 @@ const Native = VencordNative.pluginHelpers.OpenInApp as PluginNative | undefined; export default definePlugin({ name: "ReactErrorDecoder", - description: 'Replaces "Minifed React Error" with the actual error.', + description: 'Replaces "Minified React Error" with the actual error.', + tags: ["Developers"], authors: [Devs.Cyn, Devs.maisymoe], patches: [ { diff --git a/src/plugins/readAllNotificationsButton/index.tsx b/src/plugins/readAllNotificationsButton/index.tsx index d7fa59acb..c91e969d9 100644 --- a/src/plugins/readAllNotificationsButton/index.tsx +++ b/src/plugins/readAllNotificationsButton/index.tsx @@ -67,6 +67,7 @@ const ReadAllButton = () => ( export default definePlugin({ name: "ReadAllNotificationsButton", description: t("vencord.readAllNotificationsButton.description"), + tags: ["Notifications", "Shortcuts"], authors: [Devs.kemo, EquicordDevs.KrystalSkull], dependencies: ["ServerListAPI"], diff --git a/src/plugins/relationshipNotifier/index.ts b/src/plugins/relationshipNotifier/index.ts index 5e9d6aadc..3400f6b60 100644 --- a/src/plugins/relationshipNotifier/index.ts +++ b/src/plugins/relationshipNotifier/index.ts @@ -27,6 +27,7 @@ import { syncAndRunChecks, syncFriends, syncGroups, syncGuilds } from "./utils"; export default definePlugin({ name: "RelationshipNotifier", description: t("vencord.relationshipNotifier.description"), + tags: ["Friends", "Notifications"], authors: [Devs.nick], settings, diff --git a/src/plugins/replaceGoogleSearch/index.tsx b/src/plugins/replaceGoogleSearch/index.tsx index c9593cc2c..5b3ba5146 100644 --- a/src/plugins/replaceGoogleSearch/index.tsx +++ b/src/plugins/replaceGoogleSearch/index.tsx @@ -132,6 +132,7 @@ migratePluginSettings("ReplaceGoogleSearch", "Search"); export default definePlugin({ name: "ReplaceGoogleSearch", description: t("vencord.replaceGoogleSearch.description"), + tags: ["Utility", "Customisation"], authors: [Devs.Moxxie, Devs.Ethan], settings, diff --git a/src/plugins/replyTimestamp/index.tsx b/src/plugins/replyTimestamp/index.tsx index ec1b5a4dc..41dcff1c4 100644 --- a/src/plugins/replyTimestamp/index.tsx +++ b/src/plugins/replyTimestamp/index.tsx @@ -59,6 +59,7 @@ function ReplyTimestamp({ export default definePlugin({ name: "ReplyTimestamp", description: t("vencord.replyTimestamp.description"), + tags: ["Chat", "Appearance"], authors: [Devs.Kyuuhachi], patches: [ diff --git a/src/plugins/revealAllSpoilers/index.ts b/src/plugins/revealAllSpoilers/index.ts index 1192c5dc3..df8a5817d 100644 --- a/src/plugins/revealAllSpoilers/index.ts +++ b/src/plugins/revealAllSpoilers/index.ts @@ -28,7 +28,7 @@ export default definePlugin({ name: "RevealAllSpoilers", description: t("vencord.revealAllSpoilers.description"), authors: [Devs.whqwert], - + tags: ["Accessibility", "Chat", "Shortcuts", "Utility"], patches: [ { find: ".removeObscurity,", diff --git a/src/plugins/reverseImageSearch/index.tsx b/src/plugins/reverseImageSearch/index.tsx index 1551e9364..26e98e662 100644 --- a/src/plugins/reverseImageSearch/index.tsx +++ b/src/plugins/reverseImageSearch/index.tsx @@ -103,8 +103,9 @@ const imageContextMenuPatch: NavContextMenuPatchCallback = (children, props) => export default definePlugin({ name: "ReverseImageSearch", description: t("vencord.reverseImageSearch.description"), + tags: ["Media", "Utility"], authors: [Devs.Ven, Devs.Nuckyz], - tags: ["ImageUtilities"], + searchTerms: ["ImageUtilities"], patches: [ { diff --git a/src/plugins/reviewDB/components/ReviewsView.tsx b/src/plugins/reviewDB/components/ReviewsView.tsx index e858d13b8..2564eff20 100644 --- a/src/plugins/reviewDB/components/ReviewsView.tsx +++ b/src/plugins/reviewDB/components/ReviewsView.tsx @@ -66,10 +66,11 @@ export default function ReviewsView({ fallbackValue: null, deps: [refetchSignal, signal, page], onSuccess: data => { - if (settings.store.hideBlockedUsers) - data!.reviews = data!.reviews?.filter(r => !RelationshipStore.isBlocked(r.sender.discordID)); + if (settings.store.hideBlockedUsers) data!.reviews = data!.reviews?.filter(r => !RelationshipStore.isBlocked(r.sender.discordID)); + const systemReviews = data!.reviews.filter(r => r.type === ReviewType.System); + const normalReviews = data!.reviews.filter(r => r.type !== ReviewType.System); - data!.reviews.reverse(); + data!.reviews = [...systemReviews, ...normalReviews.reverse()]; scrollToTop?.(); onFetchReviews(data!); } diff --git a/src/plugins/reviewDB/index.tsx b/src/plugins/reviewDB/index.tsx index eaf871adc..cbc5faacf 100644 --- a/src/plugins/reviewDB/index.tsx +++ b/src/plugins/reviewDB/index.tsx @@ -58,6 +58,8 @@ const userContextPatch: NavContextMenuPatchCallback = (children, { user }: { use export default definePlugin({ name: "ReviewDB", description: t("vencord.reviewDB.description"), + dependencies: ["ProfileCollectionsAPI"], + tags: ["Friends", "Servers"], authors: [Devs.mantikafasi, Devs.Ven], isModified: true, diff --git a/src/plugins/roleColorEverywhere/index.tsx b/src/plugins/roleColorEverywhere/index.tsx index 5972bb240..6ebbdf1c2 100644 --- a/src/plugins/roleColorEverywhere/index.tsx +++ b/src/plugins/roleColorEverywhere/index.tsx @@ -76,6 +76,7 @@ export default definePlugin({ name: "RoleColorEverywhere", authors: [Devs.KingFish, Devs.lewisakura, Devs.AutumnVN, Devs.Kyuuhachi, Devs.jamesbt365], description: "Adds the top role color anywhere possible", + tags: ["Roles", "Appearance"], settings, patches: [ diff --git a/src/plugins/secretRingTone/index.ts b/src/plugins/secretRingTone/index.ts index 836573640..e9279043b 100644 --- a/src/plugins/secretRingTone/index.ts +++ b/src/plugins/secretRingTone/index.ts @@ -6,8 +6,8 @@ import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; -import definePlugin, { OptionType } from "@utils/types"; import { t } from "@utils/translation"; +import definePlugin, { OptionType } from "@utils/types"; const settings = definePluginSettings({ onlySnow: { @@ -21,6 +21,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "SecretRingToneEnabler", description: t("vencord.secretRingTone.description"), + tags: ["Notifications", "Fun"], authors: [Devs.AndrewDLO, Devs.FieryFlames, Devs.RamziAH], settings, patches: [ diff --git a/src/plugins/seeSummaries/index.tsx b/src/plugins/seeSummaries/index.tsx index e40bc7fa0..20e25999a 100644 --- a/src/plugins/seeSummaries/index.tsx +++ b/src/plugins/seeSummaries/index.tsx @@ -53,6 +53,7 @@ interface ChannelSummaries { export default definePlugin({ name: "Summaries", description: t("vencord.seeSummaries.description"), + tags: ["Chat", "Fun"], authors: [Devs.mantikafasi], settings, patches: [ diff --git a/src/plugins/sendTimestamps/index.tsx b/src/plugins/sendTimestamps/index.tsx index 9fc061764..b831acbcf 100644 --- a/src/plugins/sendTimestamps/index.tsx +++ b/src/plugins/sendTimestamps/index.tsx @@ -171,6 +171,8 @@ const SendTimestampButton: ChatBarButtonFactory = ({ isAnyChat }) => { export default definePlugin({ name: "SendTimestamps", description: t("vencord.sendTimestamps.description"), + dependencies: ["ChatInputButtonAPI", "MessagePopoverAPI"], + tags: ["Chat", "Commands"], authors: [Devs.Ven, Devs.Tyler, Devs.Grzesiek11], settings, diff --git a/src/plugins/serverInfo/index.tsx b/src/plugins/serverInfo/index.tsx index c2a6c630b..d7f72a2e0 100644 --- a/src/plugins/serverInfo/index.tsx +++ b/src/plugins/serverInfo/index.tsx @@ -51,9 +51,10 @@ export const settings = definePluginSettings({ export default definePlugin({ name: "ServerInfo", description: t("vencord.serverInfo.description"), + tags: ["Servers", "Utility"], authors: [Devs.Ven, Devs.Nuckyz, EquicordDevs.Z1xus], dependencies: ["DynamicImageModalAPI"], - tags: ["guild", "info", "ServerProfile"], + searchTerms: ["guild", "info", "ServerProfile"], isModified: true, contextMenus: { "guild-context": Patch, diff --git a/src/plugins/serverListIndicators/index.tsx b/src/plugins/serverListIndicators/index.tsx index be1893d65..e80742e55 100644 --- a/src/plugins/serverListIndicators/index.tsx +++ b/src/plugins/serverListIndicators/index.tsx @@ -142,6 +142,7 @@ export const settings = definePluginSettings({ export default definePlugin({ name: "ServerListIndicators", description: t("vencord.serverListIndicators.description"), + tags: ["Servers", "Appearance"], authors: [Devs.dzshn, EquicordDevs.Panniku], dependencies: ["ServerListAPI"], settings, diff --git a/src/plugins/shikiCodeblocks.desktop/index.ts b/src/plugins/shikiCodeblocks.desktop/index.ts index 056b59001..dc1059833 100644 --- a/src/plugins/shikiCodeblocks.desktop/index.ts +++ b/src/plugins/shikiCodeblocks.desktop/index.ts @@ -20,8 +20,8 @@ import "./shiki.css"; import { enableStyle } from "@api/Styles"; import { Devs } from "@utils/constants"; -import definePlugin, { ReporterTestable } from "@utils/types"; import { t } from "@utils/translation"; +import definePlugin, { ReporterTestable } from "@utils/types"; import previewExampleText from "file://previewExample.tsx"; import { shiki } from "./api/shiki"; @@ -34,6 +34,7 @@ import { clearStyles } from "./utils/createStyle"; export default definePlugin({ name: "ShikiCodeblocks", description: t("vencord.shikiCodeblocks.description"), + tags: ["Appearance", "Chat", "Customisation"], authors: [Devs.Vap], reporterTestable: ReporterTestable.Patches, settings, diff --git a/src/plugins/showAllMessageButtons/index.ts b/src/plugins/showAllMessageButtons/index.ts index 2d1f4bcb1..92c1479f8 100644 --- a/src/plugins/showAllMessageButtons/index.ts +++ b/src/plugins/showAllMessageButtons/index.ts @@ -5,7 +5,7 @@ */ import { definePluginSettings } from "@api/Settings"; -import { Devs, EquicordDevs } from "@utils/constants"; +import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; import { MessageActions, PinActions } from "@webpack/common"; @@ -25,7 +25,8 @@ const settings = definePluginSettings({ export default definePlugin({ name: "ShowAllMessageButtons", description: "Always show all message buttons no matter if you are holding the shift key or not.", - authors: [Devs.Nuckyz, EquicordDevs.mochienya], + tags: ["Chat", "Utility"], + authors: [Devs.Nuckyz], settings, patches: [ diff --git a/src/plugins/showConnections/index.tsx b/src/plugins/showConnections/index.tsx index 68d899a33..848a9e451 100644 --- a/src/plugins/showConnections/index.tsx +++ b/src/plugins/showConnections/index.tsx @@ -162,6 +162,7 @@ function CompactConnectionComponent({ connection, theme }: { connection: Connect export default definePlugin({ name: "ShowConnections", description: t("vencord.showConnections.description"), + tags: ["Friends", "Appearance"], authors: [Devs.TheKodeToad], settings, diff --git a/src/plugins/showHiddenChannels/index.tsx b/src/plugins/showHiddenChannels/index.tsx index 0ed7926eb..9b3b19163 100644 --- a/src/plugins/showHiddenChannels/index.tsx +++ b/src/plugins/showHiddenChannels/index.tsx @@ -83,6 +83,7 @@ function isUncategorized(objChannel: { channel: Channel; comparator: number; }) export default definePlugin({ name: "ShowHiddenChannels", description: t("vencord.showHiddenChannels.description"), + tags: ["Servers", "Utility"], authors: [Devs.BigDuck, Devs.AverageReactEnjoyer, Devs.D3SOX, Devs.Ven, Devs.Nuckyz, Devs.Nickyux, Devs.dzshn, EquicordDevs.Oggetto], isModified: true, settings, diff --git a/src/plugins/showHiddenThings/index.ts b/src/plugins/showHiddenThings/index.ts index 39b12f0c8..020f7467e 100644 --- a/src/plugins/showHiddenThings/index.ts +++ b/src/plugins/showHiddenThings/index.ts @@ -19,8 +19,8 @@ import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; import { Logger } from "@utils/Logger"; -import definePlugin, { OptionType, PluginSettingDef } from "@utils/types"; import { t } from "@utils/translation"; +import definePlugin, { OptionType, PluginSettingDef } from "@utils/types"; import { GuildMember, Role } from "@vencord/discord-types"; const opt = (description: string) => ({ @@ -38,8 +38,8 @@ const settings = definePluginSettings({ export default definePlugin({ name: "ShowHiddenThings", - tags: ["ShowTimeouts", "ShowInvitesPaused", "ShowModView", "DisableDiscoveryFilters"], description: t("vencord.showHiddenThings.description"), + tags: ["Servers", "Utility"], authors: [Devs.Dolfies], settings, diff --git a/src/plugins/showMeYourName/index.tsx b/src/plugins/showMeYourName/index.tsx index 75b632ff2..8b43573b7 100644 --- a/src/plugins/showMeYourName/index.tsx +++ b/src/plugins/showMeYourName/index.tsx @@ -1070,7 +1070,8 @@ export default definePlugin({ name: "ShowMeYourName", description: "Display any permutation of custom nicknames, friend nicknames, server nicknames, display names, and usernames in chat.", authors: [EquicordDevs.Etorix, Devs.Rini, Devs.TheKodeToad, Devs.sadan, Devs.prism], - tags: ["SMYN", "Nicknames", "Custom Nicknames",], + tags: ["Appearance", "Customisation"], + searchTerms: ["SMYN", "Nicknames", "Custom Nicknames"], isModified: true, settings, @@ -1139,7 +1140,7 @@ export default definePlugin({ // Attach the group ID to their messages to allow animating gradients within a group. find: "CUSTOM_GIFT?\"\":", replacement: { - match: /(isHovered:(\i).{0,1300}?\(\i,\i,\i\);)(let \i=\i.id===\i)/, + match: /(isHovered:(\i).{0,1300})(let \i=\i.id===\i,\i=)/, replace: "$1arguments[0].message.showMeYourNameGroupId=!!arguments[0].groupId?`g-${arguments[0].groupId}`:null;$self.handleHoveringMessage(arguments[0].message,$2);$3" }, }, diff --git a/src/plugins/showTimeoutDuration/index.tsx b/src/plugins/showTimeoutDuration/index.tsx index 659fc2621..5e28887a1 100644 --- a/src/plugins/showTimeoutDuration/index.tsx +++ b/src/plugins/showTimeoutDuration/index.tsx @@ -70,6 +70,7 @@ function renderTimeout(message: Message, inline: boolean) { export default definePlugin({ name: "ShowTimeoutDuration", description: t("vencord.showTimeoutDuration.description"), + tags: ["Servers", "Utility"], authors: [Devs.Ven, Devs.Sqaaakoi], settings, diff --git a/src/plugins/silentMessageToggle/index.tsx b/src/plugins/silentMessageToggle/index.tsx index e97b19b3d..23444c7ad 100644 --- a/src/plugins/silentMessageToggle/index.tsx +++ b/src/plugins/silentMessageToggle/index.tsx @@ -111,6 +111,8 @@ export default definePlugin({ name: "SilentMessageToggle", authors: [Devs.Nuckyz, Devs.CatNoir, EquicordDevs.Z1xus], description: t("vencord.silentMessageToggle.description"), + dependencies: ["ChatInputButtonAPI"], + tags: ["Chat", "Utility"], settings, chatBarButton: { diff --git a/src/plugins/silentTyping/index.tsx b/src/plugins/silentTyping/index.tsx index f9c553abe..3aac5e209 100644 --- a/src/plugins/silentTyping/index.tsx +++ b/src/plugins/silentTyping/index.tsx @@ -298,6 +298,8 @@ export default definePlugin({ name: "SilentTyping", authors: [Devs.Ven, Devs.Rini, Devs.ImBanana, EquicordDevs.Etorix], description: t("vencord.silentTyping.description"), + dependencies: ["CommandsAPI", "ChatInputButtonAPI"], + tags: ["Chat", "Privacy"], isModified: true, settings, diff --git a/src/plugins/sortFriendRequests/index.tsx b/src/plugins/sortFriendRequests/index.tsx index 1a9c49833..c9faa0851 100644 --- a/src/plugins/sortFriendRequests/index.tsx +++ b/src/plugins/sortFriendRequests/index.tsx @@ -57,6 +57,7 @@ export default definePlugin({ name: "SortFriends", authors: [Devs.Megu, EquicordDevs.CallMeGii], description: t("vencord.sortFriendRequests.description"), + tags: ["Friends", "Organisation"], isModified: true, settings, diff --git a/src/plugins/spotifyCrack/index.ts b/src/plugins/spotifyCrack/index.ts index b26c6f023..0545bae55 100644 --- a/src/plugins/spotifyCrack/index.ts +++ b/src/plugins/spotifyCrack/index.ts @@ -18,8 +18,8 @@ import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; -import definePlugin, { OptionType } from "@utils/types"; import { t } from "@utils/translation"; +import definePlugin, { OptionType } from "@utils/types"; const settings = definePluginSettings({ noSpotifyAutoPause: { @@ -39,6 +39,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "SpotifyCrack", description: t("vencord.spotifyCrack.description"), + tags: ["Media", "Utility"], authors: [Devs.Cyn, Devs.Nuckyz], settings, diff --git a/src/plugins/spotifyShareCommands/index.ts b/src/plugins/spotifyShareCommands/index.ts index c8c48e8cb..586145037 100644 --- a/src/plugins/spotifyShareCommands/index.ts +++ b/src/plugins/spotifyShareCommands/index.ts @@ -19,8 +19,8 @@ import { ApplicationCommandInputType, findOption, OptionalMessageOption, sendBotMessage } from "@api/Commands"; import { Devs } from "@utils/constants"; import { sendMessage } from "@utils/discord"; -import definePlugin from "@utils/types"; import { t } from "@utils/translation"; +import definePlugin from "@utils/types"; import { Command } from "@vencord/discord-types"; import { findByPropsLazy } from "@webpack"; import { FluxDispatcher, MessageActions, PendingReplyStore } from "@webpack/common"; @@ -99,6 +99,8 @@ function makeCommand(name: string, formatUrl: (track: Track) => string): Command export default definePlugin({ name: "SpotifyShareCommands", description: t("vencord.spotifyShareCommands.description"), + dependencies: ["CommandsAPI"], + tags: ["Media", "Commands"], authors: [Devs.katlyn], commands: [ makeCommand("track", track => `https://open.spotify.com/track/${track.id}`), diff --git a/src/plugins/startupTimings/index.tsx b/src/plugins/startupTimings/index.tsx index 6dc7191de..ebae28e0b 100644 --- a/src/plugins/startupTimings/index.tsx +++ b/src/plugins/startupTimings/index.tsx @@ -20,14 +20,15 @@ import { ClockIcon } from "@components/Icons"; import SettingsPlugin from "@plugins/_core/settings"; import { Devs } from "@utils/constants"; import { removeFromArray } from "@utils/misc"; -import definePlugin from "@utils/types"; import { t } from "@utils/translation"; +import definePlugin from "@utils/types"; import StartupTimingPage from "./StartupTimingPage"; export default definePlugin({ name: "StartupTimings", description: t("vencord.startupTimings.description"), + tags: ["Developers"], authors: [Devs.Megu], start() { SettingsPlugin.customEntries.push({ diff --git a/src/plugins/stickerPaste/index.ts b/src/plugins/stickerPaste/index.ts index 77873ded5..1b0455c76 100644 --- a/src/plugins/stickerPaste/index.ts +++ b/src/plugins/stickerPaste/index.ts @@ -5,12 +5,13 @@ */ import { Devs } from "@utils/constants"; -import definePlugin from "@utils/types"; import { t } from "@utils/translation"; +import definePlugin from "@utils/types"; export default definePlugin({ name: "StickerPaste", description: t("vencord.stickerPaste.description"), + tags: ["Emotes", "Chat"], authors: [Devs.ImBanana], patches: [ diff --git a/src/plugins/streamerModeOnStream/index.ts b/src/plugins/streamerModeOnStream/index.ts index 9dc6f9448..45e5046e5 100644 --- a/src/plugins/streamerModeOnStream/index.ts +++ b/src/plugins/streamerModeOnStream/index.ts @@ -17,8 +17,8 @@ */ import { Devs } from "@utils/constants"; -import definePlugin from "@utils/types"; import { t } from "@utils/translation"; +import definePlugin from "@utils/types"; import { FluxDispatcher, UserStore } from "@webpack/common"; interface StreamEvent { @@ -38,6 +38,7 @@ function toggleStreamerMode({ streamKey }: StreamEvent, value: boolean) { export default definePlugin({ name: "StreamerModeOn", description: t("vencord.streamerModeOnStream.description"), + tags: ["Privacy", "Utility"], authors: [Devs.IcedMarina], flux: { STREAM_CREATE: d => toggleStreamerMode(d, true), diff --git a/src/plugins/superReactionTweaks/index.ts b/src/plugins/superReactionTweaks/index.ts index 19ae1dca0..de7876c55 100644 --- a/src/plugins/superReactionTweaks/index.ts +++ b/src/plugins/superReactionTweaks/index.ts @@ -6,8 +6,8 @@ import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; -import definePlugin, { OptionType } from "@utils/types"; import { t } from "@utils/translation"; +import definePlugin, { OptionType } from "@utils/types"; import { OverridePremiumTypeStore } from "@webpack/common"; export const settings = definePluginSettings({ @@ -38,6 +38,7 @@ export const settings = definePluginSettings({ export default definePlugin({ name: "SuperReactionTweaks", description: t("vencord.superReactionTweaks.description"), + tags: ["Reactions", "Emotes"], authors: [Devs.FieryFlames, Devs.ant0n], patches: [ { diff --git a/src/plugins/textReplace/index.tsx b/src/plugins/textReplace/index.tsx index c29b314b9..2bd651278 100644 --- a/src/plugins/textReplace/index.tsx +++ b/src/plugins/textReplace/index.tsx @@ -305,9 +305,10 @@ const TEXT_REPLACE_RULES_EXEMPT_CHANNEL_IDS = [ export default definePlugin({ name: "TextReplace", description: t("vencord.textReplace.description"), + dependencies: ["MessagePopoverAPI"], + tags: ["Chat", "Customisation", "Utility"], authors: [Devs.AutumnVN, Devs.TheKodeToad, EquicordDevs.Etorix], isModified: true, - settings, modifyIncomingMessage, diff --git a/src/plugins/themeAttributes/index.ts b/src/plugins/themeAttributes/index.ts index 985de1123..2045e98ca 100644 --- a/src/plugins/themeAttributes/index.ts +++ b/src/plugins/themeAttributes/index.ts @@ -6,14 +6,15 @@ import { Devs } from "@utils/constants"; import { Logger } from "@utils/Logger"; -import definePlugin from "@utils/types"; import { t } from "@utils/translation"; +import definePlugin from "@utils/types"; import { Message } from "@vencord/discord-types"; import { UserStore } from "@webpack/common"; export default definePlugin({ name: "ThemeAttributes", description: t("vencord.themeAttributes.description"), + tags: ["Appearance", "Customisation"], authors: [Devs.Ven, Devs.Board], patches: [ diff --git a/src/plugins/translate/index.tsx b/src/plugins/translate/index.tsx index 84b2929a2..47f077f92 100644 --- a/src/plugins/translate/index.tsx +++ b/src/plugins/translate/index.tsx @@ -64,6 +64,8 @@ let tooltipTimeout: any; export default definePlugin({ name: "Translate", description: t("vencord.translate.description"), + dependencies: ["ChatInputButtonAPI", "MessageAccessoriesAPI", "MessagePopoverAPI"], + tags: ["Chat", "Utility"], authors: [Devs.Ven, Devs.AshtonMemer], settings, contextMenus: { diff --git a/src/plugins/typingIndicator/index.tsx b/src/plugins/typingIndicator/index.tsx index 9fcd4380c..b0e616688 100644 --- a/src/plugins/typingIndicator/index.tsx +++ b/src/plugins/typingIndicator/index.tsx @@ -167,6 +167,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "TypingIndicator", description: t("vencord.typingIndicator.description"), + tags: ["Notifications", "Appearance", "Servers"], authors: [Devs.Nuckyz, Devs.fawn, Devs.Sqaaakoi], isModified: true, settings, diff --git a/src/plugins/typingTweaks/index.tsx b/src/plugins/typingTweaks/index.tsx index 5125661f9..bbcd06be4 100644 --- a/src/plugins/typingTweaks/index.tsx +++ b/src/plugins/typingTweaks/index.tsx @@ -115,6 +115,7 @@ migratePluginToSettings(true, "TypingTweaks", "AmITyping", "amITyping"); export default definePlugin({ name: "TypingTweaks", description: t("vencord.typingTweaks.description"), + tags: ["Appearance", "Customisation"], authors: [Devs.zt, Devs.sadan, EquicordDevs.MrDiamond], settings, isModified: true, diff --git a/src/plugins/unindent/index.ts b/src/plugins/unindent/index.ts index 8f597fd74..3e3bb9aa3 100644 --- a/src/plugins/unindent/index.ts +++ b/src/plugins/unindent/index.ts @@ -18,12 +18,14 @@ import { MessageObject } from "@api/MessageEvents"; import { Devs } from "@utils/constants"; -import definePlugin from "@utils/types"; import { t } from "@utils/translation"; +import definePlugin from "@utils/types"; export default definePlugin({ name: "Unindent", description: t("vencord.unindent.description"), + dependencies: ["MessageEventsAPI"], + tags: ["Chat", "Utility"], authors: [Devs.Ven], patches: [ diff --git a/src/plugins/unlockedAvatarZoom/index.ts b/src/plugins/unlockedAvatarZoom/index.ts index 97b1be6b5..561327ba3 100644 --- a/src/plugins/unlockedAvatarZoom/index.ts +++ b/src/plugins/unlockedAvatarZoom/index.ts @@ -6,8 +6,8 @@ import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; -import definePlugin, { makeRange, OptionType } from "@utils/types"; import { t } from "@utils/translation"; +import definePlugin, { makeRange, OptionType } from "@utils/types"; const settings = definePluginSettings({ zoomMultiplier: { @@ -21,6 +21,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "UnlockedAvatarZoom", description: t("vencord.unlockedAvatarZoom.description"), + tags: ["Media", "Utility"], authors: [Devs.nakoyasha], settings, patches: [ diff --git a/src/plugins/unsuppressEmbeds/index.tsx b/src/plugins/unsuppressEmbeds/index.tsx index 1fa5752fa..02abfc195 100644 --- a/src/plugins/unsuppressEmbeds/index.tsx +++ b/src/plugins/unsuppressEmbeds/index.tsx @@ -63,6 +63,7 @@ export default definePlugin({ name: "UnsuppressEmbeds", authors: [Devs.rad, Devs.HypedDomi], description: t("vencord.unsuppressEmbeds.description"), + tags: ["Chat", "Utility"], contextMenus: { "message": messageContextMenuPatch } diff --git a/src/plugins/userMessagesPronouns/index.ts b/src/plugins/userMessagesPronouns/index.ts index 80d6c5a77..d56b1f9b8 100644 --- a/src/plugins/userMessagesPronouns/index.ts +++ b/src/plugins/userMessagesPronouns/index.ts @@ -18,8 +18,8 @@ import { migratePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; -import definePlugin from "@utils/types"; import { t } from "@utils/translation"; +import definePlugin from "@utils/types"; import { CompactPronounsChatComponentWrapper, PronounsChatComponentWrapper } from "./PronounsChatComponent"; import { settings } from "./settings"; @@ -29,6 +29,7 @@ export default definePlugin({ name: "UserMessagesPronouns", authors: [Devs.Tyman, Devs.TheKodeToad, Devs.Ven, Devs.Elvyra], description: t("vencord.userMessagesPronouns.description"), + tags: ["Chat", "Appearance"], settings, patches: [ diff --git a/src/plugins/userVoiceShow/index.tsx b/src/plugins/userVoiceShow/index.tsx index 29ba94232..ef77c4a37 100644 --- a/src/plugins/userVoiceShow/index.tsx +++ b/src/plugins/userVoiceShow/index.tsx @@ -49,6 +49,8 @@ const settings = definePluginSettings({ export default definePlugin({ name: "UserVoiceShow", description: t("vencord.userVoiceShow.description"), + dependencies: ["MemberListDecoratorsAPI", "MessageDecorationsAPI", "NicknameIconsAPI"], + tags: ["Voice", "Appearance", "Friends"], authors: [Devs.Nuckyz, Devs.LordElias, EquicordDevs.omaw], settings, renderNicknameIcon({ userId }) { diff --git a/src/plugins/usrbg/index.tsx b/src/plugins/usrbg/index.tsx index 01020d665..f2605e102 100644 --- a/src/plugins/usrbg/index.tsx +++ b/src/plugins/usrbg/index.tsx @@ -55,6 +55,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "USRBG", description: t("vencord.usrbg.description"), + tags: ["Appearance", "Customisation"], authors: [Devs.AutumnVN, Devs.katlyn, Devs.pylix, Devs.TheKodeToad], settings, patches: [ diff --git a/src/plugins/validReply/index.ts b/src/plugins/validReply/index.ts index 075705c82..6c77eead1 100644 --- a/src/plugins/validReply/index.ts +++ b/src/plugins/validReply/index.ts @@ -5,8 +5,8 @@ */ import { Devs } from "@utils/constants"; -import definePlugin from "@utils/types"; import { t } from "@utils/translation"; +import definePlugin from "@utils/types"; import { Channel, Message, User } from "@vencord/discord-types"; import { findByCodeLazy } from "@webpack"; import { FluxDispatcher, RestAPI } from "@webpack/common"; @@ -34,6 +34,7 @@ const createMessageRecord = findByCodeLazy(".createFromServer(", ".isBlockedForM export default definePlugin({ name: "ValidReply", description: t("vencord.validReply.description"), + tags: ["Chat", "Utility"], authors: [Devs.newwares], patches: [ { diff --git a/src/plugins/validUser/index.tsx b/src/plugins/validUser/index.tsx index 1ac269f2f..1018a79ea 100644 --- a/src/plugins/validUser/index.tsx +++ b/src/plugins/validUser/index.tsx @@ -178,8 +178,9 @@ function MentionWrapper({ data, UserMention, RoleMention, parse, props }: Mentio export default definePlugin({ name: "ValidUser", description: t("vencord.validUser.description"), + tags: ["Chat", "Utility"], authors: [Devs.Ven, Devs.Dolfies], - tags: ["MentionCacheFix"], + searchTerms: ["MentionCacheFix"], patches: [ { diff --git a/src/plugins/vcDoubleClick/index.ts b/src/plugins/vcDoubleClick/index.ts index d0c7f3185..cdc2720ea 100644 --- a/src/plugins/vcDoubleClick/index.ts +++ b/src/plugins/vcDoubleClick/index.ts @@ -17,8 +17,8 @@ */ import { Devs } from "@utils/constants"; -import definePlugin from "@utils/types"; import { t } from "@utils/translation"; +import definePlugin from "@utils/types"; import { ChannelRouter, ChannelStore, SelectedChannelStore } from "@webpack/common"; const timers = {} as Record{$self.openAvatar($1)},", + match: /(?<=avatarProps:(\i),eventHandlers:(\i).{0,50}?)return null==/, + replace: 'Object.assign($2,{style:{cursor:"pointer"},onClick:()=>$self.openAvatar($1.src)});$&', } }, // Banners diff --git a/src/plugins/viewRaw/index.tsx b/src/plugins/viewRaw/index.tsx index 558f9aede..29fe4f0e1 100644 --- a/src/plugins/viewRaw/index.tsx +++ b/src/plugins/viewRaw/index.tsx @@ -177,6 +177,8 @@ const devContextCallback: NavContextMenuPatchCallback = (children, { id }: { id: export default definePlugin({ name: "ViewRaw", description: t("vencord.viewRaw.description"), + dependencies: ["MessagePopoverAPI"], + tags: ["Chat", "Developers"], authors: [Devs.KingFish, Devs.Ven, Devs.rad, Devs.ImLvna], settings, diff --git a/src/plugins/voiceDownload/index.tsx b/src/plugins/voiceDownload/index.tsx index fd14e56f2..513711d52 100644 --- a/src/plugins/voiceDownload/index.tsx +++ b/src/plugins/voiceDownload/index.tsx @@ -13,6 +13,7 @@ import definePlugin from "@utils/types"; export default definePlugin({ name: "VoiceDownload", description: t("vencord.voiceDownload.description"), + tags: ["Voice", "Media"], authors: [Devs.puv], patches: [ { diff --git a/src/plugins/voiceMessages/index.tsx b/src/plugins/voiceMessages/index.tsx index 2664d21f0..cbaed46b3 100644 --- a/src/plugins/voiceMessages/index.tsx +++ b/src/plugins/voiceMessages/index.tsx @@ -280,8 +280,8 @@ export default definePlugin({ name: "VoiceMessages", description: t("vencord.voiceMessages.description"), authors: [Devs.Ven, Devs.Vap, Devs.Nickyux, EquicordDevs.Z1xus, Devs.prism], + tags: ["Voice"], settings, - contextMenus: { "channel-attach": ctxMenuPatch } diff --git a/src/plugins/volumeBooster/index.ts b/src/plugins/volumeBooster/index.ts index dbfe27f82..7ecbdc053 100644 --- a/src/plugins/volumeBooster/index.ts +++ b/src/plugins/volumeBooster/index.ts @@ -18,8 +18,8 @@ import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; -import definePlugin, { makeRange, OptionType } from "@utils/types"; import { t } from "@utils/translation"; +import definePlugin, { makeRange, OptionType } from "@utils/types"; const settings = definePluginSettings({ multiplier: { @@ -52,6 +52,7 @@ export default definePlugin({ name: "VolumeBooster", authors: [Devs.Nuckyz, Devs.sadan], description: t("vencord.volumeBooster.description"), + tags: ["Voice", "Utility"], settings, patches: [ diff --git a/src/plugins/webContextMenus.web/index.ts b/src/plugins/webContextMenus.web/index.ts index 14fa7cf5a..3c2c75993 100644 --- a/src/plugins/webContextMenus.web/index.ts +++ b/src/plugins/webContextMenus.web/index.ts @@ -19,8 +19,8 @@ import { definePluginSettings } from "@api/Settings"; import { copyToClipboard } from "@utils/clipboard"; import { Devs } from "@utils/constants"; -import definePlugin, { OptionType } from "@utils/types"; import { t } from "@utils/translation"; +import definePlugin, { OptionType } from "@utils/types"; import { saveFile } from "@utils/web"; import { filters, mapMangledModuleLazy } from "@webpack"; import { ComponentDispatch } from "@webpack/common"; @@ -89,6 +89,7 @@ function fixImageUrl(urlString: string) { export default definePlugin({ name: "WebContextMenus", description: t("vencord.webContextMenus.description"), + tags: ["Utility"], authors: [Devs.Ven], enabledByDefault: true, required: requiredByPlatform, diff --git a/src/plugins/webKeybinds.web/index.ts b/src/plugins/webKeybinds.web/index.ts index 8833bfb34..4b1c21fb8 100644 --- a/src/plugins/webKeybinds.web/index.ts +++ b/src/plugins/webKeybinds.web/index.ts @@ -17,8 +17,8 @@ */ import { Devs, IS_MAC } from "@utils/constants"; -import definePlugin from "@utils/types"; import { t } from "@utils/translation"; +import definePlugin from "@utils/types"; import { findByPropsLazy } from "@webpack"; import { ComponentDispatch, FluxDispatcher, NavigationRouter, SelectedGuildStore, SettingsRouter } from "@webpack/common"; @@ -27,6 +27,7 @@ const KeyBinds = findByPropsLazy("JUMP_TO_GUILD", "SERVER_NEXT"); export default definePlugin({ name: "WebKeybinds", description: t("vencord.webKeybinds.description"), + tags: ["Shortcuts"], authors: [Devs.Ven], enabledByDefault: true, diff --git a/src/plugins/webScreenShareFixes.web/index.ts b/src/plugins/webScreenShareFixes.web/index.ts index dee9b8f55..c26a24ad6 100644 --- a/src/plugins/webScreenShareFixes.web/index.ts +++ b/src/plugins/webScreenShareFixes.web/index.ts @@ -5,13 +5,14 @@ */ import { Devs } from "@utils/constants"; -import definePlugin from "@utils/types"; import { t } from "@utils/translation"; +import definePlugin from "@utils/types"; export default definePlugin({ name: "WebScreenShareFixes", authors: [Devs.Kaitlyn], description: t("vencord.webScreenShareFixes.description"), + tags: ["Voice"], enabledByDefault: true, patches: [ diff --git a/src/plugins/whoReacted/index.tsx b/src/plugins/whoReacted/index.tsx index 8ce3b11b4..fe3b30aa8 100644 --- a/src/plugins/whoReacted/index.tsx +++ b/src/plugins/whoReacted/index.tsx @@ -89,6 +89,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "WhoReacted", description: t("vencord.whoReacted.description"), + tags: ["Reactions", "Chat", "Appearance"], authors: [Devs.Ven, Devs.KannaDev, Devs.newwares], isModified: true, settings, diff --git a/src/plugins/xsOverlay/index.tsx b/src/plugins/xsOverlay/index.tsx index 36afcf036..deb6b0210 100644 --- a/src/plugins/xsOverlay/index.tsx +++ b/src/plugins/xsOverlay/index.tsx @@ -189,8 +189,9 @@ const Native = VencordNative.pluginHelpers.XSOverlay as PluginNative); // iife so #__PURE__ works correctly diff --git a/src/utils/text.ts b/src/utils/text.ts index 76f7f1eca..eb925df4e 100644 --- a/src/utils/text.ts +++ b/src/utils/text.ts @@ -180,7 +180,6 @@ export function toInlineCode(s: string) { return "``" + ZWSP + s.replaceAll("`", ZWSP + "`" + ZWSP) + ZWSP + "``"; } -// @ts-expect-error Missing RegExp.escape export const escapeRegExp: (s: string) => string = RegExp.escape ?? function (s: string) { return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); }; diff --git a/src/utils/types.ts b/src/utils/types.ts index ac078d5e5..c33114a5c 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -46,6 +46,32 @@ export function makeRange(start: number, end: number, step = 1) { return ranges; } +export const PluginTags = [ + "Accessibility", + "Activity", + "Appearance", + "Chat", + "Commands", + "Console", + "Customisation", + "Developers", + "Emotes", + "Friends", + "Fun", + "Media", + "Notifications", + "Organisation", + "Privacy", + "Reactions", + "Roles", + "Servers", + "Shortcuts", + "Utility", + "Voice" +] as const; + +export type PluginTag = typeof PluginTags[number]; + export type ReplaceFn = (match: string, ...groups: string[]) => string; export interface PatchReplacement { @@ -105,6 +131,9 @@ export type IconProps = { height?: number | string; width?: number | string; cla export interface PluginDef { name: string; description: string; + /** Additional search terms that will bring up your plugin */ + searchTerms?: string[]; + tags?: PluginTag[]; authors: PluginAuthor[]; start?(): void; stop?(): void; @@ -182,8 +211,6 @@ export interface PluginDef { */ toolboxActions?: Record void> | (() => ReactNode); - tags?: string[]; - /** * Managed style to automatically enable and disable when the plugin is enabled or disabled */ diff --git a/src/webpack/common/components.ts b/src/webpack/common/components.ts index 2a1ca4efb..98d453abf 100644 --- a/src/webpack/common/components.ts +++ b/src/webpack/common/components.ts @@ -58,8 +58,8 @@ export const TooltipContainer = TooltipContainerComponent as never; export const TextInput = waitForComponent("TextInput", filters.componentByCode("#{intl::MAXIMUM_LENGTH_ERROR}", '"input"')); export const TextArea = waitForComponent("TextArea", filters.componentByCode("this.getPaddingRight()},id:")); -export const Select = waitForComponent("Select", filters.componentByCode('"Select"')); -export const SearchableSelect = waitForComponent("SearchableSelect", filters.componentByCode('"SearchableSelect"')); +export const Select = waitForComponent("Select", filters.componentByCode('selectionMode:"single",onSelectionChange:', "isSelected:")); +export const SearchableSelect = waitForComponent("SearchableSelect", filters.componentByCode('?"multiple":"single",required:')); export const Slider = waitForComponent("Slider", filters.componentByCode("markDash", "this.renderMark(")); export const Popout = waitForComponent("Popout", filters.componentByCode("ref:this.ref,", "renderPopout:this.renderPopout,")); export const Dialog = waitForComponent("Dialog", filters.componentByCode('role:"dialog",tabIndex:-1')); diff --git a/src/webpack/patchWebpack.ts b/src/webpack/patchWebpack.ts index fb31cbc23..2b1994f20 100644 --- a/src/webpack/patchWebpack.ts +++ b/src/webpack/patchWebpack.ts @@ -5,14 +5,14 @@ */ import { Settings } from "@api/Settings"; +import { reporterData } from "@debug/reporterData"; +import { traceFunctionWithResults } from "@debug/Tracer"; import { makeLazy } from "@utils/lazy"; import { Logger } from "@utils/Logger"; import { interpolateIfDefined } from "@utils/misc"; import { Patch, PatchReplacement } from "@utils/types"; import { WebpackRequire } from "@vencord/discord-types/webpack"; -import { reporterData } from "debug/reporterData"; -import { traceFunctionWithResults } from "../debug/Tracer"; import { AnyModuleFactory, AnyWebpackRequire, MaybePatchedModuleFactory, PatchedModuleFactory } from "./types"; import { _blacklistBadModules, _initWebpack, factoryListeners, findModuleFactory, moduleListeners, waitForSubscriptions, wreq } from "./webpack"; diff --git a/src/webpack/webpack.ts b/src/webpack/webpack.ts index 5917d9073..4060bd45b 100644 --- a/src/webpack/webpack.ts +++ b/src/webpack/webpack.ts @@ -16,6 +16,7 @@ * along with this program. If not, see . */ +import { traceFunction } from "@debug/Tracer"; import { makeLazy, proxyLazy } from "@utils/lazy"; import { LazyComponent } from "@utils/lazyReact"; import { Logger } from "@utils/Logger"; @@ -24,7 +25,6 @@ import { escapeRegExp } from "@utils/text"; import type { FluxStore } from "@vencord/discord-types"; import type { ModuleExports, ModuleFactory, WebpackRequire } from "@vencord/discord-types/webpack"; -import { traceFunction } from "../debug/Tracer"; import type { AnyModuleFactory, AnyWebpackRequire } from "./types"; const logger = new Logger("Webpack"); diff --git a/tsconfig.json b/tsconfig.json index 1f98a1af4..fc7a573ce 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -19,43 +19,48 @@ "noImplicitAny": false, "target": "ESNEXT", "jsx": "preserve", - "baseUrl": "./src/", "paths": { "@main/*": [ - "./main/*" + "./src/main/*" ], "@api/*": [ - "./api/*" + "./src/api/*" ], "@components/*": [ - "./components/*" + "./src/components/*" + ], + "@debug/*": [ + "./src/debug/*" ], "@utils/*": [ - "./utils/*" + "./src/utils/*" ], "@plugins/*": [ - "./plugins/*" + "./src/plugins/*" ], "@shared/*": [ - "./shared/*" + "./src/shared/*" ], "@webpack/common": [ - "./webpack/common" + "./src/webpack/common" ], "@webpack/common/*": [ - "./webpack/common/*" + "./src/webpack/common/*" ], "@webpack": [ - "./webpack/webpack" + "./src/webpack/webpack" ], "@webpack/patcher": [ - "./webpack/patchWebpack" + "./src/webpack/patchWebpack" ], "@webpack/wreq.d": [ - "./webpack/wreq.d" + "./src/webpack/wreq.d" + ], + "@webpack/types": [ + "./src/webpack/types" ], "@equicordplugins/*": [ - "./equicordplugins/*" + "./src/equicordplugins/*" ] }, "plugins": [