129 lines
5.5 KiB
JavaScript
129 lines
5.5 KiB
JavaScript
/**
|
|
* This is an example of how you should add custom elements instead of manipulating the DOM directly
|
|
*/
|
|
|
|
// Import custom components
|
|
const customVueComponent = require('./components/vuecomponent');
|
|
const customReactComponent = require('./components/reactcomponent');
|
|
|
|
module.exports = (Plugin, Api, Vendor) => {
|
|
|
|
// Destructure some apis
|
|
const { Logger, ReactComponents, Patcher, monkeyPatch, Reflection, Utils, CssUtils, VueInjector, Vuewrap, requireUncached } = Api;
|
|
const { Vue } = Vendor;
|
|
const { React } = Reflection.modules; // This should be in vendor
|
|
|
|
return class extends Plugin {
|
|
|
|
async onStart() {
|
|
this.injectStyle();
|
|
this.patchGuildTextChannel();
|
|
this.patchMessages();
|
|
return true;
|
|
}
|
|
|
|
async onStop() {
|
|
// The automatic unpatcher is not there yet
|
|
Patcher.unpatchAll();
|
|
CssUtils.deleteAllStyles();
|
|
|
|
// Force update elements to remove our changes
|
|
const GuildTextChannel = await ReactComponents.getComponent('GuildTextChannel');
|
|
GuildTextChannel.forceUpdateAll();
|
|
const MessageContent = await ReactComponents.getComponent('MessageContent', { selector: Reflection.resolve('container', 'containerCozy', 'containerCompact', 'edited').selector }, m => m.defaultProps && m.defaultProps.hasOwnProperty('disableButtons'));
|
|
MessageContent.forceUpdateAll();
|
|
return true;
|
|
}
|
|
|
|
/* Inject some style for our custom element */
|
|
async injectStyle() {
|
|
const css = `
|
|
.exampleCustomElement {
|
|
background: #7a7d82;
|
|
color: #FFF;
|
|
border-radius: 5px;
|
|
font-size: 12px;
|
|
font-weight: 600;
|
|
opacity: .5;
|
|
&:hover {
|
|
opacity: 1;
|
|
}
|
|
}
|
|
.exampleBtnGroup {
|
|
.bd-button {
|
|
font-size: 14px;
|
|
padding: 5px;
|
|
}
|
|
}
|
|
`;
|
|
await CssUtils.injectSass(css);
|
|
}
|
|
|
|
async patchGuildTextChannel() {
|
|
// Get the GuildTextChannel component and patch it's render function
|
|
const GuildTextChannel = await ReactComponents.getComponent('GuildTextChannel');
|
|
monkeyPatch(GuildTextChannel.component.prototype).after('render', this.injectCustomElements.bind(this));
|
|
// Force update to see our changes immediatly
|
|
GuildTextChannel.forceUpdateAll();
|
|
}
|
|
|
|
async patchMessages() {
|
|
// Get Message component and patch it's render function
|
|
const MessageContent = await ReactComponents.getComponent('MessageContent', { selector: Reflection.resolve('container', 'containerCozy', 'containerCompact', 'edited').selector });
|
|
monkeyPatch(MessageContent.component.prototype).after('render', this.injectGenericComponents.bind(this));
|
|
// Force update to see our changes immediatly
|
|
MessageContent.forceUpdateAll();
|
|
}
|
|
|
|
/*
|
|
* Injecting a custom React element using React.createElement
|
|
* https://reactjs.org/docs/react-api.html#createelement
|
|
* Injecting a custom Vue element using Vue.component
|
|
* https://vuejs.org/v2/guide/render-function.html
|
|
**/
|
|
injectCustomElements(that, args, returnValue) {
|
|
// Get the child we want using a treewalker since we know the child we want has a channel property and children.
|
|
const child = Utils.findInReactTree(returnValue, filter => filter.hasOwnProperty('channel') && filter.children);
|
|
if (!child) return;
|
|
// If children is not an array make it into one
|
|
if (!child.children instanceof Array) child.children = [child.children];
|
|
|
|
// Add our custom components to children
|
|
child.children.push(customReactComponent(React, { onClick: e => this.handleClick(e, child.channel) }));
|
|
child.children.push(customVueComponent(Vuewrap, { onClick: e => this.handleClick(e, child.channel) }));
|
|
}
|
|
|
|
/**
|
|
* Inject generic components provided by BD
|
|
*/
|
|
injectGenericComponents(that, args, returnValue) {
|
|
// If children is not an array make it into one
|
|
if (!returnValue.props.children instanceof Array) returnValue.props.children = [returnValue.props.children];
|
|
// Add a generic Button component provided by BD
|
|
returnValue.props.children.push(Api.Components.ButtonGroup({
|
|
classes: [ 'exampleBtnGroup' ], // Additional classes for button group
|
|
buttons: [
|
|
{
|
|
classes: ['exampleBtn'], // Additional classes for button
|
|
text: 'Hello World!', // Text for button
|
|
onClick: e => Logger.log('Hello World!') // Button click handler
|
|
},
|
|
{
|
|
classes: ['exampleBtn'],
|
|
text: 'Button',
|
|
onClick: e => Logger.log('Button!')
|
|
}
|
|
]
|
|
}).render()); // Render will return the wrapped component that can then be displayed
|
|
}
|
|
|
|
/**
|
|
* Will log the channel object
|
|
*/
|
|
handleClick(e, channel) {
|
|
Logger.log('Clicked!', channel);
|
|
}
|
|
}
|
|
|
|
};
|