Compare commits
5 Commits
75372ad0cc
...
2bba186c9e
Author | SHA1 | Date |
---|---|---|
Cohee | 2bba186c9e | |
Cohee | 61241df0d4 | |
Cohee | b6b9b542d7 | |
Cohee | 71f41d5233 | |
Cohee | a421af9ea9 |
|
@ -53,11 +53,11 @@ import { ScraperManager } from './scrapers.js';
|
|||
* @returns {Promise<string>} Converted file text
|
||||
*/
|
||||
|
||||
const fileSizeLimit = 1024 * 1024 * 10; // 10 MB
|
||||
const fileSizeLimit = 1024 * 1024 * 100; // 100 MB
|
||||
const ATTACHMENT_SOURCE = {
|
||||
GLOBAL: 'global',
|
||||
CHAT: 'chat',
|
||||
CHARACTER: 'character',
|
||||
CHAT: 'chat',
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -670,6 +670,55 @@ async function editAttachment(attachment, source, 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.
|
||||
* @param {FileAttachment} attachment Attachment to delete
|
||||
|
@ -765,6 +814,8 @@ async function openAttachmentManager() {
|
|||
attachmentTemplate.find('.viewAttachmentButton').on('click', () => openFilePopup(attachment));
|
||||
attachmentTemplate.find('.editAttachmentButton').on('click', () => editAttachment(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);
|
||||
}
|
||||
}
|
||||
|
@ -863,6 +914,50 @@ async function openAttachmentManager() {
|
|||
template.find('.chatAttachmentsName').text(chatName);
|
||||
}
|
||||
|
||||
function addDragAndDrop() {
|
||||
$(document.body).on('dragover', '.dialogue_popup', (event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
$(event.target).closest('.dialogue_popup').addClass('dragover');
|
||||
});
|
||||
|
||||
$(document.body).on('dragleave', '.dialogue_popup', (event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
$(event.target).closest('.dialogue_popup').removeClass('dragover');
|
||||
});
|
||||
|
||||
$(document.body).on('drop', '.dialogue_popup', async (event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
$(event.target).closest('.dialogue_popup').removeClass('dragover');
|
||||
|
||||
const files = Array.from(event.originalEvent.dataTransfer.files);
|
||||
let selectedTarget = ATTACHMENT_SOURCE.GLOBAL;
|
||||
const targets = getAvailableTargets();
|
||||
|
||||
const targetSelectTemplate = $(await renderExtensionTemplateAsync('attachments', 'files-dropped', { count: files.length, targets: targets }));
|
||||
targetSelectTemplate.find('.droppedFilesTarget').on('input', function () {
|
||||
selectedTarget = String($(this).val());
|
||||
});
|
||||
const result = await callGenericPopup(targetSelectTemplate, POPUP_TYPE.CONFIRM, '', { wide: false, large: false, okButton: 'Upload', cancelButton: 'Cancel' });
|
||||
if (result !== POPUP_RESULT.AFFIRMATIVE) {
|
||||
console.log('File upload cancelled');
|
||||
return;
|
||||
}
|
||||
for (const file of files) {
|
||||
await uploadFileAttachmentToServer(file, selectedTarget);
|
||||
}
|
||||
renderAttachments();
|
||||
});
|
||||
}
|
||||
|
||||
function removeDragAndDrop() {
|
||||
$(document.body).off('dragover', '.shadow_popup');
|
||||
$(document.body).off('dragleave', '.shadow_popup');
|
||||
$(document.body).off('drop', '.shadow_popup');
|
||||
}
|
||||
|
||||
let sortField = localStorage.getItem('DataBank_sortField') || 'created';
|
||||
let sortOrder = localStorage.getItem('DataBank_sortOrder') || 'desc';
|
||||
let filterString = '';
|
||||
|
@ -888,9 +983,32 @@ async function openAttachmentManager() {
|
|||
const cleanupFn = await renderButtons();
|
||||
await verifyAttachments();
|
||||
await renderAttachments();
|
||||
addDragAndDrop();
|
||||
await callGenericPopup(template, POPUP_TYPE.TEXT, '', { wide: true, large: true, okButton: 'Close' });
|
||||
|
||||
cleanupFn();
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
<div class="flex-container justifyCenter alignItemsBaseline">
|
||||
<span>Save <span class="droppedFilesCount">{{count}}</span> file(s) to...</span>
|
||||
<select class="droppedFilesTarget">
|
||||
{{#each targets}}
|
||||
<option value="{{this}}">{{this}}</option>
|
||||
{{/each}}
|
||||
</select>
|
||||
</div>
|
|
@ -1,6 +1,9 @@
|
|||
import { renderExtensionTemplateAsync } from '../../extensions.js';
|
||||
import { registerSlashCommand } from '../../slash-commands.js';
|
||||
|
||||
jQuery(async () => {
|
||||
const buttons = await renderExtensionTemplateAsync('attachments', 'buttons', {});
|
||||
$('#extensionsMenu').prepend(buttons);
|
||||
|
||||
registerSlashCommand('db', () => document.getElementById('manageAttachments')?.click(), ['databank', 'data-bank'], '– open the data bank', true, true);
|
||||
});
|
||||
|
|
|
@ -7,8 +7,13 @@
|
|||
<div data-i18n="These files will be available for extensions that support attachments (e.g. Vector Storage).">
|
||||
These files will be available for extensions that support attachments (e.g. Vector Storage).
|
||||
</div>
|
||||
<div data-i18n="Supported file types: Plain Text, PDF, Markdown, HTML, EPUB." class="marginTopBot5">
|
||||
Supported file types: Plain Text, PDF, Markdown, HTML, EPUB.
|
||||
<div class="marginTopBot5">
|
||||
<span data-i18n="Supported file types: Plain Text, PDF, Markdown, HTML, EPUB." >
|
||||
Supported file types: Plain Text, PDF, Markdown, HTML, EPUB.
|
||||
</span>
|
||||
<span data-i18n="Drag and drop files here to upload.">
|
||||
Drag and drop files here to upload.
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex-container marginTopBot5">
|
||||
<input type="search" id="attachmentSearch" class="attachmentSearch text_pole margin0 flex1" placeholder="Search...">
|
||||
|
@ -102,7 +107,9 @@
|
|||
<small class="attachmentListItemCreated"></small>
|
||||
<small class="attachmentListItemSize"></small>
|
||||
<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="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>
|
||||
</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>
|
|
@ -2262,6 +2262,11 @@ grammarly-extension {
|
|||
}
|
||||
}
|
||||
|
||||
.dialogue_popup.dragover {
|
||||
filter: brightness(1.1) saturate(1.1);
|
||||
outline: 3px dashed var(--SmartThemeBorderColor);
|
||||
}
|
||||
|
||||
#bgtest {
|
||||
display: none;
|
||||
width: 100vw;
|
||||
|
@ -4015,4 +4020,4 @@ body:not(.movingUI) .drawer-content.maximized {
|
|||
height: 100vh;
|
||||
z-index: 9999;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -511,7 +511,7 @@ async function tryAutoLogin(request) {
|
|||
const userHandles = await getAllUserHandles();
|
||||
if (userHandles.length === 1) {
|
||||
const user = await storage.getItem(toKey(userHandles[0]));
|
||||
if (!user.password) {
|
||||
if (user && !user.password) {
|
||||
request.session.handle = userHandles[0];
|
||||
return true;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue