"open" action will save note to temp directory to try it then open with native application, #1304

This commit is contained in:
zadam 2020-10-13 22:50:45 +02:00
parent 04ea8dd4b3
commit 18cc9f2475
5 changed files with 86 additions and 39 deletions

77
package-lock.json generated
View File

@ -1,6 +1,6 @@
{
"name": "trilium",
"version": "0.44.5",
"version": "0.44.6",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@ -1409,6 +1409,15 @@
"path-is-absolute": "^1.0.0"
}
},
"rimraf": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
"optional": true,
"requires": {
"glob": "^7.1.3"
}
},
"tmp-promise": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-1.1.0.tgz",
@ -1417,6 +1426,17 @@
"requires": {
"bluebird": "^3.5.0",
"tmp": "0.1.0"
},
"dependencies": {
"tmp": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.1.0.tgz",
"integrity": "sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw==",
"optional": true,
"requires": {
"rimraf": "^2.6.3"
}
}
}
}
}
@ -4605,7 +4625,6 @@
"version": "7.1.6",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
"dev": true,
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
@ -8456,37 +8475,11 @@
"integrity": "sha1-9PrTM0R7wLB9TcjpIJ2POaisd+g="
},
"tmp": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.1.0.tgz",
"integrity": "sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw==",
"optional": true,
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz",
"integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==",
"requires": {
"rimraf": "^2.6.3"
},
"dependencies": {
"glob": {
"version": "7.1.4",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz",
"integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==",
"optional": true,
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.4",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
}
},
"rimraf": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
"optional": true,
"requires": {
"glob": "^7.1.3"
}
}
"rimraf": "^3.0.0"
}
},
"tmp-promise": {
@ -8496,6 +8489,26 @@
"optional": true,
"requires": {
"tmp": "0.1.0"
},
"dependencies": {
"rimraf": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
"optional": true,
"requires": {
"glob": "^7.1.3"
}
},
"tmp": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.1.0.tgz",
"integrity": "sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw==",
"optional": true,
"requires": {
"rimraf": "^2.6.3"
}
}
}
},
"to-object-path": {

View File

@ -67,6 +67,7 @@
"serve-favicon": "2.5.0",
"session-file-store": "1.4.0",
"striptags": "3.1.1",
"tmp": "^0.2.1",
"turndown": "6.0.0",
"turndown-plugin-gfm": "1.0.2",
"unescape": "1.0.1",

View File

@ -75,11 +75,17 @@ export default class FileTypeWidget extends TypeWidget {
this.$downloadButton.on('click', () => utils.download(this.getFileUrl()));
this.$openButton.on('click', () => {
this.$openButton.on('click', async () => {
if (utils.isElectron()) {
const open = utils.dynamicRequire("open");
const resp = await server.post("notes/" + this.noteId + "/saveToTmpDir");
open(this.getFileUrl(), {url: true});
const electron = utils.dynamicRequire('electron');
const res = await electron.shell.openPath(resp.tmpFilePath);
if (res) {
// fallback in case there's no default application for this file
open(this.getFileUrl(), {url: true});
}
}
else {
window.location.href = this.getFileUrl();

View File

@ -4,6 +4,8 @@ const protectedSessionService = require('../../services/protected_session');
const repository = require('../../services/repository');
const utils = require('../../services/utils');
const noteRevisionService = require('../../services/note_revisions');
const tmp = require('tmp');
const fs = require('fs');
function updateFile(req) {
const {noteId} = req.params;
@ -31,6 +33,12 @@ function updateFile(req) {
};
}
function getFilename(note) {
// (one) reason we're not using the originFileName (available as label) is that it's not
// available for older note revisions and thus would be inconsistent
return utils.formatDownloadTitle(note.title, note.type, note.mime);
}
function downloadNoteFile(noteId, res, contentDisposition = true) {
const note = repository.getNote(noteId);
@ -43,9 +51,7 @@ function downloadNoteFile(noteId, res, contentDisposition = true) {
}
if (contentDisposition) {
// (one) reason we're not using the originFileName (available as label) is that it's not
// available for older note revisions and thus would be inconsistent
const filename = utils.formatDownloadTitle(note.title, note.type, note.mime);
const filename = getFilename(note);
res.setHeader('Content-Disposition', utils.getContentDisposition(filename));
}
@ -67,9 +73,29 @@ function openFile(req, res) {
return downloadNoteFile(noteId, res, false);
}
function saveToTmpDir(req) {
const noteId = req.params.noteId;
const note = repository.getNote(noteId);
if (!note) {
return [404,`Note ${noteId} doesn't exist.`];
}
const tmpObj = tmp.fileSync({postfix: getFilename(note)});
fs.writeSync(tmpObj.fd, note.getContent());
fs.closeSync(tmpObj.fd);
return {
tmpFilePath: tmpObj.name
};
}
module.exports = {
updateFile,
openFile,
downloadFile,
downloadNoteFile
downloadNoteFile,
saveToTmpDir
};

View File

@ -171,6 +171,7 @@ function register(app) {
route(GET, '/api/notes/:noteId/download', [auth.checkApiAuthOrElectron], filesRoute.downloadFile);
// this "hacky" path is used for easier referencing of CSS resources
route(GET, '/api/notes/download/:noteId', [auth.checkApiAuthOrElectron], filesRoute.downloadFile);
apiRoute(POST, '/api/notes/:noteId/saveToTmpDir', filesRoute.saveToTmpDir);
apiRoute(GET, '/api/notes/:noteId/attributes', attributesRoute.getEffectiveNoteAttributes);
apiRoute(PUT, '/api/notes/:noteId/attributes', attributesRoute.updateNoteAttributes);