XL v1.3.0
This commit is contained in:
parent
59f46f2b3b
commit
9a6bc32ff7
|
@ -23,7 +23,7 @@
|
|||
|
||||
@else@*/
|
||||
/*
|
||||
* Copyright© 2019-2020, _Lighty_
|
||||
* Copyright © 2019-2020, _Lighty_
|
||||
* All rights reserved.
|
||||
* Code may not be redistributed, modified or otherwise taken without explicit permission.
|
||||
*/
|
||||
|
@ -41,16 +41,33 @@ var XenoLib = (() => {
|
|||
twitter_username: ''
|
||||
}
|
||||
],
|
||||
version: '1.2.3',
|
||||
version: '1.3.0',
|
||||
description: 'Simple library to complement plugins with shared code without lowering performance.',
|
||||
github: 'https://github.com/1Lighty',
|
||||
github_raw: 'https://raw.githubusercontent.com/1Lighty/BetterDiscordPlugins/master/Plugins/1XenoLib.plugin.js'
|
||||
},
|
||||
changelog: [
|
||||
{
|
||||
title: 'Hopefully fixed',
|
||||
type: 'fixed',
|
||||
items: ['Fixed BDFDB causing issues with patching context menus']
|
||||
title: 'Boring changes',
|
||||
type: 'Added',
|
||||
items: ['User, Channel and Guild context menus now have a state object, setState and forceUpdate functions.', 'Notifications system has been implemented but is still WIP.', 'Now able to stop the context menu from closing when clicking on a context menu item, by passing noClose prop in the third argument of XenoLib.createContextMenuItem.']
|
||||
}
|
||||
],
|
||||
defaultConfig: [
|
||||
{
|
||||
type: 'category',
|
||||
id: 'notifications',
|
||||
name: 'Notification settings',
|
||||
collapsible: true,
|
||||
shown: true,
|
||||
settings: [
|
||||
{
|
||||
name: 'Notification position',
|
||||
id: 'position',
|
||||
type: 'position',
|
||||
value: 'topLeft'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
@ -68,6 +85,11 @@ var XenoLib = (() => {
|
|||
Patcher.unpatchAll();
|
||||
PluginUtilities.removeStyle('XenoLib-CSS');
|
||||
if (global.BDEvents) BDEvents.off('plugin-unloaded', listener);
|
||||
const notifWrapper = document.querySelector('.xenoLib-notifications');
|
||||
if (notifWrapper) {
|
||||
ReactDOM.unmountComponentAtNode(notifWrapper);
|
||||
notifWrapper.remove();
|
||||
}
|
||||
};
|
||||
|
||||
PluginUtilities.addStyle(
|
||||
|
@ -111,6 +133,73 @@ var XenoLib = (() => {
|
|||
opacity: 0;
|
||||
transform: translate3d(-200%,0,0);
|
||||
}
|
||||
.xenoLib-notifications {
|
||||
position: absolute;
|
||||
color: white;
|
||||
width: 100%;
|
||||
min-height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
z-index: 1000;
|
||||
pointer-events: none;
|
||||
font-size: 14px;
|
||||
}
|
||||
.xenoLib-notification {
|
||||
min-width: 200px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.xenoLib-notification-content-wrapper {
|
||||
padding: 20px 20px 0 0;
|
||||
}
|
||||
.xenoLib-notification-content {
|
||||
padding: 12px;
|
||||
overflow: hidden;
|
||||
background: #474747;
|
||||
pointer-events: all;
|
||||
position: relative;
|
||||
width: 20vw;
|
||||
}
|
||||
.xenoLib-notification-loadbar {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0px;
|
||||
width: auto;
|
||||
background-image: linear-gradient(130deg,var(--grad-one),var(--grad-two));
|
||||
height: 5px;
|
||||
}
|
||||
.xenoLib-notification-loadbar-striped:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 5px;
|
||||
background: linear-gradient(
|
||||
-20deg,
|
||||
transparent 35%,
|
||||
var(--bar-color) 35%,
|
||||
var(--bar-color) 70%,
|
||||
transparent 70%
|
||||
);
|
||||
animation: shift 1s linear infinite;
|
||||
background-size: 60px 100%;
|
||||
box-shadow: inset 0 0px 1px rgba(0, 0, 0, 0.2),
|
||||
inset 0 -2px 1px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
@keyframes shift {
|
||||
to {
|
||||
background-position: 60px 100%;
|
||||
}
|
||||
}
|
||||
.xenoLib-notification-close {
|
||||
float: right;
|
||||
padding: 0;
|
||||
height: unset;
|
||||
}
|
||||
.xenLib-notification-counter {
|
||||
float: right;
|
||||
margin-top: 2px;
|
||||
}
|
||||
`
|
||||
);
|
||||
|
||||
|
@ -228,9 +317,18 @@ var XenoLib = (() => {
|
|||
} else if (isValid(children)) return children.props.children;
|
||||
};
|
||||
function patchAllContextMenus() {
|
||||
const handleContextMenu = (_this, ret) => {
|
||||
const handleContextMenu = (_this, ret, noRender) => {
|
||||
const menuGroups = getContextMenuChild(ret) || ret;
|
||||
if (!menuGroups) return Logger.warn('Failed to get context menu groups!', _this, ret);
|
||||
let [value, set] = noRender ? React.useState(false) : [];
|
||||
let [state, setState] = noRender ? React.useState({}) : [];
|
||||
/* emulate a react component */
|
||||
if (noRender) {
|
||||
_this.forceUpdate = () => set(!value);
|
||||
_this.state = state;
|
||||
_this.setState = setState;
|
||||
}
|
||||
if (!_this.state) _this.state = {};
|
||||
XenoLib.__contextPatches.forEach(e => {
|
||||
try {
|
||||
e(_this, menuGroups);
|
||||
|
@ -259,7 +357,7 @@ var XenoLib = (() => {
|
|||
if (!menu) return Logger.warn('Special context menu is undefined!');
|
||||
const origDef = menu.exports.default;
|
||||
const originalFunc = Utilities.getNestedProp(menu, 'exports.BDFDBpatch.default.originalMethod') || menu.exports.default;
|
||||
Patcher.after(menu.exports, 'default', (_, [props], ret) => handleContextMenu({ props }, ret));
|
||||
Patcher.after(menu.exports, 'default', (_, [props], ret) => handleContextMenu({ props }, ret, true));
|
||||
/* make it friendly to other plugins and libraries that search by string
|
||||
note: removing this makes BDFDB shit itself
|
||||
*/
|
||||
|
@ -269,7 +367,7 @@ var XenoLib = (() => {
|
|||
this function is never called in BDFDB, it's only stored for restore
|
||||
*/
|
||||
if (origDef.isBDFDBpatched && menu.exports.BDFDBpatch && typeof menu.exports.BDFDBpatch.default.originalMethod === 'function') {
|
||||
Patcher.after(menu.exports.BDFDBpatch.default, 'originalMethod', (_, [props], ret) => handleContextMenu({ props }, ret));
|
||||
Patcher.after(menu.exports.BDFDBpatch.default, 'originalMethod', (_, [props], ret) => handleContextMenu({ props }, ret, true));
|
||||
/* make it friendly to other plugins and libraries that search by string
|
||||
note: removing this makes BDFDB shit itself
|
||||
*/
|
||||
|
@ -303,7 +401,7 @@ var XenoLib = (() => {
|
|||
React.createElement(ContextMenuItem, {
|
||||
label,
|
||||
action: () => {
|
||||
ContextMenuActions.closeContextMenu();
|
||||
if (!options.noClose) ContextMenuActions.closeContextMenu();
|
||||
action();
|
||||
},
|
||||
...options
|
||||
|
@ -556,11 +654,12 @@ var XenoLib = (() => {
|
|||
}
|
||||
};
|
||||
|
||||
XenoLib.loadData = (name, key, defaultData) => {
|
||||
XenoLib.loadData = (name, key, defaultData, returnNull) => {
|
||||
try {
|
||||
return Object.assign(defaultData ? Utilities.deepclone(defaultData) : {}, BdApi.getData(name, key));
|
||||
} catch (err) {
|
||||
Logger.err(name, 'Unable to load data: ', err);
|
||||
if (returnNull) return null;
|
||||
return Utilities.deepclone(defaultData);
|
||||
}
|
||||
};
|
||||
|
@ -596,6 +695,365 @@ var XenoLib = (() => {
|
|||
}
|
||||
};
|
||||
|
||||
/* NOTIFICATIONS START */
|
||||
try {
|
||||
const zustand = WebpackModules.getByString('console.warn("Zustand: the 2nd arg');
|
||||
const [useStore, api] = zustand(e => ({ data: [] }));
|
||||
const defaultOptions = {
|
||||
loading: false,
|
||||
progress: -1,
|
||||
channelId: undefined,
|
||||
timeout: 1000,
|
||||
color: '#2196f3'
|
||||
};
|
||||
const utils = {
|
||||
success(content, options = {}) {
|
||||
return this.show(content, Object.assign({ color: '#43b581' }, options));
|
||||
},
|
||||
info(content, options = {}) {
|
||||
return this.show(content, Object.assign({ color: '#4a90e2' }, options));
|
||||
},
|
||||
warning(content, options = {}) {
|
||||
return this.show(content, Object.assign({ color: '#ffa600' }, options));
|
||||
},
|
||||
danger(content, options = { n }) {
|
||||
return this.show(content, Object.assign({ color: '#f04747' }, options));
|
||||
},
|
||||
error(content, options = {}) {
|
||||
return this.danger(content, options);
|
||||
},
|
||||
/**
|
||||
* @param {string|*} content - Content to display. If it's a string, it'll be formatted with markdown, including URL support [like this](https://google.com/)
|
||||
* @param {object} options
|
||||
* @param {string} [options.channelId] Channel ID if content is a string which gets formatted, and you want to mention a role for example.
|
||||
* @param {Number} [options.timeout] Set to 0 to keep it permanently until user closes it, or if you want a progress bar
|
||||
* @param {Boolean} [options.loading] Makes the bar animate differently instead of fading in and out slowly
|
||||
* @param {Number} [options.progress] 0-100, -1 sets it to 100%, setting it to 100% closes the notification automatically
|
||||
* @param {string} [options.color] Bar color
|
||||
* @param {string} [options.allowDuplicates] By default, notifications that are similar get grouped together, use true to disable that
|
||||
* @return {Number} - Notification ID. Store this if you plan on force closing it, changing its content or want to set the progress
|
||||
*/
|
||||
show(content, options = {}) {
|
||||
let id = null;
|
||||
api.setState(state => {
|
||||
if (state.data.length >= 100) return state;
|
||||
if (!options.allowDuplicates) {
|
||||
const notif = state.data.find(n => n.content === content && n.timeout === options.timeout);
|
||||
if (notif) {
|
||||
id = notif.id;
|
||||
Dispatcher.dispatch({ type: 'XL_NOTIFS_DUPLICATE', id: notif.id });
|
||||
return state;
|
||||
}
|
||||
}
|
||||
do {
|
||||
id = Math.floor(4294967296 * Math.random());
|
||||
} while (state.data.findIndex(n => n.id === id) !== -1);
|
||||
return { data: [].concat(state.data, [{ content, ...Object.assign(Utilities.deepclone(defaultOptions), options), id }]) };
|
||||
});
|
||||
return id;
|
||||
},
|
||||
remove(id) {
|
||||
Dispatcher.dispatch({ type: 'XL_NOTIFS_REMOVE', id });
|
||||
},
|
||||
/**
|
||||
* @param {Number} id Notification ID
|
||||
* @param {object} options
|
||||
* @param {string} [options.channelId] Channel ID if content is a string which gets formatted, and you want to mention a role for example.
|
||||
* @param {Boolean} [options.loading] Makes the bar animate differently instead of fading in and out slowly
|
||||
* @param {Number} [options.progress] 0-100, -1 sets it to 100%, setting it to 100% closes the notification automatically
|
||||
* @param {string} [options.color] Bar color
|
||||
*/
|
||||
update(id, options) {
|
||||
delete options.id;
|
||||
api.setState(state => {
|
||||
const idx = state.data.findIndex(n => n.id === id);
|
||||
if (idx === -1) return state;
|
||||
state.data[idx] = Object.assign(state.data[idx], options);
|
||||
return state;
|
||||
});
|
||||
Dispatcher.dispatch({ type: 'XL_NOTIFS_UPDATE', id, ...options });
|
||||
}
|
||||
};
|
||||
XenoLib.Notifications = utils;
|
||||
XenoLib.Notifications.__api = api;
|
||||
XenoLib.Notifications.__api._DO_NOT_USE_THIS_IN_YOUR_PLUGIN_OR_YOU_WILL_CRY = 'Because it may be removed at any point in the future';
|
||||
const ReactSpring = WebpackModules.getByProps('useTransition');
|
||||
const BadgesModule = WebpackModules.getByProps('NumberBadge');
|
||||
const ParsersModule = WebpackModules.getByProps('parseAllowLinks', 'parse');
|
||||
const CloseButton = WebpackModules.getByProps('CloseButton').CloseButton;
|
||||
class Notification extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
closeFast: false /* close button pressed, XL_NOTIFS_REMOVE dispatch */,
|
||||
offscreen: false /* don't do anything special if offscreen, not timeout */,
|
||||
counter: 1 /* how many times this notification was shown */,
|
||||
resetBar: false /* reset bar to 0 in the event counter goes up */,
|
||||
hovered: false,
|
||||
leaving: true /* prevent hover events from messing up things */,
|
||||
loading: props.loading /* loading animation, enable progress */,
|
||||
progress: props.progress /* -1 means undetermined */,
|
||||
content: props.content,
|
||||
contentParsed: this.parseContent(props.content, props.channelId),
|
||||
color: props.color
|
||||
};
|
||||
this._contentRef = null;
|
||||
this._ref;
|
||||
this._animationCancel = () => {};
|
||||
this._oldOffsetHeight = 0;
|
||||
this._initialProgress = !this.props.timeout ? (this.state.loading && this.state.progress !== -1 ? this.state.progress : 100) : 0;
|
||||
XenoLib.DiscordUtils.bindAll(this, ['closeNow', 'handleResizeEvent', 'handleDispatch']);
|
||||
}
|
||||
componentDidMount() {
|
||||
this._unsubscribe = api.subscribe(_ => this.checkOffScreen());
|
||||
window.addEventListener('resize', this.handleResizeEvent);
|
||||
Dispatcher.subscribe('XL_NOTIFS_DUPLICATE', this.handleDispatch);
|
||||
Dispatcher.subscribe('XL_NOTIFS_REMOVE', this.handleDispatch);
|
||||
Dispatcher.subscribe('XL_NOTIFS_UPDATE', this.handleDispatch);
|
||||
Dispatcher.subscribe('XL_NOTIFS_ANIMATED', this.handleDispatch);
|
||||
}
|
||||
componentWillUnmount() {
|
||||
this._unsubscribe();
|
||||
window.window.removeEventListener('resize', this.handleResizeEvent);
|
||||
Dispatcher.unsubscribe('XL_NOTIFS_DUPLICATE', this.handleDispatch);
|
||||
Dispatcher.unsubscribe('XL_NOTIFS_REMOVE', this.handleDispatch);
|
||||
Dispatcher.unsubscribe('XL_NOTIFS_UPDATE', this.handleDispatch);
|
||||
Dispatcher.unsubscribe('XL_NOTIFS_ANIMATED', this.handleDispatch);
|
||||
}
|
||||
handleDispatch(e) {
|
||||
if (e.type === 'XL_NOTIFS_ANIMATED') this.checkOffScreen();
|
||||
if (e.id !== this.props.id) return;
|
||||
const { content, channelId, loading, progress, color } = e;
|
||||
const { content: curContent, channelId: curChannelId, loading: curLoading, progress: curProgress, color: curColor } = this.state;
|
||||
switch (e.type) {
|
||||
case 'XL_NOTIFS_REMOVE':
|
||||
this.closeNow();
|
||||
break;
|
||||
case 'XL_NOTIFS_DUPLICATE':
|
||||
this._animationCancel();
|
||||
this.setState({ counter: this.state.counter + 1, resetBar: !!this.props.timeout });
|
||||
break;
|
||||
case 'XL_NOTIFS_UPDATE':
|
||||
this._animationCancel();
|
||||
this.setState({
|
||||
content: content || curContent,
|
||||
channelId: channelId || curChannelId,
|
||||
contentParsed: this.parseContent(content || curContent, channelId || curChannelId),
|
||||
loading: typeof loading !== 'undefined' ? loading : curLoading,
|
||||
progress: typeof progress !== 'undefined' ? progress : curProgress,
|
||||
color: color || curColor
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
parseContent(content, channelId) {
|
||||
return typeof content === 'string' ? ParsersModule.parseAllowLinks(content, true, { channelId }) : content;
|
||||
}
|
||||
checkOffScreen() {
|
||||
const bcr = this._contentRef.getBoundingClientRect();
|
||||
if (bcr.bottom > Structs.Screen.height) {
|
||||
if (!this.state.offscreen) {
|
||||
this._animationCancel();
|
||||
this.setState({ offscreen: true });
|
||||
}
|
||||
} else if (this.state.offscreen) {
|
||||
this._animationCancel();
|
||||
this.setState({ offscreen: false });
|
||||
}
|
||||
}
|
||||
closeNow() {
|
||||
this._animationCancel();
|
||||
this.setState({ closeFast: true });
|
||||
}
|
||||
handleResizeEvent() {
|
||||
if (this._oldOffsetHeight !== this._contentRef.offsetHeight) {
|
||||
this._animationCancel();
|
||||
this.forceUpdate();
|
||||
}
|
||||
}
|
||||
render() {
|
||||
const config = { tension: 125, friction: 20 };
|
||||
if (this._contentRef) this._oldOffsetHeight = this._contentRef.offsetHeight;
|
||||
return React.createElement(
|
||||
ReactSpring.Spring,
|
||||
{
|
||||
native: true,
|
||||
from: { opacity: 0, height: 0, progress: this._initialProgress, loadbrightness: 1 },
|
||||
to: async (next, cancel) => {
|
||||
this.state.leaving = false;
|
||||
this._animationCancel = cancel;
|
||||
if (this.state.offscreen) {
|
||||
if (this.state.closeFast) {
|
||||
this.state.leaving = true;
|
||||
await next({ opacity: 0, height: 0 });
|
||||
api.setState(state => ({ data: state.data.filter(n => n.id !== this.props.id) }));
|
||||
return;
|
||||
}
|
||||
await next({ opacity: 1, height: this._contentRef.offsetHeight, loadbrightness: 1 });
|
||||
if (this.props.timeout) {
|
||||
await next({ progress: 0 });
|
||||
} else {
|
||||
if (this.state.loading && this.state.progress !== -1) {
|
||||
await next({ progress: 0 });
|
||||
} else {
|
||||
await next({ progress: 100 });
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
const isSettingHeight = this._ref.offsetHeight !== this._contentRef.offsetHeight;
|
||||
await next({ opacity: 1, height: this._contentRef.offsetHeight });
|
||||
if (isSettingHeight) Dispatcher.dispatch({ type: 'XL_NOTIFS_ANIMATED' });
|
||||
if (this.state.resetBar || this.state.hovered) {
|
||||
await next({ progress: 0 }); /* shit gets reset */
|
||||
this.state.resetBar = false;
|
||||
}
|
||||
|
||||
if (!this.props.timeout && !this.state.closeFast) {
|
||||
if (!this.state.loading) {
|
||||
await next({ progress: 100 });
|
||||
while (!this.state.closeFast) {
|
||||
await next({ loadbrightness: 0.7 });
|
||||
await next({ loadbrightness: 1 });
|
||||
}
|
||||
} else {
|
||||
await next({ loadbrightness: 1 });
|
||||
if (this.state.progress === -1) await next({ progress: 100 });
|
||||
else await next({ progress: this.state.progress });
|
||||
}
|
||||
if (this.state.progress !== 100 || !this.state.loading) return;
|
||||
}
|
||||
if (this.state.hovered && !this.state.closeFast) return;
|
||||
await next({ progress: 100 });
|
||||
this.state.leaving = true;
|
||||
await next({ opacity: 0, height: 0 });
|
||||
api.setState(state => ({ data: state.data.filter(n => n.id !== this.props.id) }));
|
||||
},
|
||||
config: key => {
|
||||
if (key === 'progress') {
|
||||
let duration = this.props.timeout;
|
||||
if (this.state.closeFast || !this.props.timeout || this.state.resetBar || this.state.hovered) duration = 150;
|
||||
if (this.state.offscreen) duration = 0; /* don't animate at all */
|
||||
return { duration };
|
||||
}
|
||||
if (key === 'loadbrightness') return { duration: 750 };
|
||||
return config;
|
||||
}
|
||||
},
|
||||
e => {
|
||||
return React.createElement(
|
||||
ReactSpring.animated.div,
|
||||
{
|
||||
style: {
|
||||
height: e.height,
|
||||
opacity: e.opacity
|
||||
},
|
||||
className: 'xenoLib-notification',
|
||||
ref: e => e && (this._ref = e)
|
||||
},
|
||||
React.createElement(
|
||||
'div',
|
||||
{
|
||||
className: 'xenoLib-notification-content-wrapper',
|
||||
ref: e => e && (this._contentRef = e),
|
||||
onMouseEnter: e => {
|
||||
if (this.state.leaving || !this.props.timeout) return;
|
||||
this._animationCancel();
|
||||
this.setState({ hovered: true });
|
||||
},
|
||||
onMouseLeave: e => {
|
||||
if (this.state.leaving || !this.props.timeout) return;
|
||||
this._animationCancel();
|
||||
this.setState({ hovered: false });
|
||||
},
|
||||
style: {
|
||||
'--grad-one': this.state.color,
|
||||
'--grad-two': ColorConverter.lightenColor(this.state.color, 20),
|
||||
'--bar-color': ColorConverter.darkenColor(this.state.color, 30)
|
||||
},
|
||||
onClick: e => {
|
||||
if (!this.props.onClick) return;
|
||||
this.props.onClick();
|
||||
this.closeNow();
|
||||
},
|
||||
onContextMenu: e => {
|
||||
if (!this.props.onContext) return;
|
||||
this.props.onContext();
|
||||
this.closeNow();
|
||||
}
|
||||
},
|
||||
React.createElement(
|
||||
'div',
|
||||
{
|
||||
className: 'xenoLib-notification-content'
|
||||
},
|
||||
React.createElement(ReactSpring.animated.div, {
|
||||
className: XenoLib.joinClassNames('xenoLib-notification-loadbar', { 'xenoLib-notification-loadbar-striped': !this.props.timeout && this.state.loading }),
|
||||
style: { right: e.progress.to(e => 100 - e + '%'), filter: e.loadbrightness.to(e => `brightness(${e * 100}%)`) }
|
||||
}),
|
||||
React.createElement(CloseButton, {
|
||||
onClick: e => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
this.closeNow();
|
||||
},
|
||||
onContextMenu: e => {
|
||||
ContextMenuActions.openContextMenu(e, e =>
|
||||
React.createElement(
|
||||
'div',
|
||||
{ className: DiscordClasses.ContextMenu.contextMenu },
|
||||
XenoLib.createContextMenuGroup([
|
||||
XenoLib.createContextMenuItem('Close All', () => {
|
||||
const state = api.getState();
|
||||
state.data.forEach(notif => utils.remove(notif.id));
|
||||
})
|
||||
])
|
||||
)
|
||||
);
|
||||
},
|
||||
className: 'xenoLib-notification-close'
|
||||
}),
|
||||
this.state.counter > 1 && BadgesModule.NumberBadge({ count: this.state.counter, className: 'xenLib-notification-counter', color: '#2196f3' }),
|
||||
this.state.contentParsed
|
||||
/* React.createElement('a', { onClick: this.closeNow }, 'close') */
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
function NotificationsWrapper(e) {
|
||||
const notifications = useStore(e => {
|
||||
return e.data;
|
||||
});
|
||||
return [
|
||||
/* React.createElement(
|
||||
'div',
|
||||
{
|
||||
style: {
|
||||
pointerEvents: 'all'
|
||||
}
|
||||
},
|
||||
React.createElement(WebpackModules.getByDisplayName('Backdrop'), {
|
||||
backdropStyle: 'DARK',
|
||||
zIndexBoost: -1000,
|
||||
onClick: e => e.preventDefault()
|
||||
})
|
||||
), */
|
||||
notifications.map(item => React.createElement(Notification, { ...item, key: item.id })).reverse()
|
||||
];
|
||||
}
|
||||
NotificationsWrapper.displayName = 'XenoLibNotifications';
|
||||
const DOMElement = document.createElement('div');
|
||||
DOMElement.className = 'xenoLib-notifications';
|
||||
ReactDOM.render(React.createElement(NotificationsWrapper, {}), DOMElement);
|
||||
document.querySelector('#app-mount').appendChild(DOMElement);
|
||||
} catch (e) {
|
||||
Logger.stacktrace('There has been an error loading the Notifications system', e);
|
||||
}
|
||||
/* NOTIFICATIONS END */
|
||||
|
||||
global.XenoLib = XenoLib;
|
||||
const listener = e => {
|
||||
if (e !== 'XenoLib') return;
|
||||
|
@ -608,11 +1066,36 @@ var XenoLib = (() => {
|
|||
}
|
||||
|
||||
XenoLib.changeName(__filename, '1XenoLib'); /* prevent user from changing libs filename */
|
||||
/*
|
||||
class NotificationPosition extends React.PureComponent {
|
||||
render() {
|
||||
return React.createElement('div', {},
|
||||
React.createElement('div', {
|
||||
className: XenoLib.joinClassNames()
|
||||
})
|
||||
)
|
||||
}
|
||||
} */
|
||||
|
||||
class NotificationPositionField extends Settings.SettingField {
|
||||
constructor(name, note, onChange) {
|
||||
super(name, note, onChange, WebpackModules.getByDisplayName('NotificationSettings'), {
|
||||
position: 'topRight',
|
||||
onChange: (a, b) => console.log(a, b)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return class XenoLib extends Plugin {
|
||||
onStart() {
|
||||
Toasts.info('Starting me does nothing :)');
|
||||
/* buildSetting(data) {
|
||||
if (data.type === 'position') {
|
||||
return new NotificationPositionField(data.name, data.note, console.log);
|
||||
}
|
||||
return super.buildSetting(data);
|
||||
}
|
||||
getSettingsPanel() {
|
||||
return this.buildSettingsPanel().getElement();
|
||||
} */
|
||||
get name() {
|
||||
return config.info.name;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue