1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-10-31 00:07:48 +02:00

Allow attaching files in Electron ap

This commit is contained in:
Laurent Cozic
2017-11-10 22:18:00 +00:00
parent f543015714
commit 49c11fb22e
15 changed files with 437 additions and 86 deletions

View File

@@ -2,15 +2,8 @@ const { BaseCommand } = require('./base-command.js');
const { app } = require('./app.js');
const { _ } = require('lib/locale.js');
const { BaseModel } = require('lib/base-model.js');
const { Folder } = require('lib/models/folder.js');
const { Note } = require('lib/models/note.js');
const { Resource } = require('lib/models/resource.js');
const { uuid } = require('lib/uuid.js');
const { filename } = require('lib/path-utils.js');
const { shim } = require('lib/shim.js');
const fs = require('fs-extra');
const mime = require('mime/lite');
const sharp = require('sharp');
class Command extends BaseCommand {
@@ -22,22 +15,6 @@ class Command extends BaseCommand {
return _('Attaches the given file to the note.');
}
resizeImage_(filePath, targetPath) {
return new Promise((resolve, reject) => {
sharp(filePath)
.resize(Resource.IMAGE_MAX_DIMENSION, Resource.IMAGE_MAX_DIMENSION)
.max()
.withoutEnlargement()
.toFile(targetPath, (err, info) => {
if (err) {
reject(err);
} else {
resolve(info);
}
});
});
}
async action(args) {
let title = args['note'];
@@ -45,26 +22,8 @@ class Command extends BaseCommand {
if (!note) throw new Error(_('Cannot find "%s".', title));
const localFilePath = args['file'];
if (!(await fs.pathExists(localFilePath))) throw new Error(_('Cannot access %s', localFilePath));
let resource = Resource.new();
resource.id = uuid.create();
resource.mime = mime.getType(localFilePath);
resource.title = filename(localFilePath);
let targetPath = Resource.fullPath(resource);
if (resource.mime == 'image/jpeg' || resource.mime == 'image/jpg' || resource.mime == 'image/png') {
const result = await this.resizeImage_(localFilePath, targetPath);
this.logger().info(result);
} else {
await fs.copy(localFilePath, targetPath, { overwrite: true });
}
await Resource.save(resource, { isNew: true });
note.body += "\n\n" + Resource.markdownTag(resource);
await Note.save(note);
await shim.attachFileToNote(note, localFilePath);
}
}

View File

@@ -126,10 +126,6 @@ msgstr ""
msgid "Cannot find \"%s\"."
msgstr ""
#, javascript-format
msgid "Cannot access %s"
msgstr ""
msgid "Displays the given note."
msgstr ""
@@ -496,6 +492,10 @@ msgid ""
"destination."
msgstr ""
#, javascript-format
msgid "Cannot access %s"
msgstr ""
#, javascript-format
msgid "Created local items: %d."
msgstr ""

View File

@@ -127,10 +127,6 @@ msgstr "Joindre le fichier fourni à la note."
msgid "Cannot find \"%s\"."
msgstr "Impossible de trouver \"%s\"."
#, javascript-format
msgid "Cannot access %s"
msgstr "Impossible d'accéder à %s"
msgid "Displays the given note."
msgstr "Affiche la note."
@@ -550,6 +546,10 @@ msgstr ""
"Veuillez attribuer une valeur au paramètre de configuration \"sync.2.path\" "
"pour indiquer le dossier où devra se faire la synchronisation."
#, javascript-format
msgid "Cannot access %s"
msgstr "Impossible d'accéder à %s"
#, javascript-format
msgid "Created local items: %d."
msgstr "Objets créés localement : %d."

View File

@@ -126,10 +126,6 @@ msgstr ""
msgid "Cannot find \"%s\"."
msgstr ""
#, javascript-format
msgid "Cannot access %s"
msgstr ""
msgid "Displays the given note."
msgstr ""
@@ -496,6 +492,10 @@ msgid ""
"destination."
msgstr ""
#, javascript-format
msgid "Cannot access %s"
msgstr ""
#, javascript-format
msgid "Created local items: %d."
msgstr ""

View File

@@ -20,6 +20,11 @@ class Bridge {
return { width: s[0], height: s[1] };
}
showOpenDialog(options) {
const {dialog} = require('electron');
return dialog.showOpenDialog(options);
}
showMessageBox(options) {
const {dialog} = require('electron');
return dialog.showMessageBox(options);

View File

@@ -0,0 +1,38 @@
const React = require('react');
const { connect } = require('react-redux');
const { themeStyle } = require('../theme.js');
class IconButton extends React.Component {
render() {
const style = this.props.style;
const theme = themeStyle(this.props.theme);
const iconStyle = {
color: theme.color,
fontSize: theme.fontSize * 1.4,
};
const icon = <i style={iconStyle} className={"fa " + this.props.iconName}></i>
const rootStyle = Object.assign({
display: 'flex',
textDecoration: 'none',
padding: 10,
width: theme.buttonMinHeight,
height: theme.buttonMinHeight,
boxSizing: 'border-box',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: theme.backgroundColor,
cursor: 'default',
}, style);
return (
<a href="#" style={rootStyle} className="icon-button" onClick={() => { if (this.props.onClick) this.props.onClick() }}>
{ icon }
</a>
);
}
}
module.exports = { IconButton };

View File

@@ -1,5 +1,6 @@
const React = require('react');
const { Note } = require('lib/models/note.js');
const { IconButton } = require('./IconButton.min.js');
const { connect } = require('react-redux');
const { _ } = require('lib/locale.js');
const { reg } = require('lib/registry.js');
@@ -8,8 +9,11 @@ const shared = require('lib/components/shared/note-screen-shared.js');
const { bridge } = require('electron').remote.require('./bridge');
const { themeStyle } = require('../theme.js');
const AceEditor = require('react-ace').default;
require('brace/mode/markdown');
const Menu = bridge().Menu;
const MenuItem = bridge().MenuItem;
const { shim } = require('lib/shim.js');
require('brace/mode/markdown');
// https://ace.c9.io/build/kitchen-sink.html
// https://highlightjs.org/static/demo/
require('brace/theme/chrome');
@@ -281,6 +285,31 @@ class NoteTextComponent extends React.Component {
this.scheduleSave();
}
itemContextMenu(event) {
const noteId = this.props.noteId;
if (!noteId) return;
const menu = new Menu()
menu.append(new MenuItem({label: _('Attach file'), click: async () => {
const filePaths = bridge().showOpenDialog({
properties: ['openFile', 'createDirectory'],
});
if (!filePaths || !filePaths.length) return;
await this.saveIfNeeded();
const note = await Note.load(noteId);
const newNote = await shim.attachFileToNote(note, filePaths[0]);
this.setState({
note: newNote,
lastSavedNote: Object.assign({}, newNote),
});
}}));
menu.popup(bridge().window());
}
render() {
const style = this.props.style;
const note = this.state.note;
@@ -307,21 +336,28 @@ class NoteTextComponent extends React.Component {
return <div style={emptyDivStyle}></div>
}
const titleEditorStyle = {
const titleBarStyle = {
width: innerWidth - rootStyle.paddingLeft,
height: 24,
display: 'block',
height: 30,
boxSizing: 'border-box',
marginTop: 10,
marginBottom: 10,
display: 'flex',
flexDirection: 'row',
};
const titleEditorStyle = {
display: 'flex',
flex: 1,
display: 'inline-block',
paddingTop: 5,
paddingBottom: 5,
paddingLeft: 8,
paddingRight: 8,
marginTop: 10,
marginBottom: 10,
marginRight: rootStyle.paddingLeft,
};
const bottomRowHeight = rootStyle.height - titleEditorStyle.height - titleEditorStyle.marginBottom - titleEditorStyle.marginTop;
const bottomRowHeight = rootStyle.height - titleBarStyle.height - titleBarStyle.marginBottom - titleBarStyle.marginTop;
const viewerStyle = {
width: Math.floor(innerWidth / 2),
@@ -382,6 +418,10 @@ class NoteTextComponent extends React.Component {
onChange={(event) => { this.title_changeText(event); }}
/>
const titleBarMenuButton = <IconButton style={{
display: 'flex',
}} iconName="fa-caret-down" theme={this.props.theme} onClick={() => { this.itemContextMenu() }} />
const viewer = <webview
style={viewerStyle}
nodeintegration="1"
@@ -421,7 +461,10 @@ class NoteTextComponent extends React.Component {
return (
<div style={rootStyle}>
{ titleEditor }
<div style={titleBarStyle}>
{ titleEditor }
{ titleBarMenuButton }
</div>
{ editor }
{ viewer }
</div>

View File

@@ -880,6 +880,17 @@
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
"dev": true
},
"caw": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/caw/-/caw-2.0.1.tgz",
"integrity": "sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA==",
"requires": {
"get-proxy": "2.1.0",
"isurl": "1.0.0",
"tunnel-agent": "0.6.0",
"url-to-options": "1.0.1"
}
},
"chalk": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
@@ -916,8 +927,7 @@
"chownr": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz",
"integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=",
"dev": true
"integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE="
},
"chromium-pickle-js": {
"version": "0.2.0",
@@ -975,6 +985,25 @@
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
"dev": true
},
"color": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color/-/color-2.0.1.tgz",
"integrity": "sha512-ubUCVVKfT7r2w2D3qtHakj8mbmKms+tThR8gI8zEYCbUBl8/voqFGt3kgBqGwXAopgXybnkuOq+qMYCRrp4cXw==",
"requires": {
"color-convert": "1.9.1",
"color-string": "1.5.2"
},
"dependencies": {
"color-convert": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz",
"integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==",
"requires": {
"color-name": "1.1.3"
}
}
}
},
"color-convert": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.0.tgz",
@@ -987,8 +1016,16 @@
"color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
"dev": true
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
},
"color-string": {
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.2.tgz",
"integrity": "sha1-JuRYFLw8mny9Z1FkikFDRRSnc6k=",
"requires": {
"color-name": "1.1.3",
"simple-swizzle": "0.2.2"
}
},
"colors": {
"version": "1.1.2",
@@ -1034,6 +1071,15 @@
"typedarray": "0.0.6"
}
},
"config-chain": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.11.tgz",
"integrity": "sha1-q6CXR9++TD5w52am5BWG4YWfxvI=",
"requires": {
"ini": "1.3.4",
"proto-list": "1.2.4"
}
},
"configstore": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.1.tgz",
@@ -1160,6 +1206,14 @@
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
"integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU="
},
"decompress-response": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz",
"integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=",
"requires": {
"mimic-response": "1.0.0"
}
},
"deep-extend": {
"version": "0.4.2",
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz",
@@ -1192,6 +1246,11 @@
"repeating": "2.0.1"
}
},
"detect-libc": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-0.2.0.tgz",
"integrity": "sha1-R/31ZzSKF+wl/L8LnkRjSKdvn7U="
},
"dmg-builder": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-2.1.5.tgz",
@@ -1813,6 +1872,24 @@
}
}
},
"follow-redirects": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.2.5.tgz",
"integrity": "sha512-lMhwQTryFbG+wYsAIEKC1Kf5IGDlVNnONRogIBllh7LLoV7pNIxW0z9fhjRar9NBql+hd2Y49KboVVNxf6GEfg==",
"requires": {
"debug": "2.6.9"
},
"dependencies": {
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"requires": {
"ms": "2.0.0"
}
}
}
},
"for-in": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
@@ -1913,6 +1990,14 @@
"integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=",
"dev": true
},
"get-proxy": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-2.1.0.tgz",
"integrity": "sha512-zmZIaQTWnNQb4R4fJUEp/FC51eZsc6EkErspy3xtIYStaq8EB/hDIWipxsal+E8rz0qD7f2sL/NA9Xee4RInJw==",
"requires": {
"npm-conf": "1.1.3"
}
},
"get-stdin": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
@@ -2052,6 +2137,19 @@
"integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
"dev": true
},
"has-symbol-support-x": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.1.tgz",
"integrity": "sha512-JkaetveU7hFbqnAC1EV1sF4rlojU2D4Usc5CmS69l6NfmPDnpnFUegzFg33eDkkpNCxZ0mQp65HwUDrNFS/8MA=="
},
"has-to-string-tag-x": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz",
"integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==",
"requires": {
"has-symbol-support-x": "1.4.1"
}
},
"has-unicode": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
@@ -2169,8 +2267,7 @@
"ini": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz",
"integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=",
"dev": true
"integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4="
},
"int64-buffer": {
"version": "0.1.9",
@@ -2320,6 +2417,11 @@
"integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=",
"dev": true
},
"is-object": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz",
"integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA="
},
"is-path-inside": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz",
@@ -2428,6 +2530,15 @@
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
"dev": true
},
"isurl": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz",
"integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==",
"requires": {
"has-to-string-tag-x": "1.4.1",
"is-object": "1.0.1"
}
},
"js-tokens": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
@@ -2782,8 +2893,7 @@
"mime": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/mime/-/mime-2.0.3.tgz",
"integrity": "sha512-TrpAd/vX3xaLPDgVRm6JkZwLR0KHfukMdU2wTEbqMDdCnY6Yo3mE+mjs9YE6oMNw2QRfXVeBEYpmpO94BIqiug==",
"dev": true
"integrity": "sha512-TrpAd/vX3xaLPDgVRm6JkZwLR0KHfukMdU2wTEbqMDdCnY6Yo3mE+mjs9YE6oMNw2QRfXVeBEYpmpO94BIqiug=="
},
"mime-db": {
"version": "1.30.0",
@@ -2805,6 +2915,11 @@
"integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=",
"dev": true
},
"mimic-response": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.0.tgz",
"integrity": "sha1-3z02Uqc/3ta5sLJBRub9BSNTRY4="
},
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
@@ -2820,11 +2935,33 @@
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
"dev": true
},
"minipass": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-2.2.1.tgz",
"integrity": "sha512-u1aUllxPJUI07cOqzR7reGmQxmCqlH88uIIsf6XZFEWgw7gXKpJdR+5R9Y3KEDmWYkdIz9wXZs3C0jOPxejk/Q==",
"requires": {
"yallist": "3.0.2"
},
"dependencies": {
"yallist": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz",
"integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k="
}
}
},
"minizlib": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.0.4.tgz",
"integrity": "sha512-sN4U9tIJtBRwKbwgFh9qJfrPIQ/GGTRr1MGqkgOeMTLy8/lM0FcWU//FqlnZ3Vb7gJ+Mxh3FOg1EklibdajbaQ==",
"requires": {
"minipass": "2.2.1"
}
},
"mkdirp": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
"dev": true,
"requires": {
"minimist": "0.0.8"
},
@@ -2832,8 +2969,7 @@
"minimist": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
"dev": true
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
}
}
},
@@ -2850,8 +2986,7 @@
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
"dev": true
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
},
"nan": {
"version": "2.7.0",
@@ -2950,6 +3085,22 @@
"remove-trailing-separator": "1.1.0"
}
},
"npm-conf": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz",
"integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==",
"requires": {
"config-chain": "1.1.11",
"pify": "3.0.0"
},
"dependencies": {
"pify": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
"integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY="
}
}
},
"npm-run-path": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
@@ -3035,7 +3186,6 @@
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"dev": true,
"requires": {
"wrappy": "1.0.2"
}
@@ -3367,6 +3517,11 @@
"object-assign": "4.1.1"
}
},
"proto-list": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
"integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk="
},
"pseudomap": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
@@ -3752,8 +3907,7 @@
"safe-buffer": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
"integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==",
"dev": true
"integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg=="
},
"sanitize-filename": {
"version": "1.6.1",
@@ -3773,8 +3927,7 @@
"semver": {
"version": "5.4.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz",
"integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==",
"dev": true
"integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg=="
},
"semver-diff": {
"version": "2.1.0",
@@ -3803,6 +3956,49 @@
"resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
"integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU="
},
"sharp": {
"version": "0.18.4",
"resolved": "https://registry.npmjs.org/sharp/-/sharp-0.18.4.tgz",
"integrity": "sha1-/jKcDwaJbCiqJDdt8f/wKuV/LTQ=",
"requires": {
"caw": "2.0.1",
"color": "2.0.1",
"detect-libc": "0.2.0",
"nan": "2.7.0",
"semver": "5.4.1",
"simple-get": "2.7.0",
"tar": "3.2.1"
},
"dependencies": {
"simple-get": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.7.0.tgz",
"integrity": "sha512-RkE9rGPHcxYZ/baYmgJtOSM63vH0Vyq+ma5TijBcLla41SWlh8t6XYIGMR/oeZcmr+/G8k+zrClkkVrtnQ0esg==",
"requires": {
"decompress-response": "3.3.0",
"once": "1.4.0",
"simple-concat": "1.0.0"
}
},
"tar": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/tar/-/tar-3.2.1.tgz",
"integrity": "sha512-ZSzds1E0IqutvMU8HxjMaU8eB7urw2fGwTq88ukDOVuUIh0656l7/P7LiVPxhO5kS4flcRJQk8USG+cghQbTUQ==",
"requires": {
"chownr": "1.0.1",
"minipass": "2.2.1",
"minizlib": "1.0.4",
"mkdirp": "0.5.1",
"yallist": "3.0.2"
}
},
"yallist": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz",
"integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k="
}
}
},
"shebang-command": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
@@ -3824,6 +4020,11 @@
"integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
"dev": true
},
"simple-concat": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz",
"integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY="
},
"simple-get": {
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/simple-get/-/simple-get-1.4.3.tgz",
@@ -3835,6 +4036,21 @@
"xtend": "4.0.1"
}
},
"simple-swizzle": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
"integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=",
"requires": {
"is-arrayish": "0.3.1"
},
"dependencies": {
"is-arrayish": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.1.tgz",
"integrity": "sha1-wt/DhquqDD4zxI2z/ocFnmkGXv0="
}
}
},
"single-line-log": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/single-line-log/-/single-line-log-1.1.2.tgz",
@@ -4952,7 +5168,6 @@
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
"integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
"dev": true,
"requires": {
"safe-buffer": "5.1.1"
}
@@ -5035,6 +5250,11 @@
"prepend-http": "1.0.4"
}
},
"url-to-options": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz",
"integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k="
},
"user-home": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz",
@@ -5145,8 +5365,7 @@
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"dev": true
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
},
"write-file-atomic": {
"version": "2.3.0",

View File

@@ -27,6 +27,7 @@
"dependencies": {
"app-module-path": "^2.2.0",
"electron-context-menu": "^0.9.1",
"follow-redirects": "^1.2.5",
"fs-extra": "^4.0.2",
"highlight.js": "^9.12.0",
"html-entities": "^1.2.1",
@@ -34,6 +35,7 @@
"markdown-it": "^8.4.0",
"marked": "^0.3.6",
"md5": "^2.2.1",
"mime": "^2.0.3",
"moment": "^2.19.1",
"node-fetch": "^1.7.3",
"promise": "^8.0.1",
@@ -43,6 +45,7 @@
"react-dom": "^16.0.0",
"react-redux": "^5.0.6",
"redux": "^3.7.2",
"sharp": "^0.18.4",
"sprintf-js": "^1.1.1",
"sqlite3": "^3.1.13",
"tcp-port-used": "^0.1.2"

View File

@@ -50,4 +50,10 @@ body, textarea {
.header .button {
border: 1px solid rgba(0,160,255,0);
}
.icon-button:hover {
background-color: rgba(0,0,0,0.05) !important;
border: 1px solid rgba(0,0,0,0.10);
border-radius: 5px;
}

View File

@@ -74,6 +74,12 @@ class MdToHtml {
this.loadedResources_[id] = {};
const resource = await Resource.load(id);
if (!resource) {
console.warn('Could not load resource ' + id);
return;
}
resource.base64 = await shim.readLocalFileBase64(Resource.fullPath(resource));
let newResources = Object.assign({}, this.loadedResources_);

View File

@@ -1,13 +1,13 @@
function dirname(path) {
if (!path) throw new Error('Path is empty');
let s = path.split('/');
let s = path.split(/\/|\\/);
s.pop();
return s.join('/');
}
function basename(path) {
if (!path) throw new Error('Path is empty');
let s = path.split('/');
let s = path.split(/\/|\\/);
return s[s.length - 1];
}

View File

@@ -53,6 +53,55 @@ function shimInit() {
return locale;
}
const resizeImage_ = async function(filePath, targetPath) {
const sharp = require('sharp');
const { Resource } = require('lib/models/resource.js');
return new Promise((resolve, reject) => {
sharp(filePath)
.resize(Resource.IMAGE_MAX_DIMENSION, Resource.IMAGE_MAX_DIMENSION)
.max()
.withoutEnlargement()
.toFile(targetPath, (err, info) => {
if (err) {
reject(err);
} else {
resolve(info);
}
});
});
}
shim.attachFileToNote = async function(note, filePath) {
const { Resource } = require('lib/models/resource.js');
const { uuid } = require('lib/uuid.js');
const { filename } = require('lib/path-utils.js');
const mime = require('mime/lite');
const { Note } = require('lib/models/note.js');
if (!(await fs.pathExists(filePath))) throw new Error(_('Cannot access %s', filePath));
let resource = Resource.new();
resource.id = uuid.create();
resource.mime = mime.getType(filePath);
resource.title = filename(filePath);
let targetPath = Resource.fullPath(resource);
if (resource.mime == 'image/jpeg' || resource.mime == 'image/jpg' || resource.mime == 'image/png') {
const result = await resizeImage_(filePath, targetPath);
} else {
await fs.copy(filePath, targetPath, { overwrite: true });
}
await Resource.save(resource, { isNew: true });
const newNote = Object.assign({}, note, {
body: note.body + "\n\n" + Resource.markdownTag(resource),
});
return await Note.save(newNote);
}
const nodeFetch = require('node-fetch');
shim.readLocalFileBase64 = (path) => {

View File

@@ -2,6 +2,7 @@ let shim = {};
shim.isNode = () => {
if (typeof process === 'undefined') return false;
if (shim.isElectron()) return true;
return process.title == 'node';
};
@@ -9,6 +10,26 @@ shim.isReactNative = () => {
return !shim.isNode();
};
// https://github.com/cheton/is-electron
shim.isElectron = () => {
// Renderer process
if (typeof window !== 'undefined' && typeof window.process === 'object' && window.process.type === 'renderer') {
return true;
}
// Main process
if (typeof process !== 'undefined' && typeof process.versions === 'object' && !!process.versions.electron) {
return true;
}
// Detect the user agent when the `nodeIntegration` option is set to true
if (typeof navigator === 'object' && typeof navigator.userAgent === 'string' && navigator.userAgent.indexOf('Electron') >= 0) {
return true;
}
return false;
}
shim.fetch = typeof fetch !== 'undefined' ? fetch : null;
shim.FormData = typeof FormData !== 'undefined' ? FormData : null;
shim.fs = null;
@@ -22,5 +43,6 @@ shim.clearInterval = function(id) {
return clearInterval(id);
}
shim.detectAndSetLocale = null;
shim.attachFileToNote = async (note, filePath) => {}
module.exports = { shim };

View File

@@ -17,6 +17,7 @@
"src/log.txt",
"*.min.js",
"ElectronClient/app/highlight/*.pack.js",
"app/css/font-awesome.min.css",
],
"folder_exclude_patterns":
[