Package installer & install modal
This commit is contained in:
parent
76d54f0a95
commit
cff425f916
|
@ -12,6 +12,7 @@ import { ClientLogger as Logger } from 'common';
|
|||
import { SocketProxy, EventHook, CssEditor } from 'modules';
|
||||
import { ProfileBadges, ClassNormaliser } from 'ui';
|
||||
import Updater from './updater';
|
||||
import PackageInstaller from './packageinstaller';
|
||||
|
||||
/**
|
||||
* Module Manager initializes all modules when everything is ready
|
||||
|
@ -28,7 +29,8 @@ export default class {
|
|||
new SocketProxy(),
|
||||
new EventHook(),
|
||||
CssEditor,
|
||||
Updater
|
||||
Updater,
|
||||
new PackageInstaller()
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
import EventListener from './eventlistener';
|
||||
import asar from 'asar';
|
||||
|
||||
import { Modals } from 'ui';
|
||||
import { Utils } from 'common';
|
||||
|
||||
export default class extends EventListener {
|
||||
|
||||
get eventBindings() {
|
||||
return [
|
||||
{ id: 'install-pkg', callback: this.installPackage }
|
||||
];
|
||||
}
|
||||
|
||||
async installPackage(pkg, upload) {
|
||||
try {
|
||||
const config = JSON.parse(asar.extractFile(pkg.path, 'config.json').toString());
|
||||
const { info, main } = config;
|
||||
|
||||
let icon = null;
|
||||
if (info.icon && info.icon_type) {
|
||||
const extractIcon = asar.extractFile(pkg.path, info.icon);
|
||||
icon = `data:${info.icon_type};base64,${Utils.arrayBufferToBase64(extractIcon)}`;
|
||||
}
|
||||
if (icon) config.iconEncoded = icon;
|
||||
const isPlugin = info.type && info.type === 'plugin' || main.endsWith('.js');
|
||||
|
||||
/*
|
||||
config.permissions = [
|
||||
{
|
||||
HEADER: 'Test Permission Header',
|
||||
BODY: 'Test Permission Body'
|
||||
},
|
||||
{
|
||||
HEADER: 'Test Permission Header',
|
||||
BODY: 'Test Permission Body'
|
||||
},
|
||||
{
|
||||
HEADER: 'Test Permission Header',
|
||||
BODY: 'Test Permission Body'
|
||||
},
|
||||
{
|
||||
HEADER: 'Test Permission Header',
|
||||
BODY: 'Test Permission Body'
|
||||
}
|
||||
];
|
||||
*/
|
||||
// Show install modal
|
||||
const modalResult = await Modals.installModal(`Install BetterDiscord ${isPlugin ? 'Plugin' : 'Theme'}`, config).promise;
|
||||
|
||||
if (modalResult === 0) {
|
||||
// Upload it instead
|
||||
}
|
||||
|
||||
console.log(modalResult);
|
||||
|
||||
} catch (err) {}
|
||||
}
|
||||
|
||||
}
|
|
@ -15,6 +15,7 @@ import { Utils, Filters, ClientLogger as Logger } from 'common';
|
|||
import { MonkeyPatch } from './patcher';
|
||||
import Reflection from './reflection/index';
|
||||
import DiscordApi from './discordapi';
|
||||
import Events from './events';
|
||||
|
||||
class Helpers {
|
||||
static get plannedActions() {
|
||||
|
@ -506,17 +507,17 @@ export class ReactAutoPatcher {
|
|||
|
||||
const reflect = Reflection.DOM(selector);
|
||||
const stateNode = reflect.getComponentStateNode(this.UploadArea);
|
||||
const callback = function(e) {
|
||||
const callback = function (e) {
|
||||
if (!e.dataTransfer.files.length || !e.dataTransfer.files[0].name.endsWith('.bd')) return;
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
e.stopImmediatePropagation();
|
||||
stateNode.clearDragging();
|
||||
Modals.confirm('Function not ready', `You tried to install "${e.dataTransfer.files[0].path}", but installing .bd files isn't ready yet.`)
|
||||
// Possibly something like Events.emit('install-file', e.dataTransfer.files[0]);
|
||||
|
||||
Events.emit('install-pkg', e.dataTransfer.files[0], DiscordApi.currentChannel.id);
|
||||
};
|
||||
|
||||
// Remove their handler, add ours, then readd theirs to give ours priority to stop theirs when we get a .bd file.
|
||||
// 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);
|
||||
|
|
|
@ -8,3 +8,4 @@
|
|||
@import './settings-modal';
|
||||
@import './permission-modal';
|
||||
@import './input-modal';
|
||||
@import './install-modal';
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
.bd-installModal {
|
||||
|
||||
.bd-modalInner {
|
||||
min-width: 520px;
|
||||
min-height: 200px;
|
||||
|
||||
.bd-modalBody {
|
||||
flex-grow: 1;
|
||||
padding: 0;
|
||||
|
||||
.bd-installModalBody {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
|
||||
.bd-installModalTop {
|
||||
padding: 0 15px;
|
||||
display: flex;
|
||||
height: 100px;
|
||||
|
||||
span {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.bd-installModalIcon {
|
||||
background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMTAwIDEzMCIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgMTAwIDEzMDsiIHhtbDpzcGFjZT0icHJlc2VydmUiPjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+LnN0MHtmaWxsOiNGNEY2RkM7fS5zdDF7ZmlsbDpub25lO3N0cm9rZTojMzYzOTNFO3N0cm9rZS13aWR0aDoyO30uc3Qye29wYWNpdHk6MC42O2ZpbGw6bm9uZTtzdHJva2U6IzM2MzkzRTtzdHJva2Utd2lkdGg6MjtlbmFibGUtYmFja2dyb3VuZDpuZXcgICAgO308L3N0eWxlPjxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik0xNSwxOWMwLTMuMywyLjctNiw2LTZoNDRjNC43LDAsMjAsMTUuMywyMCwyMHY3NGMwLDMuMy0yLjcsNi02LDZIMjFjLTMuMywwLTYtMi43LTYtNlYxOXoiLz48cGF0aCBjbGFzcz0ic3QxIiBkPSJNMTUsMTljMC0zLjMsMi43LTYsNi02aDQ0YzQuNywwLDIwLDE1LjMsMjAsMjB2NzRjMCwzLjMtMi43LDYtNiw2SDIxYy0zLjMsMC02LTIuNy02LTZWMTl6Ii8+PHBhdGggY2xhc3M9InN0MCIgZD0iTTY2LDE2YzAtMy4zLDEuOS00LjEsNC4yLTEuOGwxMy41LDEzLjVjMi4zLDIuMywxLjYsNC4yLTEuOCw0LjJINjljLTEuNywwLTMtMS4zLTMtM1YxNkw2NiwxNnoiLz48cGF0aCBjbGFzcz0ic3QxIiBkPSJNNjYsMTZjMC0zLjMsMS45LTQuMSw0LjItMS44bDEzLjUsMTMuNWMyLjMsMi4zLDEuNiw0LjItMS44LDQuMkg2OWMtMS43LDAtMy0xLjMtMy0zVjE2TDY2LDE2eiIvPjxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik02MSwxN0gyM2MtMi44LDAtNSwyLjItNSw1djciLz48cGF0aCBjbGFzcz0ic3QyIiBkPSJNNjksMTl2Ny41YzAsMS40LDEuMSwyLjUsMi41LDIuNUg3NCIvPjwvc3ZnPg==);
|
||||
background-size: 100% 100%;
|
||||
flex-shrink: 0;
|
||||
width: 100px;
|
||||
height: 130px;
|
||||
position: fixed;
|
||||
border-radius: 3px;
|
||||
margin-top: -30px;
|
||||
display: flex;
|
||||
align-content: center;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
justify-items: center;
|
||||
|
||||
.bd-installModalCi {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
svg {
|
||||
fill: #36393e;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
.bd-installModalInfo {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
flex-direction: column;
|
||||
padding: 15px 10px;
|
||||
margin-left: 100px;
|
||||
}
|
||||
|
||||
.bd-installModalDesc {
|
||||
margin-top: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.bd-installModalBottom {
|
||||
padding: 0 15px;
|
||||
flex-grow: 1;
|
||||
|
||||
.bd-permScope {
|
||||
&:last-child {
|
||||
.bd-permInner {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bd-installModalFooter {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding: 10px;
|
||||
background: rgba(0, 0, 0, .1);
|
||||
|
||||
.bd-button {
|
||||
font-size: 16px;
|
||||
padding: 10px;
|
||||
border-radius: 3px;
|
||||
min-width: 100px;
|
||||
background: #fff;
|
||||
background: #3ecc9c;
|
||||
transition: opacity .2s ease-in-out;
|
||||
|
||||
&:hover {
|
||||
opacity: .8;
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
background: transparent;
|
||||
transition: none;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
<template>
|
||||
<Modal class="bd-installModal" :headertext="modal.title" :closing="modal.closing" @close="modal.close" :noheader="true">
|
||||
<div slot="body" class="bd-installModalBody">
|
||||
<div class="bd-installModalTop">
|
||||
<div class="bd-installModalIcon">
|
||||
<div v-if="modal.config.iconEncoded" class="bd-installModalCi" :style="{backgroundImage: `url(${modal.config.iconEncoded})`}"/>
|
||||
<MiExtension v-else/>
|
||||
</div>
|
||||
<div class="bd-installModalInfo">
|
||||
<span>{{modal.config.info.name}} v{{modal.config.info.version.toString()}} by {{modal.config.info.authors.map(a => a.name).join(', ')}}</span>
|
||||
<div class="bd-installModalDesc">
|
||||
{{modal.config.info.description}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bd-installModalBottom">
|
||||
<div v-for="(perm, i) in modal.config.permissions" :key="`perm-${i}`" class="bd-permScope">
|
||||
<div class="bd-permAllow">
|
||||
<div class="bd-permCheck">
|
||||
<div class="bd-permCheckInner"></div>
|
||||
</div>
|
||||
<div class="bd-permInner">
|
||||
<div class="bd-permName">{{perm.HEADER}}</div>
|
||||
<div class="bd-permDesc">{{perm.BODY}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div slot="footer" class="bd-installModalFooter">
|
||||
<div class="bd-button bd-ok" @click="modal.confirm(0); modal.close();">Upload</div>
|
||||
<div class="bd-button bd-ok" @click="modal.confirm(); modal.close();">Install</div>
|
||||
</div>
|
||||
</Modal>
|
||||
</template>
|
||||
<script>
|
||||
// Imports
|
||||
import { Modal, MiExtension } from '../../common';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
installing: false
|
||||
}
|
||||
},
|
||||
props: ['modal'],
|
||||
components: {
|
||||
Modal, MiExtension
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -11,7 +11,7 @@
|
|||
<template>
|
||||
<div :class="['bd-modal', {'bd-modalOut': closing, 'bd-modalScrolled': scrolled}]">
|
||||
<div class="bd-modalInner">
|
||||
<div class="bd-modalHeader">
|
||||
<div class="bd-modalHeader" v-if="!noheader">
|
||||
<slot name="header">
|
||||
<div v-if="$slots.icon" class="bd-modalIcon">
|
||||
<slot name="icon" />
|
||||
|
@ -41,7 +41,7 @@
|
|||
import { MiClose } from './MaterialIcon';
|
||||
|
||||
export default {
|
||||
props: ['headertext', 'closing'],
|
||||
props: ['headertext', 'closing', 'noheader'],
|
||||
components: {
|
||||
MiClose
|
||||
},
|
||||
|
|
|
@ -17,6 +17,7 @@ import ErrorModal from './components/bd/modals/ErrorModal.vue';
|
|||
import SettingsModal from './components/bd/modals/SettingsModal.vue';
|
||||
import PermissionModal from './components/bd/modals/PermissionModal.vue';
|
||||
import InputModal from './components/bd/modals/InputModal.vue';
|
||||
import InstallModal from './components/bd/modals/InstallModal.vue';
|
||||
|
||||
let modals = 0;
|
||||
|
||||
|
@ -190,6 +191,19 @@ export default class Modals {
|
|||
return new Modal(modal, InputModal);
|
||||
}
|
||||
|
||||
static installModal(title, config) {
|
||||
return this.add(this.createInstallModal(title, config));
|
||||
}
|
||||
|
||||
static createInstallModal(title, config) {
|
||||
const modal = { title, config };
|
||||
modal.promise = new Promise((resolve, reject) => {
|
||||
modal.confirm = value => resolve(value);
|
||||
modal.beforeClose = () => reject();
|
||||
});
|
||||
return new Modal(modal, InstallModal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new permissions modal and adds it to the open stack.
|
||||
* The modal will have a promise property that will be set to a Promise object that is resolved or rejected if the user accepts the permissions or closes the modal.
|
||||
|
|
Loading…
Reference in New Issue