BetterDiscordApp-v2/editor/src/Editor.vue

276 lines
9.4 KiB
Vue
Raw Permalink Normal View History

2019-02-24 11:28:29 +01:00
<template>
2019-02-24 12:03:15 +01:00
<div class="container">
<div class="titlebar">
<div class="draggable"></div>
<div class="icon">
<div class="inner"></div>
</div>
<div class="title">Content 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>
2019-02-28 05:05:54 +01:00
<BDEdit :files="files"
:parentLoading="loading"
2019-02-24 17:39:28 +01:00
:snippets="snippets"
:updateContent="updateContent"
:runScript="runScript"
:newFile="newFile"
:saveFile="saveFile"
:newSnippet="newSnippet"
2019-02-25 11:41:22 +01:00
:saveSnippet="saveSnippet"
2019-02-27 07:10:04 +01:00
:readFile="readFile"
:readSnippet="readSnippet"
:injectStyle="injectStyle"
2019-02-28 05:05:54 +01:00
:toggleLiveUpdate="toggleLiveUpdate"
2019-02-28 11:37:57 +01:00
:ctxAction="ctxAction"
:toast="toast"/>
2019-02-24 12:03:15 +01:00
</div>
2019-02-24 11:28:29 +01:00
</template>
<script>
import { ClientIPC } from 'common';
import { remote } from 'electron';
2019-02-24 11:28:29 +01:00
import { BDEdit } from 'bdedit';
2019-02-28 08:46:24 +01:00
2019-02-24 12:03:15 +01:00
ace.acequire = ace.require;
2019-02-24 11:28:29 +01:00
2019-02-24 17:29:00 +01:00
const modes = {
'css': 'css',
'scss': 'scss',
2019-02-26 15:33:14 +01:00
'js': 'javascript',
2019-02-24 17:29:00 +01:00
'txt': 'text',
'json': 'json'
};
function resolveMode(fileName) {
if (!fileName.includes('.')) return 'text';
const ext = fileName.substr(fileName.lastIndexOf('.') + 1);
if (modes.hasOwnProperty(ext)) return modes[ext];
return 'text';
}
2019-02-24 11:28:29 +01:00
export default {
data() {
return {
2019-02-24 17:39:28 +01:00
files: [],
snippets: [],
loading: true,
alwaysOnTop: false,
2019-02-27 07:10:04 +01:00
error: undefined,
2019-02-28 11:37:57 +01:00
lastSaved: undefined,
toast: { active: false, msg: '' }
}
},
2019-02-24 12:03:15 +01:00
components: { BDEdit },
created() {
2019-02-27 00:33:23 +01:00
ClientIPC.on('bd-editor-addFile', (_, file) => {
if (this.files.find(f => f.name === file.name)) return;
this.addFile(file);
});
ClientIPC.on('bd-editor-remFile', (_, file) => {
this.files = this.files.filter(f => f.name !== file.name);
});
ClientIPC.on('bd-editor-addSnippet', (_, snippet) => {
if (this.snippets.find(s => s.name === snippet.name)) return;
this.addSnippet(snippet);
});
ClientIPC.on('bd-editor-remSnippet', (_, snippet) => {
this.snippets = this.snippets.filter(s => s.name !== snippet.name);
});
2019-02-27 07:10:04 +01:00
ClientIPC.on('bd-editor-fileChange', (_, file) => {
if (this.lastSaved && this.lastSaved.name === file.name) { // If we saved in our editor then don't trigger
this.lastSaved = undefined;
return;
}
const f = this.files.find(f => f.name === file.name);
if (f) f.changed = true;
});
},
2019-02-28 05:05:54 +01:00
async mounted() {
this.files = await ClientIPC.send('bd-editor-getFiles');
this.snippets = await ClientIPC.send('bd-editor-getSnippets');
this.loading = false;
},
methods: {
2019-02-24 17:39:28 +01:00
addFile(file) {
this.files.push(file);
},
2019-02-27 07:10:04 +01:00
addSnippet(snippet) { this.snippets.push(file) },
updateContent(item, content) {
item.content = content;
item.saved = item.content === item.savedContent;
if (this.liveUpdateTimeout) clearTimeout(this.liveUpdateTimeout);
if (item.liveUpdateEnabled) {
this.liveUpdateTimeout = setTimeout(() => {
this.injectStyle(item);
}, 5000);
}
},
async runScript(script) {
return ClientIPC.send('editor-runScript', script);
},
2019-02-24 17:29:00 +01:00
newFile(fileName) {
const prefix = fileName;
const mode = resolveMode(fileName);
let newName = prefix;
let iter = 0;
while (this.files.find(file => file.name === newName)) {
2019-02-27 07:10:04 +01:00
newName = `${prefix.split('.')[0]}_${iter}.${prefix.split('.')[1]}`;
2019-02-24 17:29:00 +01:00
iter++;
}
2019-02-27 07:10:04 +01:00
const newItem = { type: 'file', name: newName, content: '', mode, saved: false, read: true };
2019-02-24 17:29:00 +01:00
this.files.push(newItem);
return newItem;
},
newSnippet(snippetName) {
const prefix = snippetName;
const mode = resolveMode(snippetName);
let newName = prefix;
let iter = 0;
while (this.snippets.find(snippet => snippet.name === newName)) {
newName = `${prefix}_${iter}`;
iter++;
}
2019-02-27 07:10:04 +01:00
const newItem = { type: 'snippet', name: newName, content: '', savedContent: '', mode, saved: false, read: true };
2019-02-24 17:29:00 +01:00
this.snippets.push(newItem);
return newItem;
},
2019-02-24 17:43:58 +01:00
async saveFile(file) {
2019-02-25 16:56:56 +01:00
try {
2019-02-27 07:10:04 +01:00
this.lastSaved = file;
2019-02-25 16:56:56 +01:00
const result = await ClientIPC.send('bd-editor-saveFile', file);
file.savedContent = file.content;
file.saved = true;
} catch (err) {
console.log(err);
}
2019-02-24 17:29:00 +01:00
},
2019-02-24 17:43:58 +01:00
async saveSnippet(snippet) {
2019-02-27 07:10:04 +01:00
snippet.saved = true;
2019-02-27 19:34:11 +01:00
snippet.savedContent = snippet.content;
const result = await ClientIPC.send('bd-editor-saveSnippet', this.snippets.map(snippet => {
return {
name: snippet.name,
content: snippet.savedContent
}
}));
2019-02-27 07:10:04 +01:00
},
async readFile(file) {
const content = await ClientIPC.send('editor-readFile', file);
file.read = true;
file.changed = false;
file.content = file.savedContent = content;
return content;
},
async readSnippet(snippet) {
const content = await ClientIPC.send('editor-readSnippet', snippet);
snippet.read = true;
return content;
2019-02-24 17:29:00 +01:00
},
2019-02-25 11:41:22 +01:00
async injectStyle(item) {
2019-02-28 08:45:06 +01:00
const style = item.content.length <= 0 ? ' ' : item.content;
const result = await ClientIPC.send('bd-editor-injectStyle', { id: item.name.split('.')[0], style, mode: item.mode });
2019-02-25 11:41:22 +01:00
return result;
},
2019-02-28 05:05:54 +01:00
async ctxAction(action, item) {
if (action === 'reveal') {
ClientIPC.send('explorer', { 'static': 'userfiles' });
return;
}
if (action === 'copy') {
remote.clipboard.writeText(item.content);
return;
}
if (action === 'copyPath') {
const fullPath = await ClientIPC.send('getPath', ['userfiles', item.name]);
remote.clipboard.writeText(fullPath);
return;
}
2019-02-28 05:40:33 +01:00
if (action === 'rename') { // TODO select correct file after
this.loading = true;
const { oldName, newName } = item;
2019-02-28 11:37:57 +01:00
if (this.files.find(f => f.name === newName)) {
this.loading = false;
this.showToast('err', `File ${newName} already exists`);
return {
err: `File ${newName} already exists`
};
}
2019-02-28 05:40:33 +01:00
try {
await ClientIPC.send('rnFile', { oldName: ['userfiles', oldName], newName: ['userfiles', newName] });
2019-02-28 11:37:57 +01:00
return item;
2019-02-28 05:40:33 +01:00
} catch (err) {
console.log(err);
2019-02-28 11:37:57 +01:00
return { err };
2019-02-28 05:40:33 +01:00
} finally {
this.loading = false;
}
}
if (action === 'delete') {
this.loading = true;
try {
await ClientIPC.send('rmFile', ['userfiles', item.name]);
} catch (err) {
console.log(err);
} finally {
this.loading = false;
}
return;
}
2019-02-28 05:05:54 +01:00
},
2019-02-28 11:37:57 +01:00
showToast(type, msg, timeout = 3000) {
this.toast = { active: true, type, msg };
setTimeout(() => { this.toast.active = false }, timeout);
},
toggleLiveUpdate(item) {
item.liveUpdateEnabled = !item.liveUpdateEnabled;
return item;
},
toggleaot() {
this.alwaysOnTop = !this.alwaysOnTop;
remote.getCurrentWindow().setAlwaysOnTop(this.alwaysOnTop);
},
2019-02-24 17:39:28 +01:00
close() {
window.close();
}
2019-02-24 12:03:15 +01:00
}
2019-02-24 11:28:29 +01:00
}
</script>