mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 10:26:08 +01:00 
			
		
		
		
	improvements and logging to local image storage
This commit is contained in:
		| @@ -298,7 +298,7 @@ async function importEnex(taskContext, file, parentNote) { | |||||||
|         // save updated content with links to files/images |         // save updated content with links to files/images | ||||||
|         await noteEntity.setContent(content); |         await noteEntity.setContent(content); | ||||||
|  |  | ||||||
|         await noteService.scanForLinks(noteEntity.noteId); |         await noteService.scanForLinks(noteEntity); | ||||||
|  |  | ||||||
|         await updateDates(noteEntity.noteId, utcDateCreated, utcDateModified); |         await updateDates(noteEntity.noteId, utcDateCreated, utcDateModified); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -430,7 +430,7 @@ async function importTar(taskContext, fileBuffer, importRootNote) { | |||||||
|             } |             } | ||||||
|  |  | ||||||
|             for (const noteId in createdNoteIds) { // now the noteIds are unique |             for (const noteId in createdNoteIds) { // now the noteIds are unique | ||||||
|                 await noteService.scanForLinks(noteId); |                 await noteService.scanForLinks(await repository.getNotes(noteId)); | ||||||
|  |  | ||||||
|                 if (!metaFile) { |                 if (!metaFile) { | ||||||
|                     // if there's no meta file then the notes are created based on the order in that tar file but that |                     // if there's no meta file then the notes are created based on the order in that tar file but that | ||||||
|   | |||||||
| @@ -451,7 +451,7 @@ async function importZip(taskContext, fileBuffer, importRootNote) { | |||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     for (const noteId in createdNoteIds) { // now the noteIds are unique |     for (const noteId in createdNoteIds) { // now the noteIds are unique | ||||||
|         await noteService.scanForLinks(noteId); |         await noteService.scanForLinks(await repository.getNotes(noteId)); | ||||||
|  |  | ||||||
|         if (!metaFile) { |         if (!metaFile) { | ||||||
|             // if there's no meta file then the notes are created based on the order in that tar file but that |             // if there's no meta file then the notes are created based on the order in that tar file but that | ||||||
|   | |||||||
| @@ -124,6 +124,8 @@ async function createNewNote(params) { | |||||||
|  |  | ||||||
|     await copyChildAttributes(parentNote, note); |     await copyChildAttributes(parentNote, note); | ||||||
|  |  | ||||||
|  |     await scanForLinks(note); | ||||||
|  |  | ||||||
|     await triggerNoteTitleChanged(note); |     await triggerNoteTitleChanged(note); | ||||||
|     await triggerChildNoteCreated(note, parentNote); |     await triggerChildNoteCreated(note, parentNote); | ||||||
|  |  | ||||||
| @@ -265,24 +267,32 @@ function findRelationMapLinks(content, foundLinks) { | |||||||
| const imageUrlToNoteIdMapping = {}; | const imageUrlToNoteIdMapping = {}; | ||||||
|  |  | ||||||
| async function downloadImage(noteId, imageUrl) { | async function downloadImage(noteId, imageUrl) { | ||||||
|     const imageBuffer = await request.getImage(imageUrl); |     try { | ||||||
|     const parsedUrl = url.parse(imageUrl); |         const imageBuffer = await request.getImage(imageUrl); | ||||||
|     const title = path.basename(parsedUrl.pathname); |         const parsedUrl = url.parse(imageUrl); | ||||||
|  |         const title = path.basename(parsedUrl.pathname); | ||||||
|  |  | ||||||
|     const imageService = require('../services/image'); |         const imageService = require('../services/image'); | ||||||
|     const {note} = await imageService.saveImage(noteId, imageBuffer, title, true); |         const {note} = await imageService.saveImage(noteId, imageBuffer, title, true); | ||||||
|  |  | ||||||
|     await note.addLabel('imageUrl', imageUrl); |         await note.addLabel('imageUrl', imageUrl); | ||||||
|  |  | ||||||
|     imageUrlToNoteIdMapping[imageUrl] = note.noteId; |         imageUrlToNoteIdMapping[imageUrl] = note.noteId; | ||||||
|  |  | ||||||
|  |         log.info(`Download of ${imageUrl} succeeded and was saved as image note ${note.noteId}`); | ||||||
|  |     } | ||||||
|  |     catch (e) { | ||||||
|  |         log.error(`Downoad of ${imageUrl} for note ${noteId} failed with error: ${e.message} ${e.stack}`); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /** url => download promise */ | ||||||
| const downloadImagePromises = {}; | const downloadImagePromises = {}; | ||||||
|  |  | ||||||
| function replaceUrl(content, url, imageNote) { | function replaceUrl(content, url, imageNote) { | ||||||
|     const quoted = url.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); |     const quoted = url.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); | ||||||
|  |  | ||||||
|     return content.replace(new RegExp(quoted, "g"), `api/images/${imageNote.noteId}/${imageNote.title}`); |     return content.replace(new RegExp(`\s+src=[\"']${quoted}[\"']`, "g"), ` src="api/images/${imageNote.noteId}/${imageNote.title}"`); | ||||||
| } | } | ||||||
|  |  | ||||||
| async function downloadImages(noteId, content) { | async function downloadImages(noteId, content) { | ||||||
| @@ -294,6 +304,7 @@ async function downloadImages(noteId, content) { | |||||||
|  |  | ||||||
|         if (!url.startsWith('api/images/')) { |         if (!url.startsWith('api/images/')) { | ||||||
|             if (url in downloadImagePromises) { |             if (url in downloadImagePromises) { | ||||||
|  |                 // download is already in progress | ||||||
|                 continue; |                 continue; | ||||||
|             } |             } | ||||||
|  |  | ||||||
| @@ -321,12 +332,22 @@ async function downloadImages(noteId, content) { | |||||||
|                 continue; |                 continue; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  |             // this is done asynchronously, it would be too slow to wait for the download | ||||||
|  |             // given that save can be triggered very often | ||||||
|             downloadImagePromises[url] = downloadImage(noteId, url); |             downloadImagePromises[url] = downloadImage(noteId, url); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     Promise.all(Object.values(downloadImagePromises)).then(() => { |     Promise.all(Object.values(downloadImagePromises)).then(() => { | ||||||
|         setTimeout(async () => { |         setTimeout(async () => { | ||||||
|  |             // the normal expected flow of the offline image saving is that users will paste the image(s) | ||||||
|  |             // which will get asynchronously downloaded, during that time they keep editing the note | ||||||
|  |             // once the download is finished, the image note representing downloaded image will be used | ||||||
|  |             // to replace the IMG link. | ||||||
|  |             // However there's another flow where user pastes the image and leaves the note before the images | ||||||
|  |             // are downloaded and the IMG references are not updated. For this occassion we have this code | ||||||
|  |             // which upon the download of all the images will update the note if the links have not been fixed before | ||||||
|  |  | ||||||
|             const imageNotes = await repository.getNotes(Object.values(imageUrlToNoteIdMapping)); |             const imageNotes = await repository.getNotes(Object.values(imageUrlToNoteIdMapping)); | ||||||
|  |  | ||||||
|             const origNote = await repository.getNote(noteId); |             const origNote = await repository.getNote(noteId); | ||||||
| @@ -341,8 +362,11 @@ async function downloadImages(noteId, content) { | |||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  |             // update only if the links have not been already fixed. | ||||||
|             if (updatedContent !== origContent) { |             if (updatedContent !== origContent) { | ||||||
|                 await origNote.setContent(updatedContent); |                 await origNote.setContent(updatedContent); | ||||||
|  |  | ||||||
|  |                 console.log(`Fixed the image links for note ${noteId} to the offline saved.`); | ||||||
|             } |             } | ||||||
|         }, 5000); |         }, 5000); | ||||||
|     }); |     }); | ||||||
| @@ -632,8 +656,7 @@ async function getUndeletedParentBranches(noteId, deleteId) { | |||||||
|                       AND parentNote.isDeleted = 0`, [noteId, deleteId]); |                       AND parentNote.isDeleted = 0`, [noteId, deleteId]); | ||||||
| } | } | ||||||
|  |  | ||||||
| async function scanForLinks(noteId) { | async function scanForLinks(note) { | ||||||
|     const note = await repository.getNote(noteId); |  | ||||||
|     if (!note || !['text', 'relation-map'].includes(note.type)) { |     if (!note || !['text', 'relation-map'].includes(note.type)) { | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user