From bc9c84ebefb6c4cbb762ca803aa97126b84603da Mon Sep 17 00:00:00 2001
From: tijmen
Date: Tue, 6 Oct 2026 11:33:07 +0200
Subject: [PATCH 1/3] replace thickbox with browser dialog
---
src/class-tiny-plugin.php | 1 -
src/css/admin.css | 39 +++++++++-
src/js/admin.js | 102 ++++++++++++--------------
src/views/compress-details-backup.php | 6 +-
src/views/compress-details.php | 16 +++-
test/integration/backup.spec.ts | 6 +-
test/integration/compression.spec.ts | 4 +-
test/integration/conversion.spec.ts | 2 +-
8 files changed, 102 insertions(+), 74 deletions(-)
diff --git a/src/class-tiny-plugin.php b/src/class-tiny-plugin.php
index 735d8328..38e79a0a 100644
--- a/src/class-tiny-plugin.php
+++ b/src/class-tiny-plugin.php
@@ -210,7 +210,6 @@ public function admin_init() {
$this->tiny_compatibility();
- add_thickbox();
Tiny_Logger::init();
}
diff --git a/src/css/admin.css b/src/css/admin.css
index bad18a87..cfaa00ba 100644
--- a/src/css/admin.css
+++ b/src/css/admin.css
@@ -444,10 +444,6 @@ input[type=number][name*="tinypng_resize_original"] {
padding: 8px 10px;
}
-.tiny-compress-images .modal {
- display: none;
-}
-
.tiny-compress-images h4 {
margin: 5px 0;
}
@@ -490,6 +486,36 @@ fieldset.tinypng_convert_fields[disabled] {
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.3);
}
+.tiny-dialog::backdrop {
+ background: rgba(0, 0, 0, 0.7);
+}
+
+.tiny-details-dialog {
+ box-sizing: border-box;
+ width: min(700px, calc(100vw - 32px));
+ max-height: calc(100vh - 64px);
+ overflow: auto;
+ text-align: left;
+ white-space: normal;
+}
+
+.tiny-dialog-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ gap: 10px;
+}
+
+.tiny-dialog-close {
+ color: #646970;
+ cursor: pointer;
+}
+
+.tiny-dialog-close:hover,
+.tiny-dialog-close:focus {
+ color: #135e96;
+}
+
.tiny-dialog-error {
color: #dc3232;
}
@@ -500,6 +526,11 @@ fieldset.tinypng_convert_fields[disabled] {
justify-content: flex-end;
}
+/* Overrides .tiny-compress-images span.spinner; admin.js shows it while busy. */
+.tiny-dialog-actions span.spinner {
+ visibility: hidden;
+}
+
.tiny-dialog-title {
font-size: 1.3rem;
}
diff --git a/src/js/admin.js b/src/js/admin.js
index 9f4ccdbe..9430368e 100644
--- a/src/js/admin.js
+++ b/src/js/admin.js
@@ -13,69 +13,57 @@
jQuery(document).on('click', 'a[data-dialog-id]', function (e) {
e.preventDefault();
- const trigger = jQuery(e.currentTarget);
- const dialogID = trigger.data('dialog-id');
- if (!dialogID) {
- return;
+ const dialog = document.getElementById(jQuery(e.currentTarget).data('dialog-id'));
+ if (dialog) {
+ dialog.showModal();
}
+ });
+
+ jQuery(document).on('click', '[data-dialog-close]', function (e) {
+ e.currentTarget.closest('dialog').close();
+ });
- const dialog = document.getElementById(dialogID);
- if (!dialog) {
+ jQuery(document).on('click', 'dialog.tiny-dialog', function (e) {
+ const dialog = e.currentTarget;
+ if (e.target !== dialog) {
return;
}
+ const rect = dialog.getBoundingClientRect();
+ const inside = e.clientX >= rect.left && e.clientX <= rect.right &&
+ e.clientY >= rect.top && e.clientY <= rect.bottom;
+ if (!inside) {
+ dialog.close();
+ }
+ });
- const attachmentId = trigger.data('id');
- const container = document.querySelector(`[data-tiny-media-id="${attachmentId}"]`);
- const confirmButton = dialog.querySelector('button[value="submit"]');
-
- dialog.showModal();
-
- if (confirmButton) {
- let restoring = false;
- confirmButton.onclick = async () => {
- if (restoring) {
- return;
- }
- restoring = true;
- confirmButton.disabled = true;
-
- const spinner = dialog.querySelector('.spinner');
- let allowRetry = false;
- try {
- if (spinner) {
- spinner.style.visibility = 'visible';
- }
- const result = await restoreBackup(attachmentId);
- dialog.close();
-
- // refresh thickbox
- const modal = container.querySelector('.modal');
- const ajaxContent = document.getElementById('TB_ajaxContent');
- if (modal && ajaxContent) {
- modal.append(...ajaxContent.children);
- }
+ jQuery(document).on('click', '.tiny-restore-dialog button[value="submit"]', async function (e) {
+ const confirmButton = e.currentTarget;
+ const dialog = confirmButton.closest('dialog');
+ const detailsDialog = dialog.parentElement.closest('dialog');
+ const container = dialog.closest('.tiny-ajax-container');
+ const spinner = dialog.querySelector('.spinner');
- container.innerHTML = result;
- if (typeof tb_remove === 'function') {
- tb_remove();
- }
- } catch (err) {
- allowRetry = true;
- const errorEl = dialog.querySelector('.tiny-dialog-error');
- if (errorEl) {
- errorEl.textContent = err.responseText || 'Failed to restore backup.';
- errorEl.hidden = false;
- }
- } finally {
- restoring = false;
- if (allowRetry) {
- confirmButton.disabled = false;
- }
- if (spinner) {
- spinner.style.visibility = 'hidden';
- }
- }
- };
+ confirmButton.disabled = true;
+ if (spinner) {
+ spinner.style.visibility = 'visible';
+ }
+ try {
+ const result = await restoreBackup(container.dataset.tinyMediaId);
+ dialog.close();
+ if (detailsDialog) {
+ detailsDialog.close();
+ }
+ container.innerHTML = result;
+ } catch (err) {
+ const errorEl = dialog.querySelector('.tiny-dialog-error');
+ if (errorEl) {
+ errorEl.textContent = err.responseText || 'Failed to restore backup.';
+ errorEl.hidden = false;
+ }
+ confirmButton.disabled = false;
+ if (spinner) {
+ spinner.style.visibility = 'hidden';
+ }
}
});
diff --git a/src/views/compress-details-backup.php b/src/views/compress-details-backup.php
index f589eab0..4c5beb8a 100644
--- a/src/views/compress-details-backup.php
+++ b/src/views/compress-details-backup.php
@@ -22,18 +22,18 @@
-
+
-