mirror of
https://github.com/zadam/trilium.git
synced 2025-06-06 18:08:33 +02:00
fixes attachments
This commit is contained in:
parent
9d52f80c2f
commit
df17840dbc
@ -99,7 +99,7 @@ function setupContextMenu() {
|
||||
searchEngineName = customSearchEngineName;
|
||||
searchEngineUrl = customSearchEngineUrl;
|
||||
} else {
|
||||
searchEngineName = "Duckduckgo";
|
||||
searchEngineName = "DuckDuckGo";
|
||||
searchEngineUrl = "https://duckduckgo.com/?q={keyword}";
|
||||
}
|
||||
|
||||
|
@ -122,6 +122,9 @@ async function handleMessage(event) {
|
||||
else if (message.type === 'api-log-messages') {
|
||||
appContext.triggerEvent("apiLogMessages", {noteId: message.noteId, messages: message.messages});
|
||||
}
|
||||
else if (message.type === 'toast') {
|
||||
toastService.showMessage(message.message);
|
||||
}
|
||||
}
|
||||
|
||||
let entityChangeIdReachedListeners = [];
|
||||
|
@ -147,7 +147,7 @@ export default class AttachmentDetailWidget extends BasicWidget {
|
||||
this.$wrapper.addClass("scheduled-for-deletion");
|
||||
|
||||
const scheduledSinceTimestamp = utils.parseDate(utcDateScheduledForErasureSince)?.getTime();
|
||||
const intervalMs = options.getInt('eraseUnusedImageAttachmentsAfterSeconds') * 1000;
|
||||
const intervalMs = options.getInt('eraseUnusedAttachmentsAfterSeconds') * 1000;
|
||||
const deletionTimestamp = scheduledSinceTimestamp + intervalMs;
|
||||
const willBeDeletedInMs = deletionTimestamp - Date.now();
|
||||
|
||||
@ -159,7 +159,7 @@ export default class AttachmentDetailWidget extends BasicWidget {
|
||||
$deletionWarning.text(`This attachment will be deleted soon`);
|
||||
}
|
||||
|
||||
$deletionWarning.append(", because the image attachment is not used. To prevent deletion, add the image back into the note.");
|
||||
$deletionWarning.append(", because the attachment is not linked in the note's content. To prevent deletion, add the attachment link back into the content.");
|
||||
} else {
|
||||
this.$wrapper.removeClass("scheduled-for-deletion");
|
||||
$deletionWarning.hide();
|
||||
@ -198,8 +198,6 @@ export default class AttachmentDetailWidget extends BasicWidget {
|
||||
if (attachmentChange.isDeleted) {
|
||||
this.toggleInt(false);
|
||||
} else {
|
||||
this.attachment = await server.get(`attachments/${this.attachment.attachmentId}`);
|
||||
|
||||
this.refresh();
|
||||
}
|
||||
}
|
||||
|
@ -6,10 +6,10 @@ const TPL = `
|
||||
<div class="options-section">
|
||||
<h4>Attachment erasure timeout</h4>
|
||||
|
||||
<p>Attachment images get automatically deleted (and erased) if they are not referenced by their note anymore after a defined time out.</p>
|
||||
<p>Attachments get automatically deleted (and erased) if they are not referenced by their note anymore after a defined time out.</p>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Erase image attachments after X seconds of not being used in its note</label>
|
||||
<label>Erase attachments after X seconds of not being used in its note</label>
|
||||
<input class="erase-unused-attachments-after-time-in-seconds form-control" type="number" min="0">
|
||||
</div>
|
||||
|
||||
@ -22,17 +22,17 @@ export default class AttachmentErasureTimeoutOptions extends OptionsWidget {
|
||||
doRender() {
|
||||
this.$widget = $(TPL);
|
||||
this.$eraseUnusedAttachmentsAfterTimeInSeconds = this.$widget.find(".erase-unused-attachments-after-time-in-seconds");
|
||||
this.$eraseUnusedAttachmentsAfterTimeInSeconds.on('change', () => this.updateOption('eraseUnusedImageAttachmentsAfterSeconds', this.$eraseUnusedAttachmentsAfterTimeInSeconds.val()));
|
||||
this.$eraseUnusedAttachmentsAfterTimeInSeconds.on('change', () => this.updateOption('eraseUnusedAttachmentsAfterSeconds', this.$eraseUnusedAttachmentsAfterTimeInSeconds.val()));
|
||||
|
||||
this.$eraseUnusedAttachmentsNowButton = this.$widget.find(".erase-unused-attachments-now-button");
|
||||
this.$eraseUnusedAttachmentsNowButton.on('click', () => {
|
||||
server.post('notes/erase-unused-attachments-now').then(() => {
|
||||
toastService.showMessage("Unused image attachments have been erased.");
|
||||
toastService.showMessage("Unused attachments have been erased.");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async optionsLoaded(options) {
|
||||
this.$eraseUnusedAttachmentsAfterTimeInSeconds.val(options.eraseUnusedImageAttachmentsAfterSeconds);
|
||||
this.$eraseUnusedAttachmentsAfterTimeInSeconds.val(options.eraseUnusedAttachmentsAfterSeconds);
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ const TPL = `
|
||||
<select class="predefined-search-engine-select form-control">
|
||||
<option value="Bing">Bing</option>
|
||||
<option value="Baidu">Baidu</option>
|
||||
<option value="Duckduckgo">Duckduckgo</option>
|
||||
<option value="DuckDuckGo">Duckduckgo</option>
|
||||
<option value="Google">Google</option>
|
||||
</select>
|
||||
</div>
|
||||
@ -39,7 +39,7 @@ const TPL = `
|
||||
const SEARCH_ENGINES = {
|
||||
"Bing": "https://www.bing.com/search?q={keyword}",
|
||||
"Baidu": "https://www.baidu.com/s?wd={keyword}",
|
||||
"Duckduckgo": "https://duckduckgo.com/?q={keyword}",
|
||||
"DuckDuckGo": "https://duckduckgo.com/?q={keyword}",
|
||||
"Google": "https://www.google.com/search?q={keyword}",
|
||||
}
|
||||
|
||||
|
@ -62,7 +62,7 @@ const ALLOWED_OPTIONS = new Set([
|
||||
'minTocHeadings',
|
||||
'checkForUpdates',
|
||||
'disableTray',
|
||||
'eraseUnusedImageAttachmentsAfterSeconds',
|
||||
'eraseUnusedAttachmentsAfterSeconds',
|
||||
'disableTray',
|
||||
'customSearchEngineName',
|
||||
'customSearchEngineUrl',
|
||||
|
@ -21,6 +21,7 @@ const htmlSanitizer = require("./html_sanitizer");
|
||||
const ValidationError = require("../errors/validation_error");
|
||||
const noteTypesService = require("./note_types");
|
||||
const fs = require("fs");
|
||||
const ws = require("./ws.js");
|
||||
|
||||
/** @param {BNote} parentNote */
|
||||
function getNewNotePosition(parentNote) {
|
||||
@ -333,29 +334,34 @@ function protectNote(note, protect) {
|
||||
}
|
||||
|
||||
function checkImageAttachments(note, content) {
|
||||
const re = /src="[^"]*api\/attachments\/([a-zA-Z0-9_]+)\/image/g;
|
||||
const foundAttachmentIds = new Set();
|
||||
let match;
|
||||
|
||||
while (match = re.exec(content)) {
|
||||
const imgRegExp = /src="[^"]*api\/attachments\/([a-zA-Z0-9_]+)\/image/g;
|
||||
while (match = imgRegExp.exec(content)) {
|
||||
foundAttachmentIds.add(match[1]);
|
||||
}
|
||||
|
||||
const imageAttachments = note.getAttachmentByRole('image');
|
||||
const linkRegExp = /href="[^"]+attachmentId=([a-zA-Z0-9_]+)/g;
|
||||
while (match = linkRegExp.exec(content)) {
|
||||
foundAttachmentIds.add(match[1]);
|
||||
}
|
||||
|
||||
for (const attachment of imageAttachments) {
|
||||
const imageInContent = foundAttachmentIds.has(attachment.attachmentId);
|
||||
const attachments = note.getAttachments();
|
||||
|
||||
if (attachment.utcDateScheduledForErasureSince && imageInContent) {
|
||||
for (const attachment of attachments) {
|
||||
const attachmentInContent = foundAttachmentIds.has(attachment.attachmentId);
|
||||
|
||||
if (attachment.utcDateScheduledForErasureSince && attachmentInContent) {
|
||||
attachment.utcDateScheduledForErasureSince = null;
|
||||
attachment.save();
|
||||
} else if (!attachment.utcDateScheduledForErasureSince && !imageInContent) {
|
||||
} else if (!attachment.utcDateScheduledForErasureSince && !attachmentInContent) {
|
||||
attachment.utcDateScheduledForErasureSince = dateUtils.utcNowDateTime();
|
||||
attachment.save();
|
||||
}
|
||||
}
|
||||
|
||||
const existingAttachmentIds = new Set(imageAttachments.map(att => att.attachmentId));
|
||||
const existingAttachmentIds = new Set(attachments.map(att => att.attachmentId));
|
||||
const unknownAttachmentIds = Array.from(foundAttachmentIds).filter(foundAttId => !existingAttachmentIds.has(foundAttId));
|
||||
const unknownAttachments = becca.getAttachments(unknownAttachmentIds);
|
||||
|
||||
@ -366,6 +372,9 @@ function checkImageAttachments(note, content) {
|
||||
newAttachment.setContent(unknownAttachment.getContent(), { forceSave: true });
|
||||
|
||||
content = content.replace(`api/attachments/${unknownAttachment.attachmentId}/image`, `api/attachments/${newAttachment.attachmentId}/image`);
|
||||
content = content.replace(`attachmentId=${unknownAttachment.attachmentId}`, `attachmentId=${newAttachment.attachmentId}`);
|
||||
|
||||
ws.sendMessageToAllClients({ type: 'toast', message: `Attachment '${newAttachment.title}' has been copied to note '${note.title}'.`});
|
||||
|
||||
log.info(`Copied attachment '${unknownAttachment.attachmentId}' to new '${newAttachment.attachmentId}'`);
|
||||
}
|
||||
@ -1077,12 +1086,12 @@ function getNoteIdMapping(origNote) {
|
||||
return noteIdMapping;
|
||||
}
|
||||
|
||||
function eraseScheduledAttachments(eraseUnusedImageAttachmentsAfterSeconds = null) {
|
||||
if (eraseUnusedImageAttachmentsAfterSeconds === null) {
|
||||
eraseUnusedImageAttachmentsAfterSeconds = optionService.getOptionInt('eraseUnusedImageAttachmentsAfterSeconds');
|
||||
function eraseScheduledAttachments(eraseUnusedAttachmentsAfterSeconds = null) {
|
||||
if (eraseUnusedAttachmentsAfterSeconds === null) {
|
||||
eraseUnusedAttachmentsAfterSeconds = optionService.getOptionInt('eraseUnusedAttachmentsAfterSeconds');
|
||||
}
|
||||
|
||||
const cutOffDate = dateUtils.utcDateTimeStr(new Date(Date.now() - (eraseUnusedImageAttachmentsAfterSeconds * 1000)));
|
||||
const cutOffDate = dateUtils.utcDateTimeStr(new Date(Date.now() - (eraseUnusedAttachmentsAfterSeconds * 1000)));
|
||||
const attachmentIdsToErase = sql.getColumn('SELECT attachmentId FROM attachments WHERE utcDateScheduledForErasureSince < ?', [cutOffDate]);
|
||||
|
||||
eraseAttachments(attachmentIdsToErase);
|
||||
|
@ -88,9 +88,9 @@ const defaultOptions = [
|
||||
{ name: 'minTocHeadings', value: '5', isSynced: true },
|
||||
{ name: 'checkForUpdates', value: 'true', isSynced: true },
|
||||
{ name: 'disableTray', value: 'false', isSynced: false },
|
||||
{ name: 'eraseUnusedImageAttachmentsAfterSeconds', value: '86400', isSynced: false },
|
||||
{ name: 'customSearchEngineName', value: 'Duckduckgo', isSynced: false },
|
||||
{ name: 'customSearchEngineUrl', value: 'https://duckduckgo.com/?q={keyword}', isSynced: false },
|
||||
{ name: 'eraseUnusedAttachmentsAfterSeconds', value: '2592000', isSynced: true },
|
||||
{ name: 'customSearchEngineName', value: 'DuckDuckGo', isSynced: true },
|
||||
{ name: 'customSearchEngineUrl', value: 'https://duckduckgo.com/?q={keyword}', isSynced: true },
|
||||
];
|
||||
|
||||
function initStartupOptions() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user