Compare commits
80 Commits
2.0.0-beta
...
master
Author | SHA1 | Date |
---|---|---|
Alexei Stukov | 835cc3134c | |
Jiiks | 02b30153ee | |
Alexei Stukov | d09dc5a2a5 | |
Mega-Mewthree | 98d9a30027 | |
Alexei Stukov | 5cb4bc15bd | |
Alexei Stukov | bb2aba04d5 | |
Samuel Elliott | 82e9b0bd6a | |
Samuel Elliott | 47575d3449 | |
Samuel Elliott | 32e2582ded | |
Samuel Elliott | d58dda6f50 | |
Samuel Elliott | 648954d533 | |
Samuel Elliott | 4aa38f4582 | |
Samuel Elliott | b3ba1aef13 | |
Samuel Elliott | 2a6cbd39b7 | |
Samuel Elliott | ce5bcb9b85 | |
Samuel Elliott | 5a3821ad3e | |
Samuel Elliott | fd0032b24c | |
Samuel Elliott | 226719b36e | |
Samuel Elliott | fcfee53928 | |
Samuel Elliott | 285ae34b50 | |
Alexei Stukov | a170a97688 | |
Samuel Elliott | a770f57b28 | |
Samuel Elliott | 5757fc20c9 | |
Samuel Elliott | 421289f63b | |
Samuel Elliott | ac85316578 | |
Samuel Elliott | 08af9be061 | |
Samuel Elliott | ead0fbbd1e | |
Samuel Elliott | dc85a808f8 | |
Samuel Elliott | aecfa814f9 | |
Samuel Elliott | 436f3d3c36 | |
Alexei Stukov | 68a8187964 | |
Alexei Stukov | f30e4c12fe | |
Alexei Stukov | 686514ed1d | |
Alexei Stukov | d795da1750 | |
Alexei Stukov | 3219ff7c6e | |
Alexei Stukov | 33567a2cfd | |
Jiiks | 85310bfbff | |
Jiiks | d1d79a37b7 | |
Jiiks | d95592acc9 | |
Jiiks | f6a3fb65da | |
Alexei Stukov | 6788cca363 | |
Lars van der Zande | 1fb442e096 | |
Jiiks | 6e64ff61c5 | |
Jiiks | dd8fe68a11 | |
Jiiks | a3829089f9 | |
Jiiks | 174c1ee791 | |
Jiiks | b8793fd2b6 | |
Jiiks | 31986ca3a0 | |
Jiiks | 10ff740f75 | |
Jiiks | 83fbab63c0 | |
Jiiks | c4670946e6 | |
Jiiks | e5239d952e | |
Jiiks | a57783a9d8 | |
Jiiks | 001a6e4fda | |
Jiiks | dd621038f9 | |
Jiiks | 288c233447 | |
Jiiks | 399c6e792b | |
Jiiks | 0be6facba4 | |
Jiiks | dc7247a12d | |
Jiiks | 377c4fd104 | |
Jiiks | 252d496dc2 | |
Jiiks | 83e334c3f8 | |
Jiiks | e72ad10dfc | |
Jiiks | 9ef392c575 | |
Jiiks | 76057efbb7 | |
Jiiks | dcb121750a | |
Jiiks | 13fa769e9e | |
Jiiks | 3143991239 | |
Jiiks | 1ae0c5aa4d | |
Jiiks | 5ea39f86f7 | |
Jiiks | d6a946e096 | |
Jiiks | b68c1fbd04 | |
Jiiks | 07d3629622 | |
Jiiks | 15daa9acef | |
Jiiks | 817a4a03b6 | |
Jiiks | e63386e9eb | |
Jiiks | 402acdfea9 | |
Jiiks | b440206d07 | |
Jiiks | c7bea4a743 | |
Jiiks | 2528d87b8f |
|
@ -0,0 +1,33 @@
|
|||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: "[Bug]"
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
- [ ] Used appropriate template for the issue type
|
||||
- [ ] Searched both open and closed issues for duplicates of this issue
|
||||
- [ ] Title adequately and _concisely_ reflects the feature or the bug
|
||||
|
||||
**Describe the bug**
|
||||
<!-- A clear and concise description of what the bug is. -->
|
||||
|
||||
**To Reproduce**
|
||||
<!-- Steps to reproduce the behavior -->
|
||||
|
||||
**Expected behavior**
|
||||
<!-- A clear and concise description of what you expected to happen. -->
|
||||
|
||||
**Screenshots**
|
||||
<!-- If applicable, add screenshots to help explain your problem. -->
|
||||
|
||||
**System information**
|
||||
<!-- os, discord branch etc -->
|
||||
|
||||
**Additional context**
|
||||
<!-- Add any other context about the problem here. -->
|
||||
|
||||
**Are you willing and able to fix this?**
|
||||
<!-- "Yes" or, if "no", what can current contributors do to help you create a PR? -->
|
|
@ -0,0 +1,12 @@
|
|||
---
|
||||
name: Custom issue template
|
||||
about: Describe this issue template's purpose here.
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
- [ ] Used appropriate template for the issue type
|
||||
- [ ] Searched both open and closed issues for duplicates of this issue
|
||||
- [ ] Title adequately and _concisely_ reflects the feature or the bug
|
|
@ -0,0 +1,27 @@
|
|||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: "[Feature]"
|
||||
labels: feature
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
- [ ] Used appropriate template for the issue type
|
||||
- [ ] Searched both open and closed issues for duplicates of this issue
|
||||
- [ ] Title adequately and _concisely_ reflects the feature or the bug
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
<!-- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] -->
|
||||
|
||||
**Describe the solution you'd like**
|
||||
<!-- A clear and concise description of what you want to happen. -->
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
<!-- A clear and concise description of any alternative solutions or features you've considered. -->
|
||||
|
||||
**Additional context**
|
||||
<!-- Add any other context or screenshots about the feature request here. -->
|
||||
|
||||
**Are you willing and able to implement this?**
|
||||
<!-- "Yes" or, if "no", what can current contributors do to help you create a PR? -->
|
|
@ -4,6 +4,7 @@ dist
|
|||
etc
|
||||
release
|
||||
|
||||
tests/tmp
|
||||
tests/log.txt
|
||||
|
||||
# User data
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"name": "bdclient",
|
||||
"description": "BetterDiscord client package",
|
||||
"author": "Jiiks",
|
||||
"version": "2.0.0-beta.3",
|
||||
"version": "2.0.0-beta.6",
|
||||
"homepage": "https://betterdiscord.net",
|
||||
"license": "MIT",
|
||||
"main": "dist/betterdiscord.client.js",
|
||||
|
|
|
@ -21,7 +21,7 @@ export default new class BlockedMessages extends BuiltinModule {
|
|||
async enabled(e) {
|
||||
const MessageListComponents = Reflection.module.byProps('BlockedMessageGroup');
|
||||
MessageListComponents.OriginalBlockedMessageGroup = MessageListComponents.BlockedMessageGroup;
|
||||
MessageListComponents.BlockedMessageGroup = () => { return null; };
|
||||
MessageListComponents.BlockedMessageGroup = () => null;
|
||||
this.cancelBlockedMessages = () => {
|
||||
MessageListComponents.BlockedMessageGroup = MessageListComponents.OriginalBlockedMessageGroup;
|
||||
delete MessageListComponents.OriginalBlockedMessageGroup;
|
||||
|
|
|
@ -22,10 +22,10 @@ export default class BuiltinModule {
|
|||
this.patch = this.patch.bind(this);
|
||||
}
|
||||
|
||||
init() {
|
||||
async init() {
|
||||
this.setting.on('setting-updated', this._settingUpdated);
|
||||
if (this.setting.value) {
|
||||
if (this.enabled) this.enabled();
|
||||
if (this.enabled) await this.enabled();
|
||||
if (this.applyPatches) this.applyPatches();
|
||||
}
|
||||
}
|
||||
|
@ -38,16 +38,15 @@ export default class BuiltinModule {
|
|||
return Patcher.getPatchesByCaller(`BD:${this.moduleName}`);
|
||||
}
|
||||
|
||||
_settingUpdated(e) {
|
||||
const { value } = e;
|
||||
if (value === true) {
|
||||
if (this.enabled) this.enabled(e);
|
||||
if (this.applyPatches) this.applyPatches();
|
||||
return;
|
||||
}
|
||||
if (value === false) {
|
||||
if (this.disabled) this.disabled(e);
|
||||
async _settingUpdated(e) {
|
||||
if (e.value) {
|
||||
if (this.enabled) await this.enabled(e);
|
||||
if (this.applyPatches) await this.applyPatches();
|
||||
if (this.rerenderPatchedComponents) this.rerenderPatchedComponents();
|
||||
} else {
|
||||
if (this.disabled) await this.disabled(e);
|
||||
this.unpatch();
|
||||
if (this.rerenderPatchedComponents) this.rerenderPatchedComponents();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,12 +74,14 @@ export default class BuiltinModule {
|
|||
*/
|
||||
patch(module, fnName, cb, when = 'after') {
|
||||
if (!['before', 'after', 'instead'].includes(when)) when = 'after';
|
||||
Patch(`BD:${this.moduleName}`, module)[when](fnName, cb.bind(this));
|
||||
return Patch(`BD:${this.moduleName}`, module)[when](fnName, cb.bind(this));
|
||||
}
|
||||
|
||||
childPatch(module, fnName, child, cb, when = 'after') {
|
||||
const last = child.pop();
|
||||
|
||||
this.patch(module, fnName, (component, args, retVal) => {
|
||||
this.patch(retVal[child[0]], child[1], cb, when);
|
||||
const unpatch = this.patch(child.reduce((obj, key) => obj[key], retVal), last, function(...args) {unpatch(); return cb.call(this, component, ...args);}, when);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,10 @@ export default new class ColoredText extends BuiltinModule {
|
|||
this.intensitySetting.off('setting-updated', this._intensityUpdated);
|
||||
}
|
||||
|
||||
rerenderPatchedComponents() {
|
||||
if (this.MessageContent) this.MessageContent.forceUpdateAll();
|
||||
}
|
||||
|
||||
/* Methods */
|
||||
_intensityUpdated() {
|
||||
this.MessageContent.forceUpdateAll();
|
||||
|
@ -50,16 +54,16 @@ export default new class ColoredText extends BuiltinModule {
|
|||
/* Patches */
|
||||
async applyPatches() {
|
||||
if (this.patches.length) return;
|
||||
this.MessageContent = await ReactComponents.getComponent('MessageContent', { selector: Reflection.resolve('container', 'containerCozy', 'containerCompact', 'edited').selector }, m => m.defaultProps && m.defaultProps.hasOwnProperty('disableButtons'));
|
||||
this.MessageContent = await ReactComponents.getComponent('MessageContent');
|
||||
this.patch(this.MessageContent.component.prototype, 'render', this.injectColoredText);
|
||||
this.MessageContent.forceUpdateAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set markup text colour to match role colour
|
||||
*/
|
||||
injectColoredText(thisObject, args, originalReturn) {
|
||||
this.patch(originalReturn.props, 'children', function(obj, args, returnValue) {
|
||||
const unpatch = this.patch(originalReturn.props, 'children', (obj, args, returnValue) => {
|
||||
unpatch();
|
||||
const { TinyColor } = Reflection.modules;
|
||||
const markup = Utils.findInReactTree(returnValue, m => m && m.props && m.props.className && m.props.className.includes('da-markup'));
|
||||
const roleColor = thisObject.props.message.colorString;
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
*/
|
||||
|
||||
import { Settings, Cache, Events } from 'modules';
|
||||
import BuiltinModule from './BuiltinModule';
|
||||
import { Reflection, ReactComponents, MonkeyPatch, Patcher, DiscordApi, Security } from 'modules';
|
||||
import BuiltinModule from '../BuiltinModule';
|
||||
import { Reflection, ReactComponents, DiscordApi, Security } from 'modules';
|
||||
import { VueInjector, Modals, Toasts } from 'ui';
|
||||
import { ClientLogger as Logger, ClientIPC } from 'common';
|
||||
import { request } from 'vendor';
|
||||
|
@ -172,7 +172,7 @@ export default new class E2EE extends BuiltinModule {
|
|||
this.patch(Dispatcher, 'dispatch', this.dispatcherPatch, 'before');
|
||||
this.patchMessageContent();
|
||||
|
||||
const ChannelTextArea = await ReactComponents.getComponent('ChannelTextArea', { selector: Reflection.resolve('channelTextArea', 'emojiButton').selector });
|
||||
const ChannelTextArea = await ReactComponents.getComponent('ChannelTextArea');
|
||||
this.patchChannelTextArea(ChannelTextArea);
|
||||
this.patchChannelTextAreaSubmit(ChannelTextArea);
|
||||
ChannelTextArea.forceUpdateAll();
|
||||
|
@ -236,12 +236,14 @@ export default new class E2EE extends BuiltinModule {
|
|||
}
|
||||
|
||||
async patchMessageContent() {
|
||||
const MessageContent = await ReactComponents.getComponent('MessageContent', { selector: Reflection.resolve('container', 'containerCozy', 'containerCompact', 'edited').selector }, m => m.defaultProps && m.defaultProps.hasOwnProperty('disableButtons'));
|
||||
const MessageContent = await ReactComponents.getComponent('MessageContent');
|
||||
this.patch(MessageContent.component.prototype, 'render', this.beforeRenderMessageContent, 'before');
|
||||
this.patch(MessageContent.component.prototype, 'render', this.afterRenderMessageContent);
|
||||
this.childPatch(MessageContent.component.prototype, 'render', ['props', 'children'], this.afterRenderMessageContent);
|
||||
MessageContent.forceUpdateAll();
|
||||
|
||||
const ImageWrapper = await ReactComponents.getComponent('ImageWrapper', { selector: Reflection.resolve('imageWrapper').selector });
|
||||
const ImageWrapper = await ReactComponents.getComponent('ImageWrapper');
|
||||
this.patch(ImageWrapper.component.prototype, 'render', this.beforeRenderImageWrapper, 'before');
|
||||
ImageWrapper.forceUpdateAll();
|
||||
}
|
||||
|
||||
beforeRenderMessageContent(component) {
|
||||
|
@ -285,10 +287,16 @@ export default new class E2EE extends BuiltinModule {
|
|||
component.props.message.contentParsed = create.contentParsed;
|
||||
}
|
||||
|
||||
afterRenderMessageContent(component, args, retVal) {
|
||||
afterRenderMessageContent(component, _childrenObject, args, retVal) {
|
||||
if (!component.props.message.bd_encrypted) return;
|
||||
const buttons = Utils.findInReactTree(retVal, m => Array.isArray(m) && m[1].props && m[1].props.currentUserId);
|
||||
|
||||
const { className } = Reflection.resolve('buttonContainer', 'avatar', 'username');
|
||||
const buttonContainer = Utils.findInReactTree(retVal, m => m && m.className && m.className.indexOf(className) !== -1);
|
||||
if (!buttonContainer) return;
|
||||
|
||||
const buttons = buttonContainer.children.props.children;
|
||||
if (!buttons) return;
|
||||
|
||||
try {
|
||||
buttons.unshift(VueInjector.createReactElement(E2EEMessageButton));
|
||||
} catch (err) {
|
|
@ -45,7 +45,7 @@
|
|||
import { E2EE } from 'builtin';
|
||||
import { Settings, DiscordApi, Reflection } from 'modules';
|
||||
import { Toasts } from 'ui';
|
||||
import { MiLock, MiImagePlus, MiIcVpnKey } from '../ui/components/common/MaterialIcon';
|
||||
import { MiLock, MiImagePlus, MiIcVpnKey } from 'commoncomponents';
|
||||
|
||||
export default {
|
||||
components: {
|
|
@ -17,7 +17,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { MiLock } from '../ui/components/common/MaterialIcon';
|
||||
import { MiLock } from 'commoncomponents';
|
||||
|
||||
export default {
|
||||
components: {
|
|
@ -0,0 +1,3 @@
|
|||
export { default as default } from './E2EE';
|
||||
export { default as E2EEComponent } from './E2EEComponent.vue';
|
||||
export { default as E2EEMessageButton } from './E2EEMessageButton.vue';
|
|
@ -9,18 +9,11 @@
|
|||
*/
|
||||
|
||||
import { Settings } from 'modules';
|
||||
|
||||
import BuiltinModule from './BuiltinModule';
|
||||
import EmoteModule from './EmoteModule';
|
||||
import GlobalAc from '../ui/autocomplete';
|
||||
import BuiltinModule from '../BuiltinModule';
|
||||
import EmoteModule, { EMOTE_SOURCES } from './EmoteModule';
|
||||
import GlobalAc from 'autocomplete';
|
||||
import { BdContextMenu } from 'ui';
|
||||
|
||||
const EMOTE_SOURCES = [
|
||||
'https://static-cdn.jtvnw.net/emoticons/v1/:id/1.0',
|
||||
'https://cdn.frankerfacez.com/emoticon/:id/1',
|
||||
'https://cdn.betterttv.net/emote/:id/1x'
|
||||
]
|
||||
|
||||
export default new class EmoteAc extends BuiltinModule {
|
||||
|
||||
/* Getters */
|
|
@ -8,15 +8,10 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import VrWrapper from '../ui/vrwrapper';
|
||||
import VrWrapper from '../../ui/vrwrapper';
|
||||
import { EMOTE_SOURCES } from '.';
|
||||
import EmoteComponent from './EmoteComponent.vue';
|
||||
|
||||
const EMOTE_SOURCES = [
|
||||
'https://static-cdn.jtvnw.net/emoticons/v1/:id/1.0',
|
||||
'https://cdn.frankerfacez.com/emoticon/:id/1',
|
||||
'https://cdn.betterttv.net/emote/:id/1x'
|
||||
]
|
||||
|
||||
export default class Emote extends VrWrapper {
|
||||
|
||||
constructor(type, id, name) {
|
|
@ -5,7 +5,7 @@
|
|||
<script>
|
||||
import { ClientLogger as Logger } from 'common';
|
||||
import EmoteModule from './EmoteModule';
|
||||
import { MiStar } from '../ui/components/common';
|
||||
import { MiStar } from 'commoncomponents';
|
||||
|
||||
export default {
|
||||
components: {
|
|
@ -8,20 +8,17 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import BuiltinModule from './BuiltinModule';
|
||||
import BuiltinModule from '../BuiltinModule';
|
||||
import path from 'path';
|
||||
import { request } from 'vendor';
|
||||
|
||||
import { Utils, FileUtils } from 'common';
|
||||
import { Utils, FileUtils, ClientLogger as Logger } from 'common';
|
||||
import { DiscordApi, Settings, Globals, Reflection, ReactComponents, Database } from 'modules';
|
||||
import { DiscordContextMenu } from 'ui';
|
||||
|
||||
import Emote from './EmoteComponent.js';
|
||||
import Autocomplete from '../ui/components/common/Autocomplete.vue';
|
||||
|
||||
import GlobalAc from '../ui/autocomplete';
|
||||
|
||||
const EMOTE_SOURCES = [
|
||||
export const EMOTE_SOURCES = [
|
||||
'https://static-cdn.jtvnw.net/emoticons/v1/:id/1.0',
|
||||
'https://cdn.frankerfacez.com/emoticon/:id/1',
|
||||
'https://cdn.betterttv.net/emote/:id/1x'
|
||||
|
@ -131,6 +128,8 @@ export default new class EmoteModule extends BuiltinModule {
|
|||
|
||||
this.database.set(id, { id: emote.value.id || value, type });
|
||||
}
|
||||
|
||||
Logger.log('EmoteModule', ['Loaded emote database']);
|
||||
}
|
||||
|
||||
async loadUserData() {
|
||||
|
@ -218,15 +217,18 @@ export default new class EmoteModule extends BuiltinModule {
|
|||
async applyPatches() {
|
||||
this.patchMessageContent();
|
||||
this.patchSendAndEdit();
|
||||
const ImageWrapper = await ReactComponents.getComponent('ImageWrapper', { selector: Reflection.resolve('imageWrapper').selector });
|
||||
this.patch(ImageWrapper.component.prototype, 'render', this.beforeRenderImageWrapper, 'before');
|
||||
this.patchSpoiler();
|
||||
|
||||
const MessageAccessories = await ReactComponents.getComponent('MessageAccessories');
|
||||
this.patch(MessageAccessories.component.prototype, 'render', this.afterRenderMessageAccessories, 'after');
|
||||
MessageAccessories.forceUpdateAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Patches MessageContent render method
|
||||
*/
|
||||
async patchMessageContent() {
|
||||
const MessageContent = await ReactComponents.getComponent('MessageContent', { selector: Reflection.resolve('container', 'containerCozy', 'containerCompact', 'edited').selector }, m => m.defaultProps && m.defaultProps.hasOwnProperty('disableButtons'));
|
||||
const MessageContent = await ReactComponents.getComponent('MessageContent');
|
||||
this.childPatch(MessageContent.component.prototype, 'render', ['props', 'children'], this.afterRenderMessageContent);
|
||||
MessageContent.forceUpdateAll();
|
||||
}
|
||||
|
@ -240,10 +242,26 @@ export default new class EmoteModule extends BuiltinModule {
|
|||
this.patch(MessageActions, 'editMessage', this.handleEditMessage, 'instead');
|
||||
}
|
||||
|
||||
async patchSpoiler() {
|
||||
const Spoiler = await ReactComponents.getComponent('Spoiler');
|
||||
this.childPatch(Spoiler.component.prototype, 'render', ['props', 'children', 'props', 'children'], this.afterRenderSpoiler);
|
||||
Spoiler.forceUpdateAll();
|
||||
}
|
||||
|
||||
afterRenderSpoiler(component, _childrenObject, args, retVal) {
|
||||
const markup = Utils.findInReactTree(retVal, filter =>
|
||||
filter &&
|
||||
filter.className &&
|
||||
filter.className.includes('inlineContent'));
|
||||
if (!markup) return;
|
||||
|
||||
markup.children = this.processMarkup(markup.children);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle message render
|
||||
*/
|
||||
afterRenderMessageContent(component, args, retVal) {
|
||||
afterRenderMessageContent(component, _childrenObject, args, retVal) {
|
||||
const markup = Utils.findInReactTree(retVal, filter =>
|
||||
filter &&
|
||||
filter.className &&
|
||||
|
@ -256,13 +274,15 @@ export default new class EmoteModule extends BuiltinModule {
|
|||
/**
|
||||
* Handle send message
|
||||
*/
|
||||
async handleSendMessage(component, args, orig) {
|
||||
async handleSendMessage(MessageActions, args, orig) {
|
||||
if (!args.length) return orig(...args);
|
||||
const { content } = args[1];
|
||||
if (!content) return orig(...args);
|
||||
|
||||
Logger.log('EmoteModule', ['Sending message', MessageActions, args, orig]);
|
||||
|
||||
const emoteAsImage = Settings.getSetting('emotes', 'default', 'emoteasimage').value &&
|
||||
(DiscordApi.currentChannel.type === 'DM' || DiscordApi.currentChannel.checkPermissions(DiscordApi.modules.DiscordPermissions.ATTACH_FILES));
|
||||
(DiscordApi.currentChannel.type === 'DM' || DiscordApi.currentChannel.type === 'GROUP_DM' || DiscordApi.currentChannel.checkPermissions(DiscordApi.modules.DiscordPermissions.ATTACH_FILES));
|
||||
|
||||
if (!emoteAsImage || content.split(' ').length > 1) {
|
||||
args[1].content = args[1].content.split(' ').map(word => {
|
||||
|
@ -271,7 +291,7 @@ export default new class EmoteModule extends BuiltinModule {
|
|||
const emote = this.findByName(isEmote[1], true);
|
||||
if (!emote) return word;
|
||||
this.addToMostUsed(emote);
|
||||
return emote ? `:${isEmote[1]}:` : word;
|
||||
return emote ? `;${isEmote[1]};` : word;
|
||||
}
|
||||
return word;
|
||||
}).join(' ');
|
||||
|
@ -305,23 +325,27 @@ export default new class EmoteModule extends BuiltinModule {
|
|||
if (!content) return orig(...args);
|
||||
args[2].content = args[2].content.split(' ').map(word => {
|
||||
const isEmote = /;(.*?);/g.exec(word);
|
||||
return isEmote ? `:${isEmote[1]}:` : word;
|
||||
return isEmote ? `;${isEmote[1]};` : word;
|
||||
}).join(' ');
|
||||
return orig(...args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle imagewrapper render
|
||||
* Handle MessageAccessories render
|
||||
*/
|
||||
beforeRenderImageWrapper(component, args, retVal) {
|
||||
if (!component.props || !component.props.src) return;
|
||||
afterRenderMessageAccessories(component, args, retVal) {
|
||||
if (!component.props || !component.props.message) return;
|
||||
if (!component.props.message.attachments || component.props.message.attachments.length !== 1) return;
|
||||
|
||||
const src = component.props.original || component.props.src.split('?')[0];
|
||||
if (!src || !src.includes('.bdemote.')) return;
|
||||
const emoteName = src.split('/').pop().split('.')[0];
|
||||
const emote = this.findByName(emoteName);
|
||||
const filename = component.props.message.attachments[0].filename;
|
||||
const match = filename.match(/([^/]*)\.bdemote\.(gif|png)$/i);
|
||||
if (!match) return;
|
||||
|
||||
const emote = this.findByName(match[1]);
|
||||
if (!emote) return;
|
||||
retVal.props.children = emote.render();
|
||||
|
||||
emote.jumboable = true;
|
||||
retVal.props.children[2] = emote.render();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -339,14 +363,14 @@ export default new class EmoteModule extends BuiltinModule {
|
|||
for (const child of markup) {
|
||||
if (typeof child !== 'string') {
|
||||
if (typeof child === 'object') {
|
||||
const isEmoji = Utils.findInReactTree(child, 'emojiName');
|
||||
if (isEmoji) child.props.children.props.jumboable = jumboable;
|
||||
const isEmoji = Utils.findInReactTree(child, filter => filter && filter.emojiName);
|
||||
if (isEmoji) isEmoji.jumboable = jumboable;
|
||||
}
|
||||
newMarkup.push(child);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!/:(\w+):/g.test(child)) {
|
||||
if (!/;(\w+);/g.test(child)) {
|
||||
newMarkup.push(child);
|
||||
continue;
|
||||
}
|
||||
|
@ -355,7 +379,7 @@ export default new class EmoteModule extends BuiltinModule {
|
|||
|
||||
let s = '';
|
||||
for (const word of words) {
|
||||
const isemote = /:(.*?):/g.exec(word);
|
||||
const isemote = /;(.*?);/g.exec(word);
|
||||
if (!isemote) {
|
||||
s += word;
|
||||
continue;
|
|
@ -0,0 +1,4 @@
|
|||
export { default as EmoteModule, EMOTE_SOURCES } from './EmoteModule';
|
||||
export { default as Emote } from './EmoteComponent';
|
||||
export { default as EmoteComponent } from './EmoteComponent.vue';
|
||||
export { default as EmoteAc } from './EmoteAc';
|
|
@ -1,16 +1,19 @@
|
|||
import { default as EmoteModule } from './EmoteModule';
|
||||
import { default as ReactDevtoolsModule } from './ReactDevtoolsModule';
|
||||
import { default as VueDevtoolsModule } from './VueDevToolsModule';
|
||||
import { default as TrackingProtection } from './TrackingProtection';
|
||||
import { default as E2EE } from './E2EE';
|
||||
import { default as ColoredText } from './ColoredText';
|
||||
import { default as TwentyFourHour } from './24Hour';
|
||||
import { default as KillClyde } from './KillClyde';
|
||||
import { default as BlockedMessages } from './BlockedMessages';
|
||||
import { default as VoiceDisconnect } from './VoiceDisconnect';
|
||||
import { default as EmoteAc } from './EmoteAc';
|
||||
import { EmoteModule, EmoteAc } from './Emotes';
|
||||
import ReactDevtoolsModule from './ReactDevtoolsModule';
|
||||
import VueDevtoolsModule from './VueDevToolsModule';
|
||||
import TrackingProtection from './TrackingProtection';
|
||||
import E2EE from './E2EE';
|
||||
import ColoredText from './ColoredText';
|
||||
import TwentyFourHour from './24Hour';
|
||||
import KillClyde from './KillClyde';
|
||||
import BlockedMessages from './BlockedMessages';
|
||||
import VoiceDisconnect from './VoiceDisconnect';
|
||||
|
||||
export default class {
|
||||
static get modules() {
|
||||
return require('./builtin');
|
||||
}
|
||||
|
||||
static initAll() {
|
||||
EmoteModule.init();
|
||||
ReactDevtoolsModule.init();
|
||||
|
|
|
@ -12,7 +12,7 @@ import BuiltinModule from './BuiltinModule';
|
|||
|
||||
import { Reflection } from 'modules';
|
||||
|
||||
export default new class E2EE extends BuiltinModule {
|
||||
export default new class TrackingProtection extends BuiltinModule {
|
||||
|
||||
/* Getters */
|
||||
get moduleName() { return 'TrackingProtection' }
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export { default as EmoteModule } from './EmoteModule';
|
||||
export { EmoteModule, EmoteAc } from './Emotes';
|
||||
export { default as ReactDevtoolsModule } from './ReactDevtoolsModule';
|
||||
export { default as VueDevtoolsModule } from './VueDevToolsModule';
|
||||
export { default as TrackingProtection } from './TrackingProtection';
|
||||
|
|
|
@ -8,17 +8,16 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import { DOM, BdUI, BdMenu, Modals, Toasts, Notifications, BdContextMenu, DiscordContextMenu } from 'ui';
|
||||
import { DOM, BdUI, BdMenu, Modals, Toasts, Notifications, BdContextMenu, DiscordContextMenu, Autocomplete } from 'ui';
|
||||
import BdCss from './styles/index.scss';
|
||||
import { Events, Globals, Settings, Database, Updater, ModuleManager, PluginManager, ThemeManager, ExtModuleManager, Vendor, Patcher, MonkeyPatch, ReactComponents, ReactHelpers, ReactAutoPatcher, DiscordApi, BdWebApi, Connectivity, Cache, Reflection, PackageInstaller } from 'modules';
|
||||
import { ClientLogger as Logger, ClientIPC, Utils } from 'common';
|
||||
import { ClientLogger as Logger, ClientIPC, Utils, Axi } from 'common';
|
||||
import { BuiltinManager, EmoteModule, ReactDevtoolsModule, VueDevtoolsModule, TrackingProtection, E2EE } from 'builtin';
|
||||
import electron from 'electron';
|
||||
import path from 'path';
|
||||
import { setTimeout } from 'timers';
|
||||
|
||||
const tests = typeof PRODUCTION === 'undefined';
|
||||
const ignoreExternal = true;
|
||||
const ignoreExternal = tests && true;
|
||||
|
||||
class BetterDiscord {
|
||||
|
||||
|
@ -28,18 +27,18 @@ class BetterDiscord {
|
|||
Logger.log('main', 'BetterDiscord starting');
|
||||
|
||||
this._bd = {
|
||||
DOM, BdUI, BdMenu, Modals, Reflection, Toasts, Notifications, BdContextMenu, DiscordContextMenu,
|
||||
DOM, BdUI, BdMenu, Modals, Reflection, Toasts, Notifications, BdContextMenu, DiscordContextMenu, Autocomplete,
|
||||
|
||||
Events, Globals, Settings, Database, Updater,
|
||||
ModuleManager, PluginManager, ThemeManager, ExtModuleManager, PackageInstaller,
|
||||
Vendor,
|
||||
|
||||
Patcher, MonkeyPatch, ReactComponents, ReactHelpers, ReactAutoPatcher, DiscordApi,
|
||||
EmoteModule,
|
||||
BuiltinManager, EmoteModule,
|
||||
BdWebApi,
|
||||
Connectivity,
|
||||
Cache,
|
||||
Logger, ClientIPC, Utils,
|
||||
Logger, ClientIPC, Utils, Axi,
|
||||
|
||||
plugins: PluginManager.localContent,
|
||||
themes: ThemeManager.localContent,
|
||||
|
|
|
@ -65,6 +65,10 @@ export default class Content extends AsyncEventEmitter {
|
|||
get config() { return this.settings.categories }
|
||||
get data() { return this.userConfig.data || (this.userConfig.data = {}) }
|
||||
|
||||
get packed() { return this.dirName.packed }
|
||||
get packagePath() { return this.dirName.packagePath }
|
||||
get packageName() { return this.dirName.pkg }
|
||||
|
||||
/**
|
||||
* Opens a settings modal for this content.
|
||||
* @return {Modal}
|
||||
|
|
|
@ -220,6 +220,7 @@ export default class {
|
|||
const unpackedPath = path.join(Globals.getPath('tmp'), packageName);
|
||||
|
||||
asar.extractAll(packagePath, unpackedPath);
|
||||
|
||||
return this.preloadContent({
|
||||
config,
|
||||
contentPath: unpackedPath,
|
||||
|
@ -228,8 +229,8 @@ export default class {
|
|||
packageName,
|
||||
packed: true
|
||||
}, reload, index);
|
||||
|
||||
} catch (err) {
|
||||
Logger.log('ContentManager', ['Error extracting packed content', err]);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
@ -322,12 +323,6 @@ export default class {
|
|||
return content;
|
||||
} catch (err) {
|
||||
throw err;
|
||||
} finally {
|
||||
if (typeof dirName === 'object' && dirName.packed) {
|
||||
rimraf(dirName.contentPath, err => {
|
||||
if (err) Logger.err(err);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -353,6 +348,7 @@ export default class {
|
|||
await unload;
|
||||
|
||||
await FileUtils.recursiveDeleteDirectory(content.paths.contentPath);
|
||||
if (content.packed) await FileUtils.recursiveDeleteDirectory(content.packagePath);
|
||||
return true;
|
||||
} catch (err) {
|
||||
Logger.err(this.moduleName, err);
|
||||
|
@ -384,7 +380,7 @@ export default class {
|
|||
|
||||
if (this.unloadContentHook) this.unloadContentHook(content);
|
||||
|
||||
if (reload) return content.packed ? this.preloadPackedContent(content.packed.pkg, true, index) : this.preloadContent(content.dirName, true, index);
|
||||
if (reload) return content.packed ? this.preloadPackedContent(content.packagePath, true, index) : this.preloadContent(content.dirName, true, index);
|
||||
|
||||
this.localContent.splice(index, 1);
|
||||
} catch (err) {
|
||||
|
|
|
@ -36,10 +36,6 @@ export default new class extends Module {
|
|||
|
||||
async first() {
|
||||
const config = await ClientIPC.send('getConfig');
|
||||
config.paths.push({
|
||||
id: 'tmp',
|
||||
path: path.join(config.paths.find(p => p.id === 'base').path, 'tmp')
|
||||
});
|
||||
this.setState({ config });
|
||||
|
||||
// This is for Discord to stop error reporting :3
|
||||
|
@ -102,7 +98,7 @@ export default new class extends Module {
|
|||
}
|
||||
|
||||
get version() {
|
||||
return this.config.version;
|
||||
return this.config.versions.core;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ export default class Module {
|
|||
}
|
||||
|
||||
setState(newState) {
|
||||
const oldState = this.state;
|
||||
const oldState = Object.assign({}, this.state);
|
||||
Object.assign(this.state, newState);
|
||||
if (this.stateChanged) this.stateChanged(oldState, newState);
|
||||
}
|
||||
|
|
|
@ -6,14 +6,14 @@ import rimraf from 'rimraf';
|
|||
|
||||
import { request } from 'vendor';
|
||||
import { Modals } from 'ui';
|
||||
import { Utils } from 'common';
|
||||
import { Utils, FileUtils } from 'common';
|
||||
import PluginManager from './pluginmanager';
|
||||
import Globals from './globals';
|
||||
import Security from './security';
|
||||
import { ReactComponents } from './reactcomponents';
|
||||
import Reflection from './reflection';
|
||||
import DiscordApi from './discordapi';
|
||||
import ThemeManager from './thememanager';
|
||||
import { MonkeyPatch } from './patcher';
|
||||
import { DOM } from 'ui';
|
||||
|
||||
export default class PackageInstaller {
|
||||
|
@ -84,15 +84,10 @@ export default class PackageInstaller {
|
|||
|
||||
await oldContent.unload(true);
|
||||
|
||||
if (oldContent.packed && oldContent.packed.packageName !== nameOrId) {
|
||||
rimraf(oldContent.packed.packagePath, err => {
|
||||
if (err) throw err;
|
||||
});
|
||||
} else {
|
||||
rimraf(oldContent.contentPath, err => {
|
||||
if (err) throw err;
|
||||
});
|
||||
if (oldContent.packed && oldContent.packageName !== nameOrId) {
|
||||
await FileUtils.deleteFile(oldContent.packagePath).catch(err => null);
|
||||
}
|
||||
await FileUtils.recursiveDeleteDirectory(oldContent.contentPath).catch(err => null);
|
||||
|
||||
return manager.preloadPackedContent(outputName);
|
||||
} catch (err) {
|
||||
|
@ -133,41 +128,51 @@ export default class PackageInstaller {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Patches Discord upload area for .bd files
|
||||
*/
|
||||
static async uploadAreaPatch() {
|
||||
const { selector } = Reflection.resolve('uploadArea');
|
||||
this.UploadArea = await ReactComponents.getComponent('UploadArea', { selector });
|
||||
static async handleDrop(stateNode, e, original) {
|
||||
if (!e.dataTransfer.files.length || !e.dataTransfer.files[0].name.endsWith('.bd')) return original && original.call(stateNode, e);
|
||||
|
||||
const reflect = Reflection.DOM(selector);
|
||||
const stateNode = reflect.getComponentStateNode(this.UploadArea);
|
||||
const callback = async function (e) {
|
||||
if (!e.dataTransfer.files.length || !e.dataTransfer.files[0].name.endsWith('.bd')) return;
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
e.stopImmediatePropagation();
|
||||
stateNode.clearDragging();
|
||||
const currentChannel = DiscordApi.currentChannel;
|
||||
const canUpload = currentChannel ? currentChannel.checkPermissions(Reflection.modules.DiscordConstants.Permissions.ATTACH_FILES) : false;
|
||||
const files = Array.from(e.dataTransfer.files).slice(0);
|
||||
const actionCode = await PackageInstaller.dragAndDropHandler(e.dataTransfer.files[0].path, canUpload);
|
||||
if (actionCode === 0) stateNode.promptToUpload(files, currentChannel.id, true, !e.shiftKey);
|
||||
};
|
||||
if (stateNode) stateNode.clearDragging();
|
||||
|
||||
const currentChannel = DiscordApi.currentChannel;
|
||||
const canUpload = currentChannel ?
|
||||
currentChannel.checkPermissions(Reflection.modules.DiscordConstants.Permissions.SEND_MESSAGES) &&
|
||||
currentChannel.checkPermissions(Reflection.modules.DiscordConstants.Permissions.ATTACH_FILES) : false;
|
||||
|
||||
const files = Array.from(e.dataTransfer.files).slice(0);
|
||||
const actionCode = await this.dragAndDropHandler(e.dataTransfer.files[0].path, canUpload);
|
||||
|
||||
if (actionCode === 0 && stateNode) stateNode.promptToUpload(files, currentChannel.id, true, !e.shiftKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Patches Discord upload area for .bd files
|
||||
*/
|
||||
static async uploadAreaPatch(UploadArea) {
|
||||
// Add a listener to root for when not in a channel
|
||||
const root = DOM.getElement('#app-mount');
|
||||
root.addEventListener('drop', callback);
|
||||
const rootHandleDrop = this.handleDrop.bind(this, undefined);
|
||||
root.addEventListener('drop', rootHandleDrop);
|
||||
|
||||
// Remove their handler, add ours, then read theirs to give ours priority to stop theirs when we get a .bd file.
|
||||
reflect.element.removeEventListener('drop', stateNode.handleDrop);
|
||||
reflect.element.addEventListener('drop', callback);
|
||||
reflect.element.addEventListener('drop', stateNode.handleDrop);
|
||||
const unpatchUploadAreaHandleDrop = MonkeyPatch('BD:ReactComponents', UploadArea.component.prototype).instead('handleDrop', (component, [e], original) => this.handleDrop(component, e, original));
|
||||
|
||||
this.unpatchUploadArea = function () {
|
||||
reflect.element.removeEventListener('drop', callback);
|
||||
root.removeEventListener('drop', callback);
|
||||
this.unpatchUploadArea = () => {
|
||||
unpatchUploadAreaHandleDrop();
|
||||
root.removeEventListener('drop', rootHandleDrop);
|
||||
this.unpatchUploadArea = undefined;
|
||||
};
|
||||
|
||||
for (const element of document.querySelectorAll(UploadArea.important.selector)) {
|
||||
const stateNode = Reflection.DOM(element).getComponentStateNode(UploadArea);
|
||||
|
||||
element.removeEventListener('drop', stateNode.handleDrop);
|
||||
stateNode.handleDrop = UploadArea.component.prototype.handleDrop.bind(stateNode);
|
||||
element.addEventListener('drop', stateNode.handleDrop);
|
||||
|
||||
stateNode.forceUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -109,21 +109,9 @@ export default class extends ContentManager {
|
|||
throw {message: `Plugin ${info.name} did not return a class that extends Plugin.`};
|
||||
|
||||
const instance = new plugin({
|
||||
configs, info, main,
|
||||
paths: {
|
||||
contentPath: paths.contentPath,
|
||||
dirName: packed ? packed.packageName : paths.dirName,
|
||||
mainPath: paths.mainPath
|
||||
}
|
||||
configs, info, main, paths
|
||||
});
|
||||
|
||||
if (packed) instance.packed = {
|
||||
pkg: packed.pkg,
|
||||
packageName: packed.packageName,
|
||||
packagePath: packed.packagePath,
|
||||
packed: true
|
||||
}; else instance.packed = false;
|
||||
|
||||
if (instance.enabled && this.loaded) {
|
||||
instance.userConfig.enabled = false;
|
||||
instance.start(false);
|
||||
|
|
|
@ -173,9 +173,18 @@ class ReactComponent {
|
|||
this.important = important;
|
||||
}
|
||||
|
||||
get elements() {
|
||||
if (!this.important || !this.important.selector) return [];
|
||||
|
||||
return document.querySelectorAll(this.important.selector);
|
||||
}
|
||||
|
||||
get stateNodes() {
|
||||
return [...this.elements].map(e => Reflection.DOM(e).getComponentStateNode(this));
|
||||
}
|
||||
|
||||
forceUpdateAll() {
|
||||
if (!this.important || !this.important.selector) return;
|
||||
for (const e of document.querySelectorAll(this.important.selector)) {
|
||||
for (const e of this.elements) {
|
||||
Reflection.DOM(e).forceUpdate(this);
|
||||
}
|
||||
}
|
||||
|
@ -186,6 +195,7 @@ export class ReactComponents {
|
|||
static get unknownComponents() { return this._unknownComponents || (this._unknownComponents = []) }
|
||||
static get listeners() { return this._listeners || (this._listeners = []) }
|
||||
static get nameSetters() { return this._nameSetters || (this._nameSetters = []) }
|
||||
static get componentAliases() { return this._componentAliases || (this._componentAliases = []) }
|
||||
|
||||
static get ReactComponent() { return ReactComponent }
|
||||
|
||||
|
@ -222,6 +232,8 @@ export class ReactComponents {
|
|||
* @return {Promise => ReactComponent}
|
||||
*/
|
||||
static async getComponent(name, important, filter) {
|
||||
name = this.getComponentName(name);
|
||||
|
||||
const have = this.components.find(c => c.id === name);
|
||||
if (have) return have;
|
||||
|
||||
|
@ -239,7 +251,13 @@ export class ReactComponents {
|
|||
let component, reflect;
|
||||
for (const element of elements) {
|
||||
reflect = Reflection.DOM(element);
|
||||
component = filter ? reflect.components.find(filter) : reflect.component;
|
||||
component = filter ? reflect.components.find(component => {
|
||||
try {
|
||||
return filter.call(undefined, component);
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
}) : reflect.component;
|
||||
if (component) break;
|
||||
}
|
||||
|
||||
|
@ -276,6 +294,19 @@ export class ReactComponents {
|
|||
});
|
||||
}
|
||||
|
||||
static getComponentName(name) {
|
||||
const resolvedAliases = [];
|
||||
|
||||
while (this.componentAliases[name]) {
|
||||
resolvedAliases.push(name);
|
||||
name = this.componentAliases[name];
|
||||
|
||||
if (resolvedAliases.includes(name)) break;
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
static setName(name, filter) {
|
||||
const have = this.components.find(c => c.id === name);
|
||||
if (have) return have;
|
||||
|
@ -351,6 +382,21 @@ export class ReactAutoPatcher {
|
|||
this.Message.forceUpdateAll();
|
||||
}
|
||||
|
||||
static async patchMessageContent() {
|
||||
const { selector } = Reflection.resolve('container', 'containerCozy', 'containerCompact', 'edited');
|
||||
this.MessageContent = await ReactComponents.getComponent('MessageContent', {selector}, c => c.defaultProps && c.defaultProps.hasOwnProperty('disableButtons'));
|
||||
}
|
||||
|
||||
static async patchSpoiler() {
|
||||
const { selector } = Reflection.resolve('spoilerText', 'spoilerContainer');
|
||||
this.Spoiler = await ReactComponents.getComponent('Spoiler', {selector}, c => c.prototype.renderSpoilerText);
|
||||
}
|
||||
|
||||
static async patchMessageAccessories() {
|
||||
const { selector } = Reflection.resolve('container', 'containerCozy', 'embedWrapper');
|
||||
this.MessageAccessories = await ReactComponents.getComponent('MessageAccessories', {selector});
|
||||
}
|
||||
|
||||
static async patchMessageGroup() {
|
||||
const { selector } = Reflection.resolve('container', 'message', 'messageCozy');
|
||||
this.MessageGroup = await ReactComponents.getComponent('MessageGroup', {selector});
|
||||
|
@ -369,7 +415,16 @@ export class ReactAutoPatcher {
|
|||
this.MessageGroup.forceUpdateAll();
|
||||
}
|
||||
|
||||
static async patchImageWrapper() {
|
||||
ReactComponents.componentAliases.ImageWrapper = 'Image';
|
||||
|
||||
const { selector } = Reflection.resolve('imageWrapper');
|
||||
this.ImageWrapper = await ReactComponents.getComponent('ImageWrapper', {selector}, c => typeof c.defaultProps.children === 'function');
|
||||
}
|
||||
|
||||
static async patchChannelMember() {
|
||||
ReactComponents.componentAliases.ChannelMember = 'MemberListItem';
|
||||
|
||||
const { selector } = Reflection.resolve('member', 'memberInner', 'activity');
|
||||
this.ChannelMember = await ReactComponents.getComponent('ChannelMember', {selector}, m => m.prototype.renderActivity);
|
||||
|
||||
|
@ -385,8 +440,13 @@ export class ReactAutoPatcher {
|
|||
this.ChannelMember.forceUpdateAll();
|
||||
}
|
||||
|
||||
static async patchNameTag() {
|
||||
const { selector } = Reflection.resolve('nameTag', 'username', 'discriminator', 'ownerIcon');
|
||||
this.NameTag = await ReactComponents.getComponent('NameTag', {selector});
|
||||
}
|
||||
|
||||
static async patchGuild() {
|
||||
const selector = `div.${Reflection.resolve('guild', 'guildsWrapper').className}:not(:first-child)`;
|
||||
const selector = `div.${Reflection.resolve('container', 'guildIcon', 'selected', 'unread').className}:not(:first-child)`;
|
||||
this.Guild = await ReactComponents.getComponent('Guild', {selector}, m => m.prototype.renderBadge);
|
||||
|
||||
this.unpatchGuild = MonkeyPatch('BD:ReactComponents', this.Guild.component.prototype).after('render', (component, args, retVal) => {
|
||||
|
@ -403,7 +463,7 @@ export class ReactAutoPatcher {
|
|||
* The Channel component contains the header, message scroller, message form and member list.
|
||||
*/
|
||||
static async patchChannel() {
|
||||
const selector = '.chat';
|
||||
const { selector } = Reflection.resolve('chat', 'title', 'channelName');
|
||||
this.Channel = await ReactComponents.getComponent('Channel', {selector});
|
||||
|
||||
this.unpatchChannel = MonkeyPatch('BD:ReactComponents', this.Channel.component.prototype).after('render', (component, args, retVal) => {
|
||||
|
@ -419,10 +479,17 @@ export class ReactAutoPatcher {
|
|||
this.Channel.forceUpdateAll();
|
||||
}
|
||||
|
||||
static async patchChannelTextArea() {
|
||||
const { selector } = Reflection.resolve('channelTextArea', 'autocomplete');
|
||||
this.ChannelTextArea = await ReactComponents.getComponent('ChannelTextArea', {selector});
|
||||
}
|
||||
|
||||
/**
|
||||
* The GuildTextChannel component represents a text channel in the guild channel list.
|
||||
*/
|
||||
static async patchGuildTextChannel() {
|
||||
ReactComponents.componentAliases.GuildTextChannel = 'TextChannel';
|
||||
|
||||
const { selector } = Reflection.resolve('containerDefault', 'actionIcon');
|
||||
this.GuildTextChannel = await ReactComponents.getComponent('GuildTextChannel', {selector}, c => c.prototype.renderMentionBadge);
|
||||
|
||||
|
@ -435,6 +502,8 @@ export class ReactAutoPatcher {
|
|||
* The GuildVoiceChannel component represents a voice channel in the guild channel list.
|
||||
*/
|
||||
static async patchGuildVoiceChannel() {
|
||||
ReactComponents.componentAliases.GuildVoiceChannel = 'VoiceChannel';
|
||||
|
||||
const { selector } = Reflection.resolve('containerDefault', 'actionIcon');
|
||||
this.GuildVoiceChannel = await ReactComponents.getComponent('GuildVoiceChannel', {selector}, c => c.prototype.handleVoiceConnect);
|
||||
|
||||
|
@ -447,7 +516,9 @@ export class ReactAutoPatcher {
|
|||
* The DirectMessage component represents a channel in the direct messages list.
|
||||
*/
|
||||
static async patchDirectMessage() {
|
||||
const selector = '.channel.private';
|
||||
ReactComponents.componentAliases.DirectMessage = 'PrivateChannel';
|
||||
|
||||
const { selector } = Reflection.resolve('channel', 'avatar', 'name');
|
||||
this.DirectMessage = await ReactComponents.getComponent('DirectMessage', {selector}, c => c.prototype.renderAvatar);
|
||||
|
||||
this.unpatchDirectMessage = MonkeyPatch('BD:ReactComponents', this.DirectMessage.component.prototype).after('render', this._afterChannelRender);
|
||||
|
@ -469,15 +540,18 @@ export class ReactAutoPatcher {
|
|||
}
|
||||
|
||||
static async patchUserProfileModal() {
|
||||
ReactComponents.componentAliases.UserProfileModal = 'UserProfileBody';
|
||||
|
||||
const { selector } = Reflection.resolve('root', 'topSectionNormal');
|
||||
this.UserProfileModal = await ReactComponents.getComponent('UserProfileModal', {selector}, Filters.byPrototypeFields(['renderHeader', 'renderBadges']));
|
||||
this.UserProfileModal = await ReactComponents.getComponent('UserProfileModal', {selector}, c => c.prototype.renderHeader && c.prototype.renderBadges);
|
||||
|
||||
this.unpatchUserProfileModal = MonkeyPatch('BD:ReactComponents', this.UserProfileModal.component.prototype).after('render', (component, args, retVal) => {
|
||||
const root = retVal.props.children[0] || retVal.props.children;
|
||||
const { user } = component.props;
|
||||
if (!user) return;
|
||||
retVal.props['data-user-id'] = user.id;
|
||||
if (user.bot) retVal.props.className += ' bd-isBot';
|
||||
if (user.id === DiscordApi.currentUser.id) retVal.props.className += ' bd-isCurrentUser';
|
||||
root.props['data-user-id'] = user.id;
|
||||
if (user.bot) root.props.className += ' bd-isBot';
|
||||
if (user.id === DiscordApi.currentUser.id) root.props.className += ' bd-isCurrentUser';
|
||||
});
|
||||
|
||||
this.UserProfileModal.forceUpdateAll();
|
||||
|
@ -485,24 +559,28 @@ export class ReactAutoPatcher {
|
|||
|
||||
static async patchUserPopout() {
|
||||
const { selector } = Reflection.resolve('userPopout', 'headerNormal');
|
||||
this.UserPopout = await ReactComponents.getComponent('UserPopout', {selector});
|
||||
this.UserPopout = await ReactComponents.getComponent('UserPopout', {selector}, c => c.prototype.renderHeader);
|
||||
|
||||
this.unpatchUserPopout = MonkeyPatch('BD:ReactComponents', this.UserPopout.component.prototype).after('render', (component, args, retVal) => {
|
||||
const root = retVal.props.children[0] || retVal.props.children;
|
||||
const { user, guild, guildMember } = component.props;
|
||||
if (!user) return;
|
||||
retVal.props['data-user-id'] = user.id;
|
||||
if (user.bot) retVal.props.className += ' bd-isBot';
|
||||
if (user.id === DiscordApi.currentUser.id) retVal.props.className += ' bd-isCurrentUser';
|
||||
if (guild) retVal.props['data-guild-id'] = guild.id;
|
||||
if (guild && user.id === guild.ownerId) retVal.props.className += ' bd-isGuildOwner';
|
||||
if (guild && guildMember) retVal.props.className += ' bd-isGuildMember';
|
||||
if (guildMember && guildMember.roles.length) retVal.props.className += ' bd-hasRoles';
|
||||
root.props['data-user-id'] = user.id;
|
||||
if (user.bot) root.props.className += ' bd-isBot';
|
||||
if (user.id === DiscordApi.currentUser.id) root.props.className += ' bd-isCurrentUser';
|
||||
if (guild) root.props['data-guild-id'] = guild.id;
|
||||
if (guild && user.id === guild.ownerId) root.props.className += ' bd-isGuildOwner';
|
||||
if (guild && guildMember) root.props.className += ' bd-isGuildMember';
|
||||
if (guildMember && guildMember.roles.length) root.props.className += ' bd-hasRoles';
|
||||
});
|
||||
|
||||
this.UserPopout.forceUpdateAll();
|
||||
}
|
||||
|
||||
static async patchUploadArea() {
|
||||
PackageInstaller.uploadAreaPatch();
|
||||
const { selector } = Reflection.resolve('uploadArea');
|
||||
this.UploadArea = await ReactComponents.getComponent('UploadArea', {selector});
|
||||
|
||||
PackageInstaller.uploadAreaPatch(this.UploadArea);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -147,6 +147,11 @@ export default class Theme extends Content {
|
|||
* @param {Array} files Files to watch
|
||||
*/
|
||||
set watchfiles(files) {
|
||||
if (this.packed) {
|
||||
// Don't watch files for packed themes
|
||||
return;
|
||||
}
|
||||
|
||||
if (!files) files = [];
|
||||
|
||||
for (const file of files) {
|
||||
|
|
|
@ -36,12 +36,7 @@ export default class ThemeManager extends ContentManager {
|
|||
static async loadTheme(paths, configs, info, main) {
|
||||
try {
|
||||
const instance = new Theme({
|
||||
configs, info, main,
|
||||
paths: {
|
||||
contentPath: paths.contentPath,
|
||||
dirName: paths.dirName,
|
||||
mainPath: paths.mainPath
|
||||
}
|
||||
configs, info, main, paths
|
||||
});
|
||||
if (instance.enabled) {
|
||||
instance.userConfig.enabled = false;
|
||||
|
|
|
@ -8,81 +8,183 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import Events from './events';
|
||||
import Globals from './globals';
|
||||
import { ClientLogger as Logger } from 'common';
|
||||
import request from 'request-promise-native';
|
||||
import { Notifications } from 'ui';
|
||||
import { Reflection, Globals } from 'modules';
|
||||
|
||||
export default new class {
|
||||
import Events from './events';
|
||||
import Module from './imodule';
|
||||
|
||||
export default new class extends Module {
|
||||
|
||||
get updates() { return this.state.updates }
|
||||
get bdUpdates() { return this.state.updates.bd }
|
||||
get error() { return null; }
|
||||
get updatesAvailable() { return this.state.updatesAvailable; }
|
||||
|
||||
constructor() {
|
||||
this.updatesAvailable = false;
|
||||
this.latestVersion = undefined;
|
||||
this.error = undefined;
|
||||
|
||||
this.init = this.init.bind(this);
|
||||
this.checkForUpdates = this.checkForUpdates.bind(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* The interval to wait before checking for updates.
|
||||
*/
|
||||
get interval() {
|
||||
return 60 * 1000 * 30;
|
||||
}
|
||||
|
||||
init() {
|
||||
this.updateInterval = setInterval(this.checkForUpdates, this.interval);
|
||||
}
|
||||
|
||||
/**
|
||||
* Installs an update.
|
||||
* TODO
|
||||
*/
|
||||
async update() {
|
||||
try {
|
||||
await new Promise(resolve => setTimeout(resolve, 5000));
|
||||
|
||||
this.updatesAvailable = false;
|
||||
this.latestVersion = Globals.version;
|
||||
Events.emit('update-check-end');
|
||||
} catch (err) {
|
||||
this.error = err;
|
||||
this.checkForUpdates();
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for updates.
|
||||
* @return {Promise}
|
||||
*/
|
||||
async checkForUpdates() {
|
||||
if (this.updatesAvailable) return true;
|
||||
Events.emit('update-check-start');
|
||||
Logger.info('Updater', 'Checking for updates');
|
||||
|
||||
try {
|
||||
const response = await request({
|
||||
uri: 'https://rawgit.com/JsSucks/BetterDiscordApp/master/package.json',
|
||||
json: true
|
||||
super({
|
||||
updatesAvailable: false,
|
||||
error: null,
|
||||
updates: { bd: [] },
|
||||
updating: false
|
||||
});
|
||||
}
|
||||
|
||||
this.latestVersion = response.version;
|
||||
Events.emit('update-check-end');
|
||||
Logger.info('Updater', `Latest Version: ${response.version} - Current Version: ${Globals.version}`);
|
||||
bindings() {
|
||||
this.restartNotif = this.restartNotif.bind(this);
|
||||
this.reloadNotif = this.reloadNotif.bind(this);
|
||||
this.startUpdate = this.startUpdate.bind(this);
|
||||
this.setUpdateStatus = this.setUpdateStatus.bind(this);
|
||||
this.testUi = this.testUi.bind(this);
|
||||
}
|
||||
|
||||
if (this.latestVersion !== Globals.version) {
|
||||
this.updatesAvailable = true;
|
||||
Events.emit('updates-available');
|
||||
restartNotif() {
|
||||
Notifications.add('Updates Finished!', 'Restart required.', [
|
||||
{
|
||||
text: 'Restart Later',
|
||||
onClick: () => { setTimeout(this.restartNotif, 5 * 60000); return true; }
|
||||
},
|
||||
{
|
||||
text: 'Restart Now',
|
||||
onClick: () => {
|
||||
try {
|
||||
const { remote } = Globals.require('electron');
|
||||
window.close();
|
||||
Reflection.module.byProps('showToken', 'hideToken').showToken();
|
||||
remote.app.relaunch();
|
||||
remote.app.exit(0);
|
||||
} catch (err) {
|
||||
console.err(err);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
]);
|
||||
}
|
||||
|
||||
return false;
|
||||
} catch (err) {
|
||||
Events.emit('update-check-fail', err);
|
||||
throw err;
|
||||
reloadNotif() {
|
||||
Notifications.add('Updates Finished!', 'Reload required.', [
|
||||
{
|
||||
text: 'Reload Later',
|
||||
onClick: () => { setTimeout(this.reloadNotif, 5 * 60000); return true; }
|
||||
},
|
||||
{
|
||||
text: 'Reload Now',
|
||||
onClick: () => {
|
||||
document.location.reload();
|
||||
}
|
||||
}
|
||||
]);
|
||||
}
|
||||
|
||||
events(ipc) {
|
||||
ipc.on('updater-checkForUpdates', () => {
|
||||
if (this.state.updating) return; // We're already updating. Updater should be paused anyways at this point.
|
||||
Events.emit('update-check-start');
|
||||
});
|
||||
|
||||
ipc.on('updater-noUpdates', () => {
|
||||
if (this.state.updatesAvailable) return; // If for some reason we get this even though we have updates already.
|
||||
this.setState({
|
||||
updatesAvailable: false,
|
||||
updates: {}
|
||||
});
|
||||
});
|
||||
|
||||
ipc.on('updater-updatesAvailable', (_, updates) => {
|
||||
console.log(updates);
|
||||
if (this.state.updating) return; // If for some reason we get more updates when we're already updating
|
||||
updates.bd = updates.bd.map(update => {
|
||||
update.text = `${update.id.charAt(0).toUpperCase()}${update.id.slice(1)}`;
|
||||
update.hint = `Current: ${update.currentVersion} | Latest: ${update.version}`;
|
||||
update.status = {
|
||||
update: true,
|
||||
updating: false,
|
||||
updated: false,
|
||||
error: null
|
||||
};
|
||||
|
||||
return update;
|
||||
});
|
||||
this.setState({
|
||||
updates,
|
||||
updatesAvailable: true
|
||||
});
|
||||
});
|
||||
|
||||
ipc.on('updater-updated', (_, info) => {
|
||||
const { reloadRequired, restartRequired } = info;
|
||||
if (restartRequired) {
|
||||
this.restartNotif();
|
||||
return;
|
||||
}
|
||||
|
||||
if (reloadRequired) {
|
||||
this.reloadNotif();
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
ipc.on('updater-updateFinished', (_, update) => {
|
||||
this.setUpdateStatus(update.id, 'updated', true);
|
||||
});
|
||||
|
||||
ipc.on('updater-updateError', (_, update) => {
|
||||
this.setUpdateStatus(update.id, 'error', update.error);
|
||||
});
|
||||
}
|
||||
|
||||
stateChanged(oldState, newState) {
|
||||
if (!newState.updatesAvailable) return Events.emit('update-check-end');
|
||||
if (!oldState.updatesAvailable && newState.updatesAvailable) {
|
||||
Events.emit('updates-available');
|
||||
Notifications.add('', 'Updates Available!', [
|
||||
{
|
||||
text: 'Ignore',
|
||||
onClick: () => { return true; }
|
||||
},
|
||||
{
|
||||
text: 'Show Updates',
|
||||
onClick: () => {
|
||||
Events.emit('bd-open-menu', 'updater');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
setUpdateStatus(updateId, statusChild, statusValue) {
|
||||
for (const u of this.bdUpdates) {
|
||||
if (u.id === updateId) {
|
||||
u.status[statusChild] = statusValue;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
toggleUpdate(update) {
|
||||
update.status.update = !update.status.update;
|
||||
}
|
||||
|
||||
async startUpdate() {
|
||||
console.log('start update');
|
||||
const updates = { bd: [] };
|
||||
for (const update of this.bdUpdates) {
|
||||
if (update.status.update) {
|
||||
update.status.updating = true;
|
||||
updates.bd.push(update);
|
||||
}
|
||||
}
|
||||
console.log(updates);
|
||||
this.send('updater-startUpdate', updates);
|
||||
}
|
||||
|
||||
testUi(updates) {
|
||||
this.setState({
|
||||
updates,
|
||||
updatesAvailable: true
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
import jQuery from 'jquery';
|
||||
import lodash from 'lodash';
|
||||
import Vue from 'vue';
|
||||
import { Axi } from 'common';
|
||||
|
||||
import request from 'request-promise-native';
|
||||
|
||||
|
@ -40,6 +41,8 @@ export default class {
|
|||
*/
|
||||
static get Vue() { return Vue }
|
||||
|
||||
static get axios() { return Axi.axios }
|
||||
|
||||
static get request() { return request }
|
||||
|
||||
static get Combokeys() { return Combokeys }
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
.bd-contentColumn .bd-devview {
|
||||
display: grid;
|
||||
grid-template-columns: 33% 33% 33%;
|
||||
|
||||
.bd-button {
|
||||
font-size: 10px;
|
||||
height: 20px;
|
||||
}
|
||||
}
|
|
@ -10,3 +10,4 @@
|
|||
@import './kvp';
|
||||
@import './collection';
|
||||
@import './e2ee';
|
||||
@import './devview';
|
||||
|
|
|
@ -3,4 +3,22 @@
|
|||
margin: 0 0 10px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.bd-settingSwitch {
|
||||
.bd-spinner7 {
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.bd-updaterStatus {
|
||||
text-align: right;
|
||||
|
||||
&.bd-err {
|
||||
color: $colerr;
|
||||
}
|
||||
|
||||
&.bd-ok {
|
||||
color: $colok;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
// sass-lint:disable-all
|
||||
body:not(.bd-hideButton) {
|
||||
[class*='guildsWrapper-'] {
|
||||
[class*='layer-'] > * > [class*='wrapper-'] {
|
||||
padding-top: 49px !important;
|
||||
}
|
||||
.platform-osx [class*='guildsWrapper-'] {
|
||||
.platform-osx [class*='layer-'] > * > [class*='wrapper-'] {
|
||||
margin-top: 26px;
|
||||
}
|
||||
|
||||
[class*='guildsWrapper-'] + [class*='flex'] {
|
||||
[class*='layer-'] > * > [class*='wrapper-'] + [class*='flex'] {
|
||||
border-radius: 0 0 0 5px;
|
||||
}
|
||||
|
||||
|
@ -27,3 +27,9 @@ body:not(.bd-hideButton) {
|
|||
.bd-settingsWrapper.platform-linux {
|
||||
transform: none;
|
||||
}
|
||||
|
||||
// Remove the margin on message attachments with an emote
|
||||
.da-containerCozy + .da-containerCozy > * > .bd-emote {
|
||||
margin-top: -8px;
|
||||
margin-bottom: -8px;
|
||||
}
|
||||
|
|
|
@ -22,14 +22,14 @@
|
|||
|
||||
> .bd-scroller {
|
||||
overflow-y: scroll;
|
||||
}
|
||||
}
|
||||
|
||||
.bd-settings & {
|
||||
.platform-darwin & { // sass-lint:disable-line class-name-format
|
||||
padding-top: 22px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bd-settingswrapHeader {
|
||||
outline: 0;
|
||||
|
|
|
@ -11,7 +11,7 @@ export default new class Autocomplete {
|
|||
}
|
||||
|
||||
async init() {
|
||||
this.cta = await ReactComponents.getComponent('ChannelTextArea', { selector: Reflection.resolve('channelTextArea', 'emojiButton').selector });
|
||||
this.cta = await ReactComponents.getComponent('ChannelTextArea');
|
||||
MonkeyPatch('BD:Autocomplete', this.cta.component.prototype).after('render', this.channelTextAreaAfterRender.bind(this));
|
||||
this.initialized = true;
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
</Sidebar>
|
||||
|
||||
<div slot="sidebarfooter" class="bd-info">
|
||||
<span class="bd-vtext">v2.0.0a by Jiiks/JsSucks</span>
|
||||
<span class="bd-vtext">{{versionString}}</span>
|
||||
<div @click="openGithub" v-tooltip="'GitHub'" class="bd-materialButton">
|
||||
<MiGithubCircle size="16" />
|
||||
</div>
|
||||
|
@ -63,11 +63,11 @@
|
|||
|
||||
<script>
|
||||
// Imports
|
||||
import { Events, Settings } from 'modules';
|
||||
import { Events, Settings, Globals, Reflection } from 'modules';
|
||||
import { BdMenuItems } from 'ui';
|
||||
import { shell } from 'electron';
|
||||
import { SidebarView, Sidebar, SidebarItem, ContentColumn } from './sidebar';
|
||||
import { SettingsWrapper, SettingsPanel, CssEditorView, PluginsView, ThemesView, UpdaterView, ConnectivityView } from './bd';
|
||||
import { SettingsWrapper, SettingsPanel, CssEditorView, PluginsView, ThemesView, UpdaterView, ConnectivityView, SuperSecretView } from './bd';
|
||||
import { SvgX, MiGithubCircle, MiWeb, MiClose, MiTwitterCircle } from './common';
|
||||
|
||||
export default {
|
||||
|
@ -96,6 +96,9 @@
|
|||
category.push(item);
|
||||
}
|
||||
return categories;
|
||||
},
|
||||
versionString() {
|
||||
return Globals.version;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
@ -123,6 +126,13 @@
|
|||
},
|
||||
created() {
|
||||
Events.on('bd-open-menu', this.openMenuHandler = item => item && this.itemOnClick(this.items.find(i => i === item || i.id === item || i.contentid === item || i.set === item).id));
|
||||
|
||||
try {
|
||||
const currentUser = Reflection.module.byName('UserStore').getCurrentUser();
|
||||
if (['81388395867156480', '98003542823944192', '249746236008169473', '284056145272766465', '478559353516064769'].includes(currentUser.id)) {
|
||||
BdMenuItems.addVueComponent('BD Devs', 'Super Secret', SuperSecretView);
|
||||
}
|
||||
} catch (err) {}
|
||||
},
|
||||
destroyed() {
|
||||
if (this.openMenuHandler) Events.off('bd-open-menu', this.openMenuHandler);
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
/**
|
||||
* BetterDiscord Developer View Component
|
||||
* 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.
|
||||
*/
|
||||
|
||||
<template>
|
||||
<SettingsWrapper headertext="Super Secret">
|
||||
<div class="bd-flex bd-flexCol bd-devview">
|
||||
<FormButton @click="forceUpdate">Force Update</FormButton>
|
||||
<FormButton @click="debugConfig">Config Debug</FormButton>
|
||||
<FormButton @click="testUpdateUi">Update UI Test</FormButton>
|
||||
</div>
|
||||
</SettingsWrapper>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import SettingsWrapper from './SettingsWrapper.vue';
|
||||
import { FormButton } from '../common';
|
||||
import { Globals, Events, Updater } from 'modules';
|
||||
import { ClientIPC } from 'common';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
};
|
||||
},
|
||||
components: {
|
||||
SettingsWrapper,
|
||||
FormButton
|
||||
},
|
||||
methods: {
|
||||
forceUpdate() {
|
||||
ClientIPC.send('debug-updater-forceUpdate');
|
||||
},
|
||||
debugConfig() {
|
||||
console.log(Globals);
|
||||
},
|
||||
testUpdateUi() {
|
||||
Updater.testUi({
|
||||
'bd': [
|
||||
{
|
||||
'id': 'update',
|
||||
'version': '3.0.0',
|
||||
'currentVersion': '2.0.0',
|
||||
'text': 'Update test',
|
||||
'hint': 'Current: 2.0.0 | Latest: 3.0.0',
|
||||
'status': {
|
||||
'update': true,
|
||||
'updating': false,
|
||||
'updated': false,
|
||||
'error': null
|
||||
}
|
||||
},
|
||||
{
|
||||
'id': 'updating',
|
||||
'version': '3.0.0',
|
||||
'currentVersion': '2.0.0',
|
||||
'text': 'Updating test',
|
||||
'hint': 'Current: 2.0.0 | Latest: 3.0.0',
|
||||
'status': {
|
||||
'update': true,
|
||||
'updating': true,
|
||||
'updated': false,
|
||||
'error': null
|
||||
}
|
||||
},
|
||||
{
|
||||
'id': 'updated',
|
||||
'version': '3.0.0',
|
||||
'currentVersion': '2.0.0',
|
||||
'text': 'Updated test',
|
||||
'hint': 'Current: 2.0.0 | Latest: 3.0.0',
|
||||
'status': {
|
||||
'update': true,
|
||||
'updating': true,
|
||||
'updated': true,
|
||||
'error': null
|
||||
}
|
||||
},
|
||||
{
|
||||
'id': 'error',
|
||||
'version': '3.0.0',
|
||||
'currentVersion': '2.0.0',
|
||||
'text': 'Error test',
|
||||
'hint': 'Current: 2.0.0 | Latest: 3.0.0',
|
||||
'status': {
|
||||
'update': true,
|
||||
'updating': true,
|
||||
'updated': false,
|
||||
'error': 'Failed to update.'
|
||||
}
|
||||
}
|
||||
],
|
||||
'haveUpdates': true
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* BetterDiscord Updater Status Component
|
||||
* 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.
|
||||
*/
|
||||
|
||||
<template>
|
||||
<div class="bd-settingSwitch">
|
||||
<div class="bd-title">
|
||||
<h3>{{item.text}}</h3>
|
||||
<h3 class="bd-updaterStatus bd-err" v-if="item.status.error">Update Failed!</h3>
|
||||
<h3 class="bd-updaterStatus bd-ok" v-else-if="item.status.updated">Done</h3>
|
||||
<div class="bd-spinner7" v-else-if="item.status.updating" />
|
||||
<h3 class="bd-updaterStatus" v-else>Unknown</h3>
|
||||
</div>
|
||||
<div class="bd-hint">{{item.hint}}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ['item']
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* BetterDiscord Updater Switch Component
|
||||
* 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.
|
||||
*/
|
||||
|
||||
<template>
|
||||
<div class="bd-settingSwitch">
|
||||
<div class="bd-title">
|
||||
<h3>{{item.text}}</h3>
|
||||
<div class="bd-switchWrapper" @click="() => toggle(item)">
|
||||
<input type="checkbox" class="bd-switchCheckbox" />
|
||||
<div class="bd-switch" :class="{'bd-checked': item.status.update}" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="bd-hint">{{item.hint}}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ['item', 'toggle']
|
||||
}
|
||||
</script>
|
|
@ -11,19 +11,22 @@
|
|||
<template>
|
||||
<SettingsWrapper headertext="Updates">
|
||||
<div class="bd-flex bd-flexCol bd-updaterview">
|
||||
<div v-if="error" class="bd-formItem">
|
||||
<h5 style="margin-bottom: 10px;">Error installing updates</h5>
|
||||
<div class="bd-err bd-preWrap"><div class="bd-pre">{{ error.formatted }}</div></div>
|
||||
<div class="bd-settingsCategories">
|
||||
<div class="bd-settingsCategory" v-if="bdUpdates && bdUpdates.length">
|
||||
<div class="bd-formItem">
|
||||
<h5>BetterDiscord</h5>
|
||||
</div>
|
||||
<div class="bd-formDivider"></div>
|
||||
<div v-for="update in bdUpdates">
|
||||
<UpdaterStatus :item="update" v-if="update.status.updating" />
|
||||
<UpdaterToggle :item="update" :toggle="() => updater.toggleUpdate(update)" v-else />
|
||||
<div class="bd-formDivider"></div>
|
||||
</div>
|
||||
|
||||
<template v-if="updatesAvailable">
|
||||
<p>Version {{ newVersion }} is available. You are currently running version {{ currentVersion }}.</p>
|
||||
<FormButton :onClick="install" :loading="updating">Install</FormButton>
|
||||
</template>
|
||||
<template v-else>
|
||||
<p>You're all up to date!</p>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bd-formButton bd-button" @click="update">
|
||||
Update
|
||||
</div>
|
||||
</div>
|
||||
</SettingsWrapper>
|
||||
</template>
|
||||
|
@ -32,7 +35,8 @@
|
|||
import { Globals, Updater } from 'modules';
|
||||
import { ClientLogger as Logger } from 'common';
|
||||
import SettingsWrapper from './SettingsWrapper.vue';
|
||||
import { FormButton } from '../common';
|
||||
import UpdaterToggle from './UpdaterToggle.vue';
|
||||
import UpdaterStatus from './UpdaterStatus.vue';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
|
@ -44,26 +48,29 @@
|
|||
},
|
||||
components: {
|
||||
SettingsWrapper,
|
||||
FormButton
|
||||
UpdaterToggle,
|
||||
UpdaterStatus
|
||||
},
|
||||
computed: {
|
||||
updatesAvailable() {
|
||||
return this.updater.updatesAvailable;
|
||||
},
|
||||
newVersion() {
|
||||
return this.updater.latestVersion;
|
||||
return '2.0.0-beta.4';
|
||||
},
|
||||
error() {
|
||||
return this.updater.error;
|
||||
},
|
||||
updates() {
|
||||
return this.updater.updates;
|
||||
},
|
||||
bdUpdates() {
|
||||
return this.updater.bdUpdates;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async install() {
|
||||
this.updating = true;
|
||||
try {
|
||||
await this.updater.update();
|
||||
} catch (err) {}
|
||||
this.updating = false;
|
||||
update() {
|
||||
this.updater.startUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,5 +4,8 @@ export { default as CssEditorView } from './CssEditor.vue';
|
|||
export { default as PluginsView } from './PluginsView.vue';
|
||||
export { default as ThemesView } from './ThemesView.vue';
|
||||
export { default as UpdaterView } from './UpdaterView.vue';
|
||||
export { default as UpdaterStatus } from './UpdaterStatus.vue';
|
||||
export { default as UpdaterToggle } from './UpdaterToggle.vue';
|
||||
export { default as BdBadge } from './BdBadge.vue';
|
||||
export { default as ConnectivityView } from './ConnectivityView.vue';
|
||||
export { default as SuperSecretView } from './SuperSecretView.vue';
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
*/
|
||||
|
||||
import { Utils, ClientLogger as Logger } from 'common';
|
||||
import { ReactComponents, Reflection, MonkeyPatch } from 'modules';
|
||||
import { Reflection, MonkeyPatch } from 'modules';
|
||||
import { VueInjector, Toasts } from 'ui';
|
||||
import CMGroup from './components/contextmenu/Group.vue';
|
||||
|
||||
|
|
|
@ -87,8 +87,7 @@ export default class extends Module {
|
|||
async patchNameTag() {
|
||||
if (this.PatchedNameTag) return this.PatchedNameTag;
|
||||
|
||||
const selector = Reflection.resolve('nameTag', 'username', 'discriminator', 'ownerIcon').selector;
|
||||
const NameTag = await ReactComponents.getComponent('NameTag', {selector});
|
||||
const NameTag = await ReactComponents.getComponent('NameTag');
|
||||
|
||||
this.PatchedNameTag = class extends NameTag.component {
|
||||
render() {
|
||||
|
|
|
@ -9,6 +9,7 @@ export * from './contextmenus';
|
|||
export { default as VueInjector } from './vueinjector';
|
||||
export { default as Reflection } from './reflection';
|
||||
|
||||
export { default as Autocomplete } from './autocomplete';
|
||||
export { default as ProfileBadges } from './profilebadges';
|
||||
export { default as ClassNormaliser } from './classnormaliser';
|
||||
|
||||
|
|
|
@ -28,7 +28,6 @@ module.exports = {
|
|||
},
|
||||
externals: {
|
||||
electron: 'require("electron")',
|
||||
asar: 'require("asar")',
|
||||
fs: 'require("fs")',
|
||||
path: 'require("path")',
|
||||
util: 'require("util")',
|
||||
|
|
|
@ -13,7 +13,10 @@ const config = {
|
|||
},
|
||||
plugins: [
|
||||
new webpack.NamedModulesPlugin()
|
||||
]
|
||||
],
|
||||
externals: {
|
||||
asar: 'require("asar")'
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = merge(baseconfig, config);
|
||||
|
|
|
@ -15,7 +15,10 @@ const config = {
|
|||
new webpack.DefinePlugin({
|
||||
PRODUCTION: JSON.stringify(true)
|
||||
})
|
||||
]
|
||||
],
|
||||
externals: {
|
||||
sparkplug: 'require("./sparkplug")'
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = merge(baseconfig, config);
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
/**
|
||||
* BetterDiscord axios wrapper
|
||||
* 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 axios from 'axios';
|
||||
|
||||
export default class AxiosWrapper {
|
||||
|
||||
static get axios() { return axios; }
|
||||
|
||||
static get github() {
|
||||
return this._github ? this._github : (
|
||||
this._github = {
|
||||
main: this.create('https://github.com'),
|
||||
api: this.create('https://api.github.com')
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
static get zl() {
|
||||
return this._zl ? this._zl : (this._zl = {
|
||||
api: this.create('https://zl', 1000, this.zlHeaders),
|
||||
cdn: this.create('https://zl', 1000, this.zlHeaders)
|
||||
});
|
||||
}
|
||||
|
||||
static create(baseUrl, timeout = 1000, headers = null) {
|
||||
return axios.create({ baseURL: baseUrl, timeout, headers: headers ? headers : this.defaultHeaders });
|
||||
}
|
||||
|
||||
static get defaultHeaders() {
|
||||
return {
|
||||
'User-Agent': 'BetterDiscordApp User'
|
||||
};
|
||||
}
|
||||
|
||||
static get zlHeaders() {
|
||||
return {
|
||||
'User-Agent': 'BetterDiscordApp User',
|
||||
'X-ZL-Apikey': '1a20cce89a2dbd163fc9570f3246c20891e62b2818ada55f82fa3d1d96fa7ef4',
|
||||
'X-ZL-User': 'anonymous'
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -3,3 +3,4 @@ export { default as Filters } from './filters';
|
|||
export { default as Logger, ClientLogger } from './logger';
|
||||
export { default as ClientIPC } from './bdipc';
|
||||
export { default as AsyncEventEmitter } from './async-eventemitter';
|
||||
export { default as Axi } from './axi';
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"name": "bdcore",
|
||||
"description": "BetterDiscord core package",
|
||||
"author": "Jiiks",
|
||||
"version": "2.0.0-beta.3",
|
||||
"version": "2.0.0-beta.6",
|
||||
"homepage": "https://betterdiscord.net",
|
||||
"license": "MIT",
|
||||
"main": "dist/main.js",
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"img-src": [
|
||||
"https://cdn.betterttv.net",
|
||||
"https://cdn.frankerfacez.com",
|
||||
"https://i.imgur.com"
|
||||
],
|
||||
"style-src": [
|
||||
"https://fonts.googleapis.com"
|
||||
],
|
||||
"script-src": [
|
||||
"'sha256-fSHKdpQGCHaIqWP3SpJOuUHrLp49jy4dWHzZ/RBJ/p4='",
|
||||
"'sha256-VFJcfKY5B3EBkFDgQnv3CozPwBlZcxwssfLVWlPFfZU='",
|
||||
"'sha256-VzDmLZ4PxPkOS/KY7ITzLQsSWhfCnvUrNculcj8UNgE='",
|
||||
"'sha256-l6K+77Z1cmldR9gIvaVWlboF/zr5MXCQHcsEHfnr5TU='"
|
||||
],
|
||||
"connect-src": [
|
||||
"https://github.com",
|
||||
"https://api.github.com",
|
||||
"https://betterdiscord.net",
|
||||
"https://api.betterdiscord.net",
|
||||
"https://cdn.betterdiscord.net",
|
||||
"https://api.supersecretbdapiandcdn.net",
|
||||
"https://cdn.supersecretbdapiandcdn.net"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
React Devtools: sha256-fSHKdpQGCHaIqWP3SpJOuUHrLp49jy4dWHzZ/RBJ/p4=
|
||||
Vue Devtools: sha256-VFJcfKY5B3EBkFDgQnv3CozPwBlZcxwssfLVWlPFfZU=
|
||||
Vue Detector: sha256-l6K+77Z1cmldR9gIvaVWlboF/zr5MXCQHcsEHfnr5TU=
|
|
@ -8,11 +8,24 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/*PRODUCTION*/
|
||||
const TESTS = typeof PRODUCTION === 'undefined';
|
||||
const TEST_ARGS = () => {
|
||||
const _basePath = path.resolve(__dirname, '..', '..');
|
||||
const _baseDataPath = path.resolve(_basePath, 'tests');
|
||||
|
||||
const _corePkg = require(path.resolve(_basePath, 'core', 'package.json'));
|
||||
const _clientPkg = require(path.resolve(_basePath, 'client', 'package.json'));
|
||||
const _editorPkg = require(path.resolve(_basePath, 'editor', 'package.json'));
|
||||
|
||||
const coreVersion = _corePkg.version;
|
||||
const clientVersion = _clientPkg.version;
|
||||
const editorVersion = _editorPkg.version;
|
||||
|
||||
return {
|
||||
coreVersion,
|
||||
clientVersion,
|
||||
editorVersion,
|
||||
'options': {
|
||||
'autoInject': true,
|
||||
'commonCore': true,
|
||||
|
@ -22,12 +35,16 @@ const TEST_ARGS = () => {
|
|||
'client': path.resolve(_basePath, 'client', 'dist'),
|
||||
'core': path.resolve(_basePath, 'core', 'dist'),
|
||||
'data': path.resolve(_baseDataPath, 'data'),
|
||||
'editor': path.resolve(_basePath, 'editor', 'dist')
|
||||
'editor': path.resolve(_basePath, 'editor', 'dist'),
|
||||
// tmp: path.join(_basePath, 'tmp')
|
||||
tmp: path.join(os.tmpdir(), 'betterdiscord', `${process.getuid()}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
const TEST_EDITOR = true;
|
||||
const TEST_EDITOR = TESTS && true;
|
||||
|
||||
import process from 'process';
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
import sass from 'node-sass';
|
||||
import { BrowserWindow as OriginalBrowserWindow, dialog, session, shell } from 'electron';
|
||||
|
@ -35,21 +52,13 @@ import deepmerge from 'deepmerge';
|
|||
import ContentSecurityPolicy from 'csp-parse';
|
||||
import keytar from 'keytar';
|
||||
|
||||
import { FileUtils, BDIpc, Config, WindowUtils, CSSEditor, Editor, Database } from './modules';
|
||||
import { FileUtils, BDIpc, Config, WindowUtils, Updater, Editor, Database } from './modules';
|
||||
|
||||
const packageJson = require(path.resolve(__dirname, 'package.json'));
|
||||
const sparkplug = path.resolve(__dirname, 'sparkplug.js');
|
||||
|
||||
let configProxy;
|
||||
|
||||
const CSP = {
|
||||
'img-src': ['https://cdn.betterttv.net', 'https://cdn.frankerfacez.com'],
|
||||
'script-src': [
|
||||
`'sha256-fSHKdpQGCHaIqWP3SpJOuUHrLp49jy4dWHzZ/RBJ/p4='`, // React Devtools
|
||||
`'sha256-VFJcfKY5B3EBkFDgQnv3CozPwBlZcxwssfLVWlPFfZU='`, // Vue Devtools
|
||||
`'sha256-VzDmLZ4PxPkOS/KY7ITzLQsSWhfCnvUrNculcj8UNgE=' 'sha256-l6K+77Z1cmldR9gIvaVWlboF/zr5MXCQHcsEHfnr5TU='` // Vue Detector
|
||||
]
|
||||
};
|
||||
const CSP = TESTS ? require('../src/csp.json') : require('./csp.json');
|
||||
|
||||
class Comms {
|
||||
constructor(bd) {
|
||||
|
@ -195,6 +204,8 @@ export class BetterDiscord {
|
|||
get config() { return this._config ? this._config : (this._config = new Config(this._args)); }
|
||||
get window() { return this.windowUtils ? this.windowUtils.window : undefined; }
|
||||
get editor() { return this._editor ? this._editor : (this._editor = new Editor(this, this.config.getPath('editor'))); }
|
||||
get updater() { return this._updater ? this._updater : (this._updater = new Updater(this)); }
|
||||
get sendToDiscord() { return this.windowUtils.send; }
|
||||
|
||||
constructor(args) {
|
||||
if (TESTS) args = TEST_ARGS();
|
||||
|
@ -209,13 +220,15 @@ export class BetterDiscord {
|
|||
this.config.compatibility();
|
||||
|
||||
this.bindings();
|
||||
this.parseClientPackage();
|
||||
this.extraPaths();
|
||||
this.database.init();
|
||||
this.parseClientPackage();
|
||||
this.parseEditorPackage();
|
||||
this.parseCorePackage();
|
||||
|
||||
configProxy = () => this.config;
|
||||
const autoInitComms = this.comms;
|
||||
const autoInitEditor = this.editor;
|
||||
this.updater.start();
|
||||
this.init();
|
||||
}
|
||||
|
||||
|
@ -288,6 +301,20 @@ export class BetterDiscord {
|
|||
console.log(`[BetterDiscord] Client v${this.config.clientVersion} - ${this.config.getPath('client_script')}`);
|
||||
}
|
||||
|
||||
parseCorePackage() {
|
||||
const corePath = this.config.getPath('core');
|
||||
const corePkg = TESTS ? require(`${path.resolve(corePath, '..')}/package.json`) : require(`${corePath}/package.json`);
|
||||
const { version } = corePkg;
|
||||
this.config.setCoreVersion(version);
|
||||
}
|
||||
|
||||
parseEditorPackage() {
|
||||
const editorPath = this.config.getPath('editor');
|
||||
const editorPkg = TESTS ? require(`${path.resolve(editorPath, '..')}/package.json`) : require(`${editorPath}/package.json`);
|
||||
const { version } = editorPkg;
|
||||
this.config.setEditorVersion(version);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add extra paths to config
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
/**
|
||||
* BetterDiscord axios wrapper
|
||||
* 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 axios from 'axios';
|
||||
|
||||
export default class AxiosWrapper {
|
||||
|
||||
static get axios() { return axios; }
|
||||
|
||||
static get(url) { return axios.get(url) }
|
||||
|
||||
static get github() {
|
||||
return this._github ? this._github : (
|
||||
this._github = {
|
||||
main: this.create('https://github.com'),
|
||||
api: this.create('https://api.github.com')
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
static get zl() {
|
||||
return this._zl ? this._zl : (this._zl = {
|
||||
api: this.create('https://zl', 1000, this.zlHeaders),
|
||||
cdn: this.create('https://zl', 1000, this.zlHeaders)
|
||||
});
|
||||
}
|
||||
|
||||
static create(baseUrl, timeout = 1000, headers = null) {
|
||||
return axios.create({ baseURL: baseUrl, timeout, headers: headers ? headers : this.defaultHeaders });
|
||||
}
|
||||
|
||||
static get defaultHeaders() {
|
||||
return {
|
||||
'User-Agent': 'BetterDiscordApp User'
|
||||
};
|
||||
}
|
||||
|
||||
static get zlHeaders() {
|
||||
return {
|
||||
'User-Agent': 'BetterDiscordApp User',
|
||||
'X-ZL-Apikey': '1a20cce89a2dbd163fc9570f3246c20891e62b2818ada55f82fa3d1d96fa7ef4',
|
||||
'X-ZL-User': 'anonymous'
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -16,12 +16,36 @@ export default class Config extends Module {
|
|||
return this.args.version;
|
||||
}
|
||||
|
||||
get versions() {
|
||||
return {
|
||||
core: this.coreVersion,
|
||||
client: this.clientVersion,
|
||||
editor: this.editorVersion
|
||||
};
|
||||
}
|
||||
|
||||
get coreVersion() {
|
||||
return this.state.coreVersion;
|
||||
}
|
||||
|
||||
get clientVersion() {
|
||||
return this.args.clientVersion;
|
||||
return this.state.clientVersion;
|
||||
}
|
||||
|
||||
get editorVersion() {
|
||||
return this.state.editorVersion;
|
||||
}
|
||||
|
||||
setClientVersion(clientVersion) {
|
||||
this.args.clientVersion = clientVersion;
|
||||
this.state.clientVersion = clientVersion;
|
||||
}
|
||||
|
||||
setCoreVersion(coreVersion) {
|
||||
this.state.coreVersion = coreVersion;
|
||||
}
|
||||
|
||||
setEditorVersion(editorVersion) {
|
||||
this.state.editorVersion = editorVersion;
|
||||
}
|
||||
|
||||
get paths() {
|
||||
|
@ -41,6 +65,7 @@ export default class Config extends Module {
|
|||
get config() {
|
||||
return {
|
||||
version: this.version,
|
||||
versions: this.versions,
|
||||
paths: this.paths
|
||||
};
|
||||
}
|
||||
|
|
|
@ -4,3 +4,4 @@ export { default as Config } from './config';
|
|||
export { default as CSSEditor } from './csseditor';
|
||||
export { default as Editor } from './editor';
|
||||
export { default as Database } from './database';
|
||||
export { default as Updater } from './updater';
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
/**
|
||||
* Base Module that every non-static module should extend.
|
||||
*/
|
||||
|
||||
import { default as BDIpc } from './bdipc';
|
||||
|
||||
export default class Module {
|
||||
|
||||
constructor(args) {
|
||||
|
@ -24,6 +27,7 @@ export default class Module {
|
|||
init() {
|
||||
if (this.bindings) this.bindings();
|
||||
if (this.setInitialState) this.setInitialState(this.state);
|
||||
if (this.events) this.events(BDIpc);
|
||||
}
|
||||
|
||||
set args(t) {}
|
||||
|
|
|
@ -0,0 +1,286 @@
|
|||
/**
|
||||
* BetterDiscord Updater Module
|
||||
* Copyright (c) 2015-present JsSucks - https://github.com/JsSucks
|
||||
* All rights reserved.
|
||||
* https://github.com/JsSucks - 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 from './modulebase';
|
||||
import { FileUtils } from './utils';
|
||||
import semver from 'semver';
|
||||
import Axi from './axi';
|
||||
import zlib from 'zlib';
|
||||
import tarfs from 'tar-fs';
|
||||
|
||||
const TEST_UPDATE = [
|
||||
{
|
||||
'id': 'core',
|
||||
'version': '2.0.0-beta.5'
|
||||
},
|
||||
{
|
||||
'id': 'client',
|
||||
'version': '2.0.0-beta.5'
|
||||
},
|
||||
{
|
||||
'id': 'editor',
|
||||
'version': '0.4.1'
|
||||
}
|
||||
];
|
||||
|
||||
class ReleaseInfo {
|
||||
|
||||
constructor(versions) {
|
||||
this.versions = versions;
|
||||
}
|
||||
|
||||
get core() {
|
||||
const f = this.files.find(f => f.id === 'core');
|
||||
f.upToDate = semver.satisfies(this.versions.core, `>=${f.version}`, { includePrerelease: true });
|
||||
f.currentVersion = this.versions.core;
|
||||
return f;
|
||||
}
|
||||
|
||||
get client() {
|
||||
const f = this.files.find(f => f.id === 'client');
|
||||
f.upToDate = semver.satisfies(this.versions.client, `>=${f.version}`, { includePrerelease: true });
|
||||
f.currentVersion = this.versions.client;
|
||||
return f;
|
||||
}
|
||||
|
||||
get editor() {
|
||||
const f = this.files.find(f => f.id === 'editor');
|
||||
f.upToDate = semver.satisfies(this.versions.editor, `>=${f.version}`, { includePrerelease: true });
|
||||
f.currentVersion = this.versions.editor;
|
||||
return f;
|
||||
}
|
||||
|
||||
test() {
|
||||
this.files = TEST_UPDATE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default class Updater extends Module {
|
||||
|
||||
constructor(bd) {
|
||||
super();
|
||||
this.bd = bd;
|
||||
}
|
||||
|
||||
bindings() {
|
||||
this.checkForUpdates = this.checkForUpdates.bind(this);
|
||||
this.checkForBdUpdates = this.checkForBdUpdates.bind(this);
|
||||
this.updateAll = this.updateAll.bind(this);
|
||||
this.updateFinished = this.updateFinished.bind(this);
|
||||
this.start = this.start.bind(this);
|
||||
}
|
||||
|
||||
events(ipc) {
|
||||
ipc.on('updater-startUpdate', (_, updates) => {
|
||||
clearInterval(this.updaterThread);
|
||||
this.updateAll(updates);
|
||||
});
|
||||
ipc.on('debug-updater-forceUpdate', () => {
|
||||
this.checkForUpdates(true);
|
||||
});
|
||||
}
|
||||
|
||||
async updateBd(update) {
|
||||
try {
|
||||
console.log('[BetterDiscord:Updater] Updating', update.id);
|
||||
await this.downloadTarGz(`https://github.com/JsSucks/BetterDiscordApp${update.remote}`, this.bd.config.getPath('base'));
|
||||
this.updateFinished(update);
|
||||
// Cleanup
|
||||
await FileUtils.rm(`${this.bd.config.getPath(update.id)}_old`);
|
||||
} catch (err) {
|
||||
console.log('[BetterDiscord:Updater] Failed to update', update.id);
|
||||
console.log(err);
|
||||
update.error = err;
|
||||
this.bd.sendToDiscord('updater-updateError', update);
|
||||
}
|
||||
}
|
||||
|
||||
async updateAll(updates) {
|
||||
const bd = updates.bd || [];
|
||||
const plugins = updates.plugins || [];
|
||||
const themes = updates.themes || [];
|
||||
const modules = updates.modules || [];
|
||||
|
||||
this.restartRequired = this.reloadRequired = false;
|
||||
this.finishedUpdates = 0;
|
||||
this.totalUpdates = bd.length + plugins.length + themes.length + modules.length;
|
||||
|
||||
const renamed = [];
|
||||
// TODO cleaner
|
||||
if (bd.length) {
|
||||
for (const update of bd) {
|
||||
try {
|
||||
await FileUtils.rm(`${this.bd.config.getPath(update.id)}_old`);
|
||||
// Try to rename dirs first
|
||||
await FileUtils.rn(this.bd.config.getPath(update.id), `${this.bd.config.getPath(update.id)}_old`);
|
||||
renamed.push({ 'old': this.bd.config.getPath(update.id), 'new': `${this.bd.config.getPath(update.id)}_old`});
|
||||
} catch (err) {
|
||||
if (renamed.length) {
|
||||
// Restore dirs
|
||||
for (const r of renamed) {
|
||||
await FileUtils.rn(r.new, r.old);
|
||||
}
|
||||
}
|
||||
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
for (const update of bd) {
|
||||
this.updateBd(update);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
updateFinished(update) {
|
||||
if (update.id === 'core') this.restartRequired = true;
|
||||
if (update.id === 'client') this.reloadRequired = true;
|
||||
|
||||
console.log('[BetterDiscord:Updater] Finished updating', update.id);
|
||||
this.bd.sendToDiscord('updater-updateFinished', update);
|
||||
|
||||
this.finishedUpdates++;
|
||||
if (this.finishedUpdates >= this.totalUpdates) {
|
||||
this.bd.sendToDiscord('updater-updated', { restartRequired: this.restartRequired, reloadRequired: this.reloadRequired });
|
||||
}
|
||||
}
|
||||
|
||||
start(interval = 30) {
|
||||
this.updaterThread = setInterval(this.checkForUpdates, interval * 60 * 1000);
|
||||
}
|
||||
|
||||
validate(releaseInfo) {
|
||||
return releaseInfo &&
|
||||
typeof releaseInfo === 'object' &&
|
||||
releaseInfo.files &&
|
||||
Array.isArray(releaseInfo.files) &&
|
||||
releaseInfo.files.length >= 4;
|
||||
}
|
||||
|
||||
async latestRelease() {
|
||||
try {
|
||||
const release = await Axi.github.api.get('repos/JsSucks/BetterDiscordApp/releases/latest'); // TODO replace with config
|
||||
const releaseInfoAsset = release.data.assets.find(asset => asset.name === 'releaseinfo.json');
|
||||
const releaseInfo = await Axi.get(releaseInfoAsset['browser_download_url']);
|
||||
|
||||
if (this.validate(releaseInfo.data)) return releaseInfo.data;
|
||||
return this.latestReleaseFallback();
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
return this.latestReleaseFallback();
|
||||
}
|
||||
}
|
||||
|
||||
async latestReleaseFallback() {
|
||||
console.log('fallback');
|
||||
}
|
||||
|
||||
async checkForBdUpdates(forced = false) {
|
||||
try {
|
||||
const { coreVersion, clientVersion, editorVersion } = this.bd.config;
|
||||
const releaseInfo = new ReleaseInfo({ core: coreVersion, client: clientVersion, editor: editorVersion });
|
||||
|
||||
const latestRelease = await this.latestRelease();
|
||||
|
||||
if (forced) {
|
||||
latestRelease.files = latestRelease.files.map(file => {
|
||||
file.version = '10.0.0';
|
||||
return file;
|
||||
});
|
||||
}
|
||||
|
||||
releaseInfo.files = latestRelease.files;
|
||||
|
||||
const updates = [];
|
||||
|
||||
const { core, client, editor } = releaseInfo;
|
||||
if (!core.upToDate) updates.push(core);
|
||||
if (!client.upToDate) updates.push(client);
|
||||
if (!editor.upToDate) updates.push(editor);
|
||||
|
||||
return updates;
|
||||
|
||||
} catch (err) {
|
||||
console.log('[BetterDiscord:Updater]', err);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
async checkForUpdates(forced = false) {
|
||||
console.log('[BetterDiscord:Updater] Checking for updates');
|
||||
this.bd.sendToDiscord('updater-checkForUpdates', '');
|
||||
|
||||
try {
|
||||
const bd = await this.checkForBdUpdates(forced);
|
||||
const updates = { bd, haveUpdates: false };
|
||||
|
||||
if (bd.length) updates.haveUpdates = true;
|
||||
|
||||
if (!updates.haveUpdates) {
|
||||
this.bd.sendToDiscord('updater-noUpdates', '');
|
||||
return true;
|
||||
}
|
||||
|
||||
this.bd.sendToDiscord('updater-updatesAvailable', updates);
|
||||
|
||||
return true;
|
||||
|
||||
} catch (err) {
|
||||
console.log('[BetterDiscord:Updater]', err);
|
||||
this.bd.sendToDiscord('updater-error', err);
|
||||
return 'err';
|
||||
}
|
||||
}
|
||||
|
||||
async downloadTarGz(url, dest, responseType = 'stream', headers = null) {
|
||||
try {
|
||||
const stream = await Axi.axios({
|
||||
url,
|
||||
type: 'GET',
|
||||
responseType,
|
||||
headers: headers ||
|
||||
{
|
||||
'Content-Type': 'application/octet-stream',
|
||||
'Accept': 'application/octet-stream'
|
||||
}
|
||||
});
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
stream.data.pipe(zlib.createGunzip()).pipe(tarfs.extract(dest)).on('finish', resolve).on('error', reject);
|
||||
});
|
||||
} catch (err) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
debug(releaseInfo) {
|
||||
const { core, client, editor } = releaseInfo;
|
||||
if (!core.upToDate) {
|
||||
console.log(`[BetterDiscord:Updater] Core update available: ${core.currentVersion} > ${core.version}`);
|
||||
} else {
|
||||
console.log(`[BetterDiscord:Updater] Core up to date: ${core.currentVersion} = ${core.version}`);
|
||||
}
|
||||
|
||||
if (!client.upToDate) {
|
||||
console.log(`[BetterDiscord:Updater] Client update available: ${client.currentVersion} > ${client.version}`);
|
||||
} else {
|
||||
console.log(`[BetterDiscord:Updater] Client up to date: ${client.currentVersion} = ${client.version}`);
|
||||
}
|
||||
|
||||
if (!editor.upToDate) {
|
||||
console.log(`[BetterDiscord:Updater] Editor update available: ${editor.currentVersion} > ${editor.version}`);
|
||||
} else {
|
||||
console.log(`[BetterDiscord:Updater] Editor up to date: ${editor.currentVersion} = ${editor.version}`);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
{
|
||||
"name": "bdcsseditor",
|
||||
"description": "BetterDiscord css editor package",
|
||||
"author": "Jiiks",
|
||||
"version": "0.4.0",
|
||||
"homepage": "https://betterdiscord.net",
|
||||
"license": "MIT",
|
||||
"main": "dist/csseditor.js",
|
||||
"contributors": [
|
||||
"Jiiks",
|
||||
"Pohky"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/JsSucks/BetterDiscordApp.git"
|
||||
},
|
||||
"private": false,
|
||||
"scripts": {
|
||||
"build": "webpack --progress --colors",
|
||||
"watch": "webpack --progress --colors --watch",
|
||||
"release": "webpack --progress --colors --config=webpack.production.config.js"
|
||||
}
|
||||
}
|
|
@ -1,191 +0,0 @@
|
|||
<template>
|
||||
<div class="container">
|
||||
<div class="titlebar">
|
||||
<div class="draggable"></div>
|
||||
<div class="icon">
|
||||
<div class="inner"></div>
|
||||
</div>
|
||||
<div class="title">CSS Editor</div>
|
||||
<div class="flex-spacer"></div>
|
||||
<div class="controls">
|
||||
<button :class="{active: alwaysOnTop}" ref="aot" title="Toggle always on top" @click="toggleaot">P</button>
|
||||
<button title="Close CSS Editor" @click="close">X</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="spinner" v-if="loading">
|
||||
<div class="valign">Loading Please Wait...</div>
|
||||
</div>
|
||||
<div id="editor" class="editor">
|
||||
<codemirror ref="mycm" :options="cmOptions" @input="cmOnChange" />
|
||||
</div>
|
||||
<div class="parser-error" v-if="error">{{ error.formatted }}</div>
|
||||
<div class="tools">
|
||||
<div class="flex-row">
|
||||
<button @click="save">Save</button>
|
||||
<button @click="update">Update</button>
|
||||
<div class="flex-spacer"></div>
|
||||
<div id="chkboxLiveUpdate">
|
||||
<label><input type="checkbox" @click="toggleLiveUpdate" v-model="liveUpdate" /><span>Live Update</span></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ClientIPC } from 'common';
|
||||
|
||||
import { remote } from 'electron';
|
||||
|
||||
import 'codemirror/addon/scroll/simplescrollbars.js';
|
||||
import 'codemirror/mode/css/css.js';
|
||||
import 'codemirror/addon/hint/css-hint.js';
|
||||
import 'codemirror/addon/search/search.js';
|
||||
import 'codemirror/addon/search/searchcursor.js';
|
||||
import 'codemirror/addon/search/jump-to-line.js';
|
||||
import 'codemirror/addon/dialog/dialog.js';
|
||||
import 'codemirror/addon/hint/show-hint.js';
|
||||
|
||||
const ExcludedIntelliSenseTriggerKeys = {
|
||||
'8': 'backspace',
|
||||
'9': 'tab',
|
||||
'13': 'enter',
|
||||
'16': 'shift',
|
||||
'17': 'ctrl',
|
||||
'18': 'alt',
|
||||
'19': 'pause',
|
||||
'20': 'capslock',
|
||||
'27': 'escape',
|
||||
'33': 'pageup',
|
||||
'34': 'pagedown',
|
||||
'35': 'end',
|
||||
'36': 'home',
|
||||
'37': 'left',
|
||||
'38': 'up',
|
||||
'39': 'right',
|
||||
'40': 'down',
|
||||
'45': 'insert',
|
||||
'46': 'delete',
|
||||
'91': 'left window key',
|
||||
'92': 'right window key',
|
||||
'93': 'select',
|
||||
'107': 'add',
|
||||
'109': 'subtract',
|
||||
'110': 'decimal point',
|
||||
'111': 'divide',
|
||||
'112': 'f1',
|
||||
'113': 'f2',
|
||||
'114': 'f3',
|
||||
'115': 'f4',
|
||||
'116': 'f5',
|
||||
'117': 'f6',
|
||||
'118': 'f7',
|
||||
'119': 'f8',
|
||||
'120': 'f9',
|
||||
'121': 'f10',
|
||||
'122': 'f11',
|
||||
'123': 'f12',
|
||||
'144': 'numlock',
|
||||
'145': 'scrolllock',
|
||||
'186': 'semicolon',
|
||||
'187': 'equalsign',
|
||||
'188': 'comma',
|
||||
'189': 'dash',
|
||||
'190': 'period',
|
||||
'191': 'slash',
|
||||
'192': 'graveaccent',
|
||||
'220': 'backslash',
|
||||
'222': 'quote'
|
||||
};
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
loading: true,
|
||||
codeMirror: null,
|
||||
alwaysOnTop: false,
|
||||
liveUpdate: false,
|
||||
cmOptions: {
|
||||
indentUnit: 4,
|
||||
tabSize: 4,
|
||||
mode: 'text/x-scss',
|
||||
lineNumbers: true,
|
||||
theme: 'material',
|
||||
scrollbarStyle: 'overlay',
|
||||
extraKeys: {
|
||||
'Ctrl-Space': 'autocomplete'
|
||||
},
|
||||
dialog: {
|
||||
'position': 'bottom'
|
||||
}
|
||||
},
|
||||
error: null
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
codemirror() {
|
||||
return this.$refs.mycm.codemirror;
|
||||
},
|
||||
CodeMirror() {
|
||||
return this.$refs.mycm;
|
||||
}
|
||||
},
|
||||
created() {
|
||||
ClientIPC.on('set-scss', (_, scss) => this.setScss(scss));
|
||||
|
||||
ClientIPC.on('scss-error', (_, err) => {
|
||||
this.error = err;
|
||||
this.$forceUpdate();
|
||||
if (err)
|
||||
console.error('SCSS parse error:', err);
|
||||
});
|
||||
|
||||
ClientIPC.on('set-liveupdate', (e, liveUpdate) => this.liveUpdate = liveUpdate);
|
||||
},
|
||||
mounted() {
|
||||
this.codemirror.on('keyup', this.cmOnKeyUp);
|
||||
|
||||
(async () => {
|
||||
this.setScss(await ClientIPC.sendToDiscord('get-scss'));
|
||||
this.liveUpdate = await ClientIPC.sendToDiscord('get-liveupdate');
|
||||
})();
|
||||
},
|
||||
watch: {
|
||||
liveUpdate(liveUpdate) {
|
||||
ClientIPC.sendToDiscord('set-liveupdate', liveUpdate);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
save() {
|
||||
const scss = this.codemirror.getValue();
|
||||
ClientIPC.sendToDiscord('save-scss', scss);
|
||||
},
|
||||
update() {
|
||||
const scss = this.codemirror.getValue();
|
||||
ClientIPC.sendToDiscord('update-scss', scss);
|
||||
},
|
||||
toggleaot() {
|
||||
this.alwaysOnTop = !this.alwaysOnTop;
|
||||
remote.getCurrentWindow().setAlwaysOnTop(this.alwaysOnTop);
|
||||
},
|
||||
close() {
|
||||
window.close();
|
||||
},
|
||||
setScss(scss) {
|
||||
this.loading = false;
|
||||
this.codemirror.setValue(scss || '');
|
||||
},
|
||||
cmOnChange(value) {
|
||||
if(this.liveUpdate) ClientIPC.sendToDiscord('update-scss', value);
|
||||
},
|
||||
cmOnKeyUp(editor, event) {
|
||||
if (event.ctrlKey) return;
|
||||
if (ExcludedIntelliSenseTriggerKeys[event.keyCode]) return;
|
||||
cmCommands.autocomplete(editor, null, { completeSingle: false });
|
||||
},
|
||||
toggleLiveUpdate(e) {
|
||||
this.liveUpdate = !this.liveUpdate;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -1,27 +0,0 @@
|
|||
// const styles = require('./styles/index.scss');
|
||||
|
||||
import Vue from 'vue';
|
||||
import VueCodemirror from 'vue-codemirror';
|
||||
|
||||
import Editor from './Editor.vue';
|
||||
import styles from './styles/index.scss';
|
||||
|
||||
Vue.use(VueCodemirror, {});
|
||||
|
||||
window.cmCommands = VueCodemirror.CodeMirror.commands;
|
||||
|
||||
const mount = document.createElement('div');
|
||||
mount.classList.add('container');
|
||||
document.body.appendChild(mount);
|
||||
|
||||
const vue = new Vue({
|
||||
el: mount,
|
||||
components: { Editor },
|
||||
template: '<Editor/>'
|
||||
});
|
||||
|
||||
const style = document.createElement('style');
|
||||
style.id = 'bd-main';
|
||||
style.type = 'text/css';
|
||||
style.appendChild(document.createTextNode(styles));
|
||||
document.head.appendChild(style);
|
|
@ -1,105 +0,0 @@
|
|||
.CodeMirror-scroll {
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
.CodeMirror-overlayscroll .CodeMirror-scrollbar-filler {
|
||||
background: #38444a;
|
||||
}
|
||||
|
||||
.CodeMirror-overlayscroll-horizontal div,
|
||||
.CodeMirror-overlayscroll-vertical div {
|
||||
background: rgb(41, 43, 47);
|
||||
}
|
||||
|
||||
.CodeMirror-overlayscroll-horizontal,
|
||||
.CodeMirror-overlayscroll-horizontal div {
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
.CodeMirror-overlayscroll-vertical,
|
||||
.CodeMirror-overlayscroll-vertical div {
|
||||
width: 10px;
|
||||
}
|
||||
|
||||
.CodeMirror-scrollbar-filler {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background: rgb(41, 43, 47);
|
||||
}
|
||||
|
||||
.cm-s-material.CodeMirror {
|
||||
background: #36393f;
|
||||
}
|
||||
|
||||
.CodeMirror-scroll {
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
.cm-s-material .CodeMirror-gutters {
|
||||
background: #292b2f;
|
||||
}
|
||||
|
||||
.CodeMirror-gutter {
|
||||
min-width: 34px;
|
||||
border-right: 1px solid hsla(218,5%,47%,.3);
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.CodeMirror-hints {
|
||||
/*background: #1e262a;*/
|
||||
background: #292b2f;
|
||||
box-shadow: 2px 3px 5px rgba(4, 4, 4, 0.22);
|
||||
border: 1px solid #262f33;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background-color: rgba(0,0,0,.4);
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb,
|
||||
&::-webkit-scrollbar-track {
|
||||
background-clip: padding-box;
|
||||
border-width: 3px;
|
||||
border-style: solid;
|
||||
border-radius: 7px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
background-color: transparent;
|
||||
border-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.CodeMirror-linenumber,
|
||||
.CodeMirror-line {
|
||||
padding: 0 5px !important;
|
||||
}
|
||||
|
||||
.CodeMirror-linenumber {
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
.cm-s-material .CodeMirror-linenumber {
|
||||
color: #f6f6f7;
|
||||
}
|
||||
|
||||
.CodeMirror-hint {
|
||||
color: #bac9d2;
|
||||
}
|
||||
|
||||
li.CodeMirror-hint-active {
|
||||
color: #bac9d2;
|
||||
/*background: #3b4950;*/
|
||||
background: #36393f;
|
||||
}
|
||||
|
||||
.CodeMirror-dialog-top {
|
||||
bottom: 0;
|
||||
top: auto;
|
||||
border: none;
|
||||
background: #1e262a;
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
.editor {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
overflow: hidden;
|
||||
|
||||
.vue-codemirror {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
overflow: hidden;
|
||||
|
||||
&, & .CodeMirror {
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
$logoSmallGw: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkltYWdlIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCIgdmlld0JveD0iMCAwIDUxMiA1MTIiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDUxMiA1MTI7IiB4bWw6c3BhY2U9InByZXNlcnZlIj48c3R5bGUgdHlwZT0idGV4dC9jc3MiPi5zdDB7ZGlzcGxheTpub25lO30uc3Qxe2Rpc3BsYXk6aW5saW5lO2ZpbGw6IzAyMDAzNTtzdHJva2U6IzAwMDAwMDtzdHJva2UtbWl0ZXJsaW1pdDoxMDt9LnN0MntmaWxsOiMzRUNDOUU7fS5zdDN7ZmlsbDojRkZGRkZGO308L3N0eWxlPjxnIGlkPSJMYXllcl8yIiBjbGFzcz0ic3QwIj48cmVjdCB4PSItNjQiIHk9Ii0zMiIgY2xhc3M9InN0MSIgd2lkdGg9IjYxOCIgaGVpZ2h0PSI1NzIiLz48L2c+PGcgaWQ9IkxheWVyXzEiIHhtbG5zOnZlY3Rvcm5hdG9yPSJodHRwOi8vdmVjdG9ybmF0b3IuaW8iPjxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik03MCwxOC44Yy0xMy43LDAtMjcuMywxMy43LTI3LjMsMjcuM3YyMzMuNkM0Mi43LDM5Ny43LDEzNy45LDQ5MywyNTYsNDkzYzI5LjcsMCw1OC02LjEsODMuNi0xN1YzNDEuNWMtMTksMjUuNi00OS4zLDQyLjItODMuNiw0Mi4yYy01Ny42LDAtMTA0LjEtNDYuNS0xMDQuMS0xMDQuMVY0Ni4xYzAtMTMuNy0xMy43LTI3LjMtMjcuMy0yNy4zSDcweiIvPjxwYXRoIGNsYXNzPSJzdDMiIGQ9Ik0zODcuNCwxOC44Yy0xMy43LDAtMjcuMywxMy43LTI3LjMsMjcuM3Y0Ny4zQzMyOS4zLDc2LjIsMjkzLjksNjYuMywyNTYsNjYuM2MtMjkuOCwwLTU3LjksNi4zLTgzLjYsMTcuM3YxMzQuMmMxOS0yNS42LDQ5LjMtNDIuMiw4My42LTQyLjJjNTcuNiwwLDEwNC4xLDQ2LjUsMTA0LjEsMTA0LjF2MTg2LjJjNjUuMi0zNi40LDEwOS4yLTEwNiwxMDkuMi0xODYuMlY0Ni4xYzAtMTguOC0xMy43LTI3LjMtMjcuMy0yNy4zSDM4Ny40eiIvPjwvZz48L3N2Zz4=);
|
||||
$bdicon: $logoSmallGw;
|
|
@ -1,13 +0,0 @@
|
|||
@import '../../../node_modules/codemirror/lib/codemirror.css';
|
||||
@import '../../../node_modules/codemirror/theme/material.css';
|
||||
@import '../../../node_modules/codemirror/addon/scroll/simplescrollbars.css';
|
||||
@import '../../../node_modules/codemirror/addon/dialog/dialog.css';
|
||||
@import '../../../node_modules/codemirror/addon/hint/show-hint.css';
|
||||
|
||||
@import './images.scss';
|
||||
@import './main.scss';
|
||||
@import './titlebar.scss';
|
||||
@import './spinner.scss';
|
||||
@import './editor.scss';
|
||||
@import './tools.scss';
|
||||
@import './codemirror.scss';
|
|
@ -1,36 +0,0 @@
|
|||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
max-height: 100%;
|
||||
height: 100%;
|
||||
background: #2c383e;
|
||||
min-width: 700px;
|
||||
min-height: 400px;
|
||||
}
|
||||
|
||||
* {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.flex-spacer {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.flex-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.valign {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
#spinner {
|
||||
background: rgba(51, 48, 48, 0.41);
|
||||
position: absolute;
|
||||
top: 34px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
color: #bac9d2;
|
||||
font-family: Whitney,Helvetica Neue,Helvetica,Arial,sans-serif;
|
||||
font-weight: 600;
|
||||
font-size: 2em;
|
||||
z-index: 90000;
|
||||
user-select: none;
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
.titlebar {
|
||||
display: flex;
|
||||
height: 25px;
|
||||
padding: 4px 5px;
|
||||
background: #292b2f;
|
||||
border-bottom: 1px solid hsla(218,5%,47%,.3);
|
||||
user-select: none;
|
||||
cursor: default;
|
||||
|
||||
.icon {
|
||||
width: 31px;
|
||||
height: 25px;
|
||||
|
||||
.inner {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
background-image: $bdicon;
|
||||
background-size: 22px 22px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
color: #bac9d2;
|
||||
font-family: Whitney,Helvetica Neue,Helvetica,Arial,sans-serif;
|
||||
line-height: 25px;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.controls {
|
||||
margin: 0 0 0 2px;
|
||||
font-size: 0;
|
||||
|
||||
button {
|
||||
-webkit-app-region: no-drag;
|
||||
border-radius: 3px;
|
||||
width: 25px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
background: #36393f;
|
||||
color: #bac9d2;
|
||||
font-family: Whitney,Helvetica Neue,Helvetica,Arial,sans-serif;
|
||||
transition: background-color .2s ease, color .2s ease;
|
||||
cursor: default;
|
||||
border: 0;
|
||||
height: 25px;
|
||||
z-index: 900062;
|
||||
padding: 0;
|
||||
margin: 0 0 0 4px;
|
||||
|
||||
&:hover {
|
||||
background: #44474e;
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
&.active {
|
||||
background: #3a71c1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.draggable {
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 63px;
|
||||
position: absolute;
|
||||
height: 33px;
|
||||
-webkit-app-region: drag;
|
||||
}
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
.parser-error {
|
||||
padding: 4px 6px;
|
||||
background: #292b2f;
|
||||
border-top: 1px solid hsla(218,5%,47%,.3);
|
||||
color: #d84040;
|
||||
font-family: monospace;
|
||||
white-space: pre-wrap;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.tools {
|
||||
height: 36px;
|
||||
background: #292b2f;
|
||||
border-top: 1px solid hsla(218,5%,47%,.3);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
user-select: none;
|
||||
|
||||
.flex-row {
|
||||
flex-grow: 1;
|
||||
padding: 4px 5px;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 3px;
|
||||
width: 100px;
|
||||
padding: 3px 10px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
background: #36393f;
|
||||
color: #bac9d2;
|
||||
font-family: Whitney,Helvetica Neue,Helvetica,Arial,sans-serif;
|
||||
transition: background-color .2s ease, color .2s ease;
|
||||
cursor: pointer;
|
||||
border: 0;
|
||||
margin-right: 4px;
|
||||
flex: 0 0 auto;
|
||||
|
||||
&:hover {
|
||||
background: #44474e;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
#chkboxLiveUpdate {
|
||||
padding: 3px 10px;
|
||||
line-height: 22px;
|
||||
flex: 0 0 auto;
|
||||
|
||||
label {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
input[type="checkbox"] {
|
||||
margin: 0 6px 0 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: #bac9d2;
|
||||
font-family: Whitney,Helvetica Neue,Helvetica,Arial,sans-serif;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
const path = require('path');
|
||||
const VueLoaderPlugin = require('vue-loader/lib/plugin');
|
||||
|
||||
const vueLoader = {
|
||||
test: /\.(vue)$/,
|
||||
exclude: /node_modules/,
|
||||
use: 'vue-loader'
|
||||
};
|
||||
|
||||
const scssLoader = {
|
||||
test: /\.(css|scss)$/,
|
||||
use: ['css-loader', 'sass-loader']
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
entry: './src/index.js',
|
||||
mode: 'development',
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
filename: 'csseditor.js'
|
||||
},
|
||||
module: {
|
||||
rules: [vueLoader, scssLoader]
|
||||
},
|
||||
externals: {
|
||||
electron: 'window.require("electron")',
|
||||
fs: 'window.require("fs")',
|
||||
util: 'window.require("util")',
|
||||
process: 'require("process")'
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
vue$: path.resolve('..', 'node_modules', 'vue', 'dist', 'vue.esm.js')
|
||||
},
|
||||
modules: [
|
||||
path.resolve('..', 'node_modules'),
|
||||
path.resolve('..', 'common', 'modules')
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
new VueLoaderPlugin()
|
||||
]
|
||||
};
|
|
@ -1,47 +0,0 @@
|
|||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const VueLoaderPlugin = require('vue-loader/lib/plugin');
|
||||
|
||||
const vueLoader = {
|
||||
test: /\.(vue)$/,
|
||||
exclude: /node_modules/,
|
||||
use: 'vue-loader'
|
||||
};
|
||||
|
||||
const scssLoader = {
|
||||
test: /\.(css|scss)$/,
|
||||
use: ['css-loader', 'sass-loader']
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
entry: './src/index.js',
|
||||
mode: 'production',
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
filename: 'csseditor-release.js'
|
||||
},
|
||||
module: {
|
||||
rules: [vueLoader, scssLoader]
|
||||
},
|
||||
externals: {
|
||||
electron: 'window.require("electron")',
|
||||
fs: 'window.require("fs")',
|
||||
util: 'window.require("util")',
|
||||
process: 'require("process")'
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
vue$: path.resolve('..', 'node_modules', 'vue', 'dist', 'vue.esm.js')
|
||||
},
|
||||
modules: [
|
||||
path.resolve('..', 'node_modules'),
|
||||
path.resolve('..', 'common', 'modules')
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
PRODUCTION: JSON.stringify(true)
|
||||
}),
|
||||
new VueLoaderPlugin()
|
||||
]
|
||||
};
|
|
@ -5,7 +5,7 @@
|
|||
"version": "0.4.0",
|
||||
"homepage": "https://betterdiscord.net",
|
||||
"license": "MIT",
|
||||
"main": "dist/csseditor.js",
|
||||
"main": "dist/editor.js",
|
||||
"contributors": [
|
||||
"Jiiks",
|
||||
"Pohky"
|
||||
|
|
|
@ -4,6 +4,7 @@ import del from 'del';
|
|||
import copy from 'gulp-copy';
|
||||
import rename from 'gulp-rename';
|
||||
import inject from 'gulp-inject-string';
|
||||
import replace from 'gulp-replace';
|
||||
import copydeps from './scripts/copydeps';
|
||||
import file from 'gulp-file';
|
||||
import editjson from 'gulp-json-editor';
|
||||
|
@ -17,7 +18,7 @@ import editorpkg from './editor/package';
|
|||
gulp.task('core-main', function() {
|
||||
return pump([
|
||||
gulp.src('core/dist/main.js'),
|
||||
inject.after(`'use strict';\n`, 'const PRODUCTION = true;\n'),
|
||||
replace('/*PRODUCTION*/', 'const PRODUCTION = true;'),
|
||||
rename(`core.${corepkg.version}.js`),
|
||||
gulp.dest('release/core')
|
||||
]);
|
||||
|
@ -50,7 +51,14 @@ gulp.task('core-sparkplug', function () {
|
|||
]);
|
||||
});
|
||||
|
||||
gulp.task('core-release', gulp.parallel('core-main', 'core-pkg', 'core-sparkplug', 'core-modules'));
|
||||
gulp.task('core-extras', function() {
|
||||
return pump([
|
||||
gulp.src(['core/src/csp.json']),
|
||||
gulp.dest('release/core')
|
||||
]);
|
||||
});
|
||||
|
||||
gulp.task('core-release', gulp.parallel('core-main', 'core-pkg', 'core-sparkplug', 'core-modules', 'core-extras'));
|
||||
|
||||
// < core-release
|
||||
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
### node-keytar bindings
|
||||
|
||||
Copy this directory to `node_modules/keytar/build/Release/keytar.node` to use.
|
||||
|
||||
keytar-4.3.0/linux-x64-64.node - poweredge-t30.fancy.org.uk
|
||||
All others - https://github.com/atom/node-keytar/releases
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
const keytar_version = require('keytar/package').version;
|
||||
|
||||
// module.exports = require('./keytar-' + process.platform + '-' + process.versions.modules + '-' + process.arch + '.node');
|
||||
module.exports = require(`./keytar-${keytar_version}/${process.platform}-${process.arch}-${process.versions.modules}.node`);
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "betterdiscord",
|
||||
"version": "2.0.0-beta",
|
||||
"version": "2.0.0-beta.4",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
@ -1583,6 +1583,15 @@
|
|||
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
|
||||
"integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ=="
|
||||
},
|
||||
"axios": {
|
||||
"version": "0.18.0",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.18.0.tgz",
|
||||
"integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=",
|
||||
"requires": {
|
||||
"follow-redirects": "^1.3.0",
|
||||
"is-buffer": "^1.1.5"
|
||||
}
|
||||
},
|
||||
"babel-loader": {
|
||||
"version": "8.0.5",
|
||||
"resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.5.tgz",
|
||||
|
@ -1776,6 +1785,12 @@
|
|||
"underscore": "~1.4.4"
|
||||
}
|
||||
},
|
||||
"binaryextensions": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-2.1.2.tgz",
|
||||
"integrity": "sha512-xVNN69YGDghOqCCtA6FI7avYrr02mTJjOgB0/f1VPD3pJC8QEvjTKWc4epDx8AqxxA75NI0QpVM2gPJXUbE4Tg==",
|
||||
"dev": true
|
||||
},
|
||||
"bl": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz",
|
||||
|
@ -3022,6 +3037,12 @@
|
|||
"object.defaults": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"easy-stack": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/easy-stack/-/easy-stack-1.0.0.tgz",
|
||||
"integrity": "sha1-EskbMIWjfwuqM26UhurEv5Tj54g=",
|
||||
"dev": true
|
||||
},
|
||||
"ecc-jsbn": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
|
||||
|
@ -3031,6 +3052,12 @@
|
|||
"safer-buffer": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"editions": {
|
||||
"version": "1.3.4",
|
||||
"resolved": "https://registry.npmjs.org/editions/-/editions-1.3.4.tgz",
|
||||
"integrity": "sha512-gzao+mxnYDzIysXKMQi/+M1mjy/rjestjg6OPoYTtI+3Izp23oiGZitsl9lPDPiTGXbcSIk1iJWhliSaglxnUg==",
|
||||
"dev": true
|
||||
},
|
||||
"editorconfig": {
|
||||
"version": "0.15.2",
|
||||
"resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.2.tgz",
|
||||
|
@ -3706,6 +3733,12 @@
|
|||
"es5-ext": "~0.10.14"
|
||||
}
|
||||
},
|
||||
"event-pubsub": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/event-pubsub/-/event-pubsub-4.3.0.tgz",
|
||||
"integrity": "sha512-z7IyloorXvKbFx9Bpie2+vMJKKx1fH1EN5yiTfp8CiLOTptSYy1g8H4yDpGlEdshL1PBiFtBHepF2cNsqeEeFQ==",
|
||||
"dev": true
|
||||
},
|
||||
"event-stream": {
|
||||
"version": "3.3.4",
|
||||
"resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz",
|
||||
|
@ -4188,6 +4221,29 @@
|
|||
"readable-stream": "^2.3.6"
|
||||
}
|
||||
},
|
||||
"follow-redirects": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.7.0.tgz",
|
||||
"integrity": "sha512-m/pZQy4Gj287eNy94nivy5wchN3Kp+Q5WgUPNy5lJSZ3sgkVKSYV/ZChMAQVIgx1SqfZ2zBZtPA2YlXIWxxJOQ==",
|
||||
"requires": {
|
||||
"debug": "^3.2.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
"version": "3.2.6",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
|
||||
"integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
|
||||
"requires": {
|
||||
"ms": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
|
||||
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"for-in": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
|
||||
|
@ -5343,6 +5399,17 @@
|
|||
"integrity": "sha512-swzbIGb/arEoFK89tPY58vg3Ok1bw+d35PfUNwWqdo7KM4jkmuGA78JiDNqR+JeZFaeeHnRg9N7aihX3YPmsyg==",
|
||||
"dev": true
|
||||
},
|
||||
"gulp-replace": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/gulp-replace/-/gulp-replace-1.0.0.tgz",
|
||||
"integrity": "sha512-lgdmrFSI1SdhNMXZQbrC75MOl1UjYWlOWNbNRnz+F/KHmgxt3l6XstBoAYIdadwETFyG/6i+vWUSCawdC3pqOw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"istextorbinary": "2.2.1",
|
||||
"readable-stream": "^2.0.1",
|
||||
"replacestream": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"gulp-watch": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/gulp-watch/-/gulp-watch-5.0.1.tgz",
|
||||
|
@ -6396,6 +6463,17 @@
|
|||
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
|
||||
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
|
||||
},
|
||||
"istextorbinary": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-2.2.1.tgz",
|
||||
"integrity": "sha512-TS+hoFl8Z5FAFMK38nhBkdLt44CclNRgDHWeMgsV8ko3nDlr/9UI2Sf839sW7enijf8oKsZYXRvM8g0it9Zmcw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"binaryextensions": "2",
|
||||
"editions": "^1.3.3",
|
||||
"textextensions": "2"
|
||||
}
|
||||
},
|
||||
"jquery": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.3.1.tgz",
|
||||
|
@ -6438,6 +6516,21 @@
|
|||
"integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==",
|
||||
"dev": true
|
||||
},
|
||||
"js-message": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/js-message/-/js-message-1.0.5.tgz",
|
||||
"integrity": "sha1-IwDSSxrwjondCVvBpMnJz8uJLRU=",
|
||||
"dev": true
|
||||
},
|
||||
"js-queue": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-queue/-/js-queue-2.0.0.tgz",
|
||||
"integrity": "sha1-NiITz4YPRo8BJfxslqvBdCUx+Ug=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"easy-stack": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
|
@ -6757,6 +6850,12 @@
|
|||
"integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=",
|
||||
"dev": true
|
||||
},
|
||||
"lodash.endswith": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/lodash.endswith/-/lodash.endswith-4.2.1.tgz",
|
||||
"integrity": "sha1-/tWawXOO0+I27dcGTsRWRIs3vAk=",
|
||||
"dev": true
|
||||
},
|
||||
"lodash.flatten": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
|
||||
|
@ -7355,6 +7454,17 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node-ipc": {
|
||||
"version": "9.1.1",
|
||||
"resolved": "https://registry.npmjs.org/node-ipc/-/node-ipc-9.1.1.tgz",
|
||||
"integrity": "sha512-FAyICv0sIRJxVp3GW5fzgaf9jwwRQxAKDJlmNFUL5hOy+W4X/I5AypyHoq0DXXbo9o/gt79gj++4cMr4jVWE/w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"event-pubsub": "4.3.0",
|
||||
"js-message": "1.0.5",
|
||||
"js-queue": "2.0.0"
|
||||
}
|
||||
},
|
||||
"node-libs-browser": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.0.tgz",
|
||||
|
@ -7908,6 +8018,59 @@
|
|||
"readable-stream": "^2.1.5"
|
||||
}
|
||||
},
|
||||
"parallel-webpack": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/parallel-webpack/-/parallel-webpack-2.3.0.tgz",
|
||||
"integrity": "sha512-RCIDF+YOqyAJeM8NumtOQ8JYjUXexDRIN4slFNfvUp1RxLB1zLeLZMAwlP6s7l9LhuR5xJ2pv8ckIsdESzSqog==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ajv": "^4.9.2",
|
||||
"bluebird": "^3.0.6",
|
||||
"chalk": "^1.1.1",
|
||||
"interpret": "^1.0.1",
|
||||
"lodash.assign": "^4.0.8",
|
||||
"lodash.endswith": "^4.0.1",
|
||||
"lodash.flatten": "^4.2.0",
|
||||
"minimist": "^1.2.0",
|
||||
"node-ipc": "^9.1.0",
|
||||
"pluralize": "^1.2.1",
|
||||
"supports-color": "^3.1.2",
|
||||
"worker-farm": "^1.3.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"ajv": {
|
||||
"version": "4.11.8",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz",
|
||||
"integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"co": "^4.6.0",
|
||||
"json-stable-stringify": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
|
||||
"integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
|
||||
"dev": true
|
||||
},
|
||||
"minimist": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
|
||||
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
|
||||
"dev": true
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "3.2.3",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
|
||||
"integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has-flag": "^1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"param-case": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz",
|
||||
|
@ -8347,6 +8510,28 @@
|
|||
"end-of-stream": "^1.1.0",
|
||||
"once": "^1.3.1"
|
||||
}
|
||||
},
|
||||
"tar-fs": {
|
||||
"version": "1.16.3",
|
||||
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.3.tgz",
|
||||
"integrity": "sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw==",
|
||||
"requires": {
|
||||
"chownr": "^1.0.1",
|
||||
"mkdirp": "^0.5.1",
|
||||
"pump": "^1.0.0",
|
||||
"tar-stream": "^1.1.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"pump": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz",
|
||||
"integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==",
|
||||
"requires": {
|
||||
"end-of-stream": "^1.1.0",
|
||||
"once": "^1.3.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -8473,7 +8658,6 @@
|
|||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
|
||||
"integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"end-of-stream": "^1.1.0",
|
||||
"once": "^1.3.1"
|
||||
|
@ -8849,6 +9033,17 @@
|
|||
"remove-trailing-separator": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"replacestream": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/replacestream/-/replacestream-4.0.3.tgz",
|
||||
"integrity": "sha512-AC0FiLS352pBBiZhd4VXB1Ab/lh0lEgpP+GGvZqbQh8a5cmXVoTe5EX/YeTFArnp4SRGTHh1qCHu9lGs1qG8sA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"escape-string-regexp": "^1.0.3",
|
||||
"object-assign": "^4.0.1",
|
||||
"readable-stream": "^2.0.2"
|
||||
}
|
||||
},
|
||||
"request": {
|
||||
"version": "2.88.0",
|
||||
"resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
|
||||
|
@ -10105,23 +10300,44 @@
|
|||
}
|
||||
},
|
||||
"tar-fs": {
|
||||
"version": "1.16.3",
|
||||
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.3.tgz",
|
||||
"integrity": "sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw==",
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.0.0.tgz",
|
||||
"integrity": "sha512-vaY0obB6Om/fso8a8vakQBzwholQ7v5+uy+tF3Ozvxv1KNezmVQAiWtcNmMHFSFPqL3dJA8ha6gdtFbfX9mcxA==",
|
||||
"requires": {
|
||||
"chownr": "^1.0.1",
|
||||
"chownr": "^1.1.1",
|
||||
"mkdirp": "^0.5.1",
|
||||
"pump": "^1.0.0",
|
||||
"tar-stream": "^1.1.2"
|
||||
"pump": "^3.0.0",
|
||||
"tar-stream": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"pump": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz",
|
||||
"integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==",
|
||||
"bl": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-3.0.0.tgz",
|
||||
"integrity": "sha512-EUAyP5UHU5hxF8BPT0LKW8gjYLhq1DQIcneOX/pL/m2Alo+OYDQAJlHq+yseMP50Os2nHXOSic6Ss3vSQeyf4A==",
|
||||
"requires": {
|
||||
"end-of-stream": "^1.1.0",
|
||||
"once": "^1.3.1"
|
||||
"readable-stream": "^3.0.1"
|
||||
}
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.2.0.tgz",
|
||||
"integrity": "sha512-RV20kLjdmpZuTF1INEb9IA3L68Nmi+Ri7ppZqo78wj//Pn62fCoJyV9zalccNzDD/OuJpMG4f+pfMl8+L6QdGw==",
|
||||
"requires": {
|
||||
"inherits": "^2.0.3",
|
||||
"string_decoder": "^1.1.1",
|
||||
"util-deprecate": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"tar-stream": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.0.1.tgz",
|
||||
"integrity": "sha512-I6OJF7wE62BC6zNPdHDtseK0D0187PBjbKSLYY4ffvVkBM6tyBn2O9plDvVM2229/mozfEL/X3++qSvYYQE2xw==",
|
||||
"requires": {
|
||||
"bl": "^3.0.0",
|
||||
"end-of-stream": "^1.4.1",
|
||||
"fs-constants": "^1.0.0",
|
||||
"inherits": "^2.0.3",
|
||||
"readable-stream": "^3.1.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10264,6 +10480,12 @@
|
|||
"integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
|
||||
"dev": true
|
||||
},
|
||||
"textextensions": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/textextensions/-/textextensions-2.4.0.tgz",
|
||||
"integrity": "sha512-qftQXnX1DzpSV8EddtHIT0eDDEiBF8ywhFYR2lI9xrGtxqKN+CvLXhACeCIGbCpQfxxERbrkZEFb8cZcDKbVZA==",
|
||||
"dev": true
|
||||
},
|
||||
"throttleit": {
|
||||
"version": "0.0.2",
|
||||
"resolved": "https://registry.npmjs.org/throttleit/-/throttleit-0.0.2.tgz",
|
||||
|
|
16
package.json
16
package.json
|
@ -2,7 +2,7 @@
|
|||
"name": "betterdiscord",
|
||||
"description": "BetterDiscord",
|
||||
"author": "Jiiks",
|
||||
"version": "2.0.0-beta.3",
|
||||
"version": "2.0.0-beta.6",
|
||||
"homepage": "https://betterdiscord.net",
|
||||
"license": "MIT",
|
||||
"main": "core/dist/main.js",
|
||||
|
@ -17,14 +17,17 @@
|
|||
"private": false,
|
||||
"dependencies": {
|
||||
"asar": "^1.0.0",
|
||||
"axios": "^0.18.0",
|
||||
"chokidar": "^2.1.2",
|
||||
"csp-parse": "github:macropodhq/csp-parse",
|
||||
"deepmerge": "^3.2.0",
|
||||
"fs-extra": "^7.0.1",
|
||||
"keytar": "^4.4.1",
|
||||
"keytar": "4.4.1",
|
||||
"nedb": "^1.8.0",
|
||||
"node-sass": "^4.11.0",
|
||||
"original-fs": "^1.0.0"
|
||||
"original-fs": "^1.0.0",
|
||||
"semver": "^5.6.0",
|
||||
"tar-fs": "^2.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.3.4",
|
||||
|
@ -51,6 +54,7 @@
|
|||
"gulp-inject-string": "^1.1.2",
|
||||
"gulp-json-editor": "^2.5.1",
|
||||
"gulp-rename": "^1.4.0",
|
||||
"gulp-replace": "^1.0.0",
|
||||
"gulp-watch": "^5.0.1",
|
||||
"hash-files": "^1.1.1",
|
||||
"html-webpack-plugin": "^3.2.0",
|
||||
|
@ -58,6 +62,7 @@
|
|||
"lodash": "^4.17.11",
|
||||
"mkdirp": "^0.5.1",
|
||||
"node-gyp": "^3.8.0",
|
||||
"parallel-webpack": "^2.3.0",
|
||||
"pump": "^3.0.0",
|
||||
"request-promise-native": "1.0.5",
|
||||
"sass-lint": "^1.12.1",
|
||||
|
@ -82,6 +87,8 @@
|
|||
"watch_core": "npm run watch --prefix core",
|
||||
"build_editor": "npm run build --prefix editor",
|
||||
"watch_editor": "npm run watch --prefix editor",
|
||||
"build_all": "parallel-webpack --progress --colors --config=webpack.all.config.js",
|
||||
"watch_all": "parallel-webpack --progress --colors --watch --config=webpack.all.config.js",
|
||||
"lint": "eslint -f unix client/src core/src editor/src common && npm run sasslint",
|
||||
"lint_fix": "eslint -f unix client/src core/src",
|
||||
"sasslint": "sass-lint client/src/styles/**/*.scss -v",
|
||||
|
@ -91,7 +98,8 @@
|
|||
"package_release": "node scripts/package-release.js",
|
||||
"gulp_release": "gulp release",
|
||||
"release": "npm run lint && npm run build_release && gulp release && npm run package_release",
|
||||
"update_release": "npm run build_release && gulp build-release",
|
||||
"release_test": "npm run build_release && gulp release",
|
||||
"update_release": "npm run build_release && gulp release",
|
||||
"inject": "node scripts/inject.js"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,12 +3,12 @@
|
|||
PLATFORM="darwin"
|
||||
ARCH="x64"
|
||||
|
||||
NODE_API_VERSION="53"
|
||||
ELECTRON_VERSION="1.6.15"
|
||||
|
||||
scripts/build-keytar.sh $PLATFORM $ARCH $NODE_API_VERSION $ELECTRON_VERSION
|
||||
|
||||
NODE_API_VERSION="64"
|
||||
ELECTRON_VERSION="4.0.0-beta.7"
|
||||
ELECTRON_VERSION="4.0.0-beta.11"
|
||||
|
||||
scripts/build-keytar.sh $PLATFORM $ARCH $NODE_API_VERSION $ELECTRON_VERSION
|
||||
|
||||
NODE_API_VERSION="69"
|
||||
ELECTRON_VERSION="4.0.8"
|
||||
|
||||
scripts/build-keytar.sh $PLATFORM $ARCH $NODE_API_VERSION $ELECTRON_VERSION
|
||||
|
|
|
@ -3,12 +3,12 @@
|
|||
PLATFORM="linux"
|
||||
ARCH="x64"
|
||||
|
||||
NODE_API_VERSION="53"
|
||||
ELECTRON_VERSION="1.6.15"
|
||||
|
||||
scripts/build-keytar.sh $PLATFORM $ARCH $NODE_API_VERSION $ELECTRON_VERSION
|
||||
|
||||
NODE_API_VERSION="64"
|
||||
ELECTRON_VERSION="4.0.0-beta.7"
|
||||
ELECTRON_VERSION="4.0.0-beta.11"
|
||||
|
||||
scripts/build-keytar.sh $PLATFORM $ARCH $NODE_API_VERSION $ELECTRON_VERSION
|
||||
|
||||
NODE_API_VERSION="69"
|
||||
ELECTRON_VERSION="4.0.8"
|
||||
|
||||
scripts/build-keytar.sh $PLATFORM $ARCH $NODE_API_VERSION $ELECTRON_VERSION
|
||||
|
|
|
@ -4,9 +4,10 @@ PLATFORM="$1"
|
|||
ARCH="$2"
|
||||
NODE_API_VERSION="$3"
|
||||
ELECTRON_VERSION="$4"
|
||||
KEYTAR_VERSION="`node -p 'require("keytar/package").version'`"
|
||||
ELECTRON_URL="https://atom.io/download/electron"
|
||||
|
||||
DIRECTORY="release-tmp/keytar.node/keytar-4.3.0"
|
||||
DIRECTORY="release-tmp/keytar.node/keytar-$KEYTAR_VERSION"
|
||||
FILENAME="$PLATFORM-$ARCH-$NODE_API_VERSION.node"
|
||||
|
||||
if [ `node -p 'process.platform'` != "$PLATFORM" ]; then
|
||||
|
|
|
@ -3,12 +3,12 @@
|
|||
PLATFORM="darwin"
|
||||
ARCH="x64"
|
||||
|
||||
NODE_API_VERSION="53"
|
||||
ELECTRON_VERSION="1.6.15"
|
||||
|
||||
scripts/build-node-sass.sh $PLATFORM $ARCH $NODE_API_VERSION $ELECTRON_VERSION
|
||||
|
||||
NODE_API_VERSION="64"
|
||||
ELECTRON_VERSION="4.0.0-beta.7"
|
||||
ELECTRON_VERSION="4.0.0-beta.11"
|
||||
|
||||
scripts/build-node-sass.sh $PLATFORM $ARCH $NODE_API_VERSION $ELECTRON_VERSION
|
||||
|
||||
NODE_API_VERSION="69"
|
||||
ELECTRON_VERSION="4.0.8"
|
||||
|
||||
scripts/build-node-sass.sh $PLATFORM $ARCH $NODE_API_VERSION $ELECTRON_VERSION
|
||||
|
|
|
@ -3,12 +3,12 @@
|
|||
PLATFORM="linux"
|
||||
ARCH="x64"
|
||||
|
||||
NODE_API_VERSION="53"
|
||||
ELECTRON_VERSION="1.6.15"
|
||||
|
||||
scripts/build-node-sass.sh $PLATFORM $ARCH $NODE_API_VERSION $ELECTRON_VERSION
|
||||
|
||||
NODE_API_VERSION="64"
|
||||
ELECTRON_VERSION="4.0.0-beta.7"
|
||||
ELECTRON_VERSION="4.0.0-beta.11"
|
||||
|
||||
scripts/build-node-sass.sh $PLATFORM $ARCH $NODE_API_VERSION $ELECTRON_VERSION
|
||||
|
||||
NODE_API_VERSION="69"
|
||||
ELECTRON_VERSION="4.0.8"
|
||||
|
||||
scripts/build-node-sass.sh $PLATFORM $ARCH $NODE_API_VERSION $ELECTRON_VERSION
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
set "PLATFORM=win32"
|
||||
|
||||
set "NODE_API_VERSION=53"
|
||||
set "ELECTRON_VERSION=1.6.15"
|
||||
|
||||
call ./scripts/build-node-sass.bat %PLATFORM% ia32 %NODE_API_VERSION% %ELECTRON_VERSION%
|
||||
call ./scripts/build-node-sass.bat %PLATFORM% x64 %NODE_API_VERSION% %ELECTRON_VERSION%
|
||||
|
||||
set "NODE_API_VERSION=64"
|
||||
set "ELECTRON_VERSION=4.0.0-beta.7"
|
||||
set "ELECTRON_VERSION=4.0.0-beta.11"
|
||||
|
||||
call ./scripts/build-node-sass.bat %PLATFORM% ia32 %NODE_API_VERSION% %ELECTRON_VERSION%
|
||||
call ./scripts/build-node-sass.bat %PLATFORM% x64 %NODE_API_VERSION% %ELECTRON_VERSION%
|
||||
|
||||
set "NODE_API_VERSION=69"
|
||||
set "ELECTRON_VERSION=4.0.8"
|
||||
|
||||
call ./scripts/build-node-sass.bat %PLATFORM% ia32 %NODE_API_VERSION% %ELECTRON_VERSION%
|
||||
call ./scripts/build-node-sass.bat %PLATFORM% x64 %NODE_API_VERSION% %ELECTRON_VERSION%
|
||||
|
|
|
@ -53,6 +53,7 @@ async function archiveCore(out = './release/core.tar.gz') {
|
|||
coreArchive.file('./release/core/package.json', { name: 'core/package.json' });
|
||||
coreArchive.file('./release/core/index.js', { name: 'core/index.js' });
|
||||
coreArchive.file(`./release/core/${mainFn}`, { name: `core/${mainFn}` });
|
||||
coreArchive.file('./release/core/csp.json', { name: 'core/csp.json' });
|
||||
coreArchive.file('./release/core/sparkplug.js', { name: 'core/sparkplug.js' });
|
||||
coreArchive.directory('./release/core/modules', 'core/modules');
|
||||
coreArchive.directory('./release/core/node_modules', 'core/node_modules');
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
"twitter_username": "Jiiksi"
|
||||
}
|
||||
],
|
||||
"version": "1.0,"
|
||||
"version": "1.0",
|
||||
"description": "Edit messages by double clicking them. This is a v1 fix"
|
||||
},
|
||||
"main": "index.js"
|
||||
|
|
|
@ -10,17 +10,19 @@ span {
|
|||
opacity: $spanOpacity2 !important;
|
||||
}
|
||||
|
||||
.chat .messages-wrapper,
|
||||
#friends .friends-table {
|
||||
.da-chat .da-messagesWrapper,
|
||||
.da-friendsTable {
|
||||
background-image: url(map-get($relative-file-test, url));
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.avatar-large {
|
||||
@if map-has-key($avatar, url) {
|
||||
.da-avatar > .da-image {
|
||||
background-image: url(map-get($avatar, url)) !important;
|
||||
border-radius: $avatarRadius !important;
|
||||
}
|
||||
}
|
||||
|
||||
// Can't use a for loop as then we don't get the index
|
||||
$index: 0;
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
const path = require('path');
|
||||
|
||||
const editor = require('./editor/webpack.config');
|
||||
|
||||
editor.output.path = path.resolve('editor', 'dist');
|
||||
editor.entry = path.resolve('editor', editor.entry);
|
||||
editor.resolve.alias['vue$'] = path.resolve('node_modules', 'vue', 'dist', 'vue.esm.js');
|
||||
editor.resolve.modules = [
|
||||
path.resolve('node_modules'),
|
||||
path.resolve('common', 'modules')
|
||||
];
|
||||
|
||||
const client = require('./client/webpack.config');
|
||||
|
||||
client.output.path = path.resolve('client', 'dist');
|
||||
client.entry = path.resolve('client', client.entry);
|
||||
client.resolve.alias['vue$'] = path.resolve('node_modules', 'vue', 'dist', 'vue.esm.js');
|
||||
client.resolve.modules = [
|
||||
path.resolve('node_modules'),
|
||||
path.resolve('common', 'modules'),
|
||||
path.resolve('client', 'src', 'modules'),
|
||||
path.resolve('client', 'src', 'ui'),
|
||||
path.resolve('client', 'src', 'plugins'),
|
||||
path.resolve('client', 'src', 'structs'),
|
||||
path.resolve('client', 'src', 'builtin')
|
||||
];
|
||||
|
||||
module.exports = [editor, client];
|
Loading…
Reference in New Issue