this repo has no description

Merge pull request #168 from moonlight-mod/componentEditor

Add Component Editor

authored by notnite.com and committed by GitHub f6f4e32b 6cc9d254

Changed files
+446
packages
core-extensions
src
types
+75
packages/core-extensions/src/componentEditor/index.ts
··· 1 + import { ExtensionWebpackModule, Patch } from "@moonlight-mod/types"; 2 + 3 + export const patches: Patch[] = [ 4 + // dm list 5 + { 6 + find: ".interactiveSystemDM]:", 7 + replace: [ 8 + { 9 + match: /decorators:(\i\.isSystemDM\(\)\?\(0,\i\.jsx\)\(.+?verified:!0}\):null)/, 10 + replacement: (_, decorators) => 11 + `decorators:require("componentEditor_dmList").default._patchDecorators([${decorators}],arguments[0])` 12 + }, 13 + { 14 + match: /(?<=selected:\i,)children:\[/, 15 + replacement: 'children:require("componentEditor_dmList").default._patchItems([' 16 + }, 17 + { 18 + match: /(?<=onMouseDown:\i}\))]/, 19 + replacement: "],arguments[0])" 20 + } 21 + ], 22 + hardFail: true 23 + }, 24 + 25 + // member list 26 + { 27 + find: ".lostPermission", 28 + replace: [ 29 + { 30 + match: /(?<=\(0,\i\.jsxs\)\(\i\.Fragment,{)children:(\[\i\(\),.+?\i\(\)])/, 31 + replacement: (_, decorators) => 32 + `children:require("componentEditor_memberList").default._patchDecorators(${decorators},arguments[0])` 33 + }, 34 + { 35 + match: /name:null==\i\?\(0,\i\.jsx\)\("span"/, 36 + replacement: (orig: string) => 37 + `children:require("componentEditor_memberList").default._patchItems([],arguments[0]),${orig}` 38 + } 39 + ] 40 + }, 41 + 42 + // messages 43 + { 44 + find: '},"new-member")),', 45 + replace: [ 46 + { 47 + match: /(?<=\.BADGES]=)(\i);/, 48 + replacement: (_, badges) => 49 + `require("componentEditor_messages").default._patchUsernameBadges(${badges},arguments[0]);` 50 + }, 51 + { 52 + match: /(?<=className:\i,)badges:(\i)/, 53 + replacement: (_, badges) => 54 + `badges:require("componentEditor_messages").default._patchBadges(${badges},arguments[0])` 55 + }, 56 + { 57 + match: /(?<=username:\(0,\i\.jsxs\)\(\i\.Fragment,{)children:(\[.+?,\i])/, 58 + replacement: (_, elements) => 59 + `children:require("componentEditor_messages").default._patchUsername(${elements},arguments[0])` 60 + } 61 + ] 62 + } 63 + ]; 64 + 65 + export const webpackModules: Record<string, ExtensionWebpackModule> = { 66 + dmList: { 67 + dependencies: [{ id: "react" }] 68 + }, 69 + memberList: { 70 + dependencies: [{ id: "react" }] 71 + }, 72 + messages: { 73 + dependencies: [{ id: "react" }] 74 + } 75 + };
+11
packages/core-extensions/src/componentEditor/manifest.json
··· 1 + { 2 + "$schema": "https://moonlight-mod.github.io/manifest.schema.json", 3 + "id": "componentEditor", 4 + "apiLevel": 2, 5 + "meta": { 6 + "name": "Component Editor", 7 + "tagline": "A library to add to commonly patched components", 8 + "authors": ["Cynosphere"], 9 + "tags": ["library"] 10 + } 11 + }
+61
packages/core-extensions/src/componentEditor/webpackModules/dmList.tsx
··· 1 + import { 2 + DMList, 3 + DMListItem, 4 + DMListDecorator, 5 + DMListAnchorIndicies, 6 + DMListDecoratorAnchorIndicies 7 + } from "@moonlight-mod/types/coreExtensions/componentEditor"; 8 + import React from "@moonlight-mod/wp/react"; 9 + 10 + const items: Record<string, DMListItem> = {}; 11 + const decorators: Record<string, DMListDecorator> = {}; 12 + 13 + function addEntries( 14 + elements: React.ReactNode[], 15 + entries: Record<string, DMListItem | DMListDecorator>, 16 + indicies: Partial<Record<keyof typeof DMListAnchorIndicies | keyof typeof DMListDecoratorAnchorIndicies, number>>, 17 + props: any 18 + ) { 19 + const originalElements = [...elements]; 20 + for (const [id, entry] of Object.entries(entries)) { 21 + const component = <entry.component {...props} key={id} />; 22 + 23 + if (entry.anchor === undefined) { 24 + if (entry.before) { 25 + elements.splice(0, 0, component); 26 + } else { 27 + elements.push(component); 28 + } 29 + } else { 30 + const index = elements.indexOf(originalElements[indicies[entry.anchor]!]); 31 + elements.splice(index! + (entry.before ? 0 : 1), 0, component); 32 + } 33 + } 34 + } 35 + 36 + export const dmList: DMList = { 37 + addItem(id, component, anchor, before = false) { 38 + items[id] = { 39 + component, 40 + anchor, 41 + before 42 + }; 43 + }, 44 + addDecorator(id, component, anchor, before = false) { 45 + decorators[id] = { 46 + component, 47 + anchor, 48 + before 49 + }; 50 + }, 51 + _patchItems(elements, props) { 52 + addEntries(elements, items, DMListAnchorIndicies, props); 53 + return elements; 54 + }, 55 + _patchDecorators(elements, props) { 56 + addEntries(elements, decorators, DMListDecoratorAnchorIndicies, props); 57 + return elements; 58 + } 59 + }; 60 + 61 + export default dmList;
+50
packages/core-extensions/src/componentEditor/webpackModules/memberList.tsx
··· 1 + import { 2 + MemberList, 3 + MemberListDecorator, 4 + MemberListDecoratorAnchorIndicies 5 + } from "@moonlight-mod/types/coreExtensions/componentEditor"; 6 + import React from "@moonlight-mod/wp/react"; 7 + 8 + const items: Record<string, React.FC<any>> = {}; 9 + const decorators: Record<string, MemberListDecorator> = {}; 10 + 11 + export const memberList: MemberList = { 12 + addItem(id, component) { 13 + items[id] = component; 14 + }, 15 + addDecorator(id, component, anchor, before = false) { 16 + decorators[id] = { 17 + component, 18 + anchor, 19 + before 20 + }; 21 + }, 22 + _patchItems(elements, props) { 23 + for (const [id, Component] of Object.entries(items)) { 24 + elements.push(<Component {...props} key={id} />); 25 + } 26 + 27 + return elements; 28 + }, 29 + _patchDecorators(elements, props) { 30 + const originalElements = [...elements]; 31 + for (const [id, entry] of Object.entries(decorators)) { 32 + const component = <entry.component {...props} key={id} />; 33 + 34 + if (entry.anchor === undefined) { 35 + if (entry.before) { 36 + elements.splice(0, 0, component); 37 + } else { 38 + elements.push(component); 39 + } 40 + } else { 41 + const index = elements.indexOf(originalElements[MemberListDecoratorAnchorIndicies[entry.anchor]!]); 42 + elements.splice(index! + (entry.before ? 0 : 1), 0, component); 43 + } 44 + } 45 + 46 + return elements; 47 + } 48 + }; 49 + 50 + export default memberList;
+82
packages/core-extensions/src/componentEditor/webpackModules/messages.tsx
··· 1 + import { 2 + MessageBadge, 3 + MessageBadgeIndicies, 4 + Messages, 5 + MessageUsername, 6 + MessageUsernameBadge, 7 + MessageUsernameBadgeIndicies, 8 + MessageUsernameIndicies 9 + } from "@moonlight-mod/types/coreExtensions/componentEditor"; 10 + import React from "@moonlight-mod/wp/react"; 11 + 12 + const username: Record<string, MessageUsername> = {}; 13 + const usernameBadges: Record<string, MessageUsernameBadge> = {}; 14 + const badges: Record<string, MessageBadge> = {}; 15 + 16 + function addEntries( 17 + elements: React.ReactNode[], 18 + entries: Record<string, MessageUsername | MessageUsernameBadge | MessageBadge>, 19 + indicies: Partial< 20 + Record< 21 + | keyof typeof MessageUsernameIndicies 22 + | keyof typeof MessageUsernameBadgeIndicies 23 + | keyof typeof MessageBadgeIndicies, 24 + number 25 + > 26 + >, 27 + props: any 28 + ) { 29 + const originalElements = [...elements]; 30 + for (const [id, entry] of Object.entries(entries)) { 31 + const component = <entry.component {...props} key={id} />; 32 + 33 + if (entry.anchor === undefined) { 34 + if (entry.before) { 35 + elements.splice(0, 0, component); 36 + } else { 37 + elements.push(component); 38 + } 39 + } else { 40 + const index = elements.indexOf(originalElements[indicies[entry.anchor]!]); 41 + elements.splice(index! + (entry.before ? 0 : 1), 0, component); 42 + } 43 + } 44 + } 45 + 46 + export const messages: Messages = { 47 + addToUsername(id, component, anchor, before = false) { 48 + username[id] = { 49 + component, 50 + anchor, 51 + before 52 + }; 53 + }, 54 + addUsernameBadge(id, component, anchor, before = false) { 55 + usernameBadges[id] = { 56 + component, 57 + anchor, 58 + before 59 + }; 60 + }, 61 + addBadge(id, component, anchor, before = false) { 62 + badges[id] = { 63 + component, 64 + anchor, 65 + before 66 + }; 67 + }, 68 + _patchUsername(elements, props) { 69 + addEntries(elements, username, MessageUsernameIndicies, props); 70 + return elements; 71 + }, 72 + _patchUsernameBadges(elements, props) { 73 + addEntries(elements, usernameBadges, MessageUsernameBadgeIndicies, props); 74 + return elements; 75 + }, 76 + _patchBadges(elements, props) { 77 + addEntries(elements, badges, MessageBadgeIndicies, props); 78 + return elements; 79 + } 80 + }; 81 + 82 + export default messages;
+1
packages/types/src/coreExtensions.ts
··· 6 6 export * as Moonbase from "./coreExtensions/moonbase"; 7 7 export * as AppPanels from "./coreExtensions/appPanels"; 8 8 export * as Commands from "./coreExtensions/commands"; 9 + export * as ComponentEditor from "./coreExtensions/componentEditor";
+145
packages/types/src/coreExtensions/componentEditor.ts
··· 1 + type Patcher<T> = (elements: React.ReactNode[], props: T) => React.ReactNode[]; 2 + 3 + //#region DM List 4 + export type DMListAnchors = 5 + | "content" 6 + | "favorite-server-indicator" 7 + | "ignored-indicator" 8 + | "blocked-indicator" 9 + | "close-button" 10 + | undefined; 11 + export type DMListDecoratorAnchors = "system-tag" | undefined; 12 + 13 + export enum DMListAnchorIndicies { 14 + content = 0, 15 + "favorite-server-indicator", 16 + "ignored-indicator", 17 + "blocked-indicator", 18 + "close-button" 19 + } 20 + export enum DMListDecoratorAnchorIndicies { 21 + "system-tag" = 0 22 + } 23 + 24 + export type DMListItem = { 25 + component: React.FC<any>; 26 + anchor: DMListAnchors; 27 + before: boolean; 28 + }; 29 + export type DMListDecorator = { 30 + component: React.FC<any>; 31 + anchor: DMListDecoratorAnchors; 32 + before: boolean; 33 + }; 34 + 35 + export type DMList = { 36 + addItem: (id: string, component: React.FC<any>, anchor?: DMListAnchors, before?: boolean) => void; 37 + addDecorator: (id: string, component: React.FC<any>, anchor?: DMListDecoratorAnchors, before?: boolean) => void; 38 + //TODO: fix props type 39 + /** 40 + * @private 41 + */ 42 + _patchItems: Patcher<any>; 43 + /** 44 + * @private 45 + */ 46 + _patchDecorators: Patcher<any>; 47 + }; 48 + //#endregion 49 + 50 + //#region Member List 51 + export type MemberListDecoratorAnchors = "bot-tag" | "owner-crown" | "boost-icon" | undefined; 52 + 53 + export enum MemberListDecoratorAnchorIndicies { 54 + "bot-tag" = 0, 55 + "owner-crown", 56 + "boost-icon" 57 + } 58 + 59 + export type MemberListDecorator = { 60 + component: React.FC<any>; 61 + anchor: MemberListDecoratorAnchors; 62 + before: boolean; 63 + }; 64 + 65 + export type MemberList = { 66 + addItem: (id: string, component: React.FC<any>) => void; 67 + addDecorator: (id: string, component: React.FC<any>, anchor?: MemberListDecoratorAnchors, before?: boolean) => void; 68 + //TODO: fix props type 69 + /** 70 + * @private 71 + */ 72 + _patchItems: Patcher<any>; 73 + /** 74 + * @private 75 + */ 76 + _patchDecorators: Patcher<any>; 77 + }; 78 + //#endregion 79 + 80 + //#region Messages 81 + export type MessageUsernameAnchors = "communication-disabled" | "username" | undefined; 82 + export type MessageUsernameBadgeAnchors = 83 + | "nitro-author" 84 + | "role-icon" 85 + | "new-member" 86 + | "leaderboard-champion" 87 + | "connections" 88 + | undefined; 89 + export type MessageBadgeAnchors = "silent" | "potion" | undefined; 90 + 91 + export type MessageUsername = { 92 + component: React.FC<any>; 93 + anchor: MessageUsernameAnchors; 94 + before: boolean; 95 + }; 96 + export type MessageUsernameBadge = { 97 + component: React.FC<any>; 98 + anchor: MessageUsernameBadgeAnchors; 99 + before: boolean; 100 + }; 101 + export type MessageBadge = { 102 + component: React.FC<any>; 103 + anchor: MessageBadgeAnchors; 104 + before: boolean; 105 + }; 106 + 107 + export enum MessageUsernameIndicies { 108 + "communication-disabled" = 0, 109 + username 110 + } 111 + export enum MessageUsernameBadgeIndicies { 112 + "nitro-author" = 0, 113 + "role-icon", 114 + "new-member", 115 + "leaderboard-champion", 116 + connections 117 + } 118 + export enum MessageBadgeIndicies { 119 + silent = 0, 120 + potion 121 + } 122 + 123 + export type Messages = { 124 + addToUsername: (id: string, component: React.FC<any>, anchor?: MessageUsernameAnchors, before?: boolean) => void; 125 + addUsernameBadge: ( 126 + id: string, 127 + component: React.FC<any>, 128 + anchor?: MessageUsernameBadgeAnchors, 129 + before?: boolean 130 + ) => void; 131 + addBadge: (id: string, component: React.FC<any>, anchor?: MessageBadgeAnchors, before?: boolean) => void; 132 + /** 133 + * @private 134 + */ 135 + _patchUsername: Patcher<any>; 136 + /** 137 + * @private 138 + */ 139 + _patchUsernameBadges: Patcher<any>; 140 + /** 141 + * @private 142 + */ 143 + _patchBadges: Patcher<any>; 144 + }; 145 + //#endregion
+5
packages/types/src/discord/require.ts
··· 1 1 import { AppPanels } from "../coreExtensions/appPanels"; 2 2 import { Commands } from "../coreExtensions/commands"; 3 + import { DMList, MemberList, Messages } from "../coreExtensions/componentEditor"; 3 4 import { ContextMenu, EvilItemParser } from "../coreExtensions/contextMenu"; 4 5 import { Markdown } from "../coreExtensions/markdown"; 5 6 import { Moonbase } from "../coreExtensions/moonbase"; ··· 12 13 declare function WebpackRequire(id: "appPanels_appPanels"): AppPanels; 13 14 14 15 declare function WebpackRequire(id: "commands_commands"): Commands; 16 + 17 + declare function WebpackRequire(id: "componentEditor_dmList"): DMList; 18 + declare function WebpackRequire(id: "componentEditor_memberList"): MemberList; 19 + declare function WebpackRequire(id: "componentEditor_messages"): Messages; 15 20 16 21 declare function WebpackRequire(id: "contextMenu_evilMenu"): EvilItemParser; 17 22 declare function WebpackRequire(id: "contextMenu_contextMenu"): ContextMenu;
+16
packages/types/src/import.d.ts
··· 12 12 13 13 declare module "@moonlight-mod/wp/common_stores"; 14 14 15 + declare module "@moonlight-mod/wp/componentEditor_dmList" { 16 + import { CoreExtensions } from "@moonlight-mod/types"; 17 + export const dmList: CoreExtensions.ComponentEditor.DMList; 18 + export default dmList; 19 + } 20 + declare module "@moonlight-mod/wp/componentEditor_memberList" { 21 + import { CoreExtensions } from "@moonlight-mod/types"; 22 + export const memberList: CoreExtensions.ComponentEditor.MemberList; 23 + export default memberList; 24 + } 25 + declare module "@moonlight-mod/wp/componentEditor_messages" { 26 + import { CoreExtensions } from "@moonlight-mod/types"; 27 + export const message: CoreExtensions.ComponentEditor.Messages; 28 + export default message; 29 + } 30 + 15 31 declare module "@moonlight-mod/wp/contextMenu_evilMenu" { 16 32 import { CoreExtensions } from "@moonlight-mod/types"; 17 33 const EvilParser: CoreExtensions.ContextMenu.EvilItemParser;