mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-10-01 20:42:22 +02:00
Squash Odysseus development history
This commit is contained in:
@@ -0,0 +1,176 @@
|
||||
// Settings modal lifecycle primitives.
|
||||
//
|
||||
// Panel-specific behavior belongs elsewhere. This module owns only the window
|
||||
// shell: dragging/docking reset, close semantics, visibility animation, and the
|
||||
// delegated link that leaves Settings for the Persona editor.
|
||||
|
||||
import { makeWindowDraggable } from '../windowDrag.js';
|
||||
import { clearDockSide } from '../modalSnap.js';
|
||||
|
||||
const _dragBound = new WeakSet();
|
||||
const _closeBound = new WeakSet();
|
||||
let _promptLinkBound = false;
|
||||
|
||||
export function bindSettingsDrag(modalEl) {
|
||||
if (!modalEl || _dragBound.has(modalEl)) return;
|
||||
|
||||
const header = modalEl.querySelector('.modal-header');
|
||||
const content = modalEl.querySelector('.settings-modal-content');
|
||||
if (!header || !content) return;
|
||||
|
||||
_dragBound.add(modalEl);
|
||||
makeWindowDraggable(modalEl, {
|
||||
content,
|
||||
header,
|
||||
skipSelector: 'button, input, select, .theme-opacity-wrap',
|
||||
enableDock: true,
|
||||
});
|
||||
}
|
||||
|
||||
export function resetSettingsWindowPlacement(modalEl) {
|
||||
const content = modalEl?.querySelector('.settings-modal-content');
|
||||
if (!content) return;
|
||||
|
||||
const hadLeft = modalEl.classList.contains('modal-left-docked');
|
||||
const hadRight = modalEl.classList.contains('modal-right-docked');
|
||||
modalEl.classList.remove('modal-left-docked', 'modal-right-docked');
|
||||
if (hadLeft) clearDockSide('left', modalEl);
|
||||
if (hadRight) clearDockSide('right', modalEl);
|
||||
|
||||
if (content._leftDockNavObs) {
|
||||
try { content._leftDockNavObs.navObs && content._leftDockNavObs.navObs.disconnect(); } catch (_) {}
|
||||
try { window.removeEventListener('resize', content._leftDockNavObs.reanchor); } catch (_) {}
|
||||
delete content._leftDockNavObs;
|
||||
}
|
||||
|
||||
delete content._preDockSnapshot;
|
||||
delete content._dockSide;
|
||||
delete content._dockSuspended;
|
||||
delete content.dataset._tilePreSnap;
|
||||
delete content.dataset._tileZone;
|
||||
|
||||
[
|
||||
'position', 'left', 'top', 'right', 'bottom', 'margin', 'transform',
|
||||
'width', 'height', 'max-width', 'max-height', 'border-radius', 'transition',
|
||||
].forEach(property => content.style.removeProperty(property));
|
||||
}
|
||||
|
||||
export function bindOpenPromptModalLink({ getModal, closeSettings } = {}) {
|
||||
if (_promptLinkBound) return;
|
||||
_promptLinkBound = true;
|
||||
|
||||
document.addEventListener('click', async event => {
|
||||
const link = event.target?.closest?.('[data-open-prompt-modal]');
|
||||
if (!link) return;
|
||||
event.preventDefault();
|
||||
|
||||
const settingsModal = typeof getModal === 'function' ? getModal() : null;
|
||||
if (
|
||||
settingsModal
|
||||
&& !settingsModal.classList.contains('hidden')
|
||||
&& typeof closeSettings === 'function'
|
||||
) {
|
||||
closeSettings();
|
||||
}
|
||||
|
||||
try {
|
||||
const module = await import('../presets.js?v=20260908personaname1');
|
||||
const openPrompt = module.openCustomPresetModal
|
||||
|| (module.default && module.default.openCustomPresetModal);
|
||||
if (typeof openPrompt === 'function') openPrompt();
|
||||
} catch (_) {
|
||||
const modal = document.getElementById('custom-preset-modal');
|
||||
if (modal) modal.classList.remove('hidden');
|
||||
}
|
||||
|
||||
const personaTab = document.querySelector(
|
||||
'#custom-preset-modal .preset-tab[data-chartab="character"]'
|
||||
);
|
||||
if (personaTab) personaTab.click();
|
||||
});
|
||||
}
|
||||
|
||||
export function bindSettingsClose(modalEl, options = {}) {
|
||||
if (!modalEl || _closeBound.has(modalEl)) return;
|
||||
_closeBound.add(modalEl);
|
||||
|
||||
const closeSettings = options.closeSettings;
|
||||
const isTouchInsideModal = options.isTouchInsideModal;
|
||||
|
||||
const closeButton = modalEl.querySelector('.close-btn');
|
||||
closeButton?.addEventListener('click', () => {
|
||||
if (typeof closeSettings === 'function') closeSettings();
|
||||
});
|
||||
|
||||
modalEl.addEventListener('mousedown', event => {
|
||||
if (typeof isTouchInsideModal === 'function' && isTouchInsideModal()) return;
|
||||
if (event.target === modalEl && typeof closeSettings === 'function') {
|
||||
closeSettings();
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('keydown', event => {
|
||||
if (event.key !== 'Escape' || modalEl.classList.contains('hidden')) return;
|
||||
|
||||
// Esc should dismiss transient popovers before the Settings window.
|
||||
const popoverOpen = modalEl.querySelector(
|
||||
'#adm-epLocalMoreMenu, #adm-epApiMoreMenu, #adm-provider-menu, #search-provider-menu, [data-popover-open="1"]'
|
||||
);
|
||||
if (
|
||||
popoverOpen
|
||||
&& popoverOpen.style.display !== 'none'
|
||||
&& !popoverOpen.classList.contains('hidden')
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Integration/account editors are nested flows. Close the editor first so
|
||||
// an accidental Esc does not discard the entire Settings context.
|
||||
const innerForm = modalEl.querySelector('#unified-intg-form, #set-email-accounts-form');
|
||||
if (
|
||||
innerForm
|
||||
&& innerForm.style.display !== 'none'
|
||||
&& innerForm.children.length > 0
|
||||
) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
innerForm.style.display = 'none';
|
||||
innerForm.innerHTML = '';
|
||||
return;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
if (typeof closeSettings === 'function') closeSettings();
|
||||
});
|
||||
}
|
||||
|
||||
export function showSettingsModal(modalEl) {
|
||||
if (!modalEl) return;
|
||||
if (modalEl.classList.contains('hidden')) {
|
||||
resetSettingsWindowPlacement(modalEl);
|
||||
}
|
||||
modalEl.classList.remove('hidden');
|
||||
}
|
||||
|
||||
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');
|
||||
}
|
||||
Reference in New Issue
Block a user