| 448 | 448 | } |
| 449 | 449 | |
| 450 | 450 | const formData = new FormData(form); |
| 451 | 451 | uploadBackgroundawait convertFileIfVideo(formData); |
| 452 | + await uploadBackground(formData); |
| 452 | 453 | form.reset(); |
| 453 | 454 | } |
| 454 | 455 | |
| 455 | 456 | /** |
| 457 | + * Converts a video file to an animated webp format if the file is a video. |
| 458 | + * @param {FormData} formData |
| 459 | + * @returns {Promise<void>} |
| 460 | + */ |
| 461 | +async function convertFileIfVideo(formData) { |
| 462 | + const file = formData.get('avatar'); |
| 463 | + if (!(file instanceof File)) { |
| 464 | + return; |
| 465 | + } |
| 466 | + if (!file.type.startsWith('video/')) { |
| 467 | + return; |
| 468 | + } |
| 469 | + if (typeof globalThis.convertVideoToAnimatedWebp !== 'function') { |
| 470 | + toastr.warning(t`Click here to install the Video Background Loader extension`, t`Video background uploads require a downloadable add-on`, { |
| 471 | + timeOut: 0, |
| 472 | + extendedTimeOut: 0, |
| 473 | + onclick: () => openThirdPartyExtensionMenu('https://github.com/SillyTavern/Extension-VideoBackgroundLoader'), |
| 474 | + }); |
| 475 | + return; |
| 476 | + } |
| 477 | + |
| 478 | + let toastMessage = jQuery(); |
| 479 | + try { |
| 480 | + toastMessage = toastr.info(t`Preparing video for upload. This may take several minutes.`, t`Please wait`, { timeOut: 0, extendedTimeOut: 0 }); |
| 481 | + const sourceBuffer = await file.arrayBuffer(); |
| 482 | + const convertedBuffer = await globalThis.convertVideoToAnimatedWebp({ buffer: new Uint8Array(sourceBuffer), name: file.name }); |
| 483 | + const convertedFileName = file.name.replace(/\.[^/.]+$/, '.webp'); |
| 484 | + const convertedFile = new File([convertedBuffer], convertedFileName, { type: 'image/webp' }); |
| 485 | + formData.set('avatar', convertedFile); |
| 486 | + toastMessage.remove(); |
| 487 | + } catch (error) { |
| 488 | + formData.delete('avatar'); |
| 489 | + toastMessage.remove(); |
| 490 | + console.error('Error converting video to animated webp:', error); |
| 491 | + toastr.error(t`Error converting video to animated webp`); |
| 492 | + } |
| 493 | +} |
| 494 | + |
| 495 | +/** |
| 456 | 496 | * Uploads a background to the server |
| 457 | 497 | * @param {FormData} formData |
| 458 | 498 | */ |
| 459 | 499 | async function uploadBackground(formData) { |
| 460 | | - jQuery.ajax({ |
| 500 | + try { |
| 461 | | - type: 'POST', |
| 501 | + if (!formData.has('avatar')) { |
| 462 | | - url: '/api/backgrounds/upload', |
| 502 | + console.log('No file provided. Background upload cancelled.'); |
| 463 | | - data: formData, |
| 503 | + return; |
| 464 | | - beforeSend: function () { |
| 504 | + } |
| 465 | | - }, |
| 505 | + |
| 466 | | - cache: false, |
| 506 | + const headers = getRequestHeaders(); |
| 467 | | - contentType: false, |
| 507 | + delete headers['Content-Type']; |
| 468 | | - processData: false, |
| 508 | + |
| 469 | | - success: async function (bg) { |
| 509 | + const response = await fetch('/api/backgrounds/upload', { |
| 470 | | - setBackground(bg, generateUrlParameter(bg, false)); |
| 510 | + method: 'POST', |
| 471 | | - await getBackgrounds(); |
| 511 | + headers: headers, |
| 472 | | - highlightNewBackground(bg); |
| 512 | + body: formData, |
| 473 | | - }, |
| 513 | + cache: 'no-cache', |
| 474 | | - error: function (jqXHR, exception) { |
| 514 | + }); |
| 475 | | - console.log(exception); |
| 515 | + |
| 476 | | - console.log(jqXHR); |
| 516 | + if (!response.ok) { |
| 477 | | - }, |
| 517 | + throw new Error('Failed to upload background'); |
| 478 | | - }); |
| 518 | + } |
| 519 | + |
| 520 | + const bg = await response.text(); |
| 521 | + setBackground(bg, generateUrlParameter(bg, false)); |
| 522 | + await getBackgrounds(); |
| 523 | + highlightNewBackground(bg); |
| 524 | + } catch (error) { |
| 525 | + console.error('Error uploading background:', error); |
| 526 | + } |
| 479 | 527 | } |
| 480 | 528 | |
| 481 | 529 | /** |