diff --git a/.gemini/styleguide.md b/.gemini/styleguide.md index baa617b84..51258faee 100644 --- a/.gemini/styleguide.md +++ b/.gemini/styleguide.md @@ -51,6 +51,7 @@ export default definePlugin({ options: { myOption: { /* ... */ } } }); ``` **Prefer declarative APIs** over manual registration: + - `flux: { EVENT_NAME(data) {} }` not manual FluxDispatcher subscribe - `contextMenus: { "nav-id": fn }` not manual addContextMenuPatch - `chatBarButton: { render, icon }` not addChatBarButton @@ -81,7 +82,6 @@ Flag these and suggest the fix: | `cdn.discordapp.com/icons/...` | `IconUtils.getGuildIconURL(...)` | Same | | `cdn.discordapp.com/banners/...` | `IconUtils.getUserBannerURL(...)` | Same | | `cdn.discordapp.com/emojis/...` | `IconUtils.getEmojiURL(...)` | Same | -| `/assets/*.png` default avatars | `IconUtils.getDefaultAvatarURL(id)` | Same | | `/api/v9/...` or `/users/@me` | `Constants.Endpoints.*` or `RestAPI` | Endpoints change | | `@api/Styles` for classNameFactory | `@utils/css` | `@api/Styles` is deprecated | | `any` for Discord objects | Import from `@vencord/discord-types` | Type safety | @@ -361,6 +361,7 @@ If a PR reimplements any of these, flag it. They already exist: **@api/Commands:** `sendBotMessage`, `findOption` **@webpack/common:** + - Stores: `UserStore`, `GuildStore`, `ChannelStore`, `GuildMemberStore`, `SelectedChannelStore`, `SelectedGuildStore`, `PresenceStore`, `RelationshipStore`, `MessageStore`, `EmojiStore`, `ThemeStore`, `PermissionStore`, `VoiceStateStore`, 30+ more - Actions: `RestAPI`, `FluxDispatcher`, `MessageActions`, `NavigationRouter`, `ChannelRouter`, `ChannelActionCreators`, `SettingsRouter` - Utils: `Constants` (`.Endpoints`), `SnowflakeUtils`, `Parser`, `PermissionsBits`, `moment`, `lodash`, `IconUtils`, `ColorUtils`, `ImageUtils`, `DateUtils`, `UsernameUtils`, `DisplayProfileUtils` diff --git a/.rules b/.rules index 1a0363222..061408c20 100644 --- a/.rules +++ b/.rules @@ -102,6 +102,7 @@ ### Patch Examples **Clean replacement:** + ```js find: "#{intl::PIN_MESSAGE}),icon:" match: /#{intl::PIN_MESSAGE}\)/ @@ -109,6 +110,7 @@ replace: "$self.getPinLabel(arguments[0]))" ``` **Appending:** + ```js find: "#{intl::VIEW_AS_ROLES_MENTIONS_WARNING}" match: /#{intl::VIEW_AS_ROLES_MENTIONS_WARNING}.{0,100}(?=])/ @@ -116,6 +118,7 @@ replace: "$&,$self.renderTooltip(arguments[0].guild)" ``` **Wrapping:** + ```js find: "#{intl::THREE_USERS_TYPING}" match: /(?<="aria-atomic":!0,children:)\i/ @@ -168,7 +171,6 @@ Use `definePluginSettings` from `@api/Settings`, not inline settings object. From `@webpack/common`. **NEVER** hardcode `cdn.discordapp.com` URLs. - `IconUtils.getUserAvatarURL(user, canAnimate?, size?)` -- `IconUtils.getDefaultAvatarURL(id)` - `IconUtils.getUserBannerURL({ id, banner, canAnimate?, size })` - `IconUtils.getGuildIconURL({ id, icon, size?, canAnimate? })` - `IconUtils.getGuildBannerURL(guild, canAnimate?)` @@ -208,4 +210,3 @@ From `@webpack/common`. **NEVER** hardcode `cdn.discordapp.com` URLs. - `"/api/v9"`, `"/users/@me"` ⟹ `Constants.Endpoints` or `RestAPI` - `console.log/warn/error` ⟹ `Logger` from `@utils/Logger` - `` `${a} ${b}` `` for class names ⟹ `classes(a, b)` from `@utils/misc` -- `"/assets/*.png"` for default avatars ⟹ `IconUtils.getDefaultAvatarURL(id)` diff --git a/package.json b/package.json index d3d234ab7..a07f6f350 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "equicord", "private": "true", - "version": "1.14.2.1", + "version": "1.14.3.0", "description": "The other cutest Discord client mod", "homepage": "https://github.com/Equicord/Equicord#readme", "bugs": { diff --git a/src/equicordplugins/profileSets/utils/profile.ts b/src/equicordplugins/profileSets/utils/profile.ts index 5b7a7bbc7..148081443 100644 --- a/src/equicordplugins/profileSets/utils/profile.ts +++ b/src/equicordplugins/profileSets/utils/profile.ts @@ -281,7 +281,7 @@ function resolvePendingAvatar(pendingChanges: PendingChanges | null): ImageInput function normalizeImageValue(value: unknown): string | null { if (typeof value === "string") return value; if (value && typeof value === "object" && "imageUri" in value) { - const { imageUri } = value as { imageUri: unknown }; + const { imageUri } = value as { imageUri: unknown; }; return typeof imageUri === "string" ? imageUri : null; } return null; diff --git a/src/equicordplugins/quoter/index.tsx b/src/equicordplugins/quoter/index.tsx index f8389de73..95825e3c1 100644 --- a/src/equicordplugins/quoter/index.tsx +++ b/src/equicordplugins/quoter/index.tsx @@ -12,11 +12,11 @@ import { getCurrentChannel } from "@utils/discord"; import { ModalCloseButton, ModalContent, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal"; import definePlugin, { OptionType } from "@utils/types"; import { Message } from "@vencord/discord-types"; -import { Button, Menu, TextInput, UploadHandler, useEffect, useState } from "@webpack/common"; +import { Button, IconUtils, Menu, TextInput, UploadHandler, useEffect, useState } from "@webpack/common"; import { QuoteIcon } from "./components/QuoteIcon"; import { QuoteFont } from "./types"; -import { createQuoteImage, ensureFontLoaded, generateFileNamePreview, getFileExtension, getMimeType, resetFontLoading, sizeUpgrade } from "./utils"; +import { createQuoteImage, ensureFontLoaded, generateFileNamePreview, getFileExtension, getMimeType, resetFontLoading } from "./utils"; const settings = definePluginSettings({ quoteFont: { @@ -105,7 +105,7 @@ function QuoteModal({ message, ...props }: ModalProps & { message: Message; }) { const generateImage = async () => { const image = await createQuoteImage({ - avatarUrl: sizeUpgrade(message.author.getAvatarURL()), + avatarUrl: IconUtils.getUserAvatarURL(message.author, true, 512), quote: message.content, grayScale: gray, author: message.author, diff --git a/src/equicordplugins/quoter/utils.tsx b/src/equicordplugins/quoter/utils.tsx index d963967ff..8ff9ae5bf 100644 --- a/src/equicordplugins/quoter/utils.tsx +++ b/src/equicordplugins/quoter/utils.tsx @@ -21,12 +21,6 @@ interface CustomEmojiToken { animated: boolean; } -export function sizeUpgrade(url: string): string { - const u = new URL(url); - u.searchParams.set("size", "512"); - return u.toString(); -} - export function canvasToBlob(canvas: HTMLCanvasElement): Promise { return new Promise((resolve, reject) => { canvas.toBlob(blob => { diff --git a/src/equicordplugins/voiceButtons/index.tsx b/src/equicordplugins/voiceButtons/index.tsx index 91360e72f..a8b18c885 100644 --- a/src/equicordplugins/voiceButtons/index.tsx +++ b/src/equicordplugins/voiceButtons/index.tsx @@ -31,8 +31,12 @@ export default definePlugin({ ], renderButtons(user: User) { if (!user) return null; + const positionClass = settings.store.buttonPosition === "right" + ? "voice-user-buttons-right" + : "voice-user-buttons-left"; + return ( - + {settings.store.showChatButton && } {settings.store.showMuteButton && } {settings.store.showDeafenButton && } diff --git a/src/equicordplugins/voiceButtons/settings.ts b/src/equicordplugins/voiceButtons/settings.ts index fb0d4a435..e12cfe7cb 100644 --- a/src/equicordplugins/voiceButtons/settings.ts +++ b/src/equicordplugins/voiceButtons/settings.ts @@ -30,46 +30,47 @@ export const settings = definePluginSettings({ type: OptionType.BOOLEAN, default: true, description: "Toggles their soundboard upon clicking deafen button.", - restartNeeded: false, }, disableVideo: { type: OptionType.BOOLEAN, default: true, description: "Toggles their video upon clicking deafen button.", - restartNeeded: false, }, useServer: { type: OptionType.BOOLEAN, description: "Use server mute/deafen instead of local when you have permission.", default: false, - restartNeeded: false, }, serverSelf: { type: OptionType.BOOLEAN, description: "Deafen / Mute yourself on the server when using mute/deafen.", default: false, - restartNeeded: false, }, showButtonsSelf: { type: OptionType.SELECT, - default: "display", description: "Whether you want to display buttons for your own user. Same functionality as other button(s) except it'll open DMs panel and mute/deafen for yourself upon clicking button(s).", restartNeeded: true, options: [ - { label: "Display", value: "display" }, + { label: "Display", value: "display", default: true }, { label: "Hide", value: "hide" }, { label: "Disable", value: "disable" }, ], }, whichNameToShow: { type: OptionType.SELECT, - default: "both", description: "Choose whether to show nickname or username in tooltip.", - restartNeeded: false, options: [ + { label: "Both", value: "both", default: true }, { label: "Global Name", value: "global" }, - { label: "Default Username", value: "username" }, - { label: "Both", value: "both" }, + { label: "Username", value: "username" }, + ], + }, + buttonPosition: { + type: OptionType.SELECT, + description: "Choose where to place voice buttons in the voice user row.", + options: [ + { label: "Left", value: "left", default: true }, + { label: "Right", value: "right" }, ], } }, { diff --git a/src/equicordplugins/voiceButtons/styles.css b/src/equicordplugins/voiceButtons/styles.css index f6edc1113..56e1da52e 100644 --- a/src/equicordplugins/voiceButtons/styles.css +++ b/src/equicordplugins/voiceButtons/styles.css @@ -2,10 +2,19 @@ flex: none !important; } +.voice-user-buttons-left { + order: -1; +} + +.voice-user-buttons-right { + order: 1; + margin-left: 4px; +} + .voice-user-button-container { padding-right: 4px; } div[class*='list'][class*='collapsed'] .voice-user-buttons { display: none; -} \ No newline at end of file +} diff --git a/src/plugins/accountPanelServerProfile/index.tsx b/src/plugins/accountPanelServerProfile/index.tsx index b1304e3fa..2fc49e85c 100644 --- a/src/plugins/accountPanelServerProfile/index.tsx +++ b/src/plugins/accountPanelServerProfile/index.tsx @@ -87,7 +87,7 @@ export default definePlugin({ replace: "$&$self.onPopoutClose();" }, { - match: /ref:(\i),style:\i(?=.{0,250}#{intl::5fWB8U::raw})/, + match: /ref:(\i),style:\i(?=.{0,250}#{intl::USER_PROFILE_ACCOUNT_POPOUT_BUTTON_A11Y_LABEL})/, replace: "$&,onContextMenu:($self.grabRef($1),$self.openAccountPanelContextMenu)" } ] diff --git a/src/plugins/betterSettings/index.tsx b/src/plugins/betterSettings/index.tsx index cdfd06b32..7b0b3517e 100644 --- a/src/plugins/betterSettings/index.tsx +++ b/src/plugins/betterSettings/index.tsx @@ -137,6 +137,28 @@ export default definePlugin({ ], predicate: () => settings.store.disableFade }, + { // Disable fade animations for settings menu + find: '"data-mana-component":"layer-modal"', + replacement: [ + { + match: /(\i)\.animated\.div(?=,\{"data-mana-component":"layer-modal")/, + replace: '"div"' + }, + { + match: /(?<="data-mana-component":"layer-modal"[^}]*?)style:\i,/, + replace: "style:{}," + } + ], + predicate: () => settings.store.disableFade + }, + { // Disable initial and exit delay for settings menu + find: "headerId:void 0,headerIdIsManaged:!1", + replacement: { + match: /let (\i)=300/, + replace: "let $1=0" + }, + predicate: () => settings.store.disableFade + }, { // Load menu TOC eagerly find: "handleOpenSettingsContextMenu=", replacement: { @@ -145,8 +167,7 @@ export default definePlugin({ }, predicate: () => settings.store.eagerLoad }, - { - // Settings cog context menu + { // Settings cog context menu find: "#{intl::USER_SETTINGS_ACTIONS_MENU_LABEL}", replacement: [ { diff --git a/src/plugins/decor/index.tsx b/src/plugins/decor/index.tsx index a3f5ca1a4..64a16e6bb 100644 --- a/src/plugins/decor/index.tsx +++ b/src/plugins/decor/index.tsx @@ -99,7 +99,7 @@ export default definePlugin({ ...[ '"Message Username"', // Messages "#{intl::COLLECTIBLES_NAMEPLATE_PREVIEW_A11Y}", // Nameplate preview - "#{intl::ayozFl::raw}", // Avatar preview + "#{intl::COLLECTIBLES_PROFILE_PREVIEW_A11Y}", // Avatar preview ].map(find => ({ find, replacement: { diff --git a/src/plugins/streamerModeOnStream/index.ts b/src/plugins/streamerModeOnStream/index.ts index 873e1fc72..26b4a279c 100644 --- a/src/plugins/streamerModeOnStream/index.ts +++ b/src/plugins/streamerModeOnStream/index.ts @@ -37,7 +37,7 @@ function toggleStreamerMode({ streamKey }: StreamEvent, value: boolean) { export default definePlugin({ name: "StreamerModeOn", description: "Automatically enables streamer mode when you start streaming in Discord", - authors: [Devs.Kodarru], + authors: [Devs.IcedMarina], flux: { STREAM_CREATE: d => toggleStreamerMode(d, true), STREAM_DELETE: d => toggleStreamerMode(d, false) diff --git a/src/plugins/translate/languages.ts b/src/plugins/translate/languages.ts index 75b7f3ae3..1023983f8 100644 --- a/src/plugins/translate/languages.ts +++ b/src/plugins/translate/languages.ts @@ -225,6 +225,7 @@ export const DeeplLanguages = { "it": "Italian", "ja": "Japanese", "jv": "Javanese", + "ko": "Korean", "pam": "Kapampangan", "kk": "Kazakh", "kmr": "Kurdish (Kurmanji)", diff --git a/src/plugins/voiceDownload/index.tsx b/src/plugins/voiceDownload/index.tsx index 19d0883f5..eac912e47 100644 --- a/src/plugins/voiceDownload/index.tsx +++ b/src/plugins/voiceDownload/index.tsx @@ -15,7 +15,7 @@ export default definePlugin({ authors: [Devs.puv], patches: [ { - find: "#{intl::LgCPMt::raw}", + find: "#{intl::VOICE_MESSAGES_PLAYBACK_RATE_LABEL}", replacement: { match: /(?<=onVolumeHide:\i\}\))/, replace: ",$self.renderDownload(arguments[0].src)" diff --git a/src/plugins/volumeBooster/index.ts b/src/plugins/volumeBooster/index.ts index cc3cad194..4ab0c332a 100644 --- a/src/plugins/volumeBooster/index.ts +++ b/src/plugins/volumeBooster/index.ts @@ -55,16 +55,21 @@ export default definePlugin({ patches: [ // Change the max volume for sliders to allow for values above 200 - ...[ - "#{intl::USER_VOLUME}", - "currentVolume:" - ].map(find => ({ - find, + { + find: "#{intl::USER_VOLUME}", replacement: { - match: /(?<=maxValue:)\i\.\i\?(\i\.\i|\d+?):(\i\.\i|\d+?)(?=,)/, - replace: (_, higherMaxVolume, minorMaxVolume) => `${higherMaxVolume}*$self.settings.store.multiplier` + match: /(?<=maxValue:)\i\.isPlatformEmbedded\?(\i\.\i):\i\.\i(?=,)/, + replace: (_, higherMaxVolume) => `${higherMaxVolume}*$self.settings.store.multiplier` } - })), + }, + // Change the max volume for sliders to allow for values above 200 + { + find: "currentVolume:", + replacement: { + match: /(?<=maxValue:)\i\.\i\?(\d+?):\d+?(?=,)/, + replace: (_, higherMaxVolume) => `${higherMaxVolume}*$self.settings.store.multiplier` + } + }, // Patches needed for web/vesktop { find: "streamSourceNode", diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 4041fe3b8..495f320a9 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -466,7 +466,7 @@ export const Devs = /* #__PURE__*/ Object.freeze({ }, nin0dev: { name: "nin0dev", - id: 886685857560539176n + id: 1395533040914141235n }, Elvyra: { name: "Elvyra", @@ -496,9 +496,9 @@ export const Devs = /* #__PURE__*/ Object.freeze({ name: "puv", id: 469441552251355137n }, - Kodarru: { - name: "Kodarru", - id: 785227396218748949n + IcedMarina: { + name: "icedmarina", + id: 594406131670188042n }, nakoyasha: { name: "nakoyasha",