diff --git a/src/public/app/services/froca.js b/src/public/app/services/froca.js index d494ac795..b06e2947e 100644 --- a/src/public/app/services/froca.js +++ b/src/public/app/services/froca.js @@ -315,14 +315,25 @@ class Froca { } /** @returns {Promise} */ - async getAttachment(attachmentId) { + async getAttachment(attachmentId, silentNotFoundError = false) { const attachment = this.attachments[attachmentId]; if (attachment) { return attachment; } // load all attachments for the given note even if one is requested, don't load one by one - const attachmentRows = await server.get(`attachments/${attachmentId}/all`); + let attachmentRows; + try { + attachmentRows = await server.get(`attachments/${attachmentId}/all`); + } + catch (e) { + if (silentNotFoundError) { + logInfo(`Attachment '${attachmentId} not found, but silentNotFoundError is enabled: ` + e.message); + } else { + throw e; + } + } + const attachments = this.processAttachmentRows(attachmentRows); if (attachments.length) { diff --git a/src/public/app/services/glob.js b/src/public/app/services/glob.js index d8547b778..f2ef87128 100644 --- a/src/public/app/services/glob.js +++ b/src/public/app/services/glob.js @@ -7,8 +7,6 @@ import froca from "./froca.js"; import linkService from "./link.js"; function setupGlobs() { - window.glob.PROFILING_LOG = false; - window.glob.isDesktop = utils.isDesktop; window.glob.isMobile = utils.isMobile; diff --git a/src/public/app/services/server.js b/src/public/app/services/server.js index 353298722..822a39bab 100644 --- a/src/public/app/services/server.js +++ b/src/public/app/services/server.js @@ -1,8 +1,6 @@ import utils from './utils.js'; import ValidationError from "./validation_error.js"; -const REQUEST_LOGGING_ENABLED = false; - async function getHeaders(headers) { const appContext = (await import('../components/app_context.js')).default; const activeNoteContext = appContext.tabManager ? appContext.tabManager.getActiveContext() : null; @@ -50,6 +48,21 @@ async function remove(url, componentId) { return await call('DELETE', url, null, {'trilium-component-id': componentId}); } +async function upload(url, fileToUpload) { + const formData = new FormData(); + formData.append('upload', fileToUpload); + + return await $.ajax({ + url: window.glob.baseApiUrl + url, + headers: await getHeaders(), + data: formData, + type: 'PUT', + timeout: 60 * 60 * 1000, + contentType: false, // NEEDED, DON'T REMOVE THIS + processData: false, // NEEDED, DON'T REMOVE THIS + }); +} + let i = 1; const reqResolves = {}; const reqRejects = {}; @@ -59,8 +72,6 @@ let maxKnownEntityChangeId = 0; async function call(method, url, data, headers = {}) { let resp; - const start = Date.now(); - headers = await getHeaders(headers); if (utils.isElectron()) { @@ -71,10 +82,6 @@ async function call(method, url, data, headers = {}) { reqResolves[requestId] = resolve; reqRejects[requestId] = reject; - if (REQUEST_LOGGING_ENABLED) { - console.log(utils.now(), `Request #${requestId} to ${method} ${url}`); - } - ipc.send('server-request', { requestId: requestId, headers: headers, @@ -88,12 +95,6 @@ async function call(method, url, data, headers = {}) { resp = await ajax(url, method, data, headers); } - const end = Date.now(); - - if (glob.PROFILING_LOG) { - console.log(`${method} ${url} took ${end - start}ms`); - } - const maxEntityChangeIdStr = resp.headers['trilium-max-entity-change-id']; if (maxEntityChangeIdStr && maxEntityChangeIdStr.trim()) { @@ -103,33 +104,6 @@ async function call(method, url, data, headers = {}) { return resp.body; } -async function reportError(method, url, statusCode, response) { - const toastService = (await import("./toast.js")).default; - let message = response; - - if (typeof response === 'string') { - try { - response = JSON.parse(response); - message = response.message; - } - catch (e) {} - } - - if ([400, 404].includes(statusCode) && response && typeof response === 'object') { - toastService.showError(message); - throw new ValidationError({ - requestUrl: url, - method, - statusCode, - ...response - }); - } else { - const title = `${statusCode} ${method} ${url}`; - toastService.showErrorTitleAndMessage(title, message); - toastService.throwError(`${title} - ${message}`); - } -} - function ajax(url, method, data, headers) { return new Promise((res, rej) => { const options = { @@ -175,24 +149,8 @@ if (utils.isElectron()) { const ipc = utils.dynamicRequire('electron').ipcRenderer; ipc.on('server-response', async (event, arg) => { - if (REQUEST_LOGGING_ENABLED) { - console.log(utils.now(), `Response #${arg.requestId}: ${arg.statusCode}`); - } - if (arg.statusCode >= 200 && arg.statusCode < 300) { - if (arg.headers['Content-Type'] === 'application/json') { - arg.body = JSON.parse(arg.body); - } - - if (!(arg.requestId in reqResolves)) { - // this can happen when reload happens between firing up the request and receiving the response - throw new Error(`Unknown requestId="${arg.requestId}"`); - } - - reqResolves[arg.requestId]({ - body: arg.body, - headers: arg.headers - }); + handleSuccessfulResponse(arg); } else { await reportError(arg.method, arg.url, arg.statusCode, arg.body); @@ -203,6 +161,49 @@ if (utils.isElectron()) { delete reqResolves[arg.requestId]; delete reqRejects[arg.requestId]; }); + + function handleSuccessfulResponse(arg) { + if (arg.headers['Content-Type'] === 'application/json') { + arg.body = JSON.parse(arg.body); + } + + if (!(arg.requestId in reqResolves)) { + // this can happen when reload happens between firing up the request and receiving the response + throw new Error(`Unknown requestId="${arg.requestId}"`); + } + + reqResolves[arg.requestId]({ + body: arg.body, + headers: arg.headers + }); + } +} + +async function reportError(method, url, statusCode, response) { + const toastService = (await import("./toast.js")).default; + let message = response; + + if (typeof response === 'string') { + try { + response = JSON.parse(response); + message = response.message; + } + catch (e) {} + } + + if ([400, 404].includes(statusCode) && response && typeof response === 'object') { + toastService.showError(message); + throw new ValidationError({ + requestUrl: url, + method, + statusCode, + ...response + }); + } else { + const title = `${statusCode} ${method} ${url}`; + toastService.showErrorTitleAndMessage(title, message); + toastService.throwError(`${title} - ${message}`); + } } export default { @@ -211,7 +212,7 @@ export default { put, patch, remove, - ajax, + upload, // don't remove, used from CKEditor image upload! getHeaders, getMaxKnownEntityChangeId: () => maxKnownEntityChangeId diff --git a/src/public/app/widgets/buttons/attachments_actions.js b/src/public/app/widgets/buttons/attachments_actions.js index d33a2884c..313d1926b 100644 --- a/src/public/app/widgets/buttons/attachments_actions.js +++ b/src/public/app/widgets/buttons/attachments_actions.js @@ -64,18 +64,7 @@ export default class AttachmentActionsWidget extends BasicWidget { const fileToUpload = this.$uploadNewRevisionInput[0].files[0]; // copy to allow reset below this.$uploadNewRevisionInput.val(''); - const formData = new FormData(); - formData.append('upload', fileToUpload); - - const result = await $.ajax({ - url: `${window.glob.baseApiUrl}attachments/${this.attachmentId}/file`, - headers: await server.getHeaders(), - data: formData, - type: 'PUT', - timeout: 60 * 60 * 1000, - contentType: false, // NEEDED, DON'T REMOVE THIS - processData: false, // NEEDED, DON'T REMOVE THIS - }); + const result = await server.upload(`attachments/${this.attachmentId}/file`, fileToUpload); if (result.uploaded) { toastService.showMessage("New attachment revision has been uploaded."); diff --git a/src/public/app/widgets/note_context_aware_widget.js b/src/public/app/widgets/note_context_aware_widget.js index ba548d2f9..753edfaa1 100644 --- a/src/public/app/widgets/note_context_aware_widget.js +++ b/src/public/app/widgets/note_context_aware_widget.js @@ -49,16 +49,8 @@ export default class NoteContextAwareWidget extends BasicWidget { async refresh() { if (this.isEnabled()) { - const start = Date.now(); - this.toggleInt(true); await this.refreshWithNote(this.note); - - const end = Date.now(); - - if (glob.PROFILING_LOG && end - start > 10) { - console.log(`Refresh of ${this.componentId} took ${end-start}ms`); - } } else { this.toggleInt(false); diff --git a/src/public/app/widgets/ribbon_widgets/file_properties.js b/src/public/app/widgets/ribbon_widgets/file_properties.js index ad842124a..1d543cef5 100644 --- a/src/public/app/widgets/ribbon_widgets/file_properties.js +++ b/src/public/app/widgets/ribbon_widgets/file_properties.js @@ -100,18 +100,7 @@ export default class FilePropertiesWidget extends NoteContextAwareWidget { const fileToUpload = this.$uploadNewRevisionInput[0].files[0]; // copy to allow reset below this.$uploadNewRevisionInput.val(''); - const formData = new FormData(); - formData.append('upload', fileToUpload); - - const result = await $.ajax({ - url: `${window.glob.baseApiUrl}notes/${this.noteId}/file`, - headers: await server.getHeaders(), - data: formData, - type: 'PUT', - timeout: 60 * 60 * 1000, - contentType: false, // NEEDED, DON'T REMOVE THIS - processData: false, // NEEDED, DON'T REMOVE THIS - }); + const result = await server.upload(`notes/${this.noteId}/file`, fileToUpload); if (result.uploaded) { toastService.showMessage("New file revision has been uploaded."); diff --git a/src/public/app/widgets/ribbon_widgets/image_properties.js b/src/public/app/widgets/ribbon_widgets/image_properties.js index e95d47075..a15f61d35 100644 --- a/src/public/app/widgets/ribbon_widgets/image_properties.js +++ b/src/public/app/widgets/ribbon_widgets/image_properties.js @@ -84,18 +84,7 @@ export default class ImagePropertiesWidget extends NoteContextAwareWidget { const fileToUpload = this.$uploadNewRevisionInput[0].files[0]; // copy to allow reset below this.$uploadNewRevisionInput.val(''); - const formData = new FormData(); - formData.append('upload', fileToUpload); - - const result = await $.ajax({ - url: `${window.glob.baseApiUrl}images/${this.noteId}`, - headers: await server.getHeaders(), - data: formData, - type: 'PUT', - timeout: 60 * 60 * 1000, - contentType: false, // NEEDED, DON'T REMOVE THIS - processData: false, // NEEDED, DON'T REMOVE THIS - }); + const result = await server.upload(`images/${this.noteId}`, fileToUpload); if (result.uploaded) { toastService.showMessage("New image revision has been uploaded."); diff --git a/src/public/app/widgets/type_widgets/attachment_detail.js b/src/public/app/widgets/type_widgets/attachment_detail.js index d336879de..93086bade 100644 --- a/src/public/app/widgets/type_widgets/attachment_detail.js +++ b/src/public/app/widgets/type_widgets/attachment_detail.js @@ -57,7 +57,7 @@ export default class AttachmentDetailTypeWidget extends TypeWidget { }) ); - const attachment = await froca.getAttachment(this.attachmentId); + const attachment = await froca.getAttachment(this.attachmentId, true); if (!attachment) { this.$wrapper.html("This attachment has been deleted.");