mirror of
https://github.com/Foundry376/Mailspring.git
synced 2024-11-14 05:41:05 +08:00
20c522ed39
[Composer Templates / Quick Reply plugin example] Add a page to preferences with a basic editor for quick reply templates, allowing add, delete, and edit (HTML and rendered text), with instructions for how to add variable regions. Add methods to TemplatesStore to enable these. Fix issues in plugin with quoted text handling, name conflicts, `this` scoping.
209 lines
6.4 KiB
JavaScript
209 lines
6.4 KiB
JavaScript
import {DraftStore, Actions, QuotedHTMLParser} from 'nylas-exports';
|
|
import NylasStore from 'nylas-store';
|
|
import shell from 'shell';
|
|
import path from 'path';
|
|
import fs from 'fs';
|
|
|
|
class TemplateStore extends NylasStore {
|
|
|
|
init(templatesDir = path.join(NylasEnv.getConfigDirPath(), 'templates')) {
|
|
this.items = this.items.bind(this);
|
|
this.templatesDirectory = this.templatesDirectory.bind(this);
|
|
this._setStoreDefaults = this._setStoreDefaults.bind(this);
|
|
this._registerListeners = this._registerListeners.bind(this);
|
|
this._populate = this._populate.bind(this);
|
|
this._onCreateTemplate = this._onCreateTemplate.bind(this);
|
|
this._onShowTemplates = this._onShowTemplates.bind(this);
|
|
this._displayError = this._displayError.bind(this);
|
|
this._writeTemplate = this._writeTemplate.bind(this);
|
|
this._onInsertTemplateId = this._onInsertTemplateId.bind(this);
|
|
this._setStoreDefaults();
|
|
this._registerListeners();
|
|
|
|
this._templatesDir = templatesDir;
|
|
this._welcomeName = 'Welcome to Templates.html';
|
|
this._welcomePath = path.join(__dirname, '..', 'assets', this._welcomeName);
|
|
|
|
// I know this is a bit of pain but don't do anything that
|
|
// could possibly slow down app launch
|
|
fs.exists(this._templatesDir, (exists) => {
|
|
if (exists) {
|
|
this._populate();
|
|
fs.watch(this._templatesDir, () => this._populate());
|
|
} else {
|
|
fs.mkdir(this._templatesDir, () => {
|
|
fs.readFile(this._welcomePath, (err, welcome) => {
|
|
fs.writeFile(path.join(this._templatesDir, this._welcomeName), welcome, () => {
|
|
fs.watch(this._templatesDir, () => this._populate());
|
|
});
|
|
});
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
items() {
|
|
return this._items;
|
|
}
|
|
|
|
templatesDirectory() {
|
|
return this._templatesDir;
|
|
}
|
|
|
|
_setStoreDefaults() {
|
|
this._items = [];
|
|
}
|
|
|
|
_registerListeners() {
|
|
this.listenTo(Actions.insertTemplateId, this._onInsertTemplateId);
|
|
this.listenTo(Actions.createTemplate, this._onCreateTemplate);
|
|
this.listenTo(Actions.showTemplates, this._onShowTemplates);
|
|
}
|
|
|
|
_populate() {
|
|
fs.readdir(this._templatesDir, (err, filenames) => {
|
|
this._items = [];
|
|
for (let i = 0, filename; i < filenames.length; i++) {
|
|
filename = filenames[i];
|
|
if (filename[0] === '.') { continue; }
|
|
const displayname = path.basename(filename, path.extname(filename));
|
|
this._items.push({
|
|
id: filename,
|
|
name: displayname,
|
|
path: path.join(this._templatesDir, filename),
|
|
});
|
|
}
|
|
this.trigger(this);
|
|
});
|
|
}
|
|
|
|
_onCreateTemplate({draftClientId, name, contents} = {}) {
|
|
if (draftClientId) {
|
|
DraftStore.sessionForClientId(draftClientId).then((session) => {
|
|
const draft = session.draft();
|
|
const draftName = name ? name : draft.subject;
|
|
const draftContents = contents ? contents : QuotedHTMLParser.removeQuotedHTML(draft.body);
|
|
if (!draftName || draftName.length === 0) {
|
|
this._displayError('Give your draft a subject to name your template.');
|
|
}
|
|
if (!draftContents || draftContents.length === 0) {
|
|
this._displayError('To create a template you need to fill the body of the current draft.');
|
|
}
|
|
this._writeTemplate(draftName, draftContents);
|
|
});
|
|
return;
|
|
}
|
|
if (!name || name.length === 0) {
|
|
this._displayError('You must provide a name for your template.');
|
|
}
|
|
if (!contents || contents.length === 0) {
|
|
this._displayError('You must provide contents for your template.');
|
|
}
|
|
this._writeTemplate(name, contents);
|
|
}
|
|
|
|
_onShowTemplates() {
|
|
const ref = this._items[0];
|
|
shell.showItemInFolder(((ref != null) ? ref.path : undefined) || this._templatesDir);
|
|
}
|
|
|
|
_displayError(message) {
|
|
const dialog = require('remote').require('dialog');
|
|
dialog.showErrorBox('Template Creation Error', message);
|
|
}
|
|
|
|
_writeTemplate(name, contents) {
|
|
this.saveTemplate(name, contents, true, (template) => {
|
|
Actions.switchPreferencesTab('Quick Replies');
|
|
Actions.openPreferences()
|
|
});
|
|
}
|
|
|
|
saveTemplate(name, contents, isNew, callback) {
|
|
const filename = `${name}.html`;
|
|
const templatePath = path.join(this._templatesDir, filename);
|
|
|
|
var template = null;
|
|
this._items.forEach((item) => {
|
|
if (item.name === name) { template = item; }
|
|
});
|
|
|
|
if(isNew && template !== null) {
|
|
this._displayError("A template with that name already exists!");
|
|
return undefined;
|
|
}
|
|
|
|
fs.writeFile(templatePath, contents, (err) => {
|
|
if (err) { this._displayError(err); }
|
|
if (template === null) {
|
|
template = {
|
|
id: filename,
|
|
name: name,
|
|
path: templatePath
|
|
};
|
|
this._items.push(template);
|
|
}
|
|
if(callback)
|
|
callback(template);
|
|
this.trigger(this);
|
|
});
|
|
}
|
|
|
|
deleteTemplate(name, callback) {
|
|
var template = null;
|
|
this._items.forEach((item) => {
|
|
if (item.name === name) { template = item; }
|
|
});
|
|
if (!template) { return undefined }
|
|
|
|
fs.unlink(template.path, () => {
|
|
this._populate();
|
|
if(callback)
|
|
callback()
|
|
});
|
|
}
|
|
|
|
renameTemplate(oldName, newName, callback) {
|
|
var template = null;
|
|
this._items.forEach((item) => {
|
|
if (item.name === oldName) { template = item; }
|
|
});
|
|
if (!template) { return undefined }
|
|
|
|
const newFilename = `${newName}.html`;
|
|
const oldPath = path.join(this._templatesDir, `${oldName}.html`);
|
|
const newPath = path.join(this._templatesDir, newFilename);
|
|
fs.rename(oldPath, newPath, () => {
|
|
template.name = newName;
|
|
template.id = newFilename;
|
|
template.path = newPath;
|
|
this.trigger(this);
|
|
callback(template)
|
|
});
|
|
}
|
|
|
|
_onInsertTemplateId({templateId, draftClientId} = {}) {
|
|
this.getTemplateContents(templateId, (body) => {
|
|
DraftStore.sessionForClientId(draftClientId).then((session)=> {
|
|
draftHtml = QuotedHTMLParser.appendQuotedHTML(body, session.draft().body);
|
|
session.changes.add({body: draftHtml});
|
|
});
|
|
});
|
|
}
|
|
|
|
getTemplateContents(templateId, callback) {
|
|
let template = null;
|
|
this._items.forEach((item) => {
|
|
if (item.id === templateId) { template = item; }
|
|
});
|
|
|
|
if (!template) { return undefined }
|
|
|
|
fs.readFile(template.path, (err, data)=> {
|
|
const body = data.toString();
|
|
callback(body);
|
|
});
|
|
}
|
|
}
|
|
|
|
module.exports = new TemplateStore();
|