From f2aeb11b0733957d8d77d7038daa3ae88442dd5b Mon Sep 17 00:00:00 2001 From: Rukario Date: Sun, 15 Dec 2024 15:12:58 -0800 Subject: [PATCH] feat: multiple popups in a hierarchy-like system (#7297) --- web/src/transmission.js | 64 +++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/web/src/transmission.js b/web/src/transmission.js index e44981e4e..24ca88fa5 100644 --- a/web/src/transmission.js +++ b/web/src/transmission.js @@ -31,8 +31,10 @@ export class Transmission extends EventTarget { // Initialize the helper classes this.action_manager = action_manager; + this.max_popups = 2; this.notifications = notifications; this.prefs = prefs; + this.popup = Array.from({ length: this.max_popups }); this.remote = new Remote(this); this.addEventListener('torrent-selection-changed', (event_) => @@ -49,8 +51,6 @@ export class Transmission extends EventTarget { this.refilterSoon = debounce(() => this._refilter(false)); this.refilterAllSoon = debounce(() => this._refilter(true)); - this.boundPopupCloseListener = this.popupCloseListener.bind(this); - this.isTouch = 'ontouchstart' in window; this.busyclick = false; @@ -125,18 +125,18 @@ export class Transmission extends EventTarget { this.setCurrentPopup(new AboutDialog(this.version_info)); break; case 'show-inspector': - if (this.popup instanceof Inspector) { - this.setCurrentPopup(null); + if (this.popup[0] instanceof Inspector) { + this.popup[0].close(); } else { - this.setCurrentPopup(new Inspector(this)); + this.setCurrentPopup(new Inspector(this), 0); } break; case 'show-move-dialog': this.setCurrentPopup(new MoveDialog(this, this.remote)); break; case 'show-overflow-menu': - if (this.popup instanceof OverflowMenu) { - this.setCurrentPopup(null); + if (this.popup[1] instanceof OverflowMenu) { + this.popup[1].close(); } else { this.setCurrentPopup( new OverflowMenu( @@ -149,7 +149,7 @@ export class Transmission extends EventTarget { } break; case 'show-preferences-dialog': - this.setCurrentPopup(new PrefsDialog(this, this.remote)); + this.setCurrentPopup(new PrefsDialog(this, this.remote), 0); break; case 'show-shortcuts-dialog': this.setCurrentPopup(new ShortcutsDialog(this.action_manager)); @@ -195,7 +195,7 @@ export class Transmission extends EventTarget { document.addEventListener('keyup', this._keyUp.bind(this)); e = document.querySelector('#torrent-container'); e.addEventListener('click', (e_) => { - if (this.popup && this.popup.name !== 'inspector') { + if (this.popup[this.max_popups - 1]) { this.setCurrentPopup(null); } if (e_.target === e_.currentTarget) { @@ -203,7 +203,7 @@ export class Transmission extends EventTarget { } }); e.addEventListener('dblclick', () => { - if (!this.popup || this.popup.name !== 'inspector') { + if (!this.popup[0] || this.popup[0].name !== 'inspector') { this.action_manager.click('show-inspector'); } }); @@ -263,8 +263,8 @@ export class Transmission extends EventTarget { clearTimeout(this.busyclick); this.busyclick = false; setTimeout(() => { - if (this.popup) { - this.popup.root.style.pointerEvents = 'auto'; + if (this.popup[1]) { + this.popup[1].root.style.pointerEvents = 'auto'; } }, 1); }); @@ -278,8 +278,8 @@ export class Transmission extends EventTarget { } else { this.elements.torrent_list.addEventListener('contextmenu', (event_) => { rightc(event_); - if (this.popup) { - this.popup.root.style.pointerEvents = 'auto'; + if (this.popup[1]) { + this.popup[1].root.style.pointerEvents = 'auto'; } }); } @@ -531,8 +531,8 @@ export class Transmission extends EventTarget { } const esc_key = keyCode === 27; // esc key pressed - if (esc_key && this.popup) { - this.setCurrentPopup(null); + if (esc_key && this.popup.some(Boolean)) { + this.setCurrentPopup(null, 0); event_.preventDefault(); return; } @@ -777,7 +777,7 @@ TODO: fix this when notifications get fixed const meta_key = event_.metaKey || event_.ctrlKey, { row } = event_.currentTarget; - if (this.popup && this.popup.name !== 'inspector') { + if (this.popup[this.max_popups - 1]) { this.setCurrentPopup(null); } @@ -1157,23 +1157,25 @@ TODO: fix this when notifications get fixed /// - popupCloseListener(event_) { - if (event_.target !== this.popup) { - throw new Error(event_); - } - this.popup.removeEventListener('close', this.boundPopupCloseListener); - delete this.popup; - } - - setCurrentPopup(popup) { - if (this.popup) { - this.popup.close(); + setCurrentPopup(popup, level = this.max_popups - 1) { + let index = level; + while (index < this.max_popups) { + if (this.popup[index]) { + this.popup[index].close(); + } + index++; } - this.popup = popup; + this.popup[level] = popup; - if (this.popup) { - this.popup.addEventListener('close', this.boundPopupCloseListener); + if (this.popup[level]) { + const listener = () => { + if (this.popup[level]) { + this.popup[level].removeEventListener('close', listener); + this.popup[level] = null; + } + }; + this.popup[level].addEventListener('close', listener); } } }