diff --git a/packages/discord-types/src/utils.d.ts b/packages/discord-types/src/utils.d.ts index 38c4f1420..a45f04eb5 100644 --- a/packages/discord-types/src/utils.d.ts +++ b/packages/discord-types/src/utils.d.ts @@ -416,3 +416,48 @@ export interface EmojiUtils { triggerFullscreenAnimation(emoji: any, node: HTMLElement): void; applyPlatformToThemedEmojiColorPalette(colors: any): any; } + +export interface OpenUserSettingsOpts { + /** + * a *sub*section of settings to navigate to + * + * to navigate to a top-level section, use the navigationTarget parameter of {@link SettingsRouter.openUserSettings} instead + * + * discord has an enum with all the possible values (go dig in the openUserSettings source) + */ + path?: string; + /** + * modal stacking behavior, defaults to "replaceAll" + */ + stackingBehavior?: "replaceAll" | "stack" | "replace"; + // ... misc analytics options +} + +export interface SettingsRouter { + openUserSettings(navigationTarget?: string, opts?: OpenUserSettingsOpts, onOpen?: () => void): Promise; +} + +export interface OpenUserProfileModalOpts { + userId: string; + guildId?: string | null; + originGuildId?: string | null; + channelId?: string | null; + messageId?: string | null; + roleId?: string | null; + sessionId?: unknown | null; + joinRequestId?: unknown; + tabSection?: unknown; + scrollTarget?: unknown; + hideRestrictedProfile?: boolean; + sourceAnalyticsLocations?: string[]; + appContext?: unknown; + /** + * defaults to null + */ + customStatusPrompt?: unknown; + onModalOpen?: unknown; +} + +export interface UserProfileModalActionCreators { + openUserProfileModal(opts: OpenUserProfileModalOpts): Promise; +} diff --git a/src/plugins/betterRoleContext/index.tsx b/src/plugins/betterRoleContext/index.tsx index ed53b55c0..2bb93a103 100644 --- a/src/plugins/betterRoleContext/index.tsx +++ b/src/plugins/betterRoleContext/index.tsx @@ -218,14 +218,22 @@ export default definePlugin({ settings, openRoleContextMenu, patches: [ - // Conflicts with RoleColorEverywhere which changes the code at the end of our match. (and also uses same find & similar match) - // However, BetterRoleContext applies first (alphabetic order), so it's not an issue + // This patch is completely overwritten by RoleColorEverywhere, but RoleColorEverywhere handles it itself + // member list role headers (in threads) { find: 'tutorialId:"whos-online', replacement: { match: /(?<=#{intl::CHANNEL_MEMBERS_A11Y_LABEL}.{0,200}?"aria-hidden":!0,)children:.{0,200}?(?:—|\\u2014) ",\i\]\}\)\]/, replace: "onContextMenu:e=>$self.openRoleContextMenu(e,arguments[0]),$&" } + }, + // member list role headers + { + find: "?null:new Intl.NumberFormat", + replacement: { + match: /(?<=#{intl::CHANNEL_MEMBERS_A11Y_LABEL},\{title:\i,count:\i\}\)\}\),\(0,\i\.jsxs\)\("div",\{)/, + replace: "onContextMenu:e=>$self.openRoleContextMenu(e,arguments[0])," + } } ], diff --git a/src/plugins/roleColorEverywhere/index.tsx b/src/plugins/roleColorEverywhere/index.tsx index 651985f67..7a5f65f77 100644 --- a/src/plugins/roleColorEverywhere/index.tsx +++ b/src/plugins/roleColorEverywhere/index.tsx @@ -16,9 +16,11 @@ * along with this program. If not, see . */ +import { isPluginEnabled } from "@api/PluginManager"; import { definePluginSettings, Settings } from "@api/Settings"; import ErrorBoundary from "@components/ErrorBoundary"; import { getCustomColorString } from "@equicordplugins/customUserColors"; +import BetterRoleContext from "@plugins/betterRoleContext"; import { Devs } from "@utils/constants"; import { Logger } from "@utils/Logger"; import definePlugin, { makeRange, OptionType } from "@utils/types"; @@ -103,23 +105,24 @@ export default definePlugin({ ], predicate: () => settings.store.chatMentions }, - // Member List Role Headers + // Member List Role Headers (in threads) { find: 'tutorialId:"whos-online', replacement: [ { - match: /(#{intl::CHANNEL_MEMBERS_A11Y_LABEL}.+}\):null,).{0,100}?(?:—|\\u2014) ",\i\]\}\)\]/, + match: /(#{intl::CHANNEL_MEMBERS_A11Y_LABEL}.{0,200}?}\):null,).{0,200}?(?:—|\\u2014) ",\i\]\}\)\]/, replace: "$1$self.RoleGroupColor(arguments[0])]" }, ], predicate: () => settings.store.memberList }, + // Member List Role Headers { - find: "#{intl::THREAD_BROWSER_PRIVATE}", + find: "?null:new Intl.NumberFormat", replacement: [ { - match: /children:\[\i," (?:—|\\u2014) ",\i\]/, - replace: "children:[$self.RoleGroupColor(arguments[0])]" + match: /\(0,\i\.jsx\)\("span",\{[^}]+\}\),null==\i\?null:\(0,\i\.jsxs\)\("span",\{children:\["\\xa0\\u2014 ",\i\]\}\)\]/, + replace: "$self.RoleGroupColor(arguments[0])]" }, ], predicate: () => settings.store.memberList @@ -129,7 +132,7 @@ export default definePlugin({ find: "#{intl::GUEST_NAME_SUFFIX})]", replacement: [ { - match: /#{intl::GUEST_NAME_SUFFIX}.{0,50}?"".{0,100}\](?=\}\))(?<=guildId:(\i),.+?user:(\i).+?)/, + match: /#{intl::GUEST_NAME_SUFFIX}.{0,50}?""\](?<=guildId:(\i),.+?user:(\i).+?)/, replace: "$&,style:$self.getColorStyle($2.id,$1)," } ], @@ -221,13 +224,18 @@ export default definePlugin({ RoleGroupColor: ErrorBoundary.wrap(({ id, count, title, guildId, label }: { id: string; count: number; title: string; guildId: string; label: string; }) => { const role = GuildRoleStore.getRole(guildId, id); + // we overwrite the context menu event added by BetterRoleContext in our patch + const wantsRoleContext = isPluginEnabled(BetterRoleContext.name); return ( - + BetterRoleContext.openRoleContextMenu(e, { guildId, id }) : undefined} + > {title ?? label} — {count} ); diff --git a/src/plugins/stickerPaste/index.ts b/src/plugins/stickerPaste/index.ts index 0dd0bd2b3..afdd53f57 100644 --- a/src/plugins/stickerPaste/index.ts +++ b/src/plugins/stickerPaste/index.ts @@ -15,9 +15,11 @@ export default definePlugin({ patches: [ { - find: ".stickers,previewSticker:", + // This function is a util func from another module + // but it only has once use here so it's inlined + find: ".CREATE_FORUM_POST||function(", replacement: { - match: /if\(\i\.\i\.getUploadCount/, + match: /(?<=\){)if\(\i\.\i\.getUploadCount/, replace: "return true;$&", } } diff --git a/src/utils/discord.tsx b/src/utils/discord.tsx index 271865294..aeeacc723 100644 --- a/src/utils/discord.tsx +++ b/src/utils/discord.tsx @@ -186,10 +186,6 @@ export async function openUserProfile(id: string) { userId: id, guildId, channelId: SelectedChannelStore.getChannelId(), - analyticsLocation: { - page: guildId ? "Guild Channel" : "DM Channel", - section: "Profile Popout" - } }); } diff --git a/src/webpack/common/utils.ts b/src/webpack/common/utils.ts index a34f9c132..129fe6de8 100644 --- a/src/webpack/common/utils.ts +++ b/src/webpack/common/utils.ts @@ -169,8 +169,9 @@ export const ChannelRouter: t.ChannelRouter = mapMangledModuleLazy('"Thread must transitionToThread: filters.byCode('"Thread must have a parent ID."') }); -export let SettingsRouter: any; -waitFor(["openUserSettings", "USER_SETTINGS_MODAL_KEY"], m => SettingsRouter = m); +export const SettingsRouter: t.SettingsRouter = mapMangledModuleLazy('type:"USER_SETTINGS_MODAL_OPEN"', { + openUserSettings: filters.byCode('type:"USER_SETTINGS_MODAL_OPEN"') +}); export const PermissionsBits: t.PermissionsBits = findLazy(m => typeof m.ADMINISTRATOR === "bigint"); @@ -184,7 +185,9 @@ export const { zustandPersist } = mapMangledModuleLazy(".onRehydrateStorage)?", export const MessageActions = findByPropsLazy("editMessage", "sendMessage"); export const MessageCache = findByPropsLazy("clearCache", "_channelMessages"); -export const UserProfileActions = findByPropsLazy("openUserProfileModal", "closeUserProfileModal"); +export const UserProfileActions: t.UserProfileModalActionCreators = mapMangledModuleLazy(".log(`Failed to fetch profile for $", { + openUserProfileModal: filters.byCode('type:"USER_PROFILE_MODAL_OPEN"') +}); export const InviteActions = findByPropsLazy("resolveInvite"); export const ChannelActionCreators = findByPropsLazy("openPrivateChannel");