chore: update eslint to 9.7.0 and stylelint to 16.7.0

This commit is contained in:
ryan-0324 2024-07-16 22:17:12 -04:00
parent 99d7ed0c08
commit 0c8e91b716
96 changed files with 689 additions and 1932 deletions

View file

@ -58,6 +58,7 @@
"@typescript-eslint/no-non-null-asserted-optional-chain": "error",
"@typescript-eslint/no-unnecessary-condition": "error",
"@typescript-eslint/no-unnecessary-type-assertion": "error",
"@typescript-eslint/no-unused-expressions": "error",
"@typescript-eslint/non-nullable-type-assertion-style": "error",
"@typescript-eslint/prefer-as-const": "error",
"@typescript-eslint/require-await": "error",

View file

@ -1,7 +1,13 @@
{
"extends": "stylelint-config-standard",
"extends": [
"stylelint-config-standard",
"@stylistic/stylelint-config"
],
"plugins": [
"@stylistic/stylelint-plugin"
],
"rules": {
"indentation": 4,
"@stylistic/indentation": 4,
"selector-class-pattern": [
"^[a-z][a-zA-Z0-9]*(-[a-z0-9][a-zA-Z0-9]*)*$",
{

133
eslint.config.mjs Normal file
View file

@ -0,0 +1,133 @@
import stylistic from "@stylistic/eslint-plugin";
import pathAlias from "eslint-plugin-path-alias";
import simpleHeader from "eslint-plugin-simple-header";
import simpleImportSort from "eslint-plugin-simple-import-sort";
import unusedImports from "eslint-plugin-unused-imports";
import tseslint from "typescript-eslint";
export default tseslint.config(
{ ignores: ["browser", "dist", "packages", "src/**/*.?(c|m)js?(x)", "eslint.config.mjs"] },
{
files: ["**/*.?(c|m)[jt]s?(x)"],
languageOptions: {
parser: tseslint.parser,
parserOptions: {
projectService: true,
warnOnUnsupportedTypeScriptVersion: false
}
},
plugins: {
"@stylistic": stylistic,
"@typescript-eslint": tseslint.plugin,
"path-alias": pathAlias,
"simple-header": simpleHeader,
"simple-import-sort": simpleImportSort,
"unused-imports": unusedImports,
},
rules: {
// Since it's only been a month and Vencord has already been stolen
// by random skids who rebranded it to "AlphaCord" and erased all license
// information
"simple-header/header": ["error", {
files: ["scripts/header-new.txt", "scripts/header-old.txt"],
templates: { author: [".*", "Vendicated and contributors"] }
}],
"@stylistic/arrow-parens": ["error", "as-needed"],
"@stylistic/block-spacing": "error",
"@stylistic/eol-last": "error",
"@stylistic/func-call-spacing": "error",
"@stylistic/indent": ["error", 4, {
// Allow both flat and indented ternary expressions
ignoredNodes: [".consequent, .alternate, .trueType, .falseType"],
SwitchCase: 1
}],
"@stylistic/jsx-quotes": "error",
"@stylistic/linebreak-style": "error",
"@stylistic/member-delimiter-style": ["error", { singleline: { requireLast: true } }],
"@stylistic/no-extra-semi": "error",
"@stylistic/no-mixed-spaces-and-tabs": "error",
"@stylistic/no-multi-spaces": "error",
"@stylistic/no-trailing-spaces": "error",
"@stylistic/no-whitespace-before-property": "error",
"@stylistic/object-curly-spacing": ["error", "always"],
"@stylistic/quotes": ["error", "double", { avoidEscape: true }],
"@stylistic/semi": "error",
"@stylistic/semi-spacing": "error",
"@stylistic/semi-style": "error",
"@stylistic/space-before-function-paren": ["error", { named: "never" }],
"@stylistic/space-in-parens": "error",
"@stylistic/spaced-comment": ["error", "always", { markers: ["!"] }],
"@typescript-eslint/array-type": "error",
"@typescript-eslint/await-thenable": "error",
"@typescript-eslint/consistent-generic-constructors": "error",
"@typescript-eslint/consistent-type-assertions": ["error", {
assertionStyle: "as",
objectLiteralTypeAssertions: "allow-as-parameter"
}],
"@typescript-eslint/consistent-type-exports": ["error", {
fixMixedExportsWithInlineTypeSpecifier: true
}],
"@typescript-eslint/consistent-type-imports": ["error", {
disallowTypeAnnotations: false,
fixStyle: "inline-type-imports"
}],
"@typescript-eslint/no-confusing-void-expression": "error",
"@typescript-eslint/no-empty-object-type": "error",
"@typescript-eslint/no-extra-non-null-assertion": "error",
"@typescript-eslint/no-import-type-side-effects": "error",
"@typescript-eslint/no-loss-of-precision": "error",
"@typescript-eslint/no-non-null-asserted-nullish-coalescing": "error",
"@typescript-eslint/no-non-null-asserted-optional-chain": "error",
"@typescript-eslint/no-unnecessary-condition": "error",
"@typescript-eslint/no-unnecessary-type-assertion": "error",
"@typescript-eslint/no-unsafe-function-type": "error",
"@typescript-eslint/no-unused-expressions": "error",
"@typescript-eslint/no-wrapper-object-types": "error",
"@typescript-eslint/non-nullable-type-assertion-style": "error",
"@typescript-eslint/prefer-as-const": "error",
"@typescript-eslint/prefer-destructuring": "error",
"@typescript-eslint/require-await": "error",
"@typescript-eslint/return-await": "error",
"dot-notation": "error",
"eqeqeq": ["error", "always", { null: "ignore" }],
"for-direction": "error",
"no-async-promise-executor": "error",
"no-cond-assign": "error",
"no-constant-condition": ["error", { checkLoops: "none" }],
"no-dupe-else-if": "error",
"no-duplicate-case": "error",
"no-duplicate-imports": "error",
"no-fallthrough": "error",
"no-invalid-regexp": "error",
"no-irregular-whitespace": "error",
"no-misleading-character-class": "error",
"no-prototype-builtins": "error",
"no-regex-spaces": "error",
"no-restricted-globals": ["error", "_", "Diff", "JSX", "React", "ReactDOM"],
"no-restricted-imports": ["error", {
patterns: [{
regex: "^discord-types(/|$)",
message: "Use @vencord/discord-types instead."
}]
}],
"no-restricted-syntax": ["error", "[operator=void]"],
"no-shadow-restricted-names": "error",
"no-unexpected-multiline": "error",
"no-unneeded-ternary": ["error", { defaultAssignment: false }],
"no-unsafe-optional-chaining": "error",
"no-useless-backreference": "error",
"no-useless-computed-key": "error",
"no-useless-escape": ["error", { extra: "i" }],
"operator-assignment": "error",
"path-alias/no-relative": "error",
"prefer-const": "error",
"prefer-object-spread": "error",
"prefer-spread": "error",
"simple-import-sort/exports": "error",
"simple-import-sort/imports": "error",
"unused-imports/no-unused-imports": "error",
"use-isnan": "error",
"yoda": "error",
}
},
);

View file

@ -26,8 +26,8 @@
"generateTypes": "tspc --emitDeclarationOnly --declaration --outDir packages/vencord-types",
"inject": "node scripts/runInstaller.mjs",
"uninject": "node scripts/runInstaller.mjs",
"lint": "eslint . --ext .mjs,.js,.jsx,.mts,.ts,.tsx --ignore-pattern src/userplugins",
"lint-styles": "stylelint \"src/**/*.css\" --ignore-pattern src/userplugins --quiet-deprecation-warnings",
"lint": "eslint . --ignore-pattern src/userplugins",
"lint-styles": "stylelint \"src/**/*.css\" --ignore-pattern src/userplugins",
"lint:fix": "pnpm lint --fix",
"test": "pnpm buildStandalone && pnpm lint && pnpm lint-styles && pnpm testTsc && pnpm generatePluginJson",
"testWeb": "pnpm lint && pnpm buildWeb && pnpm testTsc",
@ -45,6 +45,9 @@
"virtual-merge": "^1.0.1"
},
"devDependencies": {
"@stylistic/eslint-plugin": "^2.3.0",
"@stylistic/stylelint-config": "^1.0.1",
"@stylistic/stylelint-plugin": "^2.1.2",
"@types/chrome": "^0.0.268",
"@types/diff": "^5.2.1",
"@types/html-minifier-terser": "^7.0.2",
@ -53,28 +56,26 @@
"@types/react": "~18.2.79",
"@types/react-dom": "~18.2.25",
"@types/yazl": "^2.4.5",
"@typescript-eslint/eslint-plugin": "^7.16.1",
"@typescript-eslint/parser": "^7.16.1",
"@vencord/discord-types": "workspace:^",
"diff": "^5.2.0",
"discord-types": "^1.3.3",
"esbuild": "^0.23.0",
"eslint": "^8.57.0",
"eslint-import-resolver-alias": "^1.1.2",
"eslint": "^9.7.0",
"eslint-plugin-path-alias": "^2.1.0",
"eslint-plugin-simple-import-sort": "^12.1.1",
"eslint-plugin-unused-imports": "^3.2.0",
"eslint-plugin-unused-imports": "^4.0.0",
"highlight.js": "11.8.0",
"html-minifier-terser": "^7.2.0",
"moment": "2.22.2",
"puppeteer-core": "^22.13.0",
"standalone-electron-types": "^1.0.0",
"stylelint": "^15.11.0",
"stylelint-config-standard": "^33.0.0",
"stylelint": "^16.7.0",
"stylelint-config-standard": "^36.0.1",
"ts-patch": "^3.2.1",
"tsx": "^4.16.2",
"type-fest": "^4.21.0",
"typescript": "^5.5.3",
"typescript-eslint": "^8.0.0-alpha.44",
"typescript-transform-paths": "^3.4.7",
"zip-local": "^0.3.5"
},
@ -82,13 +83,12 @@
"pnpm": {
"patchedDependencies": {
"eslint-plugin-path-alias@2.1.0": "patches/eslint-plugin-path-alias@2.1.0.patch",
"eslint@8.57.0": "patches/eslint@8.57.0.patch"
"eslint@9.7.0": "patches/eslint@9.7.0.patch"
},
"peerDependencyRules": {
"ignoreMissing": [
"eslint-plugin-import",
"eslint"
]
"allowedVersions": {
"eslint": "9"
}
},
"allowedDeprecatedVersions": {
"source-map-resolve": "*",

View file

@ -158,7 +158,7 @@ export default tseslint.config(
},
{
files: ["**/*"],
ignores: ["src/**/*"],
ignores: ["src/**"],
rules: {
"simple-import-sort/imports": ["error", {
groups: [
@ -169,7 +169,7 @@ export default tseslint.config(
}
},
{
files: ["scripts/**/*", "src/**/*"],
files: ["scripts/**", "src/**"],
rules: {
"headers/header-format": ["error", {
source: "string",
@ -188,7 +188,7 @@ export default tseslint.config(
}
},
{
files: ["src/**/*"],
files: ["src/**"],
rules: {
"@typescript-eslint/member-ordering": ["error", {
default: {
@ -243,7 +243,7 @@ export default tseslint.config(
},
{
// https://github.com/import-js/eslint-plugin-import/issues/2414
files: ["src/**/*"],
files: ["src/**"],
ignores: ["src/**/index.ts"],
rules: {
"import/no-unused-modules": ["error", { missingExports: true }],

File diff suppressed because it is too large Load diff

View file

@ -18,9 +18,7 @@
/* eslint-disable no-fallthrough */
// eslint-disable-next-line spaced-comment
/// <reference types="../src/globals.d.ts" />
// eslint-disable-next-line spaced-comment
/// <reference types="../src/modules.d.ts" />
import { readFileSync } from "fs";

View file

@ -12,7 +12,6 @@
"checkJs": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"target": "ESNext"
},

View file

@ -85,9 +85,10 @@ export function _getBadges(args: BadgeUserArgs) {
})
: [{ ...badge, ...args }];
badge.position === BadgePosition.START
? badges.unshift(...b)
: badges.push(...b);
if (badge.position === BadgePosition.START)
badges.unshift(...b);
else
badges.push(...b);
}
}
const donorBadges = (Plugins.BadgeAPI as unknown as typeof import("../plugins/_api/badges").default).getDonorBadges(args.userId);

View file

@ -14,7 +14,7 @@ import { Button, ButtonLooks, ButtonWrapperClasses, Tooltip } from "@webpack/com
import type { HTMLProps, JSX, MouseEventHandler, ReactNode } from "react";
let ChannelTextAreaClasses: Record<"button" | "buttonContainer", string> | undefined;
waitFor(["buttonContainer", "channelTextArea"], m => ChannelTextAreaClasses = m);
waitFor(["buttonContainer", "channelTextArea"], m => { ChannelTextAreaClasses = m; });
export interface ChatBarProps {
channel: ChannelRecord;
@ -24,52 +24,52 @@ export interface ChatBarProps {
analyticsName: string;
attachments: boolean;
autocomplete: {
addReactionShortcut: boolean,
forceChatLayer: boolean,
addReactionShortcut: boolean;
forceChatLayer: boolean;
reactions: boolean;
},
};
commands: {
enabled: boolean;
},
};
drafts: {
type: number,
commandType: number,
type: number;
commandType: number;
autoSave: boolean;
},
};
emojis: {
button: boolean;
},
};
gifs: {
button: boolean,
button: boolean;
allowSending: boolean;
},
};
gifts: {
button: boolean;
},
};
permissions: {
requireSendMessages: boolean;
},
showThreadPromptOnReply: boolean,
};
showThreadPromptOnReply: boolean;
stickers: {
button: boolean,
allowSending: boolean,
button: boolean;
allowSending: boolean;
autoSuggest: boolean;
},
};
users: {
allowMentioning: boolean;
},
};
submit: {
button: boolean,
ignorePreference: boolean,
disableEnterToSubmit: boolean,
clearOnSubmit: boolean,
button: boolean;
ignorePreference: boolean;
disableEnterToSubmit: boolean;
clearOnSubmit: boolean;
useDisabledStylesOnSubmit: boolean;
},
uploadLongMessages: boolean,
};
uploadLongMessages: boolean;
upsellLongMessages: {
iconOnly: boolean;
},
showCharacterCount: boolean,
};
showCharacterCount: boolean;
sedReplace: boolean;
};
}

View file

@ -42,7 +42,7 @@ interface DecoratorProps {
export type Decorator = (props: DecoratorProps) => JSX.Element | null;
type OnlyIn = "guilds" | "dms";
export const decorators = new Map<string, { decorator: Decorator, onlyIn?: OnlyIn; }>();
export const decorators = new Map<string, { decorator: Decorator; onlyIn?: OnlyIn; }>();
export function addDecorator(identifier: string, decorator: Decorator, onlyIn?: OnlyIn) {
decorators.set(identifier, { decorator, onlyIn });

View file

@ -24,7 +24,7 @@ import type { Promisable } from "type-fest";
const MessageEventsLogger = new Logger("MessageEvents", "#e5c890");
export interface MessageObject {
content: string,
content: string;
validNonShortcutEmojis: GuildEmoji[];
invalidEmojis: any[];
tts: boolean;

View file

@ -19,7 +19,7 @@
import { waitFor } from "@webpack";
let NoticesModule: any;
waitFor(m => m.show && m.dismiss && !m.suppressAll, m => NoticesModule = m);
waitFor(m => m.show && m.dismiss && !m.suppressAll, m => { NoticesModule = m; });
export const noticesQueue: any[] = [];
export let currentNotice: any = null;

View file

@ -136,7 +136,7 @@ function NotificationEntry({ data }: { data: PersistentNotificationData; }) {
);
}
export function NotificationLog({ log, pending }: { log: PersistentNotificationData[], pending: boolean; }) {
export function NotificationLog({ log, pending }: { log: PersistentNotificationData[]; pending: boolean; }) {
if (!log.length && !pending)
return (
<div className={cl("container")}>

View file

@ -30,7 +30,7 @@ import plugins from "~plugins";
const logger = new Logger("Settings");
export interface Settings {
autoUpdate: boolean;
autoUpdateNotification: boolean,
autoUpdateNotification: boolean;
useQuickCss: boolean;
enableReactDevtools: boolean;
themeLinks: string[];
@ -250,11 +250,12 @@ export function definePluginSettings<
type UseSettings<T extends object> = ResolveUseSettings<T>[keyof T];
type ResolveUseSettings<T extends object> = {
[Key in keyof T]:
Key extends string
? T[Key] extends Record<string, unknown>
// @ts-ignore "Type instantiation is excessively deep and possibly infinite"
? UseSettings<T[Key]> extends string ? `${Key}.${UseSettings<T[Key]>}` : never
: Key
: never;
[Key in keyof T]: Key extends string
? T[Key] extends Record<string, unknown>
? UseSettings<T[Key]> extends string
// @ts-ignore "Type instantiation is excessively deep and possibly infinite"
? `${Key}.${UseSettings<T[Key]>}`
: never
: Key
: never;
};

View file

@ -12,7 +12,7 @@ const CodeContainerClasses: Record<string, string> = findByPropsLazy("markup", "
/**
* Renders code in a Discord codeblock
*/
export const CodeBlock = (props: { content?: string, lang: string; }) => (
export const CodeBlock = (props: { content?: string; lang: string; }) => (
<div className={CodeContainerClasses.markup}>
{MarkupUtils.defaultRules.codeBlock!.react(props, null, {})}
</div>

View file

@ -30,7 +30,7 @@ interface Props<T = any> {
/** Fallback component to render if an error occurs */
fallback?: ComponentType<PropsWithChildren<{ error: any; message: string; stack: string; }>>;
/** called when an error occurs. The props property is only available if using .wrap */
onError?(data: { error: Error, errorInfo: ErrorInfo, props: T; }): void;
onError?(data: { error: Error; errorInfo: ErrorInfo; props: T; }): void;
/** Custom error message */
message?: string;

View file

@ -3,7 +3,7 @@
width: 32px;
border-radius: 50%;
border: 4px solid var(--background-tertiary);
box-sizing: border-box
box-sizing: border-box;
}
.vc-settings-modal-links {

View file

@ -190,7 +190,12 @@ function ReplacementInput({ replacement, setReplacement, replacementError }: Rep
}
useEffect(
() => { (isFunc ? onChange(replacement) : setError(undefined)); },
() => {
if (isFunc)
onChange(replacement);
else
setError(undefined);
},
[isFunc]
);

View file

@ -134,8 +134,10 @@ const ThemeCard = ({ theme, enabled, onChange, onDelete }: ThemeCardProps) => (
href={`https://discord.gg/${theme.invite}`}
onClick={e => {
e.preventDefault();
theme.invite != null && openInviteModal(theme.invite)
.catch(() => { showToast("Invalid or expired invite"); });
if (theme.invite != null)
openInviteModal(theme.invite).catch(() => {
showToast("Invalid or expired invite");
});
}}
>
Discord Server

View file

@ -77,7 +77,7 @@ interface CommonProps {
repoPending: boolean;
}
const HashLink = ({ repo, hash, disabled = false }: { repo: string, hash: string, disabled?: boolean; }) => (
const HashLink = ({ repo, hash, disabled = false }: { repo: string; hash: string; disabled?: boolean; }) => (
<Link href={`${repo}/commit/${hash}`} disabled={disabled}>
{hash}
</Link>

View file

@ -51,7 +51,7 @@ if (!IS_VANILLA) {
const originalBuild = Menu.buildFromTemplate;
Menu.buildFromTemplate = function (template) {
if (template[0]?.label === "&File") {
const { submenu } = template[0];
const [{ submenu }] = template;
if (Array.isArray(submenu)) {
submenu.push({
label: "Quit (Hidden)",

1
src/modules.d.ts vendored
View file

@ -16,7 +16,6 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
// eslint-disable-next-line spaced-comment
/// <reference types="standalone-electron-types"/>
declare module "~plugins" {

View file

@ -49,9 +49,9 @@ interface RemoteData {
artistArtwork?: string;
}
let cachedRemoteData: { id: string, data: RemoteData; } | { id: string, failures: number; } | null = null;
let cachedRemoteData: { id: string; data: RemoteData; } | { id: string; failures: number; } | null = null;
async function fetchRemoteData({ id, name, artist, album }: { id: string, name: string, artist: string, album: string; }) {
async function fetchRemoteData({ id, name, artist, album }: { id: string; name: string; artist: string; album: string; }) {
if (id === cachedRemoteData?.id) {
if ("data" in cachedRemoteData) return cachedRemoteData.data;
if ("failures" in cachedRemoteData && cachedRemoteData.failures >= 5) return null;

View file

@ -11,7 +11,7 @@ import type { Dispatch, SetStateAction } from "react";
import type { Session } from "../types";
import { RenameModal } from "./RenameModal";
export const RenameButton = ({ session, state }: { session: Session, state: [string, Dispatch<SetStateAction<string>>]; }) => (
export const RenameButton = ({ session, state }: { session: Session; state: [string, Dispatch<SetStateAction<string>>]; }) => (
<Button
look={Button.Looks.LINK}
color={Button.Colors.LINK}

View file

@ -23,7 +23,7 @@ import type { Dispatch, KeyboardEvent, SetStateAction } from "react";
import type { Session } from "../types";
import { getDefaultName, savedSessionsCache, saveSessionsToDataStore } from "../utils";
export function RenameModal({ props, session, state }: { props: ModalProps, session: Session, state: [string, Dispatch<SetStateAction<string>>]; }) {
export function RenameModal({ props, session, state }: { props: ModalProps; session: Session; state: [string, Dispatch<SetStateAction<string>>]; }) {
const [title, setTitle] = state;
const [value, setValue] = useState(savedSessionsCache.get(session.id_hash)?.name ?? "");

View file

@ -107,7 +107,7 @@ export default definePlugin({
);
}, { noop: true }),
renderTimestamp: ErrorBoundary.wrap(({ session, timeLabel }: { session: Session, timeLabel: string; }) => (
renderTimestamp: ErrorBoundary.wrap(({ session, timeLabel }: { session: Session; timeLabel: string; }) => (
<Tooltip
text={session.approx_last_used_time.toLocaleString()}
tooltipClassName={TimestampClasses.timestampTooltip}
@ -120,7 +120,7 @@ export default definePlugin({
</Tooltip>
), { noop: true }),
renderIcon: ErrorBoundary.wrap(({ session, DeviceIcon }: { session: Session, DeviceIcon: ComponentType<any>; }) => {
renderIcon: ErrorBoundary.wrap(({ session, DeviceIcon }: { session: Session; DeviceIcon: ComponentType<any>; }) => {
const PlatformIcon = GetPlatformIcon(session.client_info.platform);
return (

View file

@ -25,7 +25,7 @@ export interface SessionInfo {
platform: string;
location: string;
};
},
};
current?: boolean;
}

View file

@ -17,7 +17,7 @@ type SettingsEntry = { section: string; label: string; };
const cl = classNameFactory("");
let Classes: Record<string, string>;
waitFor(["animating", "baseLayer", "bg", "layer", "layers"], m => Classes = m);
waitFor(["animating", "baseLayer", "bg", "layer", "layers"], m => { Classes = m; });
const settings = definePluginSettings({
disableFade: {

View file

@ -36,14 +36,14 @@ export interface Stream extends ApplicationStream {
}
export interface RTCStream {
region: string,
streamKey: string,
region: string;
streamKey: string;
viewerIds: string[];
}
export interface StreamMetadata {
id: string | null,
pid: number | null,
id: string | null;
pid: number | null;
sourceName: string | null;
}

View file

@ -26,7 +26,7 @@
.client-theme-contrast-warning {
background-color: var(--background-primary);
padding: 0.5rem;
border-radius: .5rem;
border-radius: 0.5rem;
display: flex;
flex-direction: row;
justify-content: space-between;

View file

@ -55,7 +55,7 @@ export default definePlugin({
settings,
contextMenus: {
"expression-picker"(children, { target }: { target: Target }) {
"expression-picker"(children, { target }: { target: Target; }) {
if (target.dataset.type !== "emoji") return;
children.push(

View file

@ -2,7 +2,8 @@
filter: grayscale(1);
}
.vc-dearrow-toggle-on, .vc-dearrow-toggle-off {
.vc-dearrow-toggle-on,
.vc-dearrow-toggle-off {
all: unset;
display: inline;
cursor: pointer;

View file

@ -31,7 +31,7 @@ interface UsersDecorationsState {
export const useUsersDecorationsStore: {
(): UsersDecorationsState;
getState: () => UsersDecorationsState
getState: () => UsersDecorationsState;
subscribe: (handler: (state: UsersDecorationsState) => void) => () => void;
} = proxyLazy(() => zustandCreate((set: any, get: any): UsersDecorationsState => ({
usersDecorations: new Map<string, UserDecorationData>(),

View file

@ -10,8 +10,8 @@ import { React } from "@webpack/common";
import type { ComponentType, HTMLProps, PropsWithChildren } from "react";
type DecorationGridItemComponent = ComponentType<PropsWithChildren<HTMLProps<HTMLDivElement>> & {
onSelect: () => void,
isSelected: boolean,
onSelect: () => void;
isSelected: boolean;
}>;
export let DecorationGridItem: DecorationGridItemComponent;
@ -24,8 +24,8 @@ export const AvatarDecorationModalPreview = LazyComponentWebpack(() => {
type DecorationGridDecorationComponent = ComponentType<HTMLProps<HTMLDivElement> & {
avatarDecoration: AvatarDecorationData;
onSelect: () => void,
isSelected: boolean,
onSelect: () => void;
isSelected: boolean;
}>;
export let DecorationGridDecoration: DecorationGridDecorationComponent;

View file

@ -98,11 +98,12 @@ function initWs(isManual = false) {
logger.info("Connected to WebSocket");
(settings.store.notifyOnAutoConnect || isManual) && showNotification({
title: "Dev Companion Connected",
body: "Connected to WebSocket",
noPersist: true
});
if (settings.store.notifyOnAutoConnect || isManual)
showNotification({
title: "Dev Companion Connected",
body: "Connected to WebSocket",
noPersist: true
});
});
ws.addEventListener("error", e => {

View file

@ -153,7 +153,7 @@ async function doClone(guildId: string, data: Data) {
} catch (e: any) {
let message = "Something went wrong (check console!)";
try {
message = JSON.parse(e.text).message;
({ message } = JSON.parse(e.text));
} catch { }
new Logger("EmoteCloner").error("Failed to clone", data.name, "to", guildId, e);

View file

@ -426,8 +426,8 @@ export default definePlugin({
},
handleGradientThemeSelect(backgroundGradientPresetId: number | undefined, theme: number, original: () => void) {
const premiumType = UserStore.getCurrentUser()?.premiumType ?? 0;
if (premiumType === 2 || backgroundGradientPresetId == null) {
const premiumType = UserStore.getCurrentUser()?.premiumType;
if (premiumType === UserPremiumType.TIER_2 || backgroundGradientPresetId == null) {
original();
return;
}
@ -466,37 +466,41 @@ export default definePlugin({
},
trimContent(content: any[]) {
const firstContent = content[0];
const [firstContent] = content;
if (typeof firstContent === "string") {
content[0] = firstContent.trimStart();
content[0] || content.shift();
if (!content[0]) content.shift();
} else if (typeof firstContent?.props?.children === "string") {
firstContent.props.children = firstContent.props.children.trimStart();
firstContent.props.children || content.shift();
if (!firstContent.props.children) content.shift();
}
const lastIndex = content.length - 1;
const lastContent = content[lastIndex];
if (typeof lastContent === "string") {
content[lastIndex] = lastContent.trimEnd();
content[lastIndex] || content.pop();
if (!content[lastIndex]) content.pop();
} else if (typeof lastContent?.props?.children === "string") {
lastContent.props.children = lastContent.props.children.trimEnd();
lastContent.props.children || content.pop();
if (!lastContent.props.children) content.pop();
}
},
clearEmptyArrayItems(array: any[]) {
clearEmptyArrayItems<T>(array: T[]) {
return array.filter(item => item != null);
},
ensureChildrenIsArray(child: ReactElement) {
if (!Array.isArray(child.props.children)) child.props.children = [child.props.children];
if (!Array.isArray(child.props.children))
child.props.children = [child.props.children];
},
patchFakeNitroEmojisOrRemoveStickersLinks(content: any[], inline: boolean) {
// If content has more than one child or it's a single ReactElement like a header, list or span
if ((content.length > 1 || typeof content[0]?.type === "string") && !settings.store.transformCompoundSentence) return content;
if (
(content.length > 1 || typeof content[0]?.type === "string")
&& !settings.store.transformCompoundSentence
) return content;
let nextIndex = content.length;
@ -509,7 +513,8 @@ export default definePlugin({
url = new URL(child.props.href);
} catch { }
const emojiName = EmojiStore.getCustomEmojiById(fakeNitroMatch[1])?.name ?? url?.searchParams.get("name") ?? "FakeNitroEmoji";
const emojiName = EmojiStore.getCustomEmojiById(fakeNitroMatch[1])?.name
?? url?.searchParams.get("name") ?? "FakeNitroEmoji";
return MarkupUtils.defaultRules.customEmoji!.react({
jumboable: !inline && content.length === 1 && typeof content[0].type !== "string",
@ -603,10 +608,16 @@ export default definePlugin({
if (settings.store.transformCompoundSentence) itemsToMaybePush.push(...contentItems);
else if (contentItems.length === 1) itemsToMaybePush.push(contentItems[0]!);
itemsToMaybePush.push(...message.attachments.filter(attachment => attachment.content_type === "image/gif").map(attachment => attachment.url));
itemsToMaybePush.push(...message.attachments
.filter(attachment => attachment.content_type === "image/gif")
.map(attachment => attachment.url));
for (const item of itemsToMaybePush) {
if (!settings.store.transformCompoundSentence && !item.startsWith("http") && !hyperLinkRegex.test(item)) continue;
if (
!settings.store.transformCompoundSentence
&& !item.startsWith("http")
&& !hyperLinkRegex.test(item)
) continue;
const imgMatch = item.match(fakeNitroStickerRegex);
if (imgMatch) {
@ -615,7 +626,8 @@ export default definePlugin({
url = new URL(item);
} catch { }
const stickerName = StickerStore.getStickerById(imgMatch[1]!)?.name ?? url?.searchParams.get("name") ?? "FakeNitroSticker";
const stickerName = StickerStore.getStickerById(imgMatch[1]!)?.name
?? url?.searchParams.get("name") ?? "FakeNitroSticker";
stickers.push({
format_type: StickerFormat.PNG,
id: imgMatch[1],
@ -693,19 +705,19 @@ export default definePlugin({
return link.target && fakeNitroEmojiRegex.test(link.target);
},
addFakeNotice(type: FakeNoticeType, node: ReactNode[], fake: boolean) {
addFakeNotice(type: FakeNoticeType, node: ReactNode, fake: boolean) {
if (!fake) return node;
node = Array.isArray(node) ? node : [node];
const nodeArray: ReactNode[] = Array.isArray(node) ? node : [node];
switch (type) {
case FakeNoticeType.Sticker: {
node.push(" This is a FakeNitro sticker and renders like a real sticker only for you. Appears as a link to non-plugin users.");
nodeArray.push(" This is a FakeNitro sticker and renders like a real sticker only for you. Appears as a link to non-plugin users.");
return node;
}
case FakeNoticeType.Emoji: {
node.push(" This is a FakeNitro emoji and renders like a real emoji only for you. Appears as a link to non-plugin users.");
nodeArray.push(" This is a FakeNitro emoji and renders like a real emoji only for you. Appears as a link to non-plugin users.");
return node;
}

View file

@ -53,10 +53,10 @@ interface Instance {
resultType?: string;
};
props: {
favCopy: Gif[],
favCopy: Gif[];
favorites: Gif[],
},
favorites: Gif[];
};
forceUpdate: () => void;
}

View file

@ -34,7 +34,7 @@ export default definePlugin({
}
}
],
isGuildOwner(props: { user?: UserRecord, channel?: ChannelRecord, isOwner: boolean, guildId?: string; }) {
isGuildOwner(props: { user?: UserRecord; channel?: ChannelRecord; isOwner: boolean; guildId?: string; }) {
if (!props.user?.id) return props.isOwner;
if (props.channel?.type === ChannelType.GROUP_DM)
return props.isOwner;

View file

@ -70,7 +70,7 @@ function greet(channel: ChannelRecord, message: MessageRecord, stickers: string[
}
function GreetMenu({ channel, message }: { message: MessageRecord, channel: ChannelRecord; }) {
function GreetMenu({ channel, message }: { message: MessageRecord; channel: ChannelRecord; }) {
const s = settings.use(["greetMode", "multiGreetChoices"]);
const { greetMode, multiGreetChoices = [] } = s;
@ -172,7 +172,7 @@ export default definePlugin({
pickSticker(
event: UIEvent,
props: {
channel: ChannelRecord,
channel: ChannelRecord;
message: MessageRecord & { deleted?: boolean; };
}
) {

View file

@ -303,7 +303,7 @@ export default definePlugin({
return true;
},
renderToggleGameActivityButton: (props: { id?: string; name: string, exePath: string; }, nowPlaying: boolean) => (
renderToggleGameActivityButton: (props: { id?: string; name: string; exePath: string; }, nowPlaying: boolean) => (
<ErrorBoundary noop>
<div style={{ marginLeft: 12, zIndex: 0 }}>
{ToggleActivityComponent({ id: props.id ?? props.exePath, name: props.name, type: ActivitiesTypes.Game }, nowPlaying)}

View file

@ -25,13 +25,13 @@ import { settings } from "../index";
import { waitFor } from "../utils/waitFor";
interface Vec2 {
x: number,
x: number;
y: number;
}
export interface MagnifierProps {
zoom: number;
size: number,
size: number;
instance: any;
}

View file

@ -261,7 +261,7 @@ export default definePlugin({
stop() {
disableStyle(styles);
// so componenetWillUnMount gets called if Magnifier component is still alive
this.root && this.root.unmount();
if (this.root) this.root.unmount();
this.element?.remove();
}
});

View file

@ -18,7 +18,7 @@
border-radius: 0;
}
.vc-imgzoom-nearest-neighbor>img {
.vc-imgzoom-nearest-neighbor > img {
image-rendering: pixelated;
/* https://googlechrome.github.io/samples/image-rendering-pixelated/index.html */

View file

@ -40,7 +40,7 @@ export const OnlineMemberCountStore = proxyLazy(() => {
}
return new OnlineMemberCountStore(FluxDispatcher, {
GUILD_MEMBER_LIST_UPDATE({ guildId, groups }: { guildId: string, groups: { count: number; id: string; }[]; }) {
GUILD_MEMBER_LIST_UPDATE({ guildId, groups }: { guildId: string; groups: { count: number; id: string; }[]; }) {
onlineMemberMap.set(
guildId,
groups.reduce((total, curr) => total + (curr.id === StatusType.OFFLINE ? 0 : curr.count), 0)

View file

@ -25,7 +25,7 @@ export default definePlugin({
}
}],
renderUsername: ErrorBoundary.wrap((props: { user?: UserRecord, username: string; }) => {
renderUsername: ErrorBoundary.wrap((props: { user?: UserRecord; username: string; }) => {
const { user, username } = props;
const [isHovering, setIsHovering] = useState(false);

View file

@ -18,9 +18,9 @@ type Fill = [FillValue, FillValue, FillValue];
type DiffKey = keyof Diff;
interface Diff {
days: number,
hours: number,
minutes: number,
days: number;
hours: number;
minutes: number;
seconds: number;
milliseconds: number;
}
@ -172,7 +172,7 @@ export default definePlugin({
Icon({ delta, fill, props }: {
delta: string | null;
fill: Fill,
fill: Fill;
props: {
onClick: () => void;
onMouseEnter: () => void;

View file

@ -255,7 +255,7 @@ export default definePlugin({
},
},
handleDelete(channelMessages: ChannelMessages | null | undefined, data: { ids: string[], id: string; mlDeleted?: boolean; }, isBulk: boolean) {
handleDelete(channelMessages: ChannelMessages | null | undefined, data: { ids: string[]; id: string; mlDeleted?: boolean; }, isBulk: boolean) {
try {
if (channelMessages == null || (!isBulk && !channelMessages.has(data.id)))
return channelMessages;

View file

@ -2,8 +2,9 @@
display: none;
}
.messagelogger-deleted
:is(
/* https://github.com/stylelint-stylistic/stylelint-stylistic/issues/30 */
/* stylelint-disable @stylistic/indentation */
.messagelogger-deleted:is(
video,
.emoji,
[data-type="sticker"],
@ -11,6 +12,7 @@
.messagelogger-deleted-attachment,
[class|="inlineMediaEmbed"]
) {
/* stylelint-enable @stylistic/indentation */
filter: grayscale(1) !important;
transition: 150ms filter ease-in-out;
@ -19,8 +21,9 @@
}
}
.messagelogger-deleted
:is(
/* https://github.com/stylelint-stylistic/stylelint-stylistic/issues/30 */
/* stylelint-disable @stylistic/indentation */
.messagelogger-deleted:is(
video,
.emoji,
[data-type="sticker"],
@ -28,6 +31,7 @@
.messagelogger-deleted-attachment,
[class|="inlineMediaEmbed"]
):hover {
/* stylelint-enable @stylistic/indentation */
filter: grayscale(0) !important;
}

View file

@ -61,7 +61,7 @@ const computePermissions: (options: {
excludeGuildPermissions?: boolean /* = false */;
}) => bigint = findByCodeLazy(".getCurrentUser()", ".computeLurkerPermissionsAllowList()");
const Tag: RC<{ type?: number, className?: string, useRemSizes?: boolean; }> & { Types: Record<string, number>; }
const Tag: RC<{ type?: number; className?: string; useRemSizes?: boolean; }> & { Types: Record<string, number>; }
= findLazy(m => m.Types?.[0] === "BOT");
const isWebhook = (message: MessageRecord | undefined, user: UserRecord) => !!message?.webhookId && user.isNonUserBot();
@ -332,9 +332,9 @@ export default definePlugin({
getTag({
message, user, channelId, origType, location, channel
}: {
message?: MessageRecord,
user?: UserRecord,
channel?: ChannelRecord,
message?: MessageRecord;
user?: UserRecord;
channel?: ChannelRecord;
channelId?: string;
origType?: number;
location: "chat" | "not-chat";

View file

@ -76,7 +76,7 @@ export default definePlugin({
isBotOrMe: (user: UserRecord) => user.bot || user.id === UserStore.getCurrentUser()!.id,
renderMutualGDMs: ErrorBoundary.wrap(({ user, onClose }: { user: UserRecord, onClose: () => void; }) => {
renderMutualGDMs: ErrorBoundary.wrap(({ user, onClose }: { user: UserRecord; onClose: () => void; }) => {
const entries = ChannelStore.getSortedPrivateChannels()
.filter((channel): channel is GroupDMChannelRecord =>
channel.isGroupDM()

View file

@ -78,7 +78,7 @@ const settings = definePluginSettings({
});
const makeContextMenuPatch = (shouldAddIcon: boolean) =>
((children, { guild }: { guild?: GuildRecord, onClose: () => void; }) => {
((children, { guild }: { guild?: GuildRecord; onClose: () => void; }) => {
if (!guild) return;
const group = findGroupChildrenByChildId("privacy", children);

View file

@ -160,10 +160,10 @@
width: -moz-fit-content;
width: fit-content;
height: 24px;
padding: 4px
padding: 4px;
}
.custom-profile-theme .vc-permviewer-role-button {
background: rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-6));
border-color: var(--profile-body-border-color)
background: rgb(var(--bg-overlay-color) / var(--bg-overlay-opacity-6));
border-color: var(--profile-body-border-color);
}

View file

@ -23,8 +23,8 @@ import { DEFAULT_CHUNK_SIZE } from "./constants";
import { canMoveCategory, canMoveCategoryInDirection, categories, type Category, categoryLen, collapseCategory, getAllUncollapsedChannels, getSections, init, isPinned, moveCategory, removeCategory } from "./data";
interface ChannelComponentProps {
children: ReactNode,
channel: ChannelRecord,
children: ReactNode;
channel: ChannelRecord;
selected: boolean;
}

View file

@ -6,7 +6,7 @@
text-transform: uppercase;
font-size: 12px;
line-height: 16px;
letter-spacing: .02em;
letter-spacing: 0.02em;
font-family: var(--font-display);
font-weight: 600;
flex: 1 1 auto;
@ -29,7 +29,7 @@
width: 16px;
height: 16px;
color: var(--interactive-normal);
transform: rotate(90deg)
transform: rotate(90deg);
}
.vc-pindms-collapsed .vc-pindms-collapse-icon {

View file

@ -71,7 +71,7 @@ const Icons = {
const StatusUtils = findByPropsLazy("useStatusFillColor", "StatusTypes");
const PlatformIcon = ({ platform, status, small }: { platform: ClientType, status: StatusType; small: boolean; }) => {
const PlatformIcon = ({ platform, status, small }: { platform: ClientType; status: StatusType; small: boolean; }) => {
const tooltip = platform === ClientType.EMBEDDED
? "Console"
: platform[0]!.toUpperCase() + platform.slice(1);

View file

@ -28,7 +28,7 @@ const UploadAttachmentStore: FluxStore & Record<string, any> = findStoreLazy("Up
const getDraft = (channelId: string) => DraftStore.getDraft(channelId, DraftType.CHANNEL_MESSAGE);
const getImageBox = (url: string): Promise<{ width: number, height: number; } | null> =>
const getImageBox = (url: string): Promise<{ width: number; height: number; } | null> =>
new Promise(res => {
const img = new Image();
img.onload = () => {

View file

@ -149,11 +149,11 @@ async function bulkFetchPronouns(ids: string[]): Promise<PronounsResponse> {
const SpecialCodes = new Set(["any", "ask", "avoid", "other", "unspecified"]);
export function extractPronouns(pronounSet?: { [locale: string]: PronounCode[] }): string {
export function extractPronouns(pronounSet?: { [locale: string]: PronounCode[]; }): string {
if (!pronounSet || !pronounSet.en) return PronounMapping.unspecified;
// PronounDB returns an empty set instead of {sets: {en: ["unspecified"]}}.
const pronouns = pronounSet.en;
const { pronounsFormat } = Settings.plugins.PronounDB as { pronounsFormat: PronounsFormat, enabled: boolean; };
const { pronounsFormat } = Settings.plugins.PronounDB as { pronounsFormat: PronounsFormat; enabled: boolean; };
if (pronouns.length === 1) {
// For capitalized pronouns or special codes (any, ask, avoid), we always return the normal (capitalized) string

View file

@ -29,14 +29,14 @@ export interface PronounsResponse {
[id: string]: {
sets?: {
[locale: string]: PronounCode[];
}
}
};
};
}
export interface CachePronouns {
sets?: {
[locale: string]: PronounCode[];
}
};
}
export type PronounCode = keyof typeof PronounMapping;

View file

@ -44,7 +44,7 @@ function ReplyTimestamp({
referencedMessage,
baseMessage,
}: {
referencedMessage: ReferencedMessage,
referencedMessage: ReferencedMessage;
baseMessage: MessageRecord;
}) {
if (referencedMessage.state !== ReferencedMessageState.LOADED) return null;

View file

@ -83,18 +83,18 @@ export interface ReviewDBCurrentUser extends ReviewDBUser {
}
export interface ReviewAuthor {
id: number,
discordID: string,
username: string,
profilePhoto: string,
id: number;
discordID: string;
username: string;
profilePhoto: string;
badges: Badge[];
}
export interface Review {
comment: string,
id: number,
star: number,
sender: ReviewAuthor,
comment: string;
id: number;
star: number;
sender: ReviewAuthor;
timestamp: number;
type?: ReviewType;
}

View file

@ -51,7 +51,7 @@ const guildPopoutPatch = ((children, { guild }: { guild?: GuildRecord; onClose:
);
}) satisfies NavContextMenuPatchCallback;
const userContextPatch = ((children, { user }: { user?: UserRecord, onClose(): void; }) => {
const userContextPatch = ((children, { user }: { user?: UserRecord; onClose(): void; }) => {
if (user)
children.push(
<Menu.MenuItem

View file

@ -78,9 +78,10 @@ export default definePlugin({
// idk if this is good for performance but it doesnt seem to be a problem in my experience
DataStore.update("summaries-data", summaries => {
summaries ??= {};
summaries[data.channel_id]
? summaries[data.channel_id].unshift(...incomingSummaries)
: (summaries[data.channel_id] = incomingSummaries);
if (summaries[data.channel_id])
summaries[data.channel_id].unshift(...incomingSummaries);
else
summaries[data.channel_id] = incomingSummaries;
if (summaries[data.channel_id].length > 50)
summaries[data.channel_id] = summaries[data.channel_id].slice(0, 50);

View file

@ -54,7 +54,7 @@ type Format = typeof Formats[number];
const cl = classNameFactory("vc-st-");
function PickerModal({ rootProps, close }: { rootProps: ModalProps, close(): void; }) {
function PickerModal({ rootProps, close }: { rootProps: ModalProps; close(): void; }) {
const [value, setValue] = useState<string>();
const [format, setFormat] = useState<Format>("");
const time = Math.round((new Date(value!).getTime() || Date.now()) / 1000);

View file

@ -28,7 +28,7 @@ export interface Language {
name: string;
id: string;
devicon?: string;
grammarUrl: string,
grammarUrl: string;
grammar?: ILanguageRegistration["grammar"];
scopeName: string;
aliases?: string[];

View file

@ -21,8 +21,8 @@ import type { Dispatch, SetStateAction } from "react";
type Shiki = typeof import("../api/shiki").shiki;
interface ThemeState {
id: Shiki["currentThemeUrl"],
theme: Shiki["currentTheme"],
id: Shiki["currentThemeUrl"];
theme: Shiki["currentTheme"];
}
const currentTheme: ThemeState = {

View file

@ -7,8 +7,8 @@ async function handleClick() {
}
export const Example: FC<{
real: boolean,
shigged?: number,
real: boolean;
shigged?: number;
}> = ({ real, shigged }) => (
<>
<p>{`Shigg${real ? `ies${shigged === 0x1B ? "t" : ""}` : "y"}`}</p>

View file

@ -29,8 +29,8 @@ export const shouldUseHljs = ({
lang,
tryHljs,
}: {
lang: HighlighterProps["lang"],
tryHljs: HljsSetting,
lang: HighlighterProps["lang"];
tryHljs: HljsSetting;
}) => {
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
const hljsLang = lang ? hljs?.getLanguage?.(lang) : null;

View file

@ -95,7 +95,7 @@ const profilePanelComponent = ErrorBoundary.wrap(
{ noop: true }
);
function ConnectionsComponent({ id, theme, simplified }: { id: string, theme: string, simplified?: boolean; }) {
function ConnectionsComponent({ id, theme, simplified }: { id: string; theme: string; simplified?: boolean; }) {
const profile = UserProfileStore.getUserProfile(id);
if (!profile)
return null;
@ -131,7 +131,7 @@ function ConnectionsComponent({ id, theme, simplified }: { id: string, theme: st
);
}
function CompactConnectionComponent({ connection, theme }: { connection: ProfileConnectedAccountData, theme: string; }) {
function CompactConnectionComponent({ connection, theme }: { connection: ProfileConnectedAccountData; theme: string; }) {
const platform = Platforms.get(useLegacyPlatformType(connection.type));
const url = platform.getPlatformUserUrl?.(connection);

View file

@ -162,7 +162,7 @@ function SeekBar() {
const [position, setPosition] = useState<number>(storePosition);
// eslint-disable-next-line consistent-return
useEffect(() => {
if (isPlaying && !isSettingPosition) {
setPosition(SpotifyStore.position);
@ -359,7 +359,7 @@ export function Player() {
const [shouldHide, setShouldHide] = useState(false);
// Hide player after 5 minutes of inactivity
// eslint-disable-next-line consistent-return
useEffect(() => {
setShouldHide(false);
if (!isPlaying) {

View file

@ -47,10 +47,10 @@ export interface Track {
interface PlayerState {
accountId: string;
track: Track | null;
volumePercent?: number,
isPlaying?: boolean,
repeat: boolean,
position?: number,
volumePercent?: number;
isPlaying?: boolean;
repeat: boolean;
position?: number;
context?: any;
device?: Device;

View file

@ -38,7 +38,7 @@ const Dismiss = ({ onDismiss }: { onDismiss: () => void; }) => (
</button>
);
export function TranslationAccessory({ message }: { message: MessageRecord & { vencordEmbeddedBy?: string[] }; }) {
export function TranslationAccessory({ message }: { message: MessageRecord & { vencordEmbeddedBy?: string[]; }; }) {
const [translation, setTranslation] = useState<TranslationValue>();
useEffect(() => {

View file

@ -42,7 +42,7 @@ const settings = definePluginSettings({
}
});
export const buildSeveralUsers = ({ a, b, count }: { a: string, b: string, count: number; }) => [
export const buildSeveralUsers = ({ a, b, count }: { a: string; b: string; count: number; }) => [
<strong key="0">{a}</strong>,
", ",
<strong key="1">{b}</strong>,

View file

@ -1,4 +1,4 @@
.vc-uvs-button>div {
.vc-uvs-button > div {
white-space: normal !important;
}
@ -21,7 +21,7 @@
margin-bottom: 0 !important;
}
.vc-uvs-popout-margin-self>[class^="section"] {
.vc-uvs-popout-margin-self > [class^="section"] {
padding-top: 0;
padding-bottom: 12px;
}

View file

@ -18,7 +18,7 @@ const enum ReferencedMessageState {
}
interface Reply {
baseAuthor: UserRecord,
baseAuthor: UserRecord;
baseMessage: MessageRecord;
channel: ChannelRecord;
referencedMessage: { state: ReferencedMessageState; };

View file

@ -146,7 +146,7 @@ function updateStatuses(type: string, { deaf, mute, selfDeaf, selfMute, userId,
*/
function playSample(tempSettings: any, type: string) {
const settings = Object.assign({}, Settings.plugins.VcNarrator, tempSettings);
const settings = { ...Settings.plugins.VcNarrator, ...tempSettings };
const me = UserStore.getCurrentUser()!;
const currGuildId = SelectedGuildStore.getGuildId();

View file

@ -1,16 +1,16 @@
.vc-toolbox-btn,
.vc-toolbox-btn>svg {
.vc-toolbox-btn > svg {
-webkit-app-region: no-drag;
}
.vc-toolbox-btn>svg {
.vc-toolbox-btn > svg {
color: var(--interactive-normal);
}
.vc-toolbox-btn[class*="selected"]>svg {
.vc-toolbox-btn[class*="selected"] > svg {
color: var(--interactive-active);
}
.vc-toolbox-btn:hover>svg {
.vc-toolbox-btn:hover > svg {
color: var(--interactive-hover);
}

View file

@ -135,7 +135,7 @@ function MakeContextCallback(name: "Guild" | "User" | "Channel"): NavContextMenu
if (!Array.isArray(p.children))
p.children = [p.children];
children = p.children;
({ children } = p);
}
children.splice(-1, 0,

View file

@ -81,8 +81,8 @@ export default definePlugin({
});
type AudioMetadata = {
waveform: string,
duration: number,
waveform: string;
duration: number;
};
const EMPTY_META: AudioMetadata = {

View file

@ -287,7 +287,7 @@ export default definePlugin({
},
async paste() {
const clip = (await navigator.clipboard.read())[0];
const [clip] = await navigator.clipboard.read();
if (!clip) return;
const data = new DataTransfer();

View file

@ -9,11 +9,11 @@ import type { LiteralUnion } from "type-fest";
// Resolves a possibly nested prop in the form of "some.nested.prop" to type of T.some.nested.prop
type ResolvePropDeep<T, P> = P extends `${infer Pre}.${infer Suf}`
? Pre extends keyof T
? ResolvePropDeep<T[Pre], Suf>
: any
? ResolvePropDeep<T[Pre], Suf>
: any
: P extends keyof T
? T[P]
: any;
? T[P]
: any;
interface SettingsStoreOptions {
readOnly?: boolean;
@ -26,6 +26,7 @@ interface SettingsStoreOptions {
}
// merges the SettingsStoreOptions type into the class
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
export interface SettingsStore<T extends object> extends SettingsStoreOptions { }
/**

View file

@ -32,5 +32,5 @@ document.addEventListener("DOMContentLoaded", () => {
document.head.append(Object.assign(document.createElement("style"), {
textContent: styleStr,
id: "vencord-margins"
})), { once: true };
});
}));
}, { once: true });

View file

@ -82,11 +82,11 @@ interface AwaiterOpts<T> {
export function useAwaiter<T>(factory: () => Promise<T>): AwaiterRes<T | null>;
export function useAwaiter<T>(factory: () => Promise<T>, providedOpts: AwaiterOpts<T>): AwaiterRes<T>;
export function useAwaiter<T>(factory: () => Promise<T>, providedOpts?: AwaiterOpts<T | null>): AwaiterRes<T | null> {
const opts: AwaiterOpts<T | null> = Object.assign({
const opts: AwaiterOpts<T | null> = {
fallbackValue: null,
deps: [],
onError: null,
}, providedOpts);
...providedOpts
};
const [state, setState] = useState({
value: opts.fallbackValue,
error: null,
@ -109,7 +109,7 @@ export function useAwaiter<T>(factory: () => Promise<T>, providedOpts?: AwaiterO
opts.onError?.(error);
});
return () => { (isAlive = false); };
return () => { isAlive = false; };
}, opts.deps);
return [state.value, state.error, state.pending];

View file

@ -81,7 +81,7 @@ export interface PluginDef {
* These will automatically be enabled and loaded before your plugin
* Common examples are CommandsAPI, MessageEventsAPI...
*/
dependencies?: string[],
dependencies?: string[];
/**
* Whether this plugin is required and forcefully enabled
*/
@ -98,7 +98,7 @@ export interface PluginDef {
* When to call the start() method
* @default StartAt.WebpackReady
*/
startAt?: StartAt,
startAt?: StartAt;
/**
* Which parts of the plugin can be tested by the reporter. Defaults to all parts
*/
@ -170,8 +170,9 @@ export const enum OptionType {
export type SettingsDefinition = Record<string, PluginSettingDef>;
export type SettingsChecks<D extends SettingsDefinition> = {
[K in keyof D]?: D[K] extends PluginSettingComponentDef ? IsDisabled<DefinedSettings<D>> :
(IsDisabled<DefinedSettings<D>> & IsValid<PluginSettingType<D[K]>, DefinedSettings<D>>);
[K in keyof D]?: D[K] extends PluginSettingComponentDef
? IsDisabled<DefinedSettings<D>>
: (IsDisabled<DefinedSettings<D>> & IsValid<PluginSettingType<D[K]>, DefinedSettings<D>>);
};
export type PluginSettingDef = (
@ -328,7 +329,7 @@ export interface DefinedSettings<
export type PartialExcept<T, R extends keyof T> = Partial<T> & Required<Pick<T, R>>;
export type IpcRes<V = any> = { ok: true; value: V; } | { ok: false, error: any; };
export type IpcRes<V = any> = { ok: true; value: V; } | { ok: false; error: any; };
/* -------------------------------------------- */
/* Legacy Options Types */
@ -352,6 +353,8 @@ export type PluginOptionComponent = PluginSettingComponentDef & PluginSettingCom
export type PluginNative<PluginExports extends Record<string, (event: Electron.IpcMainInvokeEvent, ...args: any[]) => any>> = {
[key in keyof PluginExports]:
PluginExports[key] extends (event: Electron.IpcMainInvokeEvent, ...args: infer Args) => infer Return
? (...args: Args) => Return extends Promise<any> ? Return : Promise<Return>
: never;
? (...args: Args) => Return extends Promise<any>
? Return
: Promise<Return>
: never;
};

View file

@ -23,10 +23,10 @@ import type * as t from "./types/components";
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
export let Forms = {} as {
FormTitle: t.FormTitle,
FormSection: t.FormSection,
FormDivider: t.FormDivider,
FormText: t.FormText,
FormTitle: t.FormTitle;
FormSection: t.FormSection;
FormDivider: t.FormDivider;
FormText: t.FormText;
};
export let Card: t.Card;

View file

@ -23,7 +23,7 @@ import type * as t from "./types/menu";
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
export let Menu = {} as t.Menu;
waitFor(["MenuItem", "MenuSliderControl"], m => Menu = m);
waitFor(["MenuItem", "MenuSliderControl"], m => { Menu = m; });
export const ContextMenuApi: t.ContextMenuApi = mapMangledModuleLazy('type:"CONTEXT_MENU_OPEN', {
closeContextMenu: filters.byCode("CONTEXT_MENU_CLOSE"),

View file

@ -55,49 +55,49 @@ export const useStateFromStoresObject: Stores.UseStateFromStoresObjectHook = pro
});
export let ChannelStore: Stores.ChannelStore;
waitForStore("ChannelStore", m => ChannelStore = m);
waitForStore("ChannelStore", m => { ChannelStore = m; });
export let DraftStore: Stores.DraftStore;
waitForStore("DraftStore", s => DraftStore = s);
waitForStore("DraftStore", s => { DraftStore = s; });
export let EmojiStore: Stores.EmojiStore;
waitForStore("EmojiStore", m => EmojiStore = m);
waitForStore("EmojiStore", m => { EmojiStore = m; });
export let GuildChannelStore: Stores.GuildChannelStore;
waitForStore("GuildChannelStore", m => GuildChannelStore = m);
waitForStore("GuildChannelStore", m => { GuildChannelStore = m; });
export let GuildMemberStore: Stores.GuildMemberStore;
waitForStore("GuildMemberStore", m => GuildMemberStore = m);
waitForStore("GuildMemberStore", m => { GuildMemberStore = m; });
export let GuildStore: Stores.GuildStore;
waitForStore("GuildStore", m => GuildStore = m);
waitForStore("GuildStore", m => { GuildStore = m; });
export let MessageStore: Stores.MessageStore;
waitForStore("MessageStore", m => MessageStore = m);
waitForStore("MessageStore", m => { MessageStore = m; });
export let PermissionStore: Stores.PermissionStore;
waitForStore("PermissionStore", m => PermissionStore = m);
waitForStore("PermissionStore", m => { PermissionStore = m; });
export let PresenceStore: Stores.PresenceStore;
waitForStore("PresenceStore", m => PresenceStore = m);
waitForStore("PresenceStore", m => { PresenceStore = m; });
export let ReadStateStore: Stores.ReadStateStore;
waitForStore("ReadStateStore", m => ReadStateStore = m);
waitForStore("ReadStateStore", m => { ReadStateStore = m; });
export let RelationshipStore: Stores.RelationshipStore;
waitForStore("RelationshipStore", m => RelationshipStore = m);
waitForStore("RelationshipStore", m => { RelationshipStore = m; });
export let SelectedChannelStore: Stores.SelectedChannelStore;
waitForStore("SelectedChannelStore", m => SelectedChannelStore = m);
waitForStore("SelectedChannelStore", m => { SelectedChannelStore = m; });
export let SelectedGuildStore: Stores.SelectedGuildStore;
waitForStore("SelectedGuildStore", m => SelectedGuildStore = m);
waitForStore("SelectedGuildStore", m => { SelectedGuildStore = m; });
export let UserProfileStore: Stores.UserProfileStore;
waitForStore("UserProfileStore", m => UserProfileStore = m);
waitForStore("UserProfileStore", m => { UserProfileStore = m; });
export let UserStore: Stores.UserStore;
waitForStore("UserStore", s => UserStore = s);
waitForStore("UserStore", m => { UserStore = m; });
export let WindowStore: Stores.WindowStore;
waitForStore("WindowStore", m => WindowStore = m);
waitForStore("WindowStore", m => { WindowStore = m; });

View file

@ -17,8 +17,8 @@
*/
export interface ImageModalClasses {
image: string,
modal: string,
image: string;
modal: string;
}
export interface ButtonWrapperClasses {

View file

@ -419,7 +419,7 @@ export type Popout = ComponentType<{
export type Dialog = ComponentType<JSX.IntrinsicElements["div"]>;
type Resolve = (data: { theme: "light" | "dark", saturation: number; }) => {
type Resolve = (data: { theme: "light" | "dark"; saturation: number; }) => {
hex(): string;
hsl(): string;
int(): number;
@ -445,7 +445,7 @@ export type MaskedLink = ComponentType<PropsWithChildren<{
href: string;
rel?: string;
target?: string;
title?: string,
title?: string;
className?: string;
tabIndex?: number;
onClick?(): void;

View file

@ -66,11 +66,11 @@ export interface Menu {
interactive?: boolean;
}>;
MenuSliderControl: RC<{
minValue: number,
maxValue: number,
value: number,
onChange(value: number): void,
renderValue?(value: number): string,
minValue: number;
maxValue: number;
value: number;
onChange(value: number): void;
renderValue?(value: number): string;
}>;
}

View file

@ -92,18 +92,18 @@ export interface RouterUtils {
export interface IconUtils {
getUserAvatarURL(user: UserRecord, canAnimate?: boolean, size?: number, format?: string): string;
getDefaultAvatarURL(id: string, discriminator?: string): string;
getUserBannerURL(data: { id: string, banner: string, canAnimate?: boolean, size: number; }): string | undefined;
getAvatarDecorationURL(data: { avatarDecoration: string, size: number; canCanimate?: boolean; }): string | undefined;
getUserBannerURL(data: { id: string; banner: string; canAnimate?: boolean; size: number; }): string | undefined;
getAvatarDecorationURL(data: { avatarDecoration: string; size: number; canCanimate?: boolean; }): string | undefined;
getGuildMemberAvatarURL(member: GuildMember, canAnimate?: string): string | null;
getGuildMemberAvatarURLSimple(data: { guildId: string, userId: string, avatar: string, canAnimate?: boolean; size?: number; }): string;
getGuildMemberBannerURL(data: { id: string, guildId: string, banner: string, canAnimate?: boolean, size: number; }): string | undefined;
getGuildMemberAvatarURLSimple(data: { guildId: string; userId: string; avatar: string; canAnimate?: boolean; size?: number; }): string;
getGuildMemberBannerURL(data: { id: string; guildId: string; banner: string; canAnimate?: boolean; size: number; }): string | undefined;
getGuildIconURL(data: { id: string, icon?: string, size?: number, canAnimate?: boolean; }): string | undefined;
getGuildIconURL(data: { id: string; icon?: string; size?: number; canAnimate?: boolean; }): string | undefined;
getGuildBannerURL(guild: GuildRecord, canAnimate?: boolean): string | null;
getChannelIconURL(data: { id: string; icon?: string | null | undefined; applicationId?: string; size?: number; }): string | undefined;
getEmojiURL(data: { id: string, animated: boolean, size: number, forcePNG?: boolean; }): string;
getEmojiURL(data: { id: string; animated: boolean; size: number; forcePNG?: boolean; }): string;
hasAnimatedGuildIcon(guild: GuildRecord): boolean;
isAnimatedIconHash(hash: string): boolean;

View file

@ -53,12 +53,12 @@ const ToastPosition = {
};
export interface ToastData {
message: string,
id: string,
message: string;
id: string;
/**
* Toasts.Type
*/
type: number,
type: number;
options?: ToastOptions;
}
@ -67,7 +67,7 @@ export interface ToastOptions {
* Toasts.Position
*/
position?: number;
component?: ReactNode,
component?: ReactNode;
duration?: number;
}
@ -102,7 +102,7 @@ export function showToast(message: string, type = ToastType.MESSAGE, options?: T
}
export let AlertActionCreators: t.AlertActionCreators;
waitFor(["show", "close"], m => AlertActionCreators = m);
waitFor(["show", "close"], m => { AlertActionCreators = m; });
export const ApplicationAssetUtils: {
fetchAssetIds: (applicationId: string, e: string[]) => Promise<string[]>;
@ -118,7 +118,7 @@ export const ClipboardUtils: t.ClipboardUtils = mapMangledModuleLazy('queryComma
});
export let ComponentDispatch: any;
waitFor(["ComponentDispatch", "ComponentDispatcher"], m => ComponentDispatch = m.ComponentDispatch);
waitFor(["ComponentDispatch", "ComponentDispatcher"], m => { ({ ComponentDispatch } = m); });
export const Constants = findByPropsLazy("Endpoints");
@ -149,7 +149,7 @@ export const InstantInviteActionCreators = findByPropsLazy("resolveInvite");
export const lodash: typeof import("lodash") = findByPropsLazy("debounce", "cloneDeep");
export let MarkupUtils: t.MarkupUtils;
waitFor("parseTopic", m => MarkupUtils = m);
waitFor("parseTopic", m => { MarkupUtils = m; });
export const MessageActionCreators = findByPropsLazy("editMessage", "sendMessage");
@ -176,7 +176,7 @@ export const RouterUtils: t.RouterUtils = mapMangledModuleLazy("Transitioning to
});
export let SnowflakeUtils: t.SnowflakeUtils;
waitFor(["fromTimestamp", "extractTimestamp"], m => SnowflakeUtils = m);
waitFor(["fromTimestamp", "extractTimestamp"], m => { SnowflakeUtils = m; });
export const UploadAttachmentActionCreators = findByPropsLazy("clearAll", "addFile");
@ -187,7 +187,7 @@ export const UserActionCreators = {
export const UserProfileModalActionCreators = findByPropsLazy("openUserProfileModal", "closeUserProfileModal");
export let UserSettingsModalActionCreators: any;
waitFor(["open", "saveAccountChanges"], m => UserSettingsModalActionCreators = m);
waitFor(["open", "saveAccountChanges"], m => { UserSettingsModalActionCreators = m; });
export const UserUtils: t.UserUtils = findByPropsLazy("useName", "getGlobalName");

View file

@ -180,7 +180,7 @@ function patchFactories(factories: Record<string, (module: any, exports: any, re
return;
}
exports = module.exports;
({ exports } = module);
if (!exports) return;
@ -245,7 +245,7 @@ function patchFactories(factories: Record<string, (module: any, exports: any, re
logger.error("Error while firing callback for Webpack subscription:\n", err, filter, callback);
}
}
} as any as { toString: () => string, original: any, (...args: any[]): void; };
} as any as { toString: () => string; original: any; (...args: any[]): void; };
factory.toString = originalMod.toString.bind(originalMod);
factory.original = originalMod;

View file

@ -603,7 +603,7 @@ export function waitFor(filter: string | PropsFilter | FilterFn, callback: Callb
else if (typeof filter !== "function")
throw new Error("filter must be a string, string[] or function, got " + typeof filter);
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (cache != null) {
const [existing, id] = find(filter, { isIndirect: true, isWaitFor: true });
if (existing) {