Plugin

FullSearchContext

Makes the message context menu in message search results have all options you'd expect

Utility
index.tsx
Download

Source

src/plugins/fullSearchContext/index.tsx
1/*
2 * FiveCord — a Discord client mod
3 * Copyright (c) 2025 FiveCord
4 * SPDX-License-Identifier: GPL-3.0-or-later
5 */
6
7import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/ContextMenu";
8import { migratePluginSettings } from "@api/Settings";
9import { Devs } from "@utils/constants";
10import { getIntlMessage } from "@utils/discord";
11import { NoopComponent } from "@utils/react";
12import definePlugin from "@utils/types";
13import { Message } from "@vencord/discord-types";
14import { filters, findByCodeLazy, waitFor } from "@webpack";
15import { ChannelStore, ContextMenuApi, UserStore } from "@webpack/common";
16
17const useMessageMenu = findByCodeLazy(".MESSAGE,commandTargetId:");
18
19interface CopyIdMenuItemProps {
20 id: string;
21 label: string;
22}
23
24let CopyIdMenuItem: (props: CopyIdMenuItemProps) => React.ReactElement | null = NoopComponent;
25waitFor(filters.componentByCode('"cannot copy null text"'), m => CopyIdMenuItem = m);
26
27function MessageMenu({ message, channel, onHeightUpdate }) {
28 const canReport = message.author &&
29 !(message.author.id === UserStore.getCurrentUser().id || message.author.system);
30
31 return useMessageMenu({
32 navId: "message-actions",
33 ariaLabel: getIntlMessage("MESSAGE_UTILITIES_A11Y_LABEL"),
34
35 message,
36 channel,
37 canReport,
38 onHeightUpdate,
39 onClose: () => ContextMenuApi.closeContextMenu(),
40
41 textSelection: "",
42 favoriteableType: null,
43 favoriteableId: null,
44 favoriteableName: null,
45 itemHref: void 0,
46 itemSrc: void 0,
47 itemSafeSrc: void 0,
48 itemTextContent: void 0,
49
50 isFullSearchContextMenu: true
51 });
52}
53
54interface MessageActionsProps {
55 message: Message;
56 isFullSearchContextMenu?: boolean;
57}
58
59const contextMenuPatch: NavContextMenuPatchCallback = (children, props: MessageActionsProps) => {
60 if (props?.isFullSearchContextMenu == null) return;
61
62 const group = findGroupChildrenByChildId("devmode-copy-id", children, true);
63 group?.push(
64 CopyIdMenuItem({ id: props.message.author.id, label: getIntlMessage("COPY_ID_AUTHOR") })
65 );
66};
67
68migratePluginSettings("FullSearchContext", "SearchReply");
69export default definePlugin({
70 name: "FullSearchContext",
71 description: "Makes the message context menu in message search results have all options you'd expect",
72 tags: ["Utility"],
73 authors: [Devs.Ven, Devs.Aria],
74
75 patches: [{
76 find: "Listbox navigator was given an unhandled action",
77 replacement: {
78 match: /this(?=\.handleContextMenu\(\i,\i\))/,
79 replace: "$self"
80 }
81 }],
82
83 handleContextMenu(event: React.MouseEvent, message: Message) {
84 const channel = ChannelStore.getChannel(message.channel_id);
85 if (!channel) return;
86
87 event.stopPropagation();
88
89 ContextMenuApi.openContextMenu(event, contextMenuProps =>
90 <MessageMenu
91 message={message}
92 channel={channel}
93 onHeightUpdate={contextMenuProps.onHeightUpdate}
94 />
95 );
96 },
97
98 contextMenus: {
99 "message-actions": contextMenuPatch
100 }
101});
102