From 8dd5d9321d940360a596cfd3f2654a737206b69e Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Sat, 27 Jul 2024 18:00:30 +0300 Subject: [PATCH] Fix gallery duplicate uploads --- public/global.d.ts | 2 + public/scripts/extensions/gallery/index.js | 88 +++++++++++++--------- 2 files changed, 56 insertions(+), 34 deletions(-) diff --git a/public/global.d.ts b/public/global.d.ts index af42edf00..1a5ee091b 100644 --- a/public/global.d.ts +++ b/public/global.d.ts @@ -16,6 +16,8 @@ declare var ai; // Jquery plugins interface JQuery { + nanogallery2(options?: any): JQuery; + nanogallery2(method: string, options?: any): JQuery; pagination(method: 'getCurrentPageNum'): number; pagination(method: string, options?: any): JQuery; pagination(options?: any): JQuery; diff --git a/public/scripts/extensions/gallery/index.js b/public/scripts/extensions/gallery/index.js index e853dadde..2e2d51a31 100644 --- a/public/scripts/extensions/gallery/index.js +++ b/public/scripts/extensions/gallery/index.js @@ -3,6 +3,7 @@ import { this_chid, characters, getRequestHeaders, + event_types, } from '../../../script.js'; import { groups, selected_group } from '../../group-chats.js'; import { loadFileToDocument, delay } from '../../utils.js'; @@ -25,6 +26,27 @@ let paginationVisiblePages = 10; let paginationMaxLinesPerPage = 2; let galleryMaxRows = 3; +$('body').on('click', '.dragClose', function () { + const relatedId = $(this).data('related-id'); // Get the ID of the related draggable + $(`body > .draggable[id="${relatedId}"]`).remove(); // Remove the associated draggable +}); + +const CUSTOM_GALLERY_REMOVED_EVENT = 'galleryRemoved'; + +const mutationObserver = new MutationObserver((mutations) => { + mutations.forEach((mutation) => { + mutation.removedNodes.forEach((node) => { + if (node instanceof HTMLElement && node.tagName === 'DIV' && node.id === 'gallery') { + eventSource.emit(CUSTOM_GALLERY_REMOVED_EVENT); + } + }); + }); +}); + +mutationObserver.observe(document.body, { + childList: true, + subtree: false, +}); /** * Retrieves a list of gallery items based on a given URL. This function calls an API endpoint @@ -59,7 +81,9 @@ async function getGalleryItems(url) { * @returns {Promise} - Promise representing the completion of the gallery initialization. */ async function initGallery(items, url) { + const nonce = `nonce-${Math.random().toString(36).substring(2, 15)}`; const gallery = $('#dragGallery'); + gallery.addClass(nonce); gallery.nanogallery2({ 'items': items, thumbnailWidth: 'auto', @@ -82,16 +106,26 @@ async function initGallery(items, url) { fnThumbnailOpen: viewWithDragbox, }); - - eventSource.on('resizeUI', function (elmntName) { - gallery.nanogallery2('resize'); - }); - - const dragDropHandler = new DragAndDropHandler('#dragGallery', async (files, event) => { + const dragDropHandler = new DragAndDropHandler(`#dragGallery.${nonce}`, async (files, event) => { let file = files[0]; uploadFile(file, url); // Added url parameter to know where to upload }); + const resizeHandler = function () { + gallery.nanogallery2('resize'); + }; + + eventSource.on('resizeUI', resizeHandler); + + eventSource.once(event_types.CHAT_CHANGED, function () { + gallery.closest('#gallery').remove(); + }); + + eventSource.once(CUSTOM_GALLERY_REMOVED_EVENT, function () { + gallery.nanogallery2('destroy'); + dragDropHandler.destroy(); + eventSource.removeListener('resizeUI', resizeHandler); + }); // Set dropzone height to be the same as the parent gallery.css('height', gallery.parent().css('height')); @@ -140,16 +174,10 @@ async function showCharGallery() { const items = await getGalleryItems(url); // if there already is a gallery, destroy it and place this one in its place - if ($('#dragGallery').length) { - $('#dragGallery').nanogallery2('destroy'); - initGallery(items, url); - } else { - makeMovable(); - setTimeout(async () => { - await initGallery(items, url); - }, 100); - } - + $('#dragGallery').closest('#gallery').remove(); + makeMovable(); + await delay(100); + await initGallery(items, url); } catch (err) { console.trace(); console.error(err); @@ -202,11 +230,11 @@ async function uploadFile(file, url) { toastr.success('File uploaded successfully. Saved at: ' + result.path); // Refresh the gallery - $('#dragGallery').nanogallery2('destroy'); // Destroy old gallery const newItems = await getGalleryItems(url); // Fetch the latest items - initGallery(newItems, url); // Reinitialize the gallery with new items and pass 'url' - - + $('#dragGallery').closest('#gallery').remove(); // Destroy old gallery + makeMovable(); + await delay(100); + await initGallery(newItems, url); // Reinitialize the gallery with new items and pass 'url' } catch (error) { console.error('There was an issue uploading the file:', error); @@ -273,11 +301,6 @@ function makeMovable(id = 'gallery') { e.preventDefault(); return false; }); - - $('body').on('click', '.dragClose', function () { - const relatedId = $(this).data('related-id'); // Get the ID of the related draggable - $(`#${relatedId}`).remove(); // Remove the associated draggable - }); } /** @@ -358,11 +381,6 @@ function makeDragImg(id, url) { } else { console.error('Failed to append the template content or retrieve the appended content.'); } - - $('body').on('click', '.dragClose', function () { - const relatedId = $(this).data('related-id'); // Get the ID of the related draggable - $(`#${relatedId}`).remove(); // Remove the associated draggable - }); } /** @@ -401,7 +419,8 @@ function viewWithDragbox(items) { // Registers a simple command for opening the char gallery. -SlashCommandParser.addCommandObject(SlashCommand.fromProps({ name: 'show-gallery', +SlashCommandParser.addCommandObject(SlashCommand.fromProps({ + name: 'show-gallery', aliases: ['sg'], callback: () => { showCharGallery(); @@ -409,7 +428,8 @@ SlashCommandParser.addCommandObject(SlashCommand.fromProps({ name: 'show-gallery }, helpString: 'Shows the gallery.', })); -SlashCommandParser.addCommandObject(SlashCommand.fromProps({ name: 'list-gallery', +SlashCommandParser.addCommandObject(SlashCommand.fromProps({ + name: 'list-gallery', aliases: ['lg'], callback: listGalleryCommand, returns: 'list of images', @@ -432,14 +452,14 @@ SlashCommandParser.addCommandObject(SlashCommand.fromProps({ name: 'list-gallery async function listGalleryCommand(args) { try { - let url = args.char ?? (args.group ? groups.find(it=>it.name == args.group)?.id : null) ?? (selected_group || this_chid); + let url = args.char ?? (args.group ? groups.find(it => it.name == args.group)?.id : null) ?? (selected_group || this_chid); if (!args.char && !args.group && !selected_group && this_chid) { const char = characters[this_chid]; url = char.avatar.replace('.png', ''); } const items = await getGalleryItems(url); - return JSON.stringify(items.map(it=>it.src)); + return JSON.stringify(items.map(it => it.src)); } catch (err) { console.trace();