From 00f18043af21ba041d1c8320364ca21e64e91737 Mon Sep 17 00:00:00 2001 From: Andy Dixon Date: Wed, 15 Apr 2026 00:00:00 +0100 Subject: [PATCH] Fix tab close: replace confirm() with custom modal window.confirm() is silently blocked in WKWebView, causing the close handler to always abort. Use a custom modal-based confirmation instead. --- frontend/src/js/tabs.js | 45 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/frontend/src/js/tabs.js b/frontend/src/js/tabs.js index 6008adc..262a9cf 100644 --- a/frontend/src/js/tabs.js +++ b/frontend/src/js/tabs.js @@ -127,7 +127,7 @@ class TabManager { // Ask for confirmation if connected and the preference is set if (session && session.state === 'connected' && this.app.state.preferences.confirmOnDisconnect) { - const ok = confirm('Disconnect and close this session?'); + const ok = await this._confirmClose(sessionId); if (!ok) return; } @@ -143,6 +143,49 @@ class TabManager { this.removeTab(sessionId); } + /** + * Shows a confirmation modal before closing a connected session. + * @param {string} sessionId + * @returns {Promise} + * @private + */ + _confirmClose(sessionId) { + const createElement = window.NexusTerminal.createElement; + const label = this._tabLabel(sessionId); + return new Promise((resolve) => { + const backdrop = createElement('div', 'modal-backdrop'); + const modal = createElement('div', 'modal modal-sm'); + modal.innerHTML = ` + + + + `; + backdrop.appendChild(modal); + document.body.appendChild(backdrop); + requestAnimationFrame(() => backdrop.classList.add('is-visible')); + + const close = (val) => { + backdrop.classList.remove('is-visible'); + setTimeout(() => backdrop.remove(), 200); + resolve(val); + }; + modal.querySelector('.modal-close').addEventListener('click', () => close(false)); + modal.querySelector('.confirm-cancel').addEventListener('click', () => close(false)); + modal.querySelector('.confirm-ok').addEventListener('click', () => close(true)); + backdrop.addEventListener('click', (e) => { if (e.target === backdrop) close(false); }); + }); + } + /** * Renames a tab. * @param {string} sessionId