mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-11-03 19:52:20 +01:00
fix(modals): keep restored settings and theme windows open (#6924)
* fix(modals): keep restored settings and theme windows open * fix(theme): cancel closing on a rapid toggle reopen * test: isolate photo routing from external MCP registry state * fix(cache): preserve the upstream editor worker key format
This commit is contained in:
+1
-2
@@ -1319,8 +1319,7 @@ function initializeEventListeners() {
|
||||
const toolThemeBtn = el('tool-theme-btn');
|
||||
if (toolThemeBtn) {
|
||||
toolThemeBtn.addEventListener('click', () => {
|
||||
const tm = document.getElementById('theme-modal');
|
||||
if (tm) tm.classList.remove('hidden');
|
||||
themeModule.openPopup();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
// Own both completion paths of an animated close so neither can outlive it.
|
||||
const _pendingCloses = new WeakMap();
|
||||
|
||||
function cancelClose(modal) {
|
||||
const pending = _pendingCloses.get(modal);
|
||||
if (!pending) return;
|
||||
clearTimeout(pending.timer);
|
||||
pending.content.removeEventListener('animationend', pending.onEnd);
|
||||
pending.content.classList.remove('modal-closing');
|
||||
_pendingCloses.delete(modal);
|
||||
}
|
||||
|
||||
export function showModal(modal) {
|
||||
if (!modal) return;
|
||||
cancelClose(modal);
|
||||
modal.classList.remove('hidden');
|
||||
}
|
||||
|
||||
export function hideModal(modal) {
|
||||
if (!modal) return;
|
||||
cancelClose(modal);
|
||||
const content = modal.querySelector('.modal-content, .settings-modal-content');
|
||||
// A minimized window has no exit animation. Registering a listener here
|
||||
// would let its next entrance animation close the newly opened window.
|
||||
if (!content || modal.classList.contains('hidden')) {
|
||||
modal.classList.add('hidden');
|
||||
return;
|
||||
}
|
||||
const pending = { content, timer: null, onEnd: null };
|
||||
const finish = () => {
|
||||
if (_pendingCloses.get(modal) !== pending) return;
|
||||
cancelClose(modal);
|
||||
modal.classList.add('hidden');
|
||||
};
|
||||
pending.onEnd = event => {
|
||||
if (event.target === content) finish();
|
||||
};
|
||||
_pendingCloses.set(modal, pending);
|
||||
content.classList.add('modal-closing');
|
||||
content.addEventListener('animationend', pending.onEnd);
|
||||
pending.timer = setTimeout(finish, 250);
|
||||
}
|
||||
@@ -6,6 +6,8 @@
|
||||
|
||||
import { makeWindowDraggable } from '../windowDrag.js';
|
||||
import { clearDockSide } from '../modalSnap.js';
|
||||
import { toggle as restoreMinimizedModal } from '../modalManager.js';
|
||||
import { showModal, hideModal } from '../modalVisibility.js';
|
||||
|
||||
const _dragBound = new WeakSet();
|
||||
const _closeBound = new WeakSet();
|
||||
@@ -147,30 +149,16 @@ export function bindSettingsClose(modalEl, options = {}) {
|
||||
|
||||
export function showSettingsModal(modalEl) {
|
||||
if (!modalEl) return;
|
||||
if (restoreMinimizedModal(modalEl.id)) {
|
||||
showModal(modalEl);
|
||||
return;
|
||||
}
|
||||
if (modalEl.classList.contains('hidden')) {
|
||||
resetSettingsWindowPlacement(modalEl);
|
||||
}
|
||||
modalEl.classList.remove('hidden');
|
||||
showModal(modalEl);
|
||||
}
|
||||
|
||||
export function hideSettingsModal(modalEl) {
|
||||
if (!modalEl) return;
|
||||
|
||||
const content = modalEl.querySelector('.modal-content, .settings-modal-content');
|
||||
if (content && !content.classList.contains('modal-closing')) {
|
||||
content.classList.add('modal-closing');
|
||||
content.addEventListener('animationend', () => {
|
||||
modalEl.classList.add('hidden');
|
||||
content.classList.remove('modal-closing');
|
||||
}, { once: true });
|
||||
setTimeout(() => {
|
||||
if (!modalEl.classList.contains('hidden')) {
|
||||
modalEl.classList.add('hidden');
|
||||
content.classList.remove('modal-closing');
|
||||
}
|
||||
}, 250);
|
||||
return;
|
||||
}
|
||||
|
||||
modalEl.classList.add('hidden');
|
||||
hideModal(modalEl);
|
||||
}
|
||||
|
||||
+16
-16
@@ -7,6 +7,8 @@ import { initColorPickers, attachColorPicker } from './colorPicker.js?v=20260910
|
||||
import { hexToRgb } from './color/hex.js';
|
||||
import { makeWindowDraggable } from './windowDrag.js';
|
||||
import { snapModalToZone } from './tileManager.js?v=20260910responsivebounds1';
|
||||
import { toggle as restoreMinimizedModal } from './modalManager.js';
|
||||
import { showModal, hideModal } from './modalVisibility.js';
|
||||
|
||||
export const THEMES = {
|
||||
dark: { bg:'#282c34', fg:'#9cdef2', panel:'#111111', border:'#355a66', red:'#e06c75' },
|
||||
@@ -1570,31 +1572,29 @@ export function makeDraggable(el, handle) {
|
||||
}
|
||||
|
||||
// Toggle the popup
|
||||
export function openPopup() {
|
||||
const modal = document.getElementById('theme-modal');
|
||||
if (!modal) return;
|
||||
restoreMinimizedModal(modal.id);
|
||||
showModal(modal);
|
||||
}
|
||||
|
||||
export function togglePopup() {
|
||||
const modal = document.getElementById('theme-modal');
|
||||
if (!modal) return;
|
||||
const visible = !modal.classList.contains('hidden');
|
||||
const visible = !modal.classList.contains('hidden')
|
||||
&& !modal.classList.contains('modal-minimized')
|
||||
&& !modal.querySelector('.modal-closing');
|
||||
if (visible) {
|
||||
modal.classList.add('hidden');
|
||||
closePopup();
|
||||
} else {
|
||||
modal.classList.remove('hidden');
|
||||
openPopup();
|
||||
}
|
||||
}
|
||||
|
||||
export function closePopup() {
|
||||
const modal = document.getElementById('theme-modal');
|
||||
if (!modal) return;
|
||||
const content = modal.querySelector('.modal-content');
|
||||
if (content && !content.classList.contains('modal-closing')) {
|
||||
content.classList.add('modal-closing');
|
||||
content.addEventListener('animationend', () => {
|
||||
modal.classList.add('hidden');
|
||||
content.classList.remove('modal-closing');
|
||||
}, { once: true });
|
||||
setTimeout(() => { if (!modal.classList.contains('hidden')) { modal.classList.add('hidden'); content.classList.remove('modal-closing'); } }, 250);
|
||||
} else {
|
||||
modal.classList.add('hidden');
|
||||
}
|
||||
hideModal(modal);
|
||||
}
|
||||
|
||||
// Expose for app.js wiring + AI ui_control
|
||||
@@ -2278,7 +2278,7 @@ function _initEmbers() {
|
||||
draw();
|
||||
}
|
||||
|
||||
const themeModule = { initThemeUI, togglePopup, closePopup, makeDraggable,
|
||||
const themeModule = { initThemeUI, openPopup, togglePopup, closePopup, makeDraggable,
|
||||
THEMES, applyColors, applyFontDensity, applyBgPattern,
|
||||
applyBgEffectColor, applyBgEffectIntensity, applyBgEffectSize, applyBgEffectSpeed,
|
||||
applyFrostedGlass,
|
||||
|
||||
@@ -38,6 +38,7 @@ const KATEX_FONTS = [
|
||||
// Both are fetched at install time, in the background. Entries must match the
|
||||
// exact URL the browser requests, query string included.
|
||||
const PRECACHE = [
|
||||
'/static/js/modalVisibility.js',
|
||||
'/static/js/compare/sse.js',
|
||||
'/',
|
||||
'/static/css/00-tokens.css?v=20261008confirmwrap1',
|
||||
|
||||
Reference in New Issue
Block a user