fixes attachments

This commit is contained in:
zadam 2023-05-29 13:02:25 +02:00
parent 9d52f80c2f
commit df17840dbc
8 changed files with 38 additions and 28 deletions

View File

@ -99,7 +99,7 @@ function setupContextMenu() {
searchEngineName = customSearchEngineName;
searchEngineUrl = customSearchEngineUrl;
} else {
searchEngineName = "Duckduckgo";
searchEngineName = "DuckDuckGo";
searchEngineUrl = "https://duckduckgo.com/?q={keyword}";
}

View File

@ -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 = [];

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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}",
}

View File

@ -62,7 +62,7 @@ const ALLOWED_OPTIONS = new Set([
'minTocHeadings',
'checkForUpdates',
'disableTray',
'eraseUnusedImageAttachmentsAfterSeconds',
'eraseUnusedAttachmentsAfterSeconds',
'disableTray',
'customSearchEngineName',
'customSearchEngineUrl',

View File

@ -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);

View File

@ -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() {