Add download and move for DB attachments
This commit is contained in:
parent
b6b9b542d7
commit
61241df0d4
|
@ -56,8 +56,8 @@ import { ScraperManager } from './scrapers.js';
|
||||||
const fileSizeLimit = 1024 * 1024 * 100; // 100 MB
|
const fileSizeLimit = 1024 * 1024 * 100; // 100 MB
|
||||||
const ATTACHMENT_SOURCE = {
|
const ATTACHMENT_SOURCE = {
|
||||||
GLOBAL: 'global',
|
GLOBAL: 'global',
|
||||||
CHAT: 'chat',
|
|
||||||
CHARACTER: 'character',
|
CHARACTER: 'character',
|
||||||
|
CHAT: 'chat',
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -670,6 +670,55 @@ async function editAttachment(attachment, source, callback) {
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Downloads an attachment to the user's device.
|
||||||
|
* @param {FileAttachment} attachment Attachment to download
|
||||||
|
*/
|
||||||
|
async function downloadAttachment(attachment) {
|
||||||
|
const fileText = attachment.text || (await getFileAttachment(attachment.url));
|
||||||
|
const blob = new Blob([fileText], { type: 'text/plain' });
|
||||||
|
const url = URL.createObjectURL(blob);
|
||||||
|
const a = document.createElement('a');
|
||||||
|
a.href = url;
|
||||||
|
a.download = attachment.name;
|
||||||
|
a.click();
|
||||||
|
URL.revokeObjectURL(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moves a file attachment to a different source.
|
||||||
|
* @param {FileAttachment} attachment Attachment to moves
|
||||||
|
* @param {string} source Source of the attachment
|
||||||
|
* @param {function} callback Success callback
|
||||||
|
* @returns {Promise<void>} A promise that resolves when the attachment is moved.
|
||||||
|
*/
|
||||||
|
async function moveAttachment(attachment, source, callback) {
|
||||||
|
let selectedTarget = source;
|
||||||
|
const targets = getAvailableTargets();
|
||||||
|
const template = $(await renderExtensionTemplateAsync('attachments', 'move-attachment', { name: attachment.name, targets }));
|
||||||
|
template.find('.moveAttachmentTarget').val(source).on('input', function () {
|
||||||
|
selectedTarget = String($(this).val());
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await callGenericPopup(template, POPUP_TYPE.CONFIRM, '', { wide: false, large: false, okButton: 'Move', cancelButton: 'Cancel' });
|
||||||
|
|
||||||
|
if (result !== POPUP_RESULT.AFFIRMATIVE) {
|
||||||
|
console.debug('Move attachment cancelled');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedTarget === source) {
|
||||||
|
console.debug('Move attachment cancelled: same source and target');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const content = await getFileAttachment(attachment.url);
|
||||||
|
const file = new File([content], attachment.name, { type: 'text/plain' });
|
||||||
|
await deleteAttachment(attachment, source, () => { }, false);
|
||||||
|
await uploadFileAttachmentToServer(file, selectedTarget);
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes an attachment from the server and the chat.
|
* Deletes an attachment from the server and the chat.
|
||||||
* @param {FileAttachment} attachment Attachment to delete
|
* @param {FileAttachment} attachment Attachment to delete
|
||||||
|
@ -765,6 +814,8 @@ async function openAttachmentManager() {
|
||||||
attachmentTemplate.find('.viewAttachmentButton').on('click', () => openFilePopup(attachment));
|
attachmentTemplate.find('.viewAttachmentButton').on('click', () => openFilePopup(attachment));
|
||||||
attachmentTemplate.find('.editAttachmentButton').on('click', () => editAttachment(attachment, source, renderAttachments));
|
attachmentTemplate.find('.editAttachmentButton').on('click', () => editAttachment(attachment, source, renderAttachments));
|
||||||
attachmentTemplate.find('.deleteAttachmentButton').on('click', () => deleteAttachment(attachment, source, renderAttachments));
|
attachmentTemplate.find('.deleteAttachmentButton').on('click', () => deleteAttachment(attachment, source, renderAttachments));
|
||||||
|
attachmentTemplate.find('.downloadAttachmentButton').on('click', () => downloadAttachment(attachment));
|
||||||
|
attachmentTemplate.find('.moveAttachmentButton').on('click', () => moveAttachment(attachment, source, renderAttachments));
|
||||||
template.find(sources[source]).append(attachmentTemplate);
|
template.find(sources[source]).append(attachmentTemplate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -882,19 +933,8 @@ async function openAttachmentManager() {
|
||||||
$(event.target).closest('.dialogue_popup').removeClass('dragover');
|
$(event.target).closest('.dialogue_popup').removeClass('dragover');
|
||||||
|
|
||||||
const files = Array.from(event.originalEvent.dataTransfer.files);
|
const files = Array.from(event.originalEvent.dataTransfer.files);
|
||||||
const targets = Object.values(ATTACHMENT_SOURCE);
|
|
||||||
|
|
||||||
const isNotCharacter = this_chid === undefined || selected_group;
|
|
||||||
const isNotInChat = getCurrentChatId() === undefined;
|
|
||||||
let selectedTarget = ATTACHMENT_SOURCE.GLOBAL;
|
let selectedTarget = ATTACHMENT_SOURCE.GLOBAL;
|
||||||
|
const targets = getAvailableTargets();
|
||||||
if (isNotCharacter) {
|
|
||||||
targets.splice(targets.indexOf(ATTACHMENT_SOURCE.CHARACTER), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isNotInChat) {
|
|
||||||
targets.splice(targets.indexOf(ATTACHMENT_SOURCE.CHAT), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const targetSelectTemplate = $(await renderExtensionTemplateAsync('attachments', 'files-dropped', { count: files.length, targets: targets }));
|
const targetSelectTemplate = $(await renderExtensionTemplateAsync('attachments', 'files-dropped', { count: files.length, targets: targets }));
|
||||||
targetSelectTemplate.find('.droppedFilesTarget').on('input', function () {
|
targetSelectTemplate.find('.droppedFilesTarget').on('input', function () {
|
||||||
|
@ -950,6 +990,27 @@ async function openAttachmentManager() {
|
||||||
removeDragAndDrop();
|
removeDragAndDrop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a list of available targets for attachments.
|
||||||
|
* @returns {string[]} List of available targets
|
||||||
|
*/
|
||||||
|
function getAvailableTargets() {
|
||||||
|
const targets = Object.values(ATTACHMENT_SOURCE);
|
||||||
|
|
||||||
|
const isNotCharacter = this_chid === undefined || selected_group;
|
||||||
|
const isNotInChat = getCurrentChatId() === undefined;
|
||||||
|
|
||||||
|
if (isNotCharacter) {
|
||||||
|
targets.splice(targets.indexOf(ATTACHMENT_SOURCE.CHARACTER), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNotInChat) {
|
||||||
|
targets.splice(targets.indexOf(ATTACHMENT_SOURCE.CHAT), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return targets;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs a known scraper on a source and saves the result as an attachment.
|
* Runs a known scraper on a source and saves the result as an attachment.
|
||||||
* @param {string} scraperId Id of the scraper
|
* @param {string} scraperId Id of the scraper
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<div class="flex-container justifyCenter alignItemsCenter">
|
<div class="flex-container justifyCenter alignItemsBaseline">
|
||||||
<span>Save <span class="droppedFilesCount">{{count}}</span> file(s) to...</span>
|
<span>Save <span class="droppedFilesCount">{{count}}</span> file(s) to...</span>
|
||||||
<select class="droppedFilesTarget">
|
<select class="droppedFilesTarget">
|
||||||
{{#each targets}}
|
{{#each targets}}
|
||||||
|
|
|
@ -102,7 +102,9 @@
|
||||||
<small class="attachmentListItemCreated"></small>
|
<small class="attachmentListItemCreated"></small>
|
||||||
<small class="attachmentListItemSize"></small>
|
<small class="attachmentListItemSize"></small>
|
||||||
<div class="viewAttachmentButton right_menu_button fa-solid fa-magnifying-glass" title="View attachment content"></div>
|
<div class="viewAttachmentButton right_menu_button fa-solid fa-magnifying-glass" title="View attachment content"></div>
|
||||||
|
<div class="moveAttachmentButton right_menu_button fa-solid fa-arrows-alt" title="Move attachment"></div>
|
||||||
<div class="editAttachmentButton right_menu_button fa-solid fa-pencil" title="Edit attachment"></div>
|
<div class="editAttachmentButton right_menu_button fa-solid fa-pencil" title="Edit attachment"></div>
|
||||||
|
<div class="downloadAttachmentButton right_menu_button fa-solid fa-download" title="Download attachment"></div>
|
||||||
<div class="deleteAttachmentButton right_menu_button fa-solid fa-trash" title="Delete attachment"></div>
|
<div class="deleteAttachmentButton right_menu_button fa-solid fa-trash" title="Delete attachment"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
<div class="flex-container justifyCenter alignItemsBaseline">
|
||||||
|
<span>Move <strong class="moveAttachmentName">{{name}}</strong> to...</span>
|
||||||
|
<select class="moveAttachmentTarget">
|
||||||
|
{{#each targets}}
|
||||||
|
<option value="{{this}}">{{this}}</option>
|
||||||
|
{{/each}}
|
||||||
|
</select>
|
||||||
|
</div>
|
Loading…
Reference in New Issue