Update ComponentPatcher (#875)
* Add onAdded util. * Update ComponentPatcher * make classes consistent, update logger import.
This commit is contained in:
parent
06a843e61e
commit
416e50a672
|
@ -4,27 +4,47 @@ import DiscordModules from "./discordmodules";
|
||||||
import Utilities from "./utilities";
|
import Utilities from "./utilities";
|
||||||
import Patcher from "./patcher";
|
import Patcher from "./patcher";
|
||||||
import BDLogo from "../ui/icons/bdlogo";
|
import BDLogo from "../ui/icons/bdlogo";
|
||||||
|
import Logger from "common/logger";
|
||||||
|
|
||||||
const React = DiscordModules.React;
|
const React = DiscordModules.React;
|
||||||
const Tooltip = WebpackModules.getByDisplayName("Tooltip");
|
const Tooltip = WebpackModules.getByDisplayName("Tooltip");
|
||||||
|
const MutedStore = WebpackModules.getByProps("isMuted");
|
||||||
|
const Anchor = WebpackModules.getByDisplayName("Anchor");
|
||||||
|
|
||||||
|
const Developers = [
|
||||||
|
/* Zerebos#7790 */
|
||||||
|
"249746236008169473"
|
||||||
|
];
|
||||||
|
|
||||||
|
const DeveloperBadge = function DeveloperBadge({type, size = 16}) {
|
||||||
|
return React.createElement(Tooltip, {color: "primary", position: "top", text: "BetterDiscord Developer"},
|
||||||
|
props => React.createElement(Anchor, Object.assign({className: `bd-${type}-badge`, href: "https://github.com/rauenzi/BetterDiscordApp", title: "BetterDiscord", target: "_blank"}, props),
|
||||||
|
React.createElement(BDLogo, {size, className: "bd-logo"})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export default new class ComponentPatcher {
|
export default new class ComponentPatcher {
|
||||||
|
warn(...message) {return Logger.warn("ComponentPatcher", ...message);}
|
||||||
|
error(...message) {return Logger.error("ComponentPatcher", ...message);}
|
||||||
|
debug(...message) {return Logger.debug("ComponentPatcher", ...message);}
|
||||||
|
|
||||||
initialize() {
|
initialize() {
|
||||||
Utilities.suppressErrors(this.patchSocial.bind(this), "BD Social Patch")();
|
Utilities.suppressErrors(this.patchSocial.bind(this), "BD Social Patch")();
|
||||||
/*
|
|
||||||
Utilities.suppressErrors(this.patchGuildPills.bind(this), "BD Guild Pills Patch")();
|
Utilities.suppressErrors(this.patchGuildPills.bind(this), "BD Guild Pills Patch")();
|
||||||
Utilities.suppressErrors(this.patchGuildListItems.bind(this), "BD Guild List Items Patch")();
|
Utilities.suppressErrors(this.patchGuildListItems.bind(this), "BD Guild List Items Patch")();
|
||||||
|
/*
|
||||||
Utilities.suppressErrors(this.patchGuildSeparator.bind(this), "BD Guild Separator Patch")();
|
Utilities.suppressErrors(this.patchGuildSeparator.bind(this), "BD Guild Separator Patch")();
|
||||||
*/
|
*/
|
||||||
Utilities.suppressErrors(this.patchMessageHeader.bind(this), "BD Message Header Patch")();
|
Utilities.suppressErrors(this.patchMessageHeader.bind(this), "BD Message Header Patch")();
|
||||||
Utilities.suppressErrors(this.patchMemberList.bind(this), "BD Member List Patch")();
|
Utilities.suppressErrors(this.patchMemberList.bind(this), "BD Member List Patch")();
|
||||||
|
Utilities.suppressErrors(this.patchProfile.bind(this), "BD Profile Badges Patch")();
|
||||||
}
|
}
|
||||||
|
|
||||||
patchSocial() {
|
patchSocial() {
|
||||||
if (this.socialPatch) return;
|
if (this.socialPatch) return;
|
||||||
const TabBar = WebpackModules.getByDisplayName("TabBar");
|
const TabBar = WebpackModules.getByDisplayName("TabBar");
|
||||||
const Anchor = WebpackModules.getByDisplayName("Anchor");
|
|
||||||
if (!TabBar) return;
|
if (!TabBar) return;
|
||||||
this.socialPatch = Patcher.after("ComponentPatcher", TabBar.prototype, "render", (thisObject, args, returnValue) => {
|
this.socialPatch = Patcher.after("ComponentPatcher", TabBar.prototype, "render", (thisObject, args, returnValue) => {
|
||||||
const children = returnValue.props.children;
|
const children = returnValue.props.children;
|
||||||
|
@ -57,15 +77,43 @@ export default new class ComponentPatcher {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
isGuildMuted(guildId) {
|
||||||
patchGuildListItems() {
|
if (!MutedStore || typeof(MutedStore.isMuted) !== "function") return false;
|
||||||
|
|
||||||
|
return MutedStore.isMuted(guildId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @updated 07.07.2021
|
||||||
|
*/
|
||||||
|
async patchGuildListItems() {
|
||||||
if (this.guildListItemsPatch) return;
|
if (this.guildListItemsPatch) return;
|
||||||
const listItemClass = DiscordModules.GuildClasses.listItem.split(" ")[0];
|
const guildClasses = WebpackModules.getByProps("downloadProgressCircle", "guilds");
|
||||||
const blobClass = DiscordModules.GuildClasses.blobContainer.split(" ")[0];
|
if (!guildClasses) return this.warn("Failed to get guilds classes!");
|
||||||
const reactInstance = Utilities.getReactInstance(document.querySelector(`.${listItemClass} .${blobClass}`).parentElement);
|
|
||||||
const GuildComponent = reactInstance.return.type;
|
const start = Date.now();
|
||||||
if (!GuildComponent) return;
|
const guilds = await new Promise((resolve) => Utilities.onAdded(`.${guildClasses.guilds}`, resolve));
|
||||||
this.guildListItemsPatch = Patcher.after("ComponentPatcher", GuildComponent.prototype, "render", (thisObject, _, returnValue) => {
|
if (!guilds) return this.error("Cannot find guilds component.");
|
||||||
|
const reactInstance = Utilities.getReactInstance(guilds);
|
||||||
|
if (!reactInstance) return this.error("Failed to get Guilds instance.");
|
||||||
|
const GuildComponent = await new Promise((resolve) => {
|
||||||
|
let tries = 0;
|
||||||
|
const searchForGuild = function () {
|
||||||
|
tries++;
|
||||||
|
const guild = Utilities.findInTree(reactInstance, e => e?.type?.displayName === "Guild", {walkable: ["child", "sibling"]});
|
||||||
|
if (guild) {resolve(guild);}
|
||||||
|
else if (tries < 10) {setTimeout(searchForGuild, 300);}
|
||||||
|
else {resolve(null);}
|
||||||
|
};
|
||||||
|
|
||||||
|
searchForGuild();
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!GuildComponent || typeof(GuildComponent.type) !== "function") return this.error("Failed to get Guild component.");
|
||||||
|
this.debug(`Found Guild component in ${Date.now() - start}ms`);
|
||||||
|
|
||||||
|
const Guild = GuildComponent.type;
|
||||||
|
this.guildListItemsPatch = Patcher.after("ComponentPatcher", Guild.prototype, "render", (thisObject, _, returnValue) => {
|
||||||
if (!returnValue || !thisObject) return;
|
if (!returnValue || !thisObject) return;
|
||||||
const guildData = thisObject.props;
|
const guildData = thisObject.props;
|
||||||
returnValue.props.className += " bd-guild";
|
returnValue.props.className += " bd-guild";
|
||||||
|
@ -75,8 +123,15 @@ export default new class ComponentPatcher {
|
||||||
if (guildData.video) returnValue.props.className += " bd-video";
|
if (guildData.video) returnValue.props.className += " bd-video";
|
||||||
if (guildData.badge) returnValue.props.className += " bd-badge";
|
if (guildData.badge) returnValue.props.className += " bd-badge";
|
||||||
if (guildData.animatable) returnValue.props.className += " bd-animatable";
|
if (guildData.animatable) returnValue.props.className += " bd-animatable";
|
||||||
|
if (guildData.unavailable) returnValue.props.className += " bd-unavailable";
|
||||||
|
if (guildData.screenshare) returnValue.props.className += " bd-screenshare";
|
||||||
|
if (guildData.liveStage) returnValue.props.className += " bd-live-stage";
|
||||||
|
if (this.isGuildMuted(guildData.guild.id)) returnValue.props.className += " bd-muted";
|
||||||
|
|
||||||
return returnValue;
|
return returnValue;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (reactInstance.forceUpdate) reactInstance.forceUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
patchGuildPills() {
|
patchGuildPills() {
|
||||||
|
@ -91,7 +146,7 @@ export default new class ComponentPatcher {
|
||||||
return returnValue;
|
return returnValue;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
patchGuildSeparator() {
|
patchGuildSeparator() {
|
||||||
if (this.guildSeparatorPatch) return;
|
if (this.guildSeparatorPatch) return;
|
||||||
const Guilds = WebpackModules.getByDisplayName("Guilds");
|
const Guilds = WebpackModules.getByDisplayName("Guilds");
|
||||||
|
@ -109,42 +164,62 @@ export default new class ComponentPatcher {
|
||||||
});
|
});
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @updated 07.07.2021
|
||||||
|
*/
|
||||||
patchMessageHeader() {
|
patchMessageHeader() {
|
||||||
if (this.messageHeaderPatch) return;
|
if (this.messageHeaderPatch) return;
|
||||||
const MessageHeader = WebpackModules.getByProps("MessageTimestamp");
|
const MessageTimestamp = WebpackModules.getModule(m => m?.default?.toString().indexOf("showTimestampOnHover") > -1);
|
||||||
const Anchor = WebpackModules.find(m => m.displayName == "Anchor");
|
this.messageHeaderPatch = Patcher.after("ComponentPatcher", MessageTimestamp, "default", (_, [{message}], returnValue) => {
|
||||||
if (!Anchor || !MessageHeader || !MessageHeader.default) return;
|
const userId = Utilities.getNestedProp(message, "author.id");
|
||||||
this.messageHeaderPatch = Patcher.after("ComponentPatcher", MessageHeader, "default", (_, args, returnValue) => {
|
if (Developers.indexOf(userId) < 0) return;
|
||||||
const author = Utilities.getNestedProp(args[0], "message.author");
|
const children = Utilities.getNestedProp(returnValue, "props.children.1.props.children");
|
||||||
const children = Utilities.getNestedProp(returnValue, "props.children.1.props.children.1.props.children");
|
|
||||||
if (!children || !author || !author.id || author.id !== "249746236008169473") return;
|
|
||||||
if (!Array.isArray(children)) return;
|
if (!Array.isArray(children)) return;
|
||||||
children.push(
|
|
||||||
React.createElement(Tooltip, {color: "primary", position: "top", text: "BetterDiscord Developer"},
|
children.splice(2, 0,
|
||||||
props => React.createElement(Anchor, Object.assign({className: "bd-chat-badge", href: "https://github.com/rauenzi/BetterDiscordApp", title: "BetterDiscord", target: "_blank"}, props),
|
React.createElement(DeveloperBadge, {
|
||||||
React.createElement(BDLogo, {size: "16px", className: "bd-logo"})
|
type: "chat"
|
||||||
)
|
})
|
||||||
)
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @updated 07.07.2021
|
||||||
|
*/
|
||||||
patchMemberList() {
|
patchMemberList() {
|
||||||
if (this.memberListPatch) return;
|
if (this.memberListPatch) return;
|
||||||
const MemberListItem = WebpackModules.findByDisplayName("MemberListItem");
|
const MemberListItem = WebpackModules.findByDisplayName("MemberListItem");
|
||||||
const Anchor = WebpackModules.find(m => m.displayName == "Anchor");
|
if (!MemberListItem?.prototype?.renderDecorators) return;
|
||||||
if (!Anchor || !MemberListItem || !MemberListItem.prototype || !MemberListItem.prototype.renderDecorators) return;
|
|
||||||
this.memberListPatch = Patcher.after("ComponentPatcher", MemberListItem.prototype, "renderDecorators", (thisObject, args, returnValue) => {
|
this.memberListPatch = Patcher.after("ComponentPatcher", MemberListItem.prototype, "renderDecorators", (thisObject, args, returnValue) => {
|
||||||
const user = Utilities.getNestedProp(thisObject, "props.user");
|
const user = Utilities.getNestedProp(thisObject, "props.user");
|
||||||
const children = Utilities.getNestedProp(returnValue, "props.children");
|
const children = Utilities.getNestedProp(returnValue, "props.children");
|
||||||
if (!children || !user || !user.id || user.id !== "249746236008169473") return;
|
if (!children || Developers.indexOf(user.id) < 0) return;
|
||||||
if (!Array.isArray(children)) return;
|
if (!Array.isArray(children)) return;
|
||||||
children.push(
|
children.push(
|
||||||
React.createElement(Tooltip, {color: "primary", position: "top", text: "BetterDiscord Developer"},
|
React.createElement(DeveloperBadge, {
|
||||||
props => React.createElement(Anchor, Object.assign({className: "bd-member-badge", href: "https://github.com/rauenzi/BetterDiscordApp", title: "BetterDiscord", target: "_blank"}, props),
|
type: "member"
|
||||||
React.createElement(BDLogo, {size: "16px", className: "bd-logo"})
|
})
|
||||||
)
|
);
|
||||||
)
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @updated 07.07.2021
|
||||||
|
*/
|
||||||
|
patchProfile() {
|
||||||
|
if (this.profilePatch) return;
|
||||||
|
const UserProfileBadgeList = WebpackModules.getModule(m => m?.default?.displayName === "UserProfileBadgeList");
|
||||||
|
this.profilePatch = Patcher.after("ComponentPatcher", UserProfileBadgeList, "default", (_, [{user}], res) => {
|
||||||
|
if (Developers.indexOf(user?.id) < 0) return;
|
||||||
|
const children = Utilities.getNestedProp(res, "props.children");
|
||||||
|
if (!Array.isArray(children)) return;
|
||||||
|
|
||||||
|
children.unshift(
|
||||||
|
React.createElement(DeveloperBadge, {
|
||||||
|
type: "profile",
|
||||||
|
size: 18
|
||||||
|
})
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,6 +80,29 @@ export default class Utilities {
|
||||||
observer.observe(document.body, {subtree: true, childList: true});
|
observer.observe(document.body, {subtree: true, childList: true});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static onAdded(selector, callback) {
|
||||||
|
if (document.body.querySelector(selector)) return callback(document.body.querySelector(selector));
|
||||||
|
|
||||||
|
const observer = new MutationObserver((mutations) => {
|
||||||
|
for (let m = 0; m < mutations.length; m++) {
|
||||||
|
for (let i = 0; i < mutations[m].addedNodes.length; i++) {
|
||||||
|
const mutation = mutations[m].addedNodes[i];
|
||||||
|
if (mutation.nodeType === 3) continue; // ignore text
|
||||||
|
const directMatch = mutation.matches(selector) && mutation;
|
||||||
|
const childrenMatch = mutation.querySelector(selector);
|
||||||
|
if (directMatch || childrenMatch) {
|
||||||
|
observer.disconnect();
|
||||||
|
return callback(directMatch ?? childrenMatch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
observer.observe(document.body, {subtree: true, childList: true});
|
||||||
|
|
||||||
|
return () => {observer.disconnect();};
|
||||||
|
}
|
||||||
|
|
||||||
static isEmpty(obj) {
|
static isEmpty(obj) {
|
||||||
if (obj === null || typeof(undefined) === "undefined" || obj === "") return true;
|
if (obj === null || typeof(undefined) === "undefined" || obj === "") return true;
|
||||||
if (typeof(obj) !== "object") return false;
|
if (typeof(obj) !== "object") return false;
|
||||||
|
|
Loading…
Reference in New Issue