Fix gallery duplicate uploads
| @@ -16,6 +16,8 @@ declare var ai; | |||
| 16 | 16 | ||
| 17 | // Jquery plugins | 17 | // Jquery plugins |
| 18 | interface JQuery { | 18 | interface JQuery { |
| 19 | nanogallery2(options?: any): JQuery; | ||
| 20 | nanogallery2(method: string, options?: any): JQuery; | ||
| 19 | pagination(method: 'getCurrentPageNum'): number; | 21 | pagination(method: 'getCurrentPageNum'): number; |
| 20 | pagination(method: string, options?: any): JQuery; | 22 | pagination(method: string, options?: any): JQuery; |
| 21 | pagination(options?: any): JQuery; | 23 | pagination(options?: any): JQuery; |
| @@ -3,6 +3,7 @@ import { | |||
| 3 | this_chid, | 3 | this_chid, |
| 4 | characters, | 4 | characters, |
| 5 | getRequestHeaders, | 5 | getRequestHeaders, |
| 6 | event_types, | ||
| 6 | } from '../../../script.js'; | 7 | } from '../../../script.js'; |
| 7 | import { groups, selected_group } from '../../group-chats.js'; | 8 | import { groups, selected_group } from '../../group-chats.js'; |
| 8 | import { loadFileToDocument, delay } from '../../utils.js'; | 9 | import { loadFileToDocument, delay } from '../../utils.js'; |
| @@ -25,6 +26,27 @@ let paginationVisiblePages = 10; | |||
| 25 | let paginationMaxLinesPerPage = 2; | 26 | let paginationMaxLinesPerPage = 2; |
| 26 | let galleryMaxRows = 3; | 27 | let galleryMaxRows = 3; |
| 27 | 28 | ||
| 29 | $('body').on('click', '.dragClose', function () { | ||
| 30 | const relatedId = $(this).data('related-id'); // Get the ID of the related draggable | ||
| 31 | $(`body > .draggable[id="${relatedId}"]`).remove(); // Remove the associated draggable | ||
| 32 | }); | ||
| 33 | |||
| 34 | const CUSTOM_GALLERY_REMOVED_EVENT = 'galleryRemoved'; | ||
| 35 | |||
| 36 | const mutationObserver = new MutationObserver((mutations) => { | ||
| 37 | mutations.forEach((mutation) => { | ||
| 38 | mutation.removedNodes.forEach((node) => { | ||
| 39 | if (node instanceof HTMLElement && node.tagName === 'DIV' && node.id === 'gallery') { | ||
| 40 | eventSource.emit(CUSTOM_GALLERY_REMOVED_EVENT); | ||
| 41 | } | ||
| 42 | }); | ||
| 43 | }); | ||
| 44 | }); | ||
| 45 | |||
| 46 | mutationObserver.observe(document.body, { | ||
| 47 | childList: true, | ||
| 48 | subtree: false, | ||
| 49 | }); | ||
| 28 | 50 | ||
| 29 | /** | 51 | /** |
| 30 | * Retrieves a list of gallery items based on a given URL. This function calls an API endpoint | 52 | * 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) { | |||
| 59 | * @returns {Promise<void>} - Promise representing the completion of the gallery initialization. | 81 | * @returns {Promise<void>} - Promise representing the completion of the gallery initialization. |
| 60 | */ | 82 | */ |
| 61 | async function initGallery(items, url) { | 83 | async function initGallery(items, url) { |
| 84 | const nonce = `nonce-${Math.random().toString(36).substring(2, 15)}`; | ||
| 62 | const gallery = $('#dragGallery'); | 85 | const gallery = $('#dragGallery'); |
| 86 | gallery.addClass(nonce); | ||
| 63 | gallery.nanogallery2({ | 87 | gallery.nanogallery2({ |
| 64 | 'items': items, | 88 | 'items': items, |
| 65 | thumbnailWidth: 'auto', | 89 | thumbnailWidth: 'auto', |
| @@ -82,16 +106,26 @@ async function initGallery(items, url) { | |||
| 82 | fnThumbnailOpen: viewWithDragbox, | 106 | fnThumbnailOpen: viewWithDragbox, |
| 83 | }); | 107 | }); |
| 84 | 108 | ||
| 109 | const dragDropHandler = new DragAndDropHandler(`#dragGallery.${nonce}`, async (files, event) => { | ||
| 110 | let file = files[0]; | ||
| 111 | uploadFile(file, url); // Added url parameter to know where to upload | ||
| 112 | }); | ||
| 85 | 113 | ||
| 86 | eventSource.on('resizeUI', function (elmntName) { | 114 | const resizeHandler = function () { |
| 87 | gallery.nanogallery2('resize'); | 115 | gallery.nanogallery2('resize'); |
| 88 | }); | 116 | }; |
| 89 | 117 | ||
| 90 | const dragDropHandler = new DragAndDropHandler('#dragGallery', async (files, event) => { | 118 | eventSource.on('resizeUI', resizeHandler); |
| 91 | let file = files[0]; | 119 | |
| 92 | uploadFile(file, url); // Added url parameter to know where to upload | 120 | eventSource.once(event_types.CHAT_CHANGED, function () { |
| 121 | gallery.closest('#gallery').remove(); | ||
| 93 | }); | 122 | }); |
| 94 | 123 | ||
| 124 | eventSource.once(CUSTOM_GALLERY_REMOVED_EVENT, function () { | ||
| 125 | gallery.nanogallery2('destroy'); | ||
| 126 | dragDropHandler.destroy(); | ||
| 127 | eventSource.removeListener('resizeUI', resizeHandler); | ||
| 128 | }); | ||
| 95 | 129 | ||
| 96 | // Set dropzone height to be the same as the parent | 130 | // Set dropzone height to be the same as the parent |
| 97 | gallery.css('height', gallery.parent().css('height')); | 131 | gallery.css('height', gallery.parent().css('height')); |
| @@ -140,16 +174,10 @@ async function showCharGallery() { | |||
| 140 | 174 | ||
| 141 | const items = await getGalleryItems(url); | 175 | const items = await getGalleryItems(url); |
| 142 | // if there already is a gallery, destroy it and place this one in its place | 176 | // if there already is a gallery, destroy it and place this one in its place |
| 143 | if ($('#dragGallery').length) { | 177 | $('#dragGallery').closest('#gallery').remove(); |
| 144 | $('#dragGallery').nanogallery2('destroy'); | 178 | makeMovable(); |
| 145 | initGallery(items, url); | 179 | await delay(100); |
| 146 | } else { | 180 | await initGallery(items, url); |
| 147 | makeMovable(); | ||
| 148 | setTimeout(async () => { | ||
| 149 | await initGallery(items, url); | ||
| 150 | }, 100); | ||
| 151 | } | ||
| 152 | |||
| 153 | } catch (err) { | 181 | } catch (err) { |
| 154 | console.trace(); | 182 | console.trace(); |
| 155 | console.error(err); | 183 | console.error(err); |
| @@ -202,11 +230,11 @@ async function uploadFile(file, url) { | |||
| 202 | toastr.success('File uploaded successfully. Saved at: ' + result.path); | 230 | toastr.success('File uploaded successfully. Saved at: ' + result.path); |
| 203 | 231 | ||
| 204 | // Refresh the gallery | 232 | // Refresh the gallery |
| 205 | $('#dragGallery').nanogallery2('destroy'); // Destroy old gallery | ||
| 206 | const newItems = await getGalleryItems(url); // Fetch the latest items | 233 | const newItems = await getGalleryItems(url); // Fetch the latest items |
| 207 | initGallery(newItems, url); // Reinitialize the gallery with new items and pass 'url' | 234 | $('#dragGallery').closest('#gallery').remove(); // Destroy old gallery |
| 208 | 235 | makeMovable(); | |
| 209 | 236 | await delay(100); | |
| 237 | await initGallery(newItems, url); // Reinitialize the gallery with new items and pass 'url' | ||
| 210 | } catch (error) { | 238 | } catch (error) { |
| 211 | console.error('There was an issue uploading the file:', error); | 239 | console.error('There was an issue uploading the file:', error); |
| 212 | 240 | ||
| @@ -273,11 +301,6 @@ function makeMovable(id = 'gallery') { | |||
| 273 | e.preventDefault(); | 301 | e.preventDefault(); |
| 274 | return false; | 302 | return false; |
| 275 | }); | 303 | }); |
| 276 | |||
| 277 | $('body').on('click', '.dragClose', function () { | ||
| 278 | const relatedId = $(this).data('related-id'); // Get the ID of the related draggable | ||
| 279 | $(`#${relatedId}`).remove(); // Remove the associated draggable | ||
| 280 | }); | ||
| 281 | } | 304 | } |
| 282 | 305 | ||
| 283 | /** | 306 | /** |
| @@ -358,11 +381,6 @@ function makeDragImg(id, url) { | |||
| 358 | } else { | 381 | } else { |
| 359 | console.error('Failed to append the template content or retrieve the appended content.'); | 382 | console.error('Failed to append the template content or retrieve the appended content.'); |
| 360 | } | 383 | } |
| 361 | |||
| 362 | $('body').on('click', '.dragClose', function () { | ||
| 363 | const relatedId = $(this).data('related-id'); // Get the ID of the related draggable | ||
| 364 | $(`#${relatedId}`).remove(); // Remove the associated draggable | ||
| 365 | }); | ||
| 366 | } | 384 | } |
| 367 | 385 | ||
| 368 | /** | 386 | /** |
| @@ -401,7 +419,8 @@ function viewWithDragbox(items) { | |||
| 401 | 419 | ||
| 402 | 420 | ||
| 403 | // Registers a simple command for opening the char gallery. | 421 | // Registers a simple command for opening the char gallery. |
| 404 | SlashCommandParser.addCommandObject(SlashCommand.fromProps({ name: 'show-gallery', | 422 | SlashCommandParser.addCommandObject(SlashCommand.fromProps({ |
| 423 | name: 'show-gallery', | ||
| 405 | aliases: ['sg'], | 424 | aliases: ['sg'], |
| 406 | callback: () => { | 425 | callback: () => { |
| 407 | showCharGallery(); | 426 | showCharGallery(); |
| @@ -409,7 +428,8 @@ SlashCommandParser.addCommandObject(SlashCommand.fromProps({ name: 'show-gallery | |||
| 409 | }, | 428 | }, |
| 410 | helpString: 'Shows the gallery.', | 429 | helpString: 'Shows the gallery.', |
| 411 | })); | 430 | })); |
| 412 | SlashCommandParser.addCommandObject(SlashCommand.fromProps({ name: 'list-gallery', | 431 | SlashCommandParser.addCommandObject(SlashCommand.fromProps({ |
| 432 | name: 'list-gallery', | ||
| 413 | aliases: ['lg'], | 433 | aliases: ['lg'], |
| 414 | callback: listGalleryCommand, | 434 | callback: listGalleryCommand, |
| 415 | returns: 'list of images', | 435 | returns: 'list of images', |
| @@ -432,14 +452,14 @@ SlashCommandParser.addCommandObject(SlashCommand.fromProps({ name: 'list-gallery | |||
| 432 | 452 | ||
| 433 | async function listGalleryCommand(args) { | 453 | async function listGalleryCommand(args) { |
| 434 | try { | 454 | try { |
| 435 | let url = args.char ?? (args.group ? groups.find(it=>it.name == args.group)?.id : null) ?? (selected_group || this_chid); | 455 | let url = args.char ?? (args.group ? groups.find(it => it.name == args.group)?.id : null) ?? (selected_group || this_chid); |
| 436 | if (!args.char && !args.group && !selected_group && this_chid) { | 456 | if (!args.char && !args.group && !selected_group && this_chid) { |
| 437 | const char = characters[this_chid]; | 457 | const char = characters[this_chid]; |
| 438 | url = char.avatar.replace('.png', ''); | 458 | url = char.avatar.replace('.png', ''); |
| 439 | } | 459 | } |
| 440 | 460 | ||
| 441 | const items = await getGalleryItems(url); | 461 | const items = await getGalleryItems(url); |
| 442 | return JSON.stringify(items.map(it=>it.src)); | 462 | return JSON.stringify(items.map(it => it.src)); |
| 443 | 463 | ||
| 444 | } catch (err) { | 464 | } catch (err) { |
| 445 | console.trace(); | 465 | console.trace(); |