Merge remote-tracking branch 'upstream/dev' into dev

This commit is contained in:
thororen 2026-08-18 23:02:48 -04:00
commit 65bcda4826
No known key found for this signature in database
43 changed files with 397 additions and 281 deletions

View file

@ -1,7 +1,7 @@
{
"name": "equicord",
"private": "true",
"version": "1.15.1.0",
"version": "1.15.2.0",
"description": "The other cutest Discord client mod",
"homepage": "https://github.com/Equicord/Equicord#readme",
"bugs": {

View file

@ -1,7 +1,26 @@
import type { ComponentType, CSSProperties, ForwardRefRenderFunction, MouseEvent, PropsWithChildren, ReactNode, UIEvent } from "react";
import { LiteralUnion } from "type-fest";
type RC<C> = ComponentType<PropsWithChildren<C & Record<string, any>>>;
type Accessory =
| {
type: "icon";
icon: ComponentType<any>;
color?: string;
size?: LiteralUnion<"refresh_sm", string>;
}
| {
type: "emoji";
emojiId?: string;
src?: string;
animated?: boolean;
}
| {
type: "image";
src: string;
};
export interface Menu {
Menu: RC<{
navId: string;
@ -20,6 +39,7 @@ export interface Menu {
label: ReactNode;
action?(e: MouseEvent): void;
icon?: ComponentType<any>;
leadingAccessory?: Accessory;
color?: string;
render?: ComponentType<any>;

View file

@ -1,7 +1,7 @@
{
"name": "@equicord/types",
"private": false,
"version": "1.14.15",
"version": "1.15.1",
"description": "",
"types": "index.d.ts",
"scripts": {
@ -19,7 +19,7 @@
"dependencies": {
"@types/lodash": "4.17.19",
"@types/node": "^26.0.1",
"@vencord/discord-types": "^1.0.1",
"@vencord/discord-types": "^1.0.2",
"highlight.js": "11.11.1",
"moment": "^2.22.2",
"ts-pattern": "^5.6.0",

210
pnpm-lock.yaml generated
View file

@ -65,7 +65,7 @@ importers:
version: 4.2.0
'@stylistic/eslint-plugin':
specifier: ^5.10.0
version: 5.10.0(eslint@10.6.0)
version: 5.10.0(eslint@10.6.0(supports-color@10.2.2))
'@types/chrome':
specifier: ^0.2.0
version: 0.2.0
@ -95,22 +95,22 @@ importers:
version: 0.28.1
eslint:
specifier: 10.6.0
version: 10.6.0
version: 10.6.0(supports-color@10.2.2)
eslint-import-resolver-alias:
specifier: ^1.1.2
version: 1.1.2(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.62.1(eslint@10.6.0)(typescript@6.0.3))(eslint@10.6.0))
version: 1.1.2(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.62.1(eslint@10.6.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint@10.6.0(supports-color@10.2.2)))
eslint-plugin-react:
specifier: ^7.37.5
version: 7.37.5(eslint@10.6.0)
version: 7.37.5(eslint@10.6.0(supports-color@10.2.2))
eslint-plugin-simple-header:
specifier: ^1.2.1
version: 1.2.2(eslint@10.6.0)
version: 1.2.2(eslint@10.6.0(supports-color@10.2.2))
eslint-plugin-simple-import-sort:
specifier: ^13.0.0
version: 13.0.0(eslint@10.6.0)
version: 13.0.0(eslint@10.6.0(supports-color@10.2.2))
eslint-plugin-unused-imports:
specifier: ^4.4.1
version: 4.4.1(@typescript-eslint/eslint-plugin@8.62.1(@typescript-eslint/parser@8.62.1(eslint@10.6.0)(typescript@6.0.3))(eslint@10.6.0)(typescript@6.0.3))(eslint@10.6.0)
version: 4.4.1(@typescript-eslint/eslint-plugin@8.62.1(@typescript-eslint/parser@8.62.1(eslint@10.6.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint@10.6.0(supports-color@10.2.2))(typescript@6.0.3))(eslint@10.6.0(supports-color@10.2.2))
highlight.js:
specifier: 11.11.1
version: 11.11.1
@ -134,10 +134,10 @@ importers:
version: 41.2.1
stylelint:
specifier: ^17.14.0
version: 17.14.0(typescript@6.0.3)
version: 17.14.0(supports-color@10.2.2)(typescript@6.0.3)
stylelint-config-standard:
specifier: ^40.0.0
version: 40.0.0(stylelint@17.14.0(typescript@6.0.3))
version: 40.0.0(stylelint@17.14.0(supports-color@10.2.2)(typescript@6.0.3))
svgo:
specifier: ^4.0.1
version: 4.0.1
@ -158,7 +158,7 @@ importers:
version: 6.0.3
typescript-eslint:
specifier: ^8.62.1
version: 8.62.1(eslint@10.6.0)(typescript@6.0.3)
version: 8.62.1(eslint@10.6.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)
typescript-transform-paths:
specifier: ^3.5.6
version: 3.5.6(typescript@6.0.3)
@ -193,8 +193,8 @@ importers:
specifier: 19.0.4
version: 19.0.4(@types/react@19.0.12)
'@vencord/discord-types':
specifier: ^1.0.1
version: 1.0.1(@types/react@19.0.12)
specifier: ^1.0.2
version: 1.0.2(@types/react@19.0.12)
highlight.js:
specifier: 11.11.1
version: 11.11.1
@ -710,10 +710,10 @@ packages:
'@vap/shiki@0.10.5':
resolution: {integrity: sha512-5BHVGvQT8qonbLSASon5aQFQ18OZU4FxSl9tLSj6oJ0sap3KdMbYcfGq25M9zFZR1g1dJN7fgjmZXBIS5omIdw==}
'@vencord/discord-types@1.0.1':
resolution: {integrity: sha512-uSQMDUTo9hMFgOMykNtTMTxScSKVVUHHFCevktO3bMyaLh1s3iDMfIvUvqU1fBkmFwvMbmEYsUrztsVKKHvang==}
'@vencord/discord-types@1.0.2':
resolution: {integrity: sha512-nq3YZebbv085/FsFcKhoVBCs9U9QuAEPy1noL9x9Bb5B29TdhQqr/hJCcApSWjY8J299+tLi30LEe0YGo3yn0Q==}
peerDependencies:
'@types/react': ^19.0.10
'@types/react': 19.1.0
acorn-jsx@5.3.2:
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
@ -1133,8 +1133,8 @@ packages:
peerDependencies:
eslint-plugin-import: '>=1.4.0'
eslint-import-resolver-node@0.3.9:
resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==}
eslint-import-resolver-node@0.3.10:
resolution: {integrity: sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ==}
eslint-module-utils@2.13.0:
resolution: {integrity: sha512-bLohSkT6469rRs8czj0tLTD8vaeIS/whvPRJVjDr7IuoTT1k5DYDERlNycjDj/HkOlvQdYurmfZ/g3fG5bgeLQ==}
@ -1815,6 +1815,10 @@ packages:
engines: {node: '>=10.5.0'}
deprecated: Use your platform's native DOMException instead
node-exports-info@1.6.2:
resolution: {integrity: sha512-kXs9Go0cah0qHVV2v389IXQLdLCeE1xfFtjOAF+iobu0OIoG1pje8At2vMHyaPMiPMnG/LWP50twML21eMcAag==}
engines: {node: '>= 0.4'}
normalize-path@3.0.0:
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
engines: {node: '>=0.10.0'}
@ -1995,11 +1999,6 @@ packages:
resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
engines: {node: '>=4'}
resolve@1.22.11:
resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==}
engines: {node: '>= 0.4'}
hasBin: true
resolve@1.22.8:
resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==}
hasBin: true
@ -2008,6 +2007,11 @@ packages:
resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==}
hasBin: true
resolve@2.0.0-next.7:
resolution: {integrity: sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==}
engines: {node: '>= 0.4'}
hasBin: true
reusify@1.1.0:
resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==}
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
@ -2259,10 +2263,6 @@ packages:
resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
engines: {node: '>= 0.8.0'}
type-fest@4.41.0:
resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==}
engines: {node: '>=16'}
type-fest@5.7.0:
resolution: {integrity: sha512-1URUxUqfHFM1c+zfSPsa3gnkO7Aq21qyH75SIduNYz4SzY964rn1X2vCMQaHSHhktiw+0kPa2iyb6PUpXqB6Vg==}
engines: {node: '>=20'}
@ -2572,17 +2572,17 @@ snapshots:
'@esbuild/win32-x64@0.28.1':
optional: true
'@eslint-community/eslint-utils@4.9.1(eslint@10.6.0)':
'@eslint-community/eslint-utils@4.9.1(eslint@10.6.0(supports-color@10.2.2))':
dependencies:
eslint: 10.6.0
eslint: 10.6.0(supports-color@10.2.2)
eslint-visitor-keys: 3.4.3
'@eslint-community/regexpp@4.12.2': {}
'@eslint/config-array@0.23.5':
'@eslint/config-array@0.23.5(supports-color@10.2.2)':
dependencies:
'@eslint/object-schema': 3.0.5
debug: 4.4.3
debug: 4.4.3(supports-color@10.2.2)
minimatch: 10.2.5
transitivePeerDependencies:
- supports-color
@ -2687,11 +2687,11 @@ snapshots:
'@streamparser/json@0.0.22': {}
'@stylistic/eslint-plugin@5.10.0(eslint@10.6.0)':
'@stylistic/eslint-plugin@5.10.0(eslint@10.6.0(supports-color@10.2.2))':
dependencies:
'@eslint-community/eslint-utils': 4.9.1(eslint@10.6.0)
'@eslint-community/eslint-utils': 4.9.1(eslint@10.6.0(supports-color@10.2.2))
'@typescript-eslint/types': 8.58.2
eslint: 10.6.0
eslint: 10.6.0(supports-color@10.2.2)
eslint-visitor-keys: 4.2.1
espree: 10.4.0
estraverse: 5.3.0
@ -2762,15 +2762,15 @@ snapshots:
dependencies:
'@types/node': 26.0.1
'@typescript-eslint/eslint-plugin@8.62.1(@typescript-eslint/parser@8.62.1(eslint@10.6.0)(typescript@6.0.3))(eslint@10.6.0)(typescript@6.0.3)':
'@typescript-eslint/eslint-plugin@8.62.1(@typescript-eslint/parser@8.62.1(eslint@10.6.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint@10.6.0(supports-color@10.2.2))(typescript@6.0.3)':
dependencies:
'@eslint-community/regexpp': 4.12.2
'@typescript-eslint/parser': 8.62.1(eslint@10.6.0)(typescript@6.0.3)
'@typescript-eslint/parser': 8.62.1(eslint@10.6.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)
'@typescript-eslint/scope-manager': 8.62.1
'@typescript-eslint/type-utils': 8.62.1(eslint@10.6.0)(typescript@6.0.3)
'@typescript-eslint/utils': 8.62.1(eslint@10.6.0)(typescript@6.0.3)
'@typescript-eslint/type-utils': 8.62.1(eslint@10.6.0(supports-color@10.2.2))(typescript@6.0.3)
'@typescript-eslint/utils': 8.62.1(eslint@10.6.0(supports-color@10.2.2))(typescript@6.0.3)
'@typescript-eslint/visitor-keys': 8.62.1
eslint: 10.6.0
eslint: 10.6.0(supports-color@10.2.2)
ignore: 7.0.5
natural-compare: 1.4.0
ts-api-utils: 2.5.0(typescript@6.0.3)
@ -2778,14 +2778,14 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@typescript-eslint/parser@8.62.1(eslint@10.6.0)(typescript@6.0.3)':
'@typescript-eslint/parser@8.62.1(eslint@10.6.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)':
dependencies:
'@typescript-eslint/scope-manager': 8.62.1
'@typescript-eslint/types': 8.62.1
'@typescript-eslint/typescript-estree': 8.62.1(typescript@6.0.3)
'@typescript-eslint/visitor-keys': 8.62.1
debug: 4.4.3
eslint: 10.6.0
debug: 4.4.3(supports-color@10.2.2)
eslint: 10.6.0(supports-color@10.2.2)
typescript: 6.0.3
transitivePeerDependencies:
- supports-color
@ -2794,7 +2794,7 @@ snapshots:
dependencies:
'@typescript-eslint/tsconfig-utils': 8.62.1(typescript@6.0.3)
'@typescript-eslint/types': 8.62.1
debug: 4.4.3
debug: 4.4.3(supports-color@10.2.2)
typescript: 6.0.3
transitivePeerDependencies:
- supports-color
@ -2808,13 +2808,13 @@ snapshots:
dependencies:
typescript: 6.0.3
'@typescript-eslint/type-utils@8.62.1(eslint@10.6.0)(typescript@6.0.3)':
'@typescript-eslint/type-utils@8.62.1(eslint@10.6.0(supports-color@10.2.2))(typescript@6.0.3)':
dependencies:
'@typescript-eslint/types': 8.62.1
'@typescript-eslint/typescript-estree': 8.62.1(typescript@6.0.3)
'@typescript-eslint/utils': 8.62.1(eslint@10.6.0)(typescript@6.0.3)
debug: 4.4.3
eslint: 10.6.0
'@typescript-eslint/utils': 8.62.1(eslint@10.6.0(supports-color@10.2.2))(typescript@6.0.3)
debug: 4.4.3(supports-color@10.2.2)
eslint: 10.6.0(supports-color@10.2.2)
ts-api-utils: 2.5.0(typescript@6.0.3)
typescript: 6.0.3
transitivePeerDependencies:
@ -2830,7 +2830,7 @@ snapshots:
'@typescript-eslint/tsconfig-utils': 8.62.1(typescript@6.0.3)
'@typescript-eslint/types': 8.62.1
'@typescript-eslint/visitor-keys': 8.62.1
debug: 4.4.3
debug: 4.4.3(supports-color@10.2.2)
minimatch: 10.2.5
semver: 7.8.5
tinyglobby: 0.2.17
@ -2839,13 +2839,13 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@typescript-eslint/utils@8.62.1(eslint@10.6.0)(typescript@6.0.3)':
'@typescript-eslint/utils@8.62.1(eslint@10.6.0(supports-color@10.2.2))(typescript@6.0.3)':
dependencies:
'@eslint-community/eslint-utils': 4.9.1(eslint@10.6.0)
'@eslint-community/eslint-utils': 4.9.1(eslint@10.6.0(supports-color@10.2.2))
'@typescript-eslint/scope-manager': 8.62.1
'@typescript-eslint/types': 8.62.1
'@typescript-eslint/typescript-estree': 8.62.1(typescript@6.0.3)
eslint: 10.6.0
eslint: 10.6.0(supports-color@10.2.2)
typescript: 6.0.3
transitivePeerDependencies:
- supports-color
@ -2865,11 +2865,11 @@ snapshots:
vscode-oniguruma: 1.7.0
vscode-textmate: 5.2.0
'@vencord/discord-types@1.0.1(@types/react@19.0.12)':
'@vencord/discord-types@1.0.2(@types/react@19.0.12)':
dependencies:
'@types/react': 19.0.12
moment: 2.30.1
type-fest: 4.41.0
moment: 2.22.2
type-fest: 5.7.0
acorn-jsx@5.3.2(acorn@8.15.0):
dependencies:
@ -3188,9 +3188,11 @@ snapshots:
dependencies:
ms: 2.1.3
debug@4.4.3:
debug@4.4.3(supports-color@10.2.2):
dependencies:
ms: 2.1.3
optionalDependencies:
supports-color: 10.2.2
deep-is@0.1.4: {}
@ -3524,29 +3526,29 @@ snapshots:
escape-string-regexp@4.0.0: {}
eslint-import-resolver-alias@1.1.2(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.62.1(eslint@10.6.0)(typescript@6.0.3))(eslint@10.6.0)):
eslint-import-resolver-alias@1.1.2(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.62.1(eslint@10.6.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint@10.6.0(supports-color@10.2.2))):
dependencies:
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.62.1(eslint@10.6.0)(typescript@6.0.3))(eslint@10.6.0)
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.62.1(eslint@10.6.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint@10.6.0(supports-color@10.2.2))
eslint-import-resolver-node@0.3.9:
eslint-import-resolver-node@0.3.10:
dependencies:
debug: 3.2.7
is-core-module: 2.16.2
resolve: 1.22.11
resolve: 2.0.0-next.7
transitivePeerDependencies:
- supports-color
eslint-module-utils@2.13.0(@typescript-eslint/parser@8.62.1(eslint@10.6.0)(typescript@6.0.3))(eslint-import-resolver-node@0.3.9)(eslint@10.6.0):
eslint-module-utils@2.13.0(@typescript-eslint/parser@8.62.1(eslint@10.6.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint-import-resolver-node@0.3.10)(eslint@10.6.0(supports-color@10.2.2)):
dependencies:
debug: 3.2.7
optionalDependencies:
'@typescript-eslint/parser': 8.62.1(eslint@10.6.0)(typescript@6.0.3)
eslint: 10.6.0
eslint-import-resolver-node: 0.3.9
'@typescript-eslint/parser': 8.62.1(eslint@10.6.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)
eslint: 10.6.0(supports-color@10.2.2)
eslint-import-resolver-node: 0.3.10
transitivePeerDependencies:
- supports-color
eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.62.1(eslint@10.6.0)(typescript@6.0.3))(eslint@10.6.0):
eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.62.1(eslint@10.6.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint@10.6.0(supports-color@10.2.2)):
dependencies:
'@rtsao/scc': 1.1.0
array-includes: 3.1.9
@ -3555,9 +3557,9 @@ snapshots:
array.prototype.flatmap: 1.3.3
debug: 3.2.7
doctrine: 2.1.0
eslint: 10.6.0
eslint-import-resolver-node: 0.3.9
eslint-module-utils: 2.13.0(@typescript-eslint/parser@8.62.1(eslint@10.6.0)(typescript@6.0.3))(eslint-import-resolver-node@0.3.9)(eslint@10.6.0)
eslint: 10.6.0(supports-color@10.2.2)
eslint-import-resolver-node: 0.3.10
eslint-module-utils: 2.13.0(@typescript-eslint/parser@8.62.1(eslint@10.6.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint-import-resolver-node@0.3.10)(eslint@10.6.0(supports-color@10.2.2))
hasown: 2.0.4
is-core-module: 2.16.2
is-glob: 4.0.3
@ -3569,13 +3571,13 @@ snapshots:
string.prototype.trimend: 1.0.10
tsconfig-paths: 3.15.0
optionalDependencies:
'@typescript-eslint/parser': 8.62.1(eslint@10.6.0)(typescript@6.0.3)
'@typescript-eslint/parser': 8.62.1(eslint@10.6.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)
transitivePeerDependencies:
- eslint-import-resolver-typescript
- eslint-import-resolver-webpack
- supports-color
eslint-plugin-react@7.37.5(eslint@10.6.0):
eslint-plugin-react@7.37.5(eslint@10.6.0(supports-color@10.2.2)):
dependencies:
array-includes: 3.1.8
array.prototype.findlast: 1.2.5
@ -3583,7 +3585,7 @@ snapshots:
array.prototype.tosorted: 1.1.4
doctrine: 2.1.0
es-iterator-helpers: 1.2.1
eslint: 10.6.0
eslint: 10.6.0(supports-color@10.2.2)
estraverse: 5.3.0
hasown: 2.0.2
jsx-ast-utils: 3.3.5
@ -3597,19 +3599,19 @@ snapshots:
string.prototype.matchall: 4.0.12
string.prototype.repeat: 1.0.0
eslint-plugin-simple-header@1.2.2(eslint@10.6.0):
eslint-plugin-simple-header@1.2.2(eslint@10.6.0(supports-color@10.2.2)):
dependencies:
eslint: 10.6.0
eslint: 10.6.0(supports-color@10.2.2)
eslint-plugin-simple-import-sort@13.0.0(eslint@10.6.0):
eslint-plugin-simple-import-sort@13.0.0(eslint@10.6.0(supports-color@10.2.2)):
dependencies:
eslint: 10.6.0
eslint: 10.6.0(supports-color@10.2.2)
eslint-plugin-unused-imports@4.4.1(@typescript-eslint/eslint-plugin@8.62.1(@typescript-eslint/parser@8.62.1(eslint@10.6.0)(typescript@6.0.3))(eslint@10.6.0)(typescript@6.0.3))(eslint@10.6.0):
eslint-plugin-unused-imports@4.4.1(@typescript-eslint/eslint-plugin@8.62.1(@typescript-eslint/parser@8.62.1(eslint@10.6.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint@10.6.0(supports-color@10.2.2))(typescript@6.0.3))(eslint@10.6.0(supports-color@10.2.2)):
dependencies:
eslint: 10.6.0
eslint: 10.6.0(supports-color@10.2.2)
optionalDependencies:
'@typescript-eslint/eslint-plugin': 8.62.1(@typescript-eslint/parser@8.62.1(eslint@10.6.0)(typescript@6.0.3))(eslint@10.6.0)(typescript@6.0.3)
'@typescript-eslint/eslint-plugin': 8.62.1(@typescript-eslint/parser@8.62.1(eslint@10.6.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint@10.6.0(supports-color@10.2.2))(typescript@6.0.3)
eslint-scope@9.1.2:
dependencies:
@ -3624,11 +3626,11 @@ snapshots:
eslint-visitor-keys@5.0.1: {}
eslint@10.6.0:
eslint@10.6.0(supports-color@10.2.2):
dependencies:
'@eslint-community/eslint-utils': 4.9.1(eslint@10.6.0)
'@eslint-community/eslint-utils': 4.9.1(eslint@10.6.0(supports-color@10.2.2))
'@eslint-community/regexpp': 4.12.2
'@eslint/config-array': 0.23.5
'@eslint/config-array': 0.23.5(supports-color@10.2.2)
'@eslint/config-helpers': 0.6.0
'@eslint/core': 1.2.1
'@eslint/plugin-kit': 0.7.2
@ -3638,7 +3640,7 @@ snapshots:
'@types/estree': 1.0.9
ajv: 6.15.0
cross-spawn: 7.0.6
debug: 4.4.3
debug: 4.4.3(supports-color@10.2.2)
escape-string-regexp: 4.0.0
eslint-scope: 9.1.2
eslint-visitor-keys: 5.0.1
@ -4242,6 +4244,13 @@ snapshots:
node-domexception@1.0.0:
optional: true
node-exports-info@1.6.2:
dependencies:
array.prototype.flatmap: 1.3.3
es-errors: 1.3.0
object.entries: 1.1.9
semver: 6.3.1
normalize-path@3.0.0: {}
nth-check@2.1.1:
@ -4437,12 +4446,6 @@ snapshots:
resolve-from@4.0.0: {}
resolve@1.22.11:
dependencies:
is-core-module: 2.16.2
path-parse: 1.0.7
supports-preserve-symlinks-flag: 1.0.0
resolve@1.22.8:
dependencies:
is-core-module: 2.16.1
@ -4455,6 +4458,15 @@ snapshots:
path-parse: 1.0.7
supports-preserve-symlinks-flag: 1.0.0
resolve@2.0.0-next.7:
dependencies:
es-errors: 1.3.0
is-core-module: 2.16.2
node-exports-info: 1.6.2
object-keys: 1.1.1
path-parse: 1.0.7
supports-preserve-symlinks-flag: 1.0.0
reusify@1.1.0: {}
run-parallel@1.2.0:
@ -4669,16 +4681,16 @@ snapshots:
strip-bom@3.0.0: {}
stylelint-config-recommended@18.0.0(stylelint@17.14.0(typescript@6.0.3)):
stylelint-config-recommended@18.0.0(stylelint@17.14.0(supports-color@10.2.2)(typescript@6.0.3)):
dependencies:
stylelint: 17.14.0(typescript@6.0.3)
stylelint: 17.14.0(supports-color@10.2.2)(typescript@6.0.3)
stylelint-config-standard@40.0.0(stylelint@17.14.0(typescript@6.0.3)):
stylelint-config-standard@40.0.0(stylelint@17.14.0(supports-color@10.2.2)(typescript@6.0.3)):
dependencies:
stylelint: 17.14.0(typescript@6.0.3)
stylelint-config-recommended: 18.0.0(stylelint@17.14.0(typescript@6.0.3))
stylelint: 17.14.0(supports-color@10.2.2)(typescript@6.0.3)
stylelint-config-recommended: 18.0.0(stylelint@17.14.0(supports-color@10.2.2)(typescript@6.0.3))
stylelint@17.14.0(typescript@6.0.3):
stylelint@17.14.0(supports-color@10.2.2)(typescript@6.0.3):
dependencies:
'@csstools/css-calc': 3.2.1(@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)
@ -4691,7 +4703,7 @@ snapshots:
cosmiconfig: 9.0.2(typescript@6.0.3)
css-functions-list: 3.3.3
css-tree: 3.2.1
debug: 4.4.3
debug: 4.4.3(supports-color@10.2.2)
fast-glob: 3.3.3
fastest-levenshtein: 1.0.16
file-entry-cache: 11.1.5
@ -4806,8 +4818,6 @@ snapshots:
dependencies:
prelude-ls: 1.2.1
type-fest@4.41.0: {}
type-fest@5.7.0:
dependencies:
tagged-tag: 1.0.0
@ -4856,13 +4866,13 @@ snapshots:
typed-query-selector@2.12.2: {}
typescript-eslint@8.62.1(eslint@10.6.0)(typescript@6.0.3):
typescript-eslint@8.62.1(eslint@10.6.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3):
dependencies:
'@typescript-eslint/eslint-plugin': 8.62.1(@typescript-eslint/parser@8.62.1(eslint@10.6.0)(typescript@6.0.3))(eslint@10.6.0)(typescript@6.0.3)
'@typescript-eslint/parser': 8.62.1(eslint@10.6.0)(typescript@6.0.3)
'@typescript-eslint/eslint-plugin': 8.62.1(@typescript-eslint/parser@8.62.1(eslint@10.6.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint@10.6.0(supports-color@10.2.2))(typescript@6.0.3)
'@typescript-eslint/parser': 8.62.1(eslint@10.6.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)
'@typescript-eslint/typescript-estree': 8.62.1(typescript@6.0.3)
'@typescript-eslint/utils': 8.62.1(eslint@10.6.0)(typescript@6.0.3)
eslint: 10.6.0
'@typescript-eslint/utils': 8.62.1(eslint@10.6.0(supports-color@10.2.2))(typescript@6.0.3)
eslint: 10.6.0(supports-color@10.2.2)
typescript: 6.0.3
transitivePeerDependencies:
- supports-color

View file

@ -18,3 +18,5 @@ verifyDepsBeforeRun: prompt
minimumReleaseAge: 7
minimumReleaseAgeExclude:
- "@song-spotlight/api"
- "@vencord/*"
- "@equicord/*"

View file

@ -80,7 +80,8 @@ async function syncSettings() {
body: "We've noticed you have cloud integrations enabled in another client! Due to limitations, you will " +
"need to re-authenticate to continue using them. Click here to go to the settings page to do so!",
color: "var(--yellow-360)",
onClick: () => SettingsRouter.openUserSettings("equicord_cloud_panel")
onClick: () => SettingsRouter.openUserSettings("equicord_cloud_panel"),
noPersist: true
});
return;
}

View file

@ -32,3 +32,11 @@
flex-shrink: 0;
padding-top: 2px;
}
.vc-form-switch-border {
margin-top: 20px;
}
.vc-form-switch-description {
color: var(--text-subtle);
}

View file

@ -9,7 +9,7 @@ import "./FormSwitch.css";
import { classes } from "@utils/misc";
import type { PropsWithChildren, ReactNode } from "react";
import { Flex } from "./Flex";
import { Divider } from "./Divider";
import { Span } from "./Span";
import { Switch } from "./Switch";
@ -26,22 +26,24 @@ export interface FormSwitchProps {
export function FormSwitch({ onChange, title, value, description, disabled, className, hideBorder }: FormSwitchProps) {
return (
<div className={classes("vc-form-switch-container", hideBorder && "vc-form-switch-no-border")}>
<label className={classes("vc-form-switch", className, disabled && "vc-form-switch-disabled")}>
<div className="vc-form-switch-text">
<Flex flexDirection="column" gap="4px">
<Span size="md" weight="medium" color="text-strong">{title}</Span>
{description && <Span size="sm" color="text-subtle">{description}</Span>}
</Flex>
<label className="vc-form-switch-wrapper">
<div className={classes("vc-form-switch", className, disabled && "vc-form-switch-disabled")}>
<div className={"vc-form-switch-text"}>
<Span size="md" weight="medium">{title}</Span>
{description && <Span size="sm" weight="normal" className="vc-form-switch-description">{description}</Span>}
</div>
<div className="vc-form-switch-control">
<Switch checked={value} onChange={onChange} disabled={disabled} />
</div>
</label>
</div>
<Switch checked={value} onChange={onChange} disabled={disabled} />
</div>
{!hideBorder && <Divider className="vc-form-switch-border" />}
</label>
);
}
// #region Old compatibility
export function FormSwitchCompat({ note, children, ...restProps }: PropsWithChildren<any>) {
return <FormSwitch title={children ?? ""} description={note} {...restProps} />;
}
// #endregion

View file

@ -1252,3 +1252,33 @@ export function StarOutlined(props: IconProps) {
</Icon>
);
}
export function SearchIcon(props: IconProps) {
return (
<Icon
{...props}
viewBox="0 0 24 24"
>
<path
fill={props.fill || "currentColor"}
fillRule="evenodd"
d="M15.62 17.03a9 9 0 1 1 1.41-1.41l4.68 4.67a1 1 0 0 1-1.42 1.42l-4.67-4.68ZM17 10a7 7 0 1 1-14 0 7 7 0 0 1 14 0Z"
clipRule="evenodd"
/>
</Icon>
);
}
export function TopRightArrow(props: IconProps) {
return (
<Icon
{...props}
viewBox="0 0 24 24"
>
<path
fill={props.fill || "currentColor"}
d="M8 5a1 1 0 0 0 0 2h7.59L5.29 17.3a1 1 0 1 0 1.42 1.4L17 8.42V16a1 1 0 1 0 2 0V6a1 1 0 0 0-1-1H8Z"
/>
</Icon>
);
}

View file

@ -39,3 +39,7 @@
margin-left: auto;
}
}
.vc-plugin-ui-elements-description {
color: var(--text-subtle);
}

View file

@ -19,7 +19,7 @@ import { Margins } from "@utils/margins";
import { classes } from "@utils/misc";
import { IconComponent } from "@utils/types";
import { RenderModalProps } from "@vencord/discord-types";
import { Clickable, Modal,openModal } from "@webpack/common";
import { Clickable, Modal, openModal } from "@webpack/common";
const cl = classNameFactory("vc-plugin-ui-elements-");
@ -75,7 +75,7 @@ function Section(props: {
return (
<section>
<BaseText tag="h3" size="lg" weight="semibold">{title}</BaseText>
<Paragraph size="sm" className={classes(Margins.top8, Margins.bottom20)}>{description}</Paragraph>
<Paragraph size="sm" className={classes(Margins.top8, Margins.bottom20, cl("description"))}>{description}</Paragraph>
<div className={cl("switches")}>
{switches.length === 0 && (

View file

@ -26,7 +26,7 @@
color: var(--text-strong);
}
.vc-plugins-setting-inline .vc-plugins-setting-description {
.vc-plugins-setting-description {
color: var(--text-subtle);
}

View file

@ -89,3 +89,8 @@
.vc-cloud-button-icon {
height: 1.25em;
}
.vc-settings-switches {
display: grid;
gap: 8px;
}

View file

@ -91,21 +91,23 @@ function Updater() {
Control how Equicord keeps itself up to date. You can choose to update automatically in the background or be notified when new updates are available.
</Paragraph>
<FormSwitch
title="Automatically update"
description="When enabled, Equicord will automatically download and install updates in the background without asking for confirmation. You'll need to restart Discord to apply the changes."
value={settings.autoUpdate}
onChange={(v: boolean) => settings.autoUpdate = v}
hideBorder
/>
<FormSwitch
value={settings.autoUpdateNotification}
onChange={(v: boolean) => settings.autoUpdateNotification = v}
title="Get notified when an automatic update completes"
description="Receive a notification when Equicord finishes downloading an update in the background, so you know when to restart Discord."
disabled={!settings.autoUpdate}
hideBorder
/>
<div className="vc-settings-switches">
<FormSwitch
title="Automatically update"
description="When enabled, Equicord will automatically download and install updates in the background without asking for confirmation. You'll need to restart Discord to apply the changes."
value={settings.autoUpdate}
onChange={(v: boolean) => settings.autoUpdate = v}
hideBorder
/>
<FormSwitch
title="Get notified when an automatic update completes"
description="Receive a notification when Equicord finishes downloading an update in the background, so you know when to restart Discord."
value={settings.autoUpdateNotification}
onChange={(v: boolean) => settings.autoUpdateNotification = v}
disabled={!settings.autoUpdate}
hideBorder
/>
</div>
<Divider className={Margins.top20} />

View file

@ -7,7 +7,6 @@
import "./VencordTab.css";
import { openNotificationLogModal } from "@api/Notifications/notificationLog";
import { plugins } from "@api/PluginManager";
import { useSettings } from "@api/Settings";
import { Button } from "@components/Button";
import { Divider } from "@components/Divider";
@ -20,6 +19,7 @@ import { openContributorModal, openPluginModal, SettingsTab, wrapTab } from "@co
import { QuickAction, QuickActionCard } from "@components/settings/QuickAction";
import { SpecialCard } from "@components/settings/SpecialCard";
import BadgeAPI from "@plugins/_api/badges";
import SettingsPlugin from "@plugins/_core/settings";
import { gitRemote } from "@shared/vencordUserAgent";
import { DONOR_ROLE_ID, GUILD_ID, IS_WINDOWS, VC_DONOR_ROLE_ID, VC_GUILD_ID } from "@utils/constants";
import { classNameFactory } from "@utils/css";
@ -55,13 +55,7 @@ function Switches() {
{
key: "useQuickCss",
title: "Enable Custom CSS",
description: "Load custom CSS from the QuickCSS editor. This allows you to customize Discord's appearance with your own styles.",
},
!IS_WEB && {
key: "enableReactDevtools",
title: "Enable React Developer Tools",
description: "Enable the React Developer Tools extension for debugging Discord's React components. Useful for plugin development.",
restartRequired: true,
description: "Apply your configured QuickCSS"
},
(!IS_WEB && !IS_DISCORD_DESKTOP || !IS_WINDOWS) && {
key: "mainWindowFrameless",
@ -95,8 +89,8 @@ function Switches() {
IS_DISCORD_DESKTOP && {
key: "disableMinSize",
title: "Disable Minimum Window Size",
description: "Allow the Discord window to be resized smaller than its default minimum size. Useful for tiling window managers or small screens.",
restartRequired: true,
description: "Allows you to resize the window to any size, even smaller than Discord's minimum size",
restartRequired: true
},
!IS_WEB && IS_WINDOWS && {
key: "winCtrlQ",
@ -104,6 +98,12 @@ function Switches() {
description: "Add Ctrl+Q as a keyboard shortcut to close Discord. This provides an alternative to Alt+F4 for quickly closing the application.",
restartRequired: true,
},
!IS_WEB && {
key: "enableReactDevtools",
title: "Enable React Developer Tools",
description: "Mainly useful for plugin developers. Ignore this if you don't know what it is",
restartRequired: true
},
] satisfies Array<false | {
key: KeysOfType<typeof settings, boolean>;
title: string;
@ -136,6 +136,7 @@ function Switches() {
)
}
value={settings[key]}
hideBorder
onChange={v => {
settings[key] = v;
@ -149,7 +150,6 @@ function Switches() {
});
}
}}
hideBorder
/>
);
});
@ -258,20 +258,19 @@ function EquicordSettings() {
<Divider className={Margins.top20} />
<Heading className={Margins.top20}>Client Settings</Heading>
<Paragraph className={Margins.bottom16}>
Configure how Equicord behaves and integrates with Discord. These settings affect the Discord client's appearance and behavior.
</Paragraph>
<Notice.Info className={Margins.bottom20} style={{ width: "100%" }}>
You can customize where this settings section appears in Discord's settings menu by configuring the{" "}
<a
role="button"
onClick={() => openPluginModal(plugins.Settings)}
style={{ cursor: "pointer", color: "var(--text-link)" }}
>
Settings Plugin
</a>.
</Notice.Info>
<section className={Margins.top16}>
<Heading tag="h5">Settings</Heading>
<Paragraph className={Margins.bottom20} style={{ color: "var(--text-muted)" }}>
Hint: You can change the position of this settings section in the{" "}
<a onClick={() => openPluginModal(SettingsPlugin)}>
settings of the Settings plugin
</a>!
</Paragraph>
<div className="vc-settings-switches">
<Switches />
</div>
</section>
<Switches />

View file

@ -14,7 +14,7 @@ import pLimit from "p-limit";
function getWebpackChunkMap() {
const sym = Symbol();
let chunksMap: unknown;
let chunksMap: unknown = null;
Object.defineProperty(Object.prototype, sym, {
get() {
@ -30,9 +30,38 @@ function getWebpackChunkMap() {
return chunksMap as Record<PropertyKey, string> | null;
}
let chunksAlreadyLoaded = false;
export async function loadLazyChunks() {
const LazyChunkLoaderLogger = new Logger("LazyChunkLoader");
if (chunksAlreadyLoaded) {
LazyChunkLoaderLogger.log("Lazy chunks have already been loaded");
return;
}
const queue = pLimit(50);
const workerAssetCache = new Map<string, Promise<boolean>>();
const WORKER_ASSET_REGEX = /importScripts\(|self\.postMessage/;
async function isWorkerAsset(url: string, useQueue: boolean = true): Promise<boolean> {
if (workerAssetCache.has(url)) {
return workerAssetCache.get(url)!;
}
const doFetch = () => {
return fetch(url)
.then(r => r.text())
.then(t => WORKER_ASSET_REGEX.test(t));
};
const res = useQueue
? queue(doFetch)
: doFetch();
workerAssetCache.set(url, res);
return res;
}
try {
LazyChunkLoaderLogger.log("Loading all chunks...");
@ -41,12 +70,12 @@ export async function loadLazyChunks() {
const invalidChunks = new Set<PropertyKey>();
const deferredRequires = new Set<PropertyKey>();
const { promise: chunksSearchingDone, resolve: chunksSearchingResolve } = Promise.withResolvers<void>();
const { promise: chunkSearchingDone, resolve: chunkSearchingDoneResolve } = Promise.withResolvers<void>();
// True if resolved, false otherwise
const chunksSearchPromises = [] as Array<() => boolean>;
// True if searching promise for that chunk is resolved, false otherwise
let chunkSearchResolvedGetters = [] as Array<() => boolean>;
// This regex loads all language packs which makes webpack finds testing extremely slow, so for now, we prioritize using the one which doesnt include those
// This regex loads all language packs which makes webpack finds testing extremely slow, so for now, we prioritize using the one which doesn't include those
const CompleteLazyChunkRegex = canonicalizeMatch(/(?:(?:Promise\.all\(\[)?((?:\i\.e\("?[^)]+?"?\),?)+?)(?:\]\))?)\.then\(\i(?:\.\i)?\.bind\(\i,"?([^)]+?)"?(?:,[^)]+?)?\)\)/g);
const PartialLazyChunkRegex = canonicalizeMatch(/(?:(?:Promise\.all\(\[)?((?:\i\.e\("?[^)]+?"?\),?)+?)(?:\]\))?)\.then\(\i\.bind\(\i,"?([^)]+?)"?\)\)/g);
@ -56,7 +85,7 @@ export async function loadLazyChunks() {
// Workaround to avoid loading the CSS debugging chunk which turns the app pink
// const hasCssDebuggingLoad = foundCssDebuggingLoad ? false : (foundCssDebuggingLoad = factoryCode.includes(".cssDebuggingEnabled&&"));
// Disabled for now since this causes lots of chunks concatenated into the same module get marked as invalid, and thus not loaded.
// Disabled for now since this causes lots of chunks concatenated into the same module to get marked as invalid, and thus not loaded.
const hasCssDebuggingLoad = foundCssDebuggingLoad = false;
const lazyChunks = factoryCode.matchAll(hasCssDebuggingLoad ? CompleteLazyChunkRegex : PartialLazyChunkRegex);
@ -93,13 +122,7 @@ export async function loadLazyChunks() {
if (wreq.u(id) == null || wreq.u(id) === "undefined.js") continue;
const isWorkerAsset = await queue(() =>
fetch(wreq.p + wreq.u(id))
.then(r => r.text())
.then(t => /importScripts\(|self\.postMessage/.test(t))
);
if (isWorkerAsset) {
if (await isWorkerAsset(wreq.p + wreq.u(id))) {
invalidChunks.add(id);
invalidChunkGroup = true;
continue;
@ -140,35 +163,27 @@ export async function loadLazyChunks() {
}
}
// setImmediate to only check if all chunks were loaded after this function resolves
// We check if all chunks were loaded every time a factory is loaded
// If we are still looking for chunks in the other factories, the array will have that factory's chunk search promise not resolved
// But, if all chunk search promises are resolved, this means we found every lazy chunk loaded by Discord code and manually loaded them
// Filter out resolved chunk search promises. If the array length is 0 that means all the pending searches and loadings are done
// and our regex has finished scanning all modules. Once this happens, the artificial "natural" loading of chunks has been completed
// and we can continue with the rest of the code.
// setImmediate here is needed so the filtering also includes the promises created from searching the modules loaded by the current invokation.
// Otherwise, it could resolve before the async code being put at the end of the event loop has a chance to run and add the promise to the array.
// The async code mentioned is the invokation of the current function from the factoryListener.
setTimeout(() => {
let allResolved = true;
for (let i = 0; i < chunksSearchPromises.length; i++) {
const isResolved = chunksSearchPromises[i]();
if (isResolved) {
// Remove finished promises to avoid having to iterate through a huge array everytime
chunksSearchPromises.splice(i--, 1);
} else {
allResolved = false;
}
chunkSearchResolvedGetters = chunkSearchResolvedGetters.filter(isResolvedGetter => !isResolvedGetter());
if (chunkSearchResolvedGetters.length === 0) {
chunkSearchingDoneResolve();
}
if (allResolved) chunksSearchingResolve();
}, 0);
}
function factoryListener(factory: AnyModuleFactory | ModuleFactory) {
let isResolved = false;
searchAndLoadLazyChunks(String(factory))
.then(() => isResolved = true)
.catch(() => isResolved = true);
.finally(() => isResolved = true);
chunksSearchPromises.push(() => isResolved);
chunkSearchResolvedGetters.push(() => isResolved);
}
Webpack.factoryListeners.add(factoryListener);
@ -176,7 +191,7 @@ export async function loadLazyChunks() {
factoryListener(wreq.m[moduleId]);
}
await chunksSearchingDone;
await chunkSearchingDone;
Webpack.factoryListeners.delete(factoryListener);
// Require deferred entry points
@ -198,17 +213,16 @@ export async function loadLazyChunks() {
});
await Promise.all(chunksLeft.map(async id => queue(async () => {
const isWorkerAsset = await fetch(wreq.p + wreq.u(id))
.then(r => r.text())
.then(t => /importScripts\(|self\.postMessage/.test(t));
// We will deadlock if we use the queue inside a queue func
const isWorkerFile = await isWorkerAsset(wreq.p + wreq.u(id), false);
// Loads the chunk. Currently this only happens with the language packs which are loaded differently
if (!isWorkerAsset) {
if (!isWorkerFile) {
await wreq.e(id);
}
})));
LazyChunkLoaderLogger.log("Finished loading all chunks!");
chunksAlreadyLoaded = true;
} catch (e) {
LazyChunkLoaderLogger.log("A fatal error occurred:", e);
}

View file

@ -19,7 +19,7 @@ async function runReporter() {
try {
ReporterLogger.log("Starting test...");
const { promise: loadLazyChunksDone, resolve: loadLazyChunksResolve } = Promise.withResolvers<void>();
const { promise: loadLazyChunksDone, resolve: loadLazyChunksDoneResolve } = Promise.withResolvers<void>();
// The main patch for starting the reporter chunk loading
addPatch({
@ -30,11 +30,10 @@ async function runReporter() {
}
}, "Equicord Reporter");
// initReporter is called in the patched entry point of Discord
// @ts-expect-error
Vencord.Webpack._initReporter = function () {
// initReporter is called in the patched entry point of Discord
// setImmediate to only start searching for lazy chunks after Discord initialized the app
setTimeout(() => loadLazyChunks().then(loadLazyChunksResolve), 0);
loadLazyChunks().then(loadLazyChunksDoneResolve);
};
await loadLazyChunksDone;

View file

@ -84,18 +84,21 @@ function CopyContextMenu({ name, type, path }: { type: string; name: string; pat
label={`Copy ${type} Name`}
action={() => copyWithToast(name)}
icon={CopyIcon}
leadingAccessory={{ type: "icon", icon: CopyIcon }}
/>
<Menu.MenuItem
id="vc-spotify-copy-link"
label={`Copy ${type} Link`}
action={() => copyWithToast("https://open.spotify.com" + path)}
icon={LinkIcon}
leadingAccessory={{ type: "icon", icon: LinkIcon }}
/>
<Menu.MenuItem
id="vc-spotify-open"
label={`Open ${type} in Spotify`}
action={() => SpotifyStore.openExternal(path)}
icon={OpenExternalIcon}
leadingAccessory={{ type: "icon", icon: OpenExternalIcon }}
/>
</Menu.Menu>
);
@ -224,6 +227,7 @@ function AlbumContextMenu({ track }: { track: Track; }) {
label="Open Album"
action={() => SpotifyStore.openExternal(`/album/${track.album.id}`)}
icon={OpenExternalIcon}
leadingAccessory={{ type: "icon", icon: OpenExternalIcon }}
/>
<Menu.MenuItem
key="view-cover"
@ -232,6 +236,7 @@ function AlbumContextMenu({ track }: { track: Track; }) {
// trolley
action={() => openImageModal(track.album.image)}
icon={ImageIcon}
leadingAccessory={{ type: "icon", icon: ImageIcon }}
/>
<Menu.MenuControlItem
id="spotify-volume"

View file

@ -20,6 +20,7 @@ import "./fixDiscordBadgePadding.css";
import { _getBadges, BadgePosition, BadgeUserArgs, ProfileBadge } from "@api/Badges";
import ErrorBoundary from "@components/ErrorBoundary";
import { CopyIcon, LinkIcon } from "@components/Icons";
import { openContributorModal } from "@components/settings/tabs";
import { Devs } from "@utils/constants";
import { copyWithToast } from "@utils/discord";
@ -114,6 +115,7 @@ export function BadgeContextMenu({ badge }: { badge: Omit<ProfileBadge, "id"> &
id="vc-badge-copy-name"
label="Copy Badge Name"
action={() => copyWithToast(badge.description!)}
leadingAccessory={{ type: "icon", icon: CopyIcon }}
/>
)}
{badge.iconSrc && (
@ -121,6 +123,7 @@ export function BadgeContextMenu({ badge }: { badge: Omit<ProfileBadge, "id"> &
id="vc-badge-copy-link"
label="Copy Badge Image Link"
action={() => copyWithToast(badge.iconSrc!)}
leadingAccessory={{ type: "icon", icon: LinkIcon }}
/>
)}
</Menu.Menu>

View file

@ -102,6 +102,7 @@ export function buildExtraRoleContextMenuItems(role: Role, guild: Guild, popoutR
GuildSettingsActions.selectRole(role.id);
}}
icon={PencilIcon}
leadingAccessory={{ type: "icon", icon: PencilIcon }}
/>
),
role.colorString && (
@ -111,6 +112,7 @@ export function buildExtraRoleContextMenuItems(role: Role, guild: Guild, popoutR
label="Copy Role Color"
action={() => copyToClipboard(role.colorString!)}
icon={AppearanceIcon}
leadingAccessory={{ type: "icon", icon: AppearanceIcon }}
/>
)
].filter(isTruthy);
@ -129,6 +131,7 @@ export function buildExtraRoleContextMenuItems(role: Role, guild: Guild, popoutR
});
}}
icon={ImageIcon}
leadingAccessory={{ type: "icon", icon: ImageIcon }}
/>
),
popoutRef && (
@ -159,6 +162,7 @@ export function buildExtraRoleContextMenuItems(role: Role, guild: Guild, popoutR
{...popoutProps}
>
<div className={MenuItemClasses.label}>View Role Members</div>
{/* FIXME: update to new icon style */}
<div className={MenuItemClasses.iconContainer}>
<RoleMembersIcon />
</div>
@ -197,6 +201,7 @@ export function openRoleContextMenu(event: React.MouseEvent<HTMLElement>, { guil
id="vc-better-role-context-copy-role-id"
label={getIntlMessage("COPY_ID_ROLE")}
icon={CopyIdIcon}
leadingAccessory={{ type: "icon", icon: CopyIdIcon }}
action={() => copyToClipboard(role.id)}
/>
</Menu.Menu>

View file

@ -70,6 +70,7 @@ export const addViewStreamContext: NavContextMenuPatchCallback = (children, { us
label="View Stream Preview"
id="view-stream-preview"
icon={ScreenshareIcon}
leadingAccessory={{ type: "icon", icon: ScreenshareIcon }}
action={() => stream && handleViewPreview(stream)}
disabled={!stream}
/>

View file

@ -5,6 +5,7 @@
*/
import { definePluginSettings } from "@api/Settings";
import { CopyIcon } from "@components/Icons";
import { Devs } from "@utils/constants";
import { copyWithToast } from "@utils/discord";
import definePlugin, { OptionType } from "@utils/types";
@ -69,6 +70,7 @@ export default definePlugin({
"Success! Copied emoji markdown."
);
}}
leadingAccessory={{ type: "icon", icon: CopyIcon }}
/>
);
},

View file

@ -18,6 +18,7 @@
import { NavContextMenuPatchCallback } from "@api/ContextMenu";
import { isPluginEnabled } from "@api/PluginManager";
import { LinkIcon, TopRightArrow } from "@components/Icons";
import ExpressionClonerPlugin from "@plugins/expressionCloner";
import { Devs } from "@utils/constants";
import { copyWithToast } from "@utils/discord";
@ -43,14 +44,17 @@ function buildMenuItem(sticker: PartialSticker, addBottomSeparator: boolean) {
<Menu.MenuItem
id="vc-copy-sticker-link"
key="vc-copy-sticker-link"
label="Copy Link"
label="Copy Sticker Link"
leadingAccessory={{ type: "icon", icon: LinkIcon }}
action={() => copyWithToast(getUrl(sticker), "Link copied!")}
/>
<Menu.MenuItem
id="vc-open-sticker-link"
key="vc-open-sticker-link"
label="Open Link"
label="Open Sticker Link"
leadingAccessory={{ type: "icon", icon: LinkIcon }}
trailingIndicator={{ type: "icon", icon: TopRightArrow }}
action={() => VencordNative.native.openExternal(getUrl(sticker))}
/>
</Menu.MenuGroup>

View file

@ -39,6 +39,7 @@ const UserContextMenuPatch: NavContextMenuPatchCallback = (children, { user }: U
label="Copy User URL"
action={() => copyToClipboard(`<https://discord.com/users/${user.id}>`)}
icon={LinkIcon}
leadingAccessory={{ type: "icon", icon: LinkIcon }}
/>
);
};

View file

@ -23,6 +23,7 @@ export default function DecorationContextMenu({ decoration }: { decoration: Deco
id={cl("decoration-context-menu-copy-hash")}
label="Copy Decoration Hash"
icon={CopyIcon}
leadingAccessory={{ type: "icon", icon: CopyIcon }}
action={() => copyToClipboard(decoration.hash)}
/>
{decoration.authorId === UserStore.getCurrentUser().id &&
@ -31,6 +32,7 @@ export default function DecorationContextMenu({ decoration }: { decoration: Deco
label="Delete Decoration"
color="danger"
icon={DeleteIcon}
leadingAccessory={{ type: "icon", icon: DeleteIcon }}
action={() => openModal(props => (
<ConfirmModal
{...props}

View file

@ -22,6 +22,7 @@ import { BaseText } from "@components/BaseText";
import { CheckedTextInput } from "@components/CheckedTextInput";
import { Flex } from "@components/Flex";
import { Heading } from "@components/Heading";
import { PlusIcon } from "@components/Icons";
import { Paragraph } from "@components/Paragraph";
import { Devs } from "@utils/constants";
import { getGuildAcronym, hasGuildFeature } from "@utils/discord";
@ -329,6 +330,7 @@ function buildMenuItem(type: "Emoji" | "Sticker", fetchData: () => Promisable<Om
id="emote-cloner"
key="emote-cloner"
label={`Clone ${type}`}
leadingAccessory={{ type: "icon", icon: PlusIcon }}
action={() =>
openModalLazy(async () => {
const res = await fetchData();

View file

@ -15,6 +15,7 @@ import { isPluginEnabled } from "@api/PluginManager";
import { definePluginSettings } from "@api/Settings";
import { disableStyle, enableStyle } from "@api/Styles";
import ErrorBoundary from "@components/ErrorBoundary";
import { DeleteIcon, EyeIcon } from "@components/Icons";
import { Devs, EQUIBOT_USER_ID, EquicordDevs, SUPPORT_CHANNEL_ID, VC_SUPPORT_CATEGORY_ID, VENBOT_USER_ID } from "@utils/constants";
import { getIntlMessage } from "@utils/discord";
import { Logger } from "@utils/Logger";
@ -120,6 +121,7 @@ const patchMessageContextMenu: NavContextMenuPatchCallback = (
id={TOGGLE_DELETE_STYLE_ID}
key={TOGGLE_DELETE_STYLE_ID}
label="Toggle Deleted Highlight"
leadingAccessory={{ type: "icon", icon: EyeIcon }}
action={() => domElement.classList.toggle("messagelogger-deleted")}
/>,
);
@ -161,6 +163,7 @@ const patchMessageContextMenu: NavContextMenuPatchCallback = (
id={REMOVE_HISTORY_ID}
key={REMOVE_HISTORY_ID}
label={label}
leadingAccessory={{ type: "icon", icon: DeleteIcon }}
color="danger"
action={() => {
clearMessageHistory(message);

View file

@ -104,6 +104,7 @@ const makeContextMenuPatch: (shouldAddIcon: boolean) => NavContextMenuPatchCallb
label="Apply NewGuildSettings"
id="vc-newguildsettings-apply"
icon={shouldAddIcon ? CogWheel : void 0}
leadingAccessory={shouldAddIcon ? { type: "icon", icon: CogWheel } : void 0}
action={() => applyDefaultSettings(guild.id)}
/>
);
@ -117,6 +118,7 @@ const makeContextMenuPatch: (shouldAddIcon: boolean) => NavContextMenuPatchCallb
label="Apply NewGuildSettings to Folder"
id="vc-newguildsettings-apply-folder"
icon={shouldAddIcon ? CogWheel : void 0}
leadingAccessory={shouldAddIcon ? { type: "icon", icon: CogWheel } : void 0}
action={async () => {
for (const guildId of folder.guildIds) {
applyDefaultSettings(guildId);

View file

@ -230,6 +230,7 @@ function RoleContextMenu({ guild, roleId, onClose }: { guild: Guild; roleId: str
id={cl("copy-role-id")}
label={getIntlMessage("COPY_ID_ROLE")}
icon={CopyIdIcon}
leadingAccessory={{ type: "icon", icon: CopyIdIcon }}
action={() => copyToClipboard(roleId)}
/>
@ -240,6 +241,7 @@ function RoleContextMenu({ guild, roleId, onClose }: { guild: Guild; roleId: str
id={cl("view-as-role")}
label={getIntlMessage("VIEW_AS_ROLE")}
icon={ViewAsRoleIcon}
leadingAccessory={{ type: "icon", icon: ViewAsRoleIcon }}
action={() => {
onClose();
FluxDispatcher.dispatch({
@ -269,6 +271,7 @@ function UserContextMenu({ userId }: { userId: string; }) {
<Menu.MenuItem
id={cl("copy-user-id")}
label={getIntlMessage("COPY_ID_USER")}
leadingAccessory={{ type: "icon", icon: CopyIdIcon }}
action={() => {
copyToClipboard(userId);
}}

View file

@ -59,13 +59,14 @@ export const settings = definePluginSettings({
},
});
function MenuItem(guildId: string, id?: string, type?: MenuItemParentType) {
function MenuItem(guildId: string, { id, type, withIcon }: { id?: string, type?: MenuItemParentType, withIcon?: boolean; }) {
if (type === MenuItemParentType.User && !GuildMemberStore.isMember(guildId, id!)) return null;
return (
<Menu.MenuItem
id="perm-viewer-permissions"
label="Permissions"
label="View Permissions"
leadingAccessory={withIcon ? { type: "icon", icon: SafetyIcon } : undefined}
action={() => {
const guild = GuildStore.getGuild(guildId);
@ -125,7 +126,7 @@ function MenuItem(guildId: string, id?: string, type?: MenuItemParentType) {
);
}
function makeContextMenuPatch(childId: string | string[], type?: MenuItemParentType): NavContextMenuPatchCallback {
function makeContextMenuPatch(childId: string | string[], type?: MenuItemParentType, withIcon = false): NavContextMenuPatchCallback {
return (children, props) => {
if (
!props ||
@ -139,9 +140,9 @@ function makeContextMenuPatch(childId: string | string[], type?: MenuItemParentT
const group = findGroupChildrenByChildId(childId, children);
const item = match(type)
.with(MenuItemParentType.User, () => MenuItem(props.guildId, props.user.id, type))
.with(MenuItemParentType.Channel, () => MenuItem(props.guild.id, props.channel.id, type))
.with(MenuItemParentType.Guild, () => MenuItem(props.guild.id))
.with(MenuItemParentType.User, () => MenuItem(props.guildId, { id: props.user.id, type, withIcon }))
.with(MenuItemParentType.Channel, () => MenuItem(props.guild.id, { id: props.channel.id, type, withIcon }))
.with(MenuItemParentType.Guild, () => MenuItem(props.guild.id, { withIcon }))
.otherwise(() => null);
if (item == null) return;
@ -214,6 +215,6 @@ export default definePlugin({
"user-context": makeContextMenuPatch("roles", MenuItemParentType.User),
"channel-context": makeContextMenuPatch(["mute-channel", "unmute-channel"], MenuItemParentType.Channel),
"guild-context": makeContextMenuPatch("privacy", MenuItemParentType.Guild),
"guild-header-popout": makeContextMenuPatch("privacy", MenuItemParentType.Guild)
"guild-header-popout": makeContextMenuPatch("privacy", MenuItemParentType.Guild, true)
}
});

View file

@ -18,6 +18,7 @@
import { ChatBarButton, ChatBarButtonFactory } from "@api/ChatButtons";
import { generateId, sendBotMessage } from "@api/Commands";
import { EyeIcon } from "@components/Icons";
import { Devs } from "@utils/constants";
import definePlugin, { IconComponent, StartAt } from "@utils/types";
import { CloudUpload, MessageAttachment } from "@vencord/discord-types";
@ -73,17 +74,12 @@ const getAttachments = async (channelId: string) =>
const PreviewIcon: IconComponent = ({ height = 20, width = 20, className }) => {
return (
<svg
fill="currentColor"
fillRule="evenodd"
<EyeIcon
width={width}
height={height}
className={className}
viewBox="0 0 24 24"
style={{ scale: "1.096", translate: "0 -1px" }}
>
<path d="M22.89 11.7c.07.2.07.4 0 .6C22.27 13.9 19.1 21 12 21c-7.11 0-10.27-7.11-10.89-8.7a.83.83 0 0 1 0-.6C1.73 10.1 4.9 3 12 3c7.11 0 10.27 7.11 10.89 8.7Zm-4.5-3.62A15.11 15.11 0 0 1 20.85 12c-.38.88-1.18 2.47-2.46 3.92C16.87 17.62 14.8 19 12 19c-2.8 0-4.87-1.38-6.39-3.08A15.11 15.11 0 0 1 3.15 12c.38-.88 1.18-2.47 2.46-3.92C7.13 6.38 9.2 5 12 5c2.8 0 4.87 1.38 6.39 3.08ZM15.56 11.77c.2-.1.44.02.44.23a4 4 0 1 1-4-4c.21 0 .33.25.23.44a2.5 2.5 0 0 0 3.32 3.32Z" />
</svg>
/>
);
};

View file

@ -6,7 +6,7 @@
import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/ContextMenu";
import { definePluginSettings, migratePluginSettings } from "@api/Settings";
import { Flex } from "@components/Flex";
import { SearchIcon } from "@components/Icons";
import { Devs } from "@utils/constants";
import definePlugin, { OptionType } from "@utils/types";
import { Menu } from "@webpack/common";
@ -89,6 +89,7 @@ function makeSearchItem(src: string) {
label="Search Text"
key="search-text"
id="vc-search-text"
leadingAccessory={{ type: "icon", icon: SearchIcon }}
>
{Object.keys(Engines).map(engine => {
const key = "vc-search-content-" + engine;
@ -96,20 +97,8 @@ function makeSearchItem(src: string) {
<Menu.MenuItem
key={key}
id={key}
label={
<Flex gap="0.5em" alignItems="center">
<img
style={{
borderRadius: "50%"
}}
aria-hidden="true"
height={16}
width={16}
src={`https://icons.duckduckgo.com/ip3/${new URL(Engines[engine]).hostname}.ico`}
/>
{engine}
</Flex>
}
label={engine}
leadingAccessory={{ type: "image", src: `https://icons.duckduckgo.com/ip3/${new URL(Engines[engine]).hostname}.ico` }}
action={() => search(src, Engines[engine])}
/>
);

View file

@ -17,8 +17,7 @@
*/
import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/ContextMenu";
import { Flex } from "@components/Flex";
import { OpenExternalIcon } from "@components/Icons";
import { OpenExternalIcon, SearchIcon } from "@components/Icons";
import { Devs } from "@utils/constants";
import definePlugin from "@utils/types";
import { Menu } from "@webpack/common";
@ -43,6 +42,7 @@ function makeSearchItem(src: string) {
label="Search Image"
key="search-image"
id="search-image"
leadingAccessory={{ type: "icon", icon: SearchIcon }}
>
{Object.keys(Engines).map((engine, i) => {
const key = "search-image-" + engine;
@ -50,20 +50,8 @@ function makeSearchItem(src: string) {
<Menu.MenuItem
key={key}
id={key}
label={
<Flex alignItems="center" gap="0.5em">
<img
style={{
borderRadius: "50%",
}}
aria-hidden="true"
height={16}
width={16}
src={`https://icons.duckduckgo.com/ip3/${new URL(Engines[engine]).host}.ico`}
/>
{engine}
</Flex>
}
label={engine}
leadingAccessory={{ type: "image", src: `https://icons.duckduckgo.com/ip3/${new URL(Engines[engine]).host}.ico` }}
action={() => search(src, Engines[engine])}
/>
);
@ -71,12 +59,8 @@ function makeSearchItem(src: string) {
<Menu.MenuItem
key="search-image-all"
id="search-image-all"
label={
<Flex alignItems="center" gap="0.5em">
<OpenExternalIcon height={16} width={16} />
All
</Flex>
}
label="All"
leadingAccessory={{ type: "icon", icon: OpenExternalIcon }}
action={() => Object.values(Engines).forEach(e => search(src, e))}
/>
</Menu.MenuItem>

View file

@ -49,6 +49,7 @@ const guildPopoutPatch: NavContextMenuPatchCallback = (children, { guild }: { gu
label="View Reviews"
id="vc-rdb-server-reviews"
icon={OpenExternalIcon}
leadingAccessory={{ type: "icon", icon: OpenExternalIcon }}
action={() => openReviewsModal(guild.id, guild.name, ReviewType.Server)}
/>
);
@ -61,6 +62,7 @@ const userContextPatch: NavContextMenuPatchCallback = (children, { user }: { use
label="View Reviews"
id="vc-rdb-user-reviews"
icon={OpenExternalIcon}
leadingAccessory={{ type: "icon", icon: OpenExternalIcon }}
action={() => openReviewsModal(user.id, user.username, ReviewType.User)}
/>
);

View file

@ -6,6 +6,7 @@
import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/ContextMenu";
import { definePluginSettings } from "@api/Settings";
import { InfoIcon } from "@components/Icons";
import { Devs, EquicordDevs } from "@utils/constants";
import definePlugin, { OptionType } from "@utils/types";
import { Guild } from "@vencord/discord-types";
@ -13,13 +14,14 @@ import { Menu } from "@webpack/common";
import { openGuildInfoModal } from "./GuildInfoModal";
const Patch: NavContextMenuPatchCallback = (children, { guild }: { guild: Guild; }) => {
const makePatch: (showIcon: boolean) => NavContextMenuPatchCallback = showIcon => (children, { guild }: { guild: Guild; }) => {
const group = findGroupChildrenByChildId("privacy", children);
group?.push(
<Menu.MenuItem
id="vc-server-info"
label="Server Info"
leadingAccessory={showIcon ? { type: "icon", icon: InfoIcon } : undefined}
action={() => openGuildInfoModal(guild)}
/>
);
@ -56,8 +58,7 @@ export default definePlugin({
searchTerms: ["guild", "info", "ServerProfile"],
isModified: true,
contextMenus: {
"guild-context": Patch,
"guild-header-popout": Patch
},
settings
"guild-context": makePatch(false),
"guild-header-popout": makePatch(true)
}
});

View file

@ -41,6 +41,7 @@ const messageCtxPatch: NavContextMenuPatchCallback = (children, { message }: { m
id="vc-trans"
label="Translate"
icon={TranslateIcon}
leadingAccessory={{ type: "icon", icon: TranslateIcon }}
action={async () => {
const trans = await translate("received", content);
handleTranslate(message.id, trans);

View file

@ -48,6 +48,7 @@ const messageContextMenuPatch: NavContextMenuPatchCallback = (
label={isEmbedSuppressed ? "Unsuppress Embeds" : "Suppress Embeds"}
color={isEmbedSuppressed ? undefined : "danger"}
icon={isEmbedSuppressed ? ImageVisible : ImageInvisible}
leadingAccessory={{ type: "icon", icon: isEmbedSuppressed ? ImageVisible : ImageInvisible }}
action={() =>
RestAPI.patch({
url: Constants.Endpoints.MESSAGE(channel.id, messageId),

View file

@ -118,13 +118,14 @@ export type VoiceChannelIndicatorProps = {
userId: string;
isMessageIndicator?: boolean;
isProfile?: boolean;
isMessage?: boolean;
isActionButton?: boolean;
shouldHighlight?: boolean;
};
const clickTimers = new Map<string, any>();
export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId, isProfile, isActionButton, shouldHighlight }: VoiceChannelIndicatorProps) => {
export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId, isProfile, isMessage, isActionButton, shouldHighlight }: VoiceChannelIndicatorProps) => {
const channelId = useStateFromStores([VoiceStateStore], () => VoiceStateStore.getVoiceStateForUser(userId)?.channelId);
const { isMuted, isDeaf } = useStateFromStores([VoiceStateStore], () => {
@ -194,7 +195,7 @@ export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId, isProfile, is
isActionButton && shouldHighlight && ActionButtonClasses.highlight,
cl(isProfile && "profile-speaker")
)}
size={isActionButton ? 20 : 16}
size={(isActionButton || isMessage) ? 20 : 16}
/>
)}
</Tooltip>

View file

@ -14,8 +14,9 @@
}
.vc-uvs-profile-speaker {
width: var(--custom-nickname-icon-size);
height: var(--custom-nickname-icon-size);
margin-right: 4px;
transform: translateY(1.3px);
}
.vc-uvs-tooltip-container {

View file

@ -43,7 +43,7 @@ interface GroupDMContextProps {
const settings = definePluginSettings({
format: {
type: OptionType.SELECT,
description: "Choose the image format to use for non animated images. Animated images will always use .gif",
description: "Choose the image format to use for non-animated images. Animated images will always use .webp",
options: [
{
label: "webp",
@ -85,7 +85,7 @@ function openImage({ url, width, height, event }: OpenImageProps) {
const format = url.startsWith("/")
? "png"
: u.searchParams.get("animated") === "true"
? "gif"
? "webp"
: settings.store.format;
u.searchParams.set("size", settings.store.imgSize);
@ -116,6 +116,7 @@ const UserContext: NavContextMenuPatchCallback = (children, { user, guildId }: U
label="View Avatar"
action={() => openAvatar(IconUtils.getUserAvatarURL(user, true))}
icon={ImageIcon}
leadingAccessory={{ type: "icon", icon: ImageIcon }}
/>
{memberAvatar && (
<Menu.MenuItem
@ -128,6 +129,7 @@ const UserContext: NavContextMenuPatchCallback = (children, { user, guildId }: U
canAnimate: true
}))}
icon={ImageIcon}
leadingAccessory={{ type: "icon", icon: ImageIcon }}
/>
)}
{avatarDecoration && (
@ -140,6 +142,7 @@ const UserContext: NavContextMenuPatchCallback = (children, { user, guildId }: U
canAnimate: true
})!)}
icon={ImageIcon}
leadingAccessory={{ type: "icon", icon: ImageIcon }}
/>
)}
</Menu.MenuGroup>
@ -166,6 +169,7 @@ const GuildContext: NavContextMenuPatchCallback = (children, { guild }: GuildCon
})!)
}
icon={ImageIcon}
leadingAccessory={{ type: "icon", icon: ImageIcon }}
/>
) : null}
{banner ? (
@ -176,6 +180,7 @@ const GuildContext: NavContextMenuPatchCallback = (children, { guild }: GuildCon
openBanner(IconUtils.getGuildBannerURL(guild, true)!)
}
icon={ImageIcon}
leadingAccessory={{ type: "icon", icon: ImageIcon }}
/>
) : null}
</Menu.MenuGroup>
@ -194,6 +199,7 @@ const GroupDMContext: NavContextMenuPatchCallback = (children, { channel }: Grou
openAvatar(IconUtils.getChannelIconURL(channel)!)
}
icon={ImageIcon}
leadingAccessory={{ type: "icon", icon: ImageIcon }}
/>
</Menu.MenuGroup>
));

View file

@ -149,6 +149,7 @@ function MakeContextCallback(name: "Guild" | "Role" | "User" | "Channel" | "Mess
label="View Raw"
action={action}
icon={CopyRawIcon}
leadingAccessory={{ type: "icon", icon: CopyRawIcon }}
/>
);
};
@ -167,6 +168,7 @@ const devContextCallback: NavContextMenuPatchCallback = (children, { id }: { id:
label="View Raw"
action={() => openViewRawModal(JSON.stringify(role, null, 4), "Role")}
icon={CopyRawIcon}
leadingAccessory={{ type: "icon", icon: CopyRawIcon }}
/>
);
};

View file

@ -1,21 +1,23 @@
:root {
/* opt out of auto-dark-mode plugins, which break discord css, such as force-dark, dark-reader etc */
color-scheme: only light;
/* force title bar to be same as WCO bar height, regardless of zoom, device pixel ratio or OS */
/* is only set when WCO is defined, otherwise sets to 0 */
--custom-app-top-bar-height: env(titlebar-area-height, 0px) !important;
/* opt out of auto-dark-mode plugins, which break discord css, such as force-dark, dark-reader etc */
color-scheme: only light;
}
/* position trailing titlebar elements alongside WCO */
[class*="bar_"] [class*="trailing_"] {
padding-right: calc(100vw - env(titlebar-area-width, 100%) - env(titlebar-area-x, 0px));
@media all and not (display-mode: browser) {
:root {
/* force title bar to be same as WCO bar height, regardless of zoom, device pixel ratio or OS, is only set when WCO is defined, otherwise sets to 0 */
--custom-app-top-bar-height: env(titlebar-area-height, 0px) !important;
}
/* position trailing titlebar elements alongside WCO */
[class*="bar_"] [class*="trailing_"] {
padding-right: calc(100vw - env(titlebar-area-width, 100%) - env(titlebar-area-x, 0px));
}
}
/* force hide trailing icons when standalone so there's no ugly pixel overflow */
@media all and (display-mode: standalone) {
[class*="bar_"] [class*="trailing_"] {
display: none;
}
[class*="bar_"] [class*="trailing_"] {
display: none;
}
}