153 lines
5.5 KiB
JavaScript
153 lines
5.5 KiB
JavaScript
/**
|
|
* BetterDiscord Developer/Contributor Profile Badges
|
|
* Copyright (c) 2015-present Jiiks/JsSucks - https://github.com/Jiiks / https://github.com/JsSucks
|
|
* All rights reserved.
|
|
* https://betterdiscord.net
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*/
|
|
|
|
import { Module, ReactComponents, ReactHelpers, MonkeyPatch, Reflection } from 'modules';
|
|
import { ClientLogger as Logger } from 'common';
|
|
import { BdBadge } from './components/bd';
|
|
import VueInjector from './vueinjector';
|
|
import contributors from '../data/contributors';
|
|
|
|
export default class extends Module {
|
|
|
|
init() {
|
|
this.patchMessage();
|
|
this.patchChannelMember();
|
|
this.patchNameTag();
|
|
this.patchUserProfileModal();
|
|
}
|
|
|
|
get contributors() {
|
|
return contributors;
|
|
}
|
|
|
|
/**
|
|
* Patches Message to render profile badges.
|
|
*/
|
|
async patchMessage() {
|
|
const Message = await ReactComponents.getComponent('Message');
|
|
|
|
this.unpatchMessageRender = MonkeyPatch('ProfileBadges', Message.component.prototype).after('render', (component, args, retVal) => {
|
|
if (!retVal.props || !retVal.props.children) return;
|
|
if (ReactHelpers.findProp(component, 'jumpSequenceId') && ReactHelpers.findProp(component, 'canFlash')) retVal = retVal.props.children;
|
|
|
|
const message = ReactHelpers.findProp(component, 'message');
|
|
if (!message || !message.author) return;
|
|
const user = message.author;
|
|
const contributor = contributors.find(c => c.id === user.id);
|
|
if (!contributor) return;
|
|
|
|
const username = ReactHelpers.findByProp(retVal, 'type', 'h2');
|
|
if (!username) return;
|
|
|
|
username.props.children.splice(1, 0, VueInjector.createReactElement(BdBadge, {
|
|
contributor,
|
|
type: 'nametag'
|
|
}));
|
|
});
|
|
|
|
// Rerender all messages
|
|
Message.forceUpdateAll();
|
|
}
|
|
|
|
/**
|
|
* Patches ChannelMember to use the extended NameTag.
|
|
* This is because NameTag is also used in places we don't really want any badges.
|
|
*/
|
|
async patchChannelMember() {
|
|
const ChannelMember = await ReactComponents.getComponent('ChannelMember');
|
|
|
|
this.unpatchChannelMemberRender = MonkeyPatch('ProfileBadges', ChannelMember.component.prototype).after('render', (component, args, retVal) => {
|
|
if (!retVal.props || !retVal.props.children) return;
|
|
|
|
const user = ReactHelpers.findProp(component, 'user');
|
|
if (!user) return;
|
|
const c = contributors.find(c => c.id === user.id);
|
|
if (!c) return;
|
|
|
|
const nameTag = retVal.props.children.props.children[1].props.children[0];
|
|
nameTag.type = this.PatchedNameTag || nameTag.type;
|
|
});
|
|
|
|
// Rerender all channel members
|
|
if (this.PatchedNameTag) {
|
|
ChannelMember.forceUpdateAll();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Creates an extended NameTag component that renders message badges.
|
|
*/
|
|
async patchNameTag() {
|
|
if (this.PatchedNameTag) return this.PatchedNameTag;
|
|
|
|
const selector = Reflection.resolve('nameTag', 'username', 'discriminator', 'ownerIcon').selector;
|
|
const NameTag = await ReactComponents.getComponent('NameTag', {selector});
|
|
|
|
this.PatchedNameTag = class extends NameTag.component {
|
|
render() {
|
|
const retVal = NameTag.component.prototype.render.call(this, arguments);
|
|
try {
|
|
if (!retVal.props || !retVal.props.children) return;
|
|
|
|
const user = ReactHelpers.findProp(this, 'user');
|
|
if (!user) return;
|
|
const contributor = contributors.find(c => c.id === user.id);
|
|
if (!contributor) return;
|
|
|
|
retVal.props.children.splice(1, 0, VueInjector.createReactElement(BdBadge, {
|
|
contributor,
|
|
type: 'nametag'
|
|
}));
|
|
} catch (err) {
|
|
Logger.err('ProfileBadges', ['Error thrown while rendering a NameTag', err]);
|
|
}
|
|
return retVal;
|
|
}
|
|
};
|
|
|
|
// Rerender all channel members
|
|
if (this.unpatchChannelMemberRender) {
|
|
const ChannelMember = await ReactComponents.getComponent('ChannelMember');
|
|
ChannelMember.forceUpdateAll();
|
|
}
|
|
|
|
return this.PatchedNameTag;
|
|
}
|
|
|
|
/**
|
|
* Patches UserProfileModal to render profile badges.
|
|
*/
|
|
async patchUserProfileModal() {
|
|
const UserProfileModal = await ReactComponents.getComponent('UserProfileModal');
|
|
|
|
this.unpatchUserProfileModal = MonkeyPatch('ProfileBadges', UserProfileModal.component.prototype).after('renderBadges', (component, args, retVal, setRetVal) => {
|
|
const user = ReactHelpers.findProp(component, 'user');
|
|
if (!user) return;
|
|
const contributor = contributors.find(c => c.id === user.id);
|
|
if (!contributor) return;
|
|
|
|
const element = VueInjector.createReactElement(BdBadge, {
|
|
contributor,
|
|
type: 'profile-modal'
|
|
});
|
|
|
|
if (!retVal) {
|
|
setRetVal(ReactHelpers.React.createElement('div', {
|
|
className: 'bd-profileBadgesWrap',
|
|
children: element
|
|
}));
|
|
} else retVal.props.children.splice(0, 0, element);
|
|
});
|
|
|
|
UserProfileModal.forceUpdateAll();
|
|
}
|
|
|
|
}
|