From ae98cfb637d037872a7ab861583843c515e5f944 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Sun, 2 Feb 2025 17:59:22 -0300 Subject: [PATCH] Wrap decorators in flex with gap to avoid adding margins --- src/api/MemberListDecorators.tsx | 19 +++++++++++++------ src/api/MessageDecorations.tsx | 18 ++++++++++++------ .../index.tsx} | 11 ++++++++--- .../_api/memberListDecorators/style.css | 11 +++++++++++ .../index.tsx} | 9 +++++++-- src/plugins/_api/messageDecorations/style.css | 15 +++++++++++++++ src/plugins/gameActivityToggle/index.tsx | 12 +++--------- src/plugins/imageZoom/index.tsx | 7 +++---- src/plugins/index.ts | 9 +++++++-- src/plugins/platformIndicators/index.tsx | 10 +++------- src/plugins/userVoiceShow/components.tsx | 6 ++---- src/plugins/userVoiceShow/index.tsx | 4 ++-- src/plugins/userVoiceShow/style.css | 10 ---------- src/utils/types.ts | 5 +++++ 14 files changed, 91 insertions(+), 55 deletions(-) rename src/plugins/_api/{memberListDecorators.ts => memberListDecorators/index.tsx} (83%) create mode 100644 src/plugins/_api/memberListDecorators/style.css rename src/plugins/_api/{messageDecorations.ts => messageDecorations/index.tsx} (87%) create mode 100644 src/plugins/_api/messageDecorations/style.css diff --git a/src/api/MemberListDecorators.tsx b/src/api/MemberListDecorators.tsx index 2199f4a6c..ab5a618bf 100644 --- a/src/api/MemberListDecorators.tsx +++ b/src/api/MemberListDecorators.tsx @@ -43,20 +43,21 @@ interface DecoratorProps { export type MemberListDecoratorFactory = (props: DecoratorProps) => JSX.Element | null; type OnlyIn = "guilds" | "dms"; -export const decorators = new Map(); +export const decoratorsFactories = new Map(); export function addMemberListDecorator(identifier: string, render: MemberListDecoratorFactory, onlyIn?: OnlyIn) { - decorators.set(identifier, { render, onlyIn }); + decoratorsFactories.set(identifier, { render, onlyIn }); } export function removeMemberListDecorator(identifier: string) { - decorators.delete(identifier); + decoratorsFactories.delete(identifier); } -export function __getDecorators(props: DecoratorProps): (JSX.Element | null)[] { +export function __getDecorators(props: DecoratorProps): JSX.Element { const isInGuild = !!(props.guildId); - return Array.from( - decorators.entries(), + + const decorators = Array.from( + decoratorsFactories.entries(), ([key, { render: Decorator, onlyIn }]) => { if ((onlyIn === "guilds" && !isInGuild) || (onlyIn === "dms" && isInGuild)) return null; @@ -68,4 +69,10 @@ export function __getDecorators(props: DecoratorProps): (JSX.Element | null)[] { ); } ); + + return ( +
+ {decorators} +
+ ); } diff --git a/src/api/MessageDecorations.tsx b/src/api/MessageDecorations.tsx index 740c95876..1b94c18d9 100644 --- a/src/api/MessageDecorations.tsx +++ b/src/api/MessageDecorations.tsx @@ -48,23 +48,29 @@ export interface MessageDecorationProps { } export type MessageDecorationFactory = (props: MessageDecorationProps) => JSX.Element | null; -export const decorations = new Map(); +export const decorationsFactories = new Map(); export function addMessageDecoration(identifier: string, decoration: MessageDecorationFactory) { - decorations.set(identifier, decoration); + decorationsFactories.set(identifier, decoration); } export function removeMessageDecoration(identifier: string) { - decorations.delete(identifier); + decorationsFactories.delete(identifier); } -export function __addDecorationsToMessage(props: MessageDecorationProps): (JSX.Element | null)[] { - return Array.from( - decorations.entries(), +export function __addDecorationsToMessage(props: MessageDecorationProps): JSX.Element { + const decorations = Array.from( + decorationsFactories.entries(), ([key, Decoration]) => ( ) ); + + return ( +
+ {decorations} +
+ ); } diff --git a/src/plugins/_api/memberListDecorators.ts b/src/plugins/_api/memberListDecorators/index.tsx similarity index 83% rename from src/plugins/_api/memberListDecorators.ts rename to src/plugins/_api/memberListDecorators/index.tsx index 0dba3608f..39c82a1ed 100644 --- a/src/plugins/_api/memberListDecorators.ts +++ b/src/plugins/_api/memberListDecorators/index.tsx @@ -19,10 +19,15 @@ import { Devs } from "@utils/constants"; import definePlugin from "@utils/types"; +import managedStyle from "./style.css?managed"; + export default definePlugin({ name: "MemberListDecoratorsAPI", description: "API to add decorators to member list (both in servers and DMs)", authors: [Devs.TheSun, Devs.Ven], + + managedStyle, + patches: [ { find: ".lostPermission)", @@ -32,7 +37,7 @@ export default definePlugin({ replace: "$&vencordProps=$1," }, { match: /#{intl::GUILD_OWNER}(?=.+?decorators:(\i)\(\)).+?\1=?\(\)=>.+?children:\[/, - replace: "$&...(typeof vencordProps=='undefined'?[]:Vencord.Api.MemberListDecorators.__getDecorators(vencordProps))," + replace: "$&(typeof vencordProps=='undefined'?null:Vencord.Api.MemberListDecorators.__getDecorators(vencordProps))," } ] }, @@ -40,8 +45,8 @@ export default definePlugin({ find: "PrivateChannel.renderAvatar", replacement: { match: /decorators:(\i\.isSystemDM\(\))\?(.+?):null/, - replace: "decorators:[...Vencord.Api.MemberListDecorators.__getDecorators(arguments[0]), $1?$2:null]" + replace: "decorators:[Vencord.Api.MemberListDecorators.__getDecorators(arguments[0]),$1?$2:null]" } } - ], + ] }); diff --git a/src/plugins/_api/memberListDecorators/style.css b/src/plugins/_api/memberListDecorators/style.css new file mode 100644 index 000000000..bd4afda9d --- /dev/null +++ b/src/plugins/_api/memberListDecorators/style.css @@ -0,0 +1,11 @@ +.vc-member-list-decorators-wrapper { + display: flex; + align-items: center; + justify-content: center; + gap: 0.25em; +} + +.vc-member-list-decorators-wrapper:not(:empty) { + /* Margin to match default Discord decorators */ + margin-left: 0.25em; +} diff --git a/src/plugins/_api/messageDecorations.ts b/src/plugins/_api/messageDecorations/index.tsx similarity index 87% rename from src/plugins/_api/messageDecorations.ts rename to src/plugins/_api/messageDecorations/index.tsx index fb63a6dde..10866baea 100644 --- a/src/plugins/_api/messageDecorations.ts +++ b/src/plugins/_api/messageDecorations/index.tsx @@ -19,17 +19,22 @@ import { Devs } from "@utils/constants"; import definePlugin from "@utils/types"; +import managedStyle from "./style.css?managed"; + export default definePlugin({ name: "MessageDecorationsAPI", description: "API to add decorations to messages", authors: [Devs.TheSun], + + managedStyle, + patches: [ { find: '"Message Username"', replacement: { match: /#{intl::GUILD_COMMUNICATION_DISABLED_BOTTOM_SHEET_TITLE}.+?}\),\i(?=\])/, - replace: "$&,...Vencord.Api.MessageDecorations.__addDecorationsToMessage(arguments[0])" + replace: "$&,Vencord.Api.MessageDecorations.__addDecorationsToMessage(arguments[0])" } } - ], + ] }); diff --git a/src/plugins/_api/messageDecorations/style.css b/src/plugins/_api/messageDecorations/style.css new file mode 100644 index 000000000..905976db5 --- /dev/null +++ b/src/plugins/_api/messageDecorations/style.css @@ -0,0 +1,15 @@ +.vc-message-decorations-wrapper { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 0.25em; +} + +.vc-message-decorations-wrapper:not(:empty) { + /* Margin to match default Discord decorators */ + margin-left: 0.25em; + + /* Align vertically */ + position: relative; + top: 0.2rem; +} diff --git a/src/plugins/gameActivityToggle/index.tsx b/src/plugins/gameActivityToggle/index.tsx index add7bfbc3..37d0ca4cd 100644 --- a/src/plugins/gameActivityToggle/index.tsx +++ b/src/plugins/gameActivityToggle/index.tsx @@ -17,14 +17,13 @@ */ import { definePluginSettings } from "@api/Settings"; -import { disableStyle, enableStyle } from "@api/Styles"; import { getUserSettingLazy } from "@api/UserSettings"; import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; import { findComponentByCodeLazy } from "@webpack"; -import style from "./style.css?managed"; +import managedStyle from "./style.css?managed"; const Button = findComponentByCodeLazy(".NONE,disabled:", ".PANEL_BUTTON"); @@ -90,6 +89,8 @@ export default definePlugin({ dependencies: ["UserSettingsAPI"], settings, + managedStyle, + patches: [ { find: "#{intl::ACCOUNT_SPEAKING_WHILE_MUTED}", @@ -102,11 +103,4 @@ export default definePlugin({ GameActivityToggleButton: ErrorBoundary.wrap(GameActivityToggleButton, { noop: true }), - start() { - enableStyle(style); - }, - - stop() { - disableStyle(style); - } }); diff --git a/src/plugins/imageZoom/index.tsx b/src/plugins/imageZoom/index.tsx index 8c50ae9f4..934a5c775 100644 --- a/src/plugins/imageZoom/index.tsx +++ b/src/plugins/imageZoom/index.tsx @@ -18,7 +18,6 @@ import { NavContextMenuPatchCallback } from "@api/ContextMenu"; import { definePluginSettings } from "@api/Settings"; -import { disableStyle, enableStyle } from "@api/Styles"; import { makeRange } from "@components/PluginSettings/components"; import { debounce } from "@shared/debounce"; import { Devs } from "@utils/constants"; @@ -29,7 +28,7 @@ import type { Root } from "react-dom/client"; import { Magnifier, MagnifierProps } from "./components/Magnifier"; import { ELEMENT_ID } from "./constants"; -import styles from "./styles.css?managed"; +import managedStyle from "./styles.css?managed"; export const settings = definePluginSettings({ saveZoomValues: { @@ -160,6 +159,8 @@ export default definePlugin({ authors: [Devs.Aria], tags: ["ImageUtilities"], + managedStyle, + patches: [ { find: ".contain,SCALE_DOWN:", @@ -252,14 +253,12 @@ export default definePlugin({ }, start() { - enableStyle(styles); this.element = document.createElement("div"); this.element.classList.add("MagnifierContainer"); document.body.appendChild(this.element); }, stop() { - disableStyle(styles); // so componenetWillUnMount gets called if Magnifier component is still alive this.root && this.root.unmount(); this.element?.remove(); diff --git a/src/plugins/index.ts b/src/plugins/index.ts index 50523e98f..306ac737d 100644 --- a/src/plugins/index.ts +++ b/src/plugins/index.ts @@ -26,6 +26,7 @@ import { addMessageDecoration, removeMessageDecoration } from "@api/MessageDecor import { addMessageClickListener, addMessagePreEditListener, addMessagePreSendListener, removeMessageClickListener, removeMessagePreEditListener, removeMessagePreSendListener } from "@api/MessageEvents"; import { addMessagePopoverButton, removeMessagePopoverButton } from "@api/MessagePopover"; import { Settings, SettingsStore } from "@api/Settings"; +import { disableStyle, enableStyle } from "@api/Styles"; import { Logger } from "@utils/Logger"; import { canonicalizeFind } from "@utils/patches"; import { Patch, Plugin, PluginDef, ReporterTestable, StartAt } from "@utils/types"; @@ -254,7 +255,7 @@ export function subscribeAllPluginsFluxEvents(fluxDispatcher: typeof FluxDispatc export const startPlugin = traceFunction("startPlugin", function startPlugin(p: Plugin) { const { - name, commands, contextMenus, userProfileBadge, + name, commands, contextMenus, managedStyle, userProfileBadge, onBeforeMessageEdit, onBeforeMessageSend, onMessageClick, renderChatBarButton, renderMemberListDecorator, renderMessageAccessory, renderMessageDecoration, renderMessagePopoverButton } = p; @@ -298,6 +299,8 @@ export const startPlugin = traceFunction("startPlugin", function startPlugin(p: } } + if (managedStyle) enableStyle(managedStyle); + if (userProfileBadge) addProfileBadge(userProfileBadge); if (onBeforeMessageEdit) addMessagePreEditListener(onBeforeMessageEdit); @@ -315,7 +318,7 @@ export const startPlugin = traceFunction("startPlugin", function startPlugin(p: export const stopPlugin = traceFunction("stopPlugin", function stopPlugin(p: Plugin) { const { - name, commands, contextMenus, userProfileBadge, + name, commands, contextMenus, managedStyle, userProfileBadge, onBeforeMessageEdit, onBeforeMessageSend, onMessageClick, renderChatBarButton, renderMemberListDecorator, renderMessageAccessory, renderMessageDecoration, renderMessagePopoverButton } = p; @@ -357,6 +360,8 @@ export const stopPlugin = traceFunction("stopPlugin", function stopPlugin(p: Plu } } + if (managedStyle) disableStyle(managedStyle); + if (userProfileBadge) removeProfileBadge(userProfileBadge); if (onBeforeMessageEdit) removeMessagePreEditListener(onBeforeMessageEdit); diff --git a/src/plugins/platformIndicators/index.tsx b/src/plugins/platformIndicators/index.tsx index 4612082f5..7829295a0 100644 --- a/src/plugins/platformIndicators/index.tsx +++ b/src/plugins/platformIndicators/index.tsx @@ -133,7 +133,7 @@ function getBadges({ userId }: BadgeUserArgs): ProfileBadge[] { })); } -const PlatformIndicator = ({ user, wantMargin = true, wantTopMargin = false, small = false }: { user: User; wantMargin?: boolean; wantTopMargin?: boolean; small?: boolean; }) => { +const PlatformIndicator = ({ user, small = false }: { user: User; small?: boolean; }) => { if (!user || user.bot) return null; ensureOwnStatus(user); @@ -155,11 +155,7 @@ const PlatformIndicator = ({ user, wantMargin = true, wantTopMargin = false, sma return ( {icons} @@ -190,7 +186,7 @@ const indicatorLocations = { description: "Inside messages", onEnable: () => addMessageDecoration("platform-indicator", props => - + ), onDisable: () => removeMessageDecoration("platform-indicator") diff --git a/src/plugins/userVoiceShow/components.tsx b/src/plugins/userVoiceShow/components.tsx index 5495397fd..4666bb907 100644 --- a/src/plugins/userVoiceShow/components.tsx +++ b/src/plugins/userVoiceShow/components.tsx @@ -130,15 +130,13 @@ function VoiceChannelTooltip({ channel, isLocked }: VoiceChannelTooltipProps) { interface VoiceChannelIndicatorProps { userId: string; - isMessageIndicator?: boolean; - isProfile?: boolean; isActionButton?: boolean; shouldHighlight?: boolean; } const clickTimers = {} as Record; -export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId, isMessageIndicator, isProfile, isActionButton, shouldHighlight }: VoiceChannelIndicatorProps) => { +export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId, isActionButton, shouldHighlight }: VoiceChannelIndicatorProps) => { const channelId = useStateFromStores([VoiceStateStore], () => VoiceStateStore.getVoiceStateForUser(userId)?.channelId as string | undefined); const channel = channelId == null ? undefined : ChannelStore.getChannel(channelId); @@ -182,7 +180,7 @@ export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId, isMessageIndi {props => { const iconProps: IconProps = { ...props, - className: classes(isMessageIndicator && cl("message-indicator"), (!isProfile && !isActionButton) && cl("speaker-margin"), isActionButton && ActionButtonClasses.actionButton, shouldHighlight && ActionButtonClasses.highlight), + className: classes(isActionButton && ActionButtonClasses.actionButton, shouldHighlight && ActionButtonClasses.highlight), size: isActionButton ? 20 : undefined, onClick }; diff --git a/src/plugins/userVoiceShow/index.tsx b/src/plugins/userVoiceShow/index.tsx index f3063f590..3d119c433 100644 --- a/src/plugins/userVoiceShow/index.tsx +++ b/src/plugins/userVoiceShow/index.tsx @@ -60,7 +60,7 @@ export default definePlugin({ find: "#{intl::USER_PROFILE_LOAD_ERROR}", replacement: { match: /(\.fetchError.+?\?)null/, - replace: (_, rest) => `${rest}$self.VoiceChannelIndicator({userId:arguments[0]?.userId,isProfile:true})` + replace: (_, rest) => `${rest}$self.VoiceChannelIndicator({userId:arguments[0]?.userId})` }, predicate: () => settings.store.showInUserProfileModal }, @@ -99,7 +99,7 @@ export default definePlugin({ addMemberListDecorator("UserVoiceShow", ({ user }) => user == null ? null : ); } if (settings.store.showInMessages) { - addMessageDecoration("UserVoiceShow", ({ message }) => message?.author == null ? null : ); + addMessageDecoration("UserVoiceShow", ({ message }) => message?.author == null ? null : ); } }, diff --git a/src/plugins/userVoiceShow/style.css b/src/plugins/userVoiceShow/style.css index d172975b8..f9fd56fbf 100644 --- a/src/plugins/userVoiceShow/style.css +++ b/src/plugins/userVoiceShow/style.css @@ -13,16 +13,6 @@ color: var(--interactive-hover); } -.vc-uvs-speaker-margin { - margin-left: 4px; -} - -.vc-uvs-message-indicator { - display: inline-flex; - top: 2.5px; - position: relative; -} - .vc-uvs-tooltip-container { max-width: 300px; } diff --git a/src/utils/types.ts b/src/utils/types.ts index 8f0ec3860..e226c5ba1 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -150,6 +150,11 @@ export interface PluginDef { tags?: string[]; + /** + * Managed style to automatically enable and disable when the plugin is enabled or disabled + */ + managedStyle?: string; + userProfileBadge?: ProfileBadge; onMessageClick?: MessageClickListener;