this repo has no description
1import { InternalItem, Menu, MenuElement } from "@moonlight-mod/types/coreExtensions/contextMenu";
2import spacepack from "@moonlight-mod/wp/spacepack_spacepack";
3import parser from "@moonlight-mod/wp/contextMenu_evilMenu";
4
5// NOTE: We originally had item as a function that returned this, but it didn't
6// quite know how to work out the type and thought it was a JSX element (it
7// *technically* was). This has less type safety, but a @ts-expect-error has
8// zero, so it's better than nothing.
9type ReturnType = MenuElement | MenuElement[];
10
11type Patch = {
12 navId: string;
13 item: React.FC<any>;
14 anchorId: string;
15 before: boolean;
16};
17
18function addItem<T = any>(navId: string, item: React.FC<T>, anchorId: string, before = false) {
19 patches.push({ navId, item, anchorId, before });
20}
21
22const patches: Patch[] = [];
23function _patchMenu(props: React.ComponentProps<Menu>, items: InternalItem[]) {
24 const matches = patches.filter((p) => p.navId === props.navId);
25 if (!matches.length) return items;
26
27 for (const patch of matches) {
28 const idx = items.findIndex((i) => i.key === patch.anchorId);
29 if (idx === -1) continue;
30 items.splice(idx + 1 - +patch.before, 0, ...parser(patch.item(menuProps) as ReturnType));
31 }
32
33 return items;
34}
35
36let menuProps: any;
37function _saveProps(self: any, el: any) {
38 menuProps = el.props;
39
40 const original = self.props.closeContextMenu;
41 self.props.closeContextMenu = function (...args: any[]) {
42 menuProps = undefined;
43 return original?.apply(this, args);
44 };
45
46 return el;
47}
48
49module.exports = {
50 patches,
51 addItem,
52 _patchMenu,
53 _saveProps
54};
55
56// Unmangle Menu elements
57const code =
58 spacepack.require.m[
59 spacepack.findByCode("Menu API only allows Items and groups of Items as children.")[0].id
60 ].toString();
61
62let MangledMenu;
63
64const typeRegex = /if\(.\.type===(.)\.(.+?)\).+?type:"(.+?)"/g;
65const typeMap: Record<string, string | undefined> = {
66 checkbox: "MenuCheckboxItem",
67 control: "MenuControlItem",
68 groupstart: "MenuGroup",
69 customitem: "MenuItem",
70 radio: "MenuRadioItem",
71 separator: "MenuSeparator"
72};
73
74for (const [, modIdent, mangled, type] of code.matchAll(typeRegex)) {
75 if (!MangledMenu) {
76 const modId = code.match(new RegExp(`${modIdent}=.\\((\\d+?)\\)`))![1];
77 MangledMenu = spacepack.require(modId);
78 }
79
80 const prop = typeMap[type];
81 if (!prop) continue;
82 module.exports[prop] = MangledMenu[mangled];
83}