// js/ui/immersive_layout_logic.js
(function ImmersiveLayoutLogic(global) {
let toggleBtn, immersiveContainer;
let mainPageContainer, tocPopupElement, chatbotModalElement, dockElement;
let immersiveTocArea, immersiveMainArea, immersiveChatbotArea, immersiveDockPlaceholderElement;
let tocVsDockResizeHandle;
let isTocDockResizing = false; // Flag to indicate dragging state
let initialTocDockMouseY, initialTocHeight, initialDockHeight;
// Original parent and next sibling of the elements to be moved
let originalMainContainerParent = null;
let originalMainContainerNextSibling = null;
let originalTocPopupParent = null;
let originalTocPopupNextSibling = null;
let originalChatbotModalParent = null;
let originalChatbotModalNextSibling = null;
let originalDockElementParent = null;
let originalDockElementNextSibling = null;
let isImmersiveActive = false;
let isSimpleImmersiveActive = false; // 新增:简单沉浸模式状态
const LS_IMMERSIVE_KEY = 'immersiveLayoutActive';
const LS_SIMPLE_IMMERSIVE_KEY = 'simpleImmersiveLayoutActive'; // 新增:简单沉浸模式存储键
const LS_PANEL_SIZES_KEY = 'immersivePanelSizes';
function initializeDomElements() {
toggleBtn = document.getElementById('toggle-immersive-btn');
immersiveContainer = document.getElementById('immersive-layout-container');
mainPageContainer = document.querySelector('.container');
tocPopupElement = document.getElementById('toc-popup');
chatbotModalElement = document.getElementById('chatbot-modal');
dockElement = document.getElementById('bottom-left-dock');
immersiveTocArea = document.getElementById('immersive-toc-area');
immersiveMainArea = document.getElementById('immersive-main-content-area');
immersiveChatbotArea = document.getElementById('immersive-chatbot-area');
// Create the dock placeholder dynamically
immersiveDockPlaceholderElement = document.createElement('div');
immersiveDockPlaceholderElement.id = 'toc-dock-placeholder';
// Basic styles can be applied here if not fully covered by CSS, or rely on CSS.
// For now, CSS will handle styling based on the ID.
return toggleBtn && immersiveContainer && mainPageContainer && tocPopupElement && immersiveTocArea && immersiveMainArea && immersiveChatbotArea && dockElement /* && immersiveDockPlaceholderElement (element itself exists, not a check if found in DOM here) */;
}
function reQueryDynamicElements() {
if (!chatbotModalElement) {
chatbotModalElement = document.getElementById('chatbot-modal');
}
if (!mainPageContainer) mainPageContainer = document.querySelector('.container');
if (!tocPopupElement) tocPopupElement = document.getElementById('toc-popup');
if (!dockElement) dockElement = document.getElementById('bottom-left-dock');
}
function storeOriginalPositions() {
if (mainPageContainer) {
originalMainContainerParent = mainPageContainer.parentNode;
originalMainContainerNextSibling = mainPageContainer.nextSibling;
}
if (tocPopupElement) {
originalTocPopupParent = tocPopupElement.parentNode;
originalTocPopupNextSibling = tocPopupElement.nextSibling;
}
if (chatbotModalElement) {
originalChatbotModalParent = chatbotModalElement.parentNode;
originalChatbotModalNextSibling = chatbotModalElement.nextSibling;
} else {
console.warn('storeOriginalPositions: chatbotModalElement not found.');
}
if (dockElement) {
originalDockElementParent = dockElement.parentNode;
originalDockElementNextSibling = dockElement.nextSibling;
} else {
console.warn('storeOriginalPositions: dockElement not found.');
}
}
function savePanelSizes() {
if (!isImmersiveActive || !immersiveContainer || immersiveContainer.style.display === 'none') return;
if (!immersiveTocArea || !immersiveMainArea || !immersiveChatbotArea) return;
const tocWidth = immersiveTocArea.style.width;
const mainWidth = immersiveMainArea.style.width;
const chatbotWidth = immersiveChatbotArea.style.width;
localStorage.setItem(LS_PANEL_SIZES_KEY, JSON.stringify({ toc: tocWidth, main: mainWidth, chatbot: chatbotWidth }));
}
function loadPanelSizes() {
if (!immersiveTocArea || !immersiveMainArea || !immersiveChatbotArea) return;
const savedSizes = localStorage.getItem(LS_PANEL_SIZES_KEY);
if (savedSizes) {
try {
const sizes = JSON.parse(savedSizes);
if (sizes.toc) immersiveTocArea.style.width = sizes.toc;
if (sizes.chatbot) immersiveChatbotArea.style.width = sizes.chatbot;
} catch (e) {
console.error('Error loading panel sizes:', e);
immersiveTocArea.style.width = '20%';
immersiveMainArea.style.flex = '1';
immersiveMainArea.style.width = '';
immersiveChatbotArea.style.width = '25%';
}
} else {
immersiveTocArea.style.width = '20%';
immersiveMainArea.style.flex = '1';
immersiveMainArea.style.width = '';
immersiveChatbotArea.style.width = '25%';
}
}
function initializeTocDockResizer() {
if (!tocVsDockResizeHandle || !tocPopupElement || !immersiveDockPlaceholderElement || !immersiveTocArea) {
console.warn("TOC vs Dock resizer: Missing one or more elements.");
return;
}
// Ensure event listeners are not duplicated if called multiple times
tocVsDockResizeHandle.removeEventListener('mousedown', handleTocDockDragStart);
tocVsDockResizeHandle.addEventListener('mousedown', handleTocDockDragStart);
}
function handleTocDockDragStart(event) {
event.preventDefault();
isTocDockResizing = true;
initialTocDockMouseY = event.clientY;
initialTocHeight = tocPopupElement.offsetHeight;
initialDockHeight = immersiveDockPlaceholderElement.offsetHeight;
// Add class to body for global cursor/selection styles
document.body.classList.add('toc-dock-resizing');
// Add temporary flex-grow overrides if needed, or rely on flex-basis
// tocPopupElement.style.flexGrow = '0';
// immersiveDockPlaceholderElement.style.flexGrow = '0';
document.addEventListener('mousemove', handleTocDockDragMove);
document.addEventListener('mouseup', handleTocDockDragEnd);
}
function handleTocDockDragMove(event) {
if (!isTocDockResizing) return;
event.preventDefault();
const deltaY = event.clientY - initialTocDockMouseY;
let newTocHeight = initialTocHeight + deltaY;
let newDockHeight = initialDockHeight - deltaY;
const minPanelHeight = 40; // Minimum height for TOC and Dock panels
// Constrain TOC height
if (newTocHeight < minPanelHeight) {
newTocHeight = minPanelHeight;
// Recalculate dock height based on constrained TOC
newDockHeight = initialTocHeight + initialDockHeight - newTocHeight;
}
// Constrain Dock height
if (newDockHeight < minPanelHeight) {
newDockHeight = minPanelHeight;
// Recalculate TOC height based on constrained Dock
newTocHeight = initialTocHeight + initialDockHeight - newDockHeight;
}
// Ensure total height of tocArea children doesn't exceed tocArea height if it's fixed
// For flexbox, adjusting flex-basis is usually better.
// The sum of newTocHeight and newDockHeight should ideally be initialTocHeight + initialDockHeight.
// The logic above ensures this if one hits minPanelHeight.
// Apply new heights using flex-basis for better control in a flex container
tocPopupElement.style.flexBasis = newTocHeight + 'px';
immersiveDockPlaceholderElement.style.flexBasis = newDockHeight + 'px';
// If not using flex-basis, and want to force height and disable grow/shrink during drag:
// tocPopupElement.style.height = newTocHeight + 'px';
// immersiveDockPlaceholderElement.style.height = newDockHeight + 'px';
// tocPopupElement.style.flexGrow = '0';
// immersiveDockPlaceholderElement.style.flexGrow = '0';
}
function handleTocDockDragEnd() {
if (!isTocDockResizing) return;
isTocDockResizing = false;
document.body.classList.remove('toc-dock-resizing');
document.removeEventListener('mousemove', handleTocDockDragMove);
document.removeEventListener('mouseup', handleTocDockDragEnd);
// Restore original flex-grow properties if they were changed during drag
// tocPopupElement.style.flexGrow = ''; // Or to its original value e.g., '10'
// immersiveDockPlaceholderElement.style.flexGrow = ''; // Or to its original value e.g., '1'
// However, since we are using flex-basis, the original flex-grow values from CSS should still apply
// once flex-basis is set, unless grow/shrink are explicitly set to 0.
// The CSS has flex-grow: 10 for toc and flex-grow: 1 for dock placeholder.
// Setting flex-basis should work fine with these grow factors if space allows.
// Optional: Save the new heights/proportions to localStorage
// const tocAreaHeight = immersiveTocArea.offsetHeight;
// if (tocAreaHeight > 0) {
// const tocRatio = tocPopupElement.offsetHeight / tocAreaHeight;
// localStorage.setItem('immersiveTocDockRatio', tocRatio.toFixed(4));
// }
}
function destroyTocDockResizer() {
if (tocVsDockResizeHandle) {
tocVsDockResizeHandle.removeEventListener('mousedown', handleTocDockDragStart);
}
// Clean up global listeners if somehow left hanging (should be removed by handleTocDockDragEnd)
document.removeEventListener('mousemove', handleTocDockDragMove);
document.removeEventListener('mouseup', handleTocDockDragEnd);
document.body.classList.remove('toc-dock-resizing');
isTocDockResizing = false; // Reset flag
}
function enterImmersiveMode() {
// 检查是否为移动端设备
if (window.innerWidth <= 700) {
console.warn('拒绝在移动端(≤700px)进入沉浸式布局');
return;
}
reQueryDynamicElements();
let missingElements = [];
if (!immersiveContainer) missingElements.push('immersiveContainer');
if (!mainPageContainer) missingElements.push('mainPageContainer');
if (!tocPopupElement) missingElements.push('tocPopupElement');
if (!chatbotModalElement) missingElements.push('chatbotModalElement');
if (!dockElement) missingElements.push('dockElement');
if (!immersiveTocArea) missingElements.push('immersiveTocArea');
if (!immersiveMainArea) missingElements.push('immersiveMainArea');
if (!immersiveChatbotArea) missingElements.push('immersiveChatbotArea');
if (!immersiveDockPlaceholderElement) missingElements.push('immersiveDockPlaceholderElement (logic error if this happens)');
if (missingElements.length > 0) {
console.warn('Immersive mode elements not found:', missingElements.join(', '));
return;
}
isImmersiveActive = true;
storeOriginalPositions();
// 添加进入动画类
document.body.classList.add('immersive-entering');
immersiveContainer.style.opacity = '0';
immersiveContainer.style.transform = 'scale(0.95)';
immersiveContainer.style.transition = 'opacity 0.4s ease, transform 0.4s ease';
// Append TOC content first
if (tocPopupElement && immersiveTocArea) {
immersiveTocArea.appendChild(tocPopupElement);
}
// Create and insert the resize handle between TOC and Dock Placeholder
if (immersiveTocArea) {
if (!tocVsDockResizeHandle) { // Create if it doesn't exist
tocVsDockResizeHandle = document.createElement('div');
tocVsDockResizeHandle.id = 'toc-vs-dock-resize-handle';
}
if (tocPopupElement && tocPopupElement.parentNode === immersiveTocArea) {
immersiveTocArea.insertBefore(tocVsDockResizeHandle, tocPopupElement.nextSibling);
} else {
immersiveTocArea.appendChild(tocVsDockResizeHandle);
}
}
// Then append the dock placeholder to TOC area
if (immersiveDockPlaceholderElement && immersiveTocArea) {
if (tocVsDockResizeHandle && tocVsDockResizeHandle.parentNode === immersiveTocArea) {
immersiveTocArea.insertBefore(immersiveDockPlaceholderElement, tocVsDockResizeHandle.nextSibling);
} else {
immersiveTocArea.appendChild(immersiveDockPlaceholderElement);
}
}
// Move other elements
if (mainPageContainer && immersiveMainArea) {
immersiveMainArea.appendChild(mainPageContainer);
}
if (chatbotModalElement && immersiveChatbotArea) {
immersiveChatbotArea.appendChild(chatbotModalElement);
}
// Move the actual dock into its placeholder
if (dockElement && immersiveDockPlaceholderElement) {
immersiveDockPlaceholderElement.appendChild(dockElement);
// Force Dock to be expanded in immersive mode
if (dockElement.classList.contains('dock-collapsed')) {
dockElement.classList.remove('dock-collapsed');
const dockToggleBtn = document.getElementById('dock-toggle-btn');
if (dockToggleBtn) {
dockToggleBtn.innerHTML = '';
dockToggleBtn.title = '折叠';
}
if (typeof window !== 'undefined' && window.docIdForLocalStorage) {
localStorage.setItem(`dockCollapsed_${window.docIdForLocalStorage}`, 'false');
}
}
}
document.body.classList.add('immersive-active', 'no-scroll');
immersiveContainer.style.display = 'flex';
// 简单的强制重新计算,修复初始化时的布局问题
setTimeout(() => {
if (immersiveContainer) {
immersiveContainer.offsetHeight; // 触发重新布局
}
}, 0);
// 动画进入效果
requestAnimationFrame(() => {
immersiveContainer.style.opacity = '1';
immersiveContainer.style.transform = 'scale(1)';
setTimeout(() => {
document.body.classList.remove('immersive-entering');
immersiveContainer.style.transition = '';
}, 400);
});
if (toggleBtn) {
toggleBtn.innerHTML = '';
toggleBtn.classList.add('immersive-exit-btn-active');
toggleBtn.title = '退出沉浸模式';
}
// 其他初始化逻辑保持不变...
if (typeof window.refreshTocList === 'function') {
window.refreshTocList();
}
if (window.ChatbotUI && typeof window.ChatbotUI.updateChatbotUI === 'function') {
window.isChatbotOpen = true;
window.isChatbotFullscreen = false;
window.forceChatbotWidthReset = true;
window.ChatbotUI.updateChatbotUI();
}
if (window.DockLogic && typeof window.DockLogic.updateStats === 'function' && window.data && window.currentVisibleTabId) {
dockElement.style.display = '';
window.DockLogic.updateStats(window.data, window.currentVisibleTabId);
}
setTimeout(() => {
if (window.DockLogic) {
if (typeof window.DockLogic.unbindScrollForCurrentScrollable === 'function') {
console.log("[ImmersiveLayout] 进入沉浸模式前,先解绑旧的滚动事件");
window.DockLogic.unbindScrollForCurrentScrollable();
}
if (typeof window.DockLogic.forceUpdateReadingProgress === 'function') {
console.log("[ImmersiveLayout] 进入沉浸模式后,延迟调用 forceUpdateReadingProgress");
window.DockLogic.forceUpdateReadingProgress();
}
}
// 为滚动容器添加标记 class,供 JS 查询使用
if (immersiveMainArea) {
const container = immersiveMainArea.querySelector('.container');
if (container) {
const tabContent = container.querySelector('.tab-content');
if (tabContent) {
// 添加 .js-scroll-container 标记,供 DockLogic 等模块查询
// CSS 通过 body.immersive-active 选择器自动控制 overflow
tabContent.classList.add('js-scroll-container');
console.log("[ImmersiveLayout] 已为 tab-content 添加 js-scroll-container 标记");
}
}
}
}, 300);
// Force TOC to be expanded in immersive mode
if (tocPopupElement && !tocPopupElement.classList.contains('toc-expanded')) {
const tocExpandBtn = document.getElementById('toc-expand-btn');
if (tocExpandBtn) {
tocPopupElement.classList.add('toc-expanded');
const icon = tocExpandBtn.querySelector('i');
if (icon) {
icon.classList.remove('fa-angles-right');
icon.classList.add('fa-angles-left');
}
tocExpandBtn.title = '收起目录';
}
}
loadPanelSizes();
initializeTocDockResizer();
localStorage.setItem(LS_IMMERSIVE_KEY, 'true');
document.dispatchEvent(new CustomEvent('immersiveModeEntered'));
}
function exitImmersiveMode() {
reQueryDynamicElements();
isImmersiveActive = false;
// 添加退出动画
document.body.classList.add('immersive-exiting');
if (immersiveContainer) {
immersiveContainer.style.transition = 'opacity 0.3s ease, transform 0.3s ease';
immersiveContainer.style.opacity = '0';
immersiveContainer.style.transform = 'scale(0.98)';
}
setTimeout(() => {
destroyTocDockResizer();
// Remove the TOC vs Dock resize handle
if (tocVsDockResizeHandle && tocVsDockResizeHandle.parentNode === immersiveTocArea) {
immersiveTocArea.removeChild(tocVsDockResizeHandle);
}
// 恢复元素位置的逻辑保持不变...
if (originalTocPopupParent && tocPopupElement && tocPopupElement.parentNode === immersiveTocArea) {
originalTocPopupParent.insertBefore(tocPopupElement, originalTocPopupNextSibling);
} else if (tocPopupElement && immersiveTocArea.contains(tocPopupElement)) {
immersiveTocArea.removeChild(tocPopupElement);
if (originalTocPopupParent) {
originalTocPopupParent.insertBefore(tocPopupElement, originalTocPopupNextSibling);
}
}
if (originalMainContainerParent && mainPageContainer && mainPageContainer.parentNode === immersiveMainArea) {
originalMainContainerParent.insertBefore(mainPageContainer, originalMainContainerNextSibling);
} else if (mainPageContainer && immersiveMainArea.contains(mainPageContainer)) {
immersiveMainArea.removeChild(mainPageContainer);
if (originalMainContainerParent) {
originalMainContainerParent.insertBefore(mainPageContainer, originalMainContainerNextSibling);
}
}
if (chatbotModalElement && originalChatbotModalParent && chatbotModalElement.parentNode === immersiveChatbotArea) {
originalChatbotModalParent.insertBefore(chatbotModalElement, originalChatbotModalNextSibling);
} else if (chatbotModalElement && immersiveChatbotArea.contains(chatbotModalElement)) {
immersiveChatbotArea.removeChild(chatbotModalElement);
if (originalChatbotModalParent) {
originalChatbotModalParent.insertBefore(chatbotModalElement, originalChatbotModalNextSibling);
}
} else if (!chatbotModalElement && originalChatbotModalParent) {
immersiveChatbotArea.innerHTML = '';
}
if (dockElement && originalDockElementParent) {
if (immersiveDockPlaceholderElement && immersiveDockPlaceholderElement.contains(dockElement)) {
immersiveDockPlaceholderElement.removeChild(dockElement);
}
originalDockElementParent.insertBefore(dockElement, originalDockElementNextSibling);
} else if (dockElement && immersiveDockPlaceholderElement && immersiveDockPlaceholderElement.contains(dockElement)){
immersiveDockPlaceholderElement.removeChild(dockElement);
}
document.body.classList.remove('immersive-active', 'no-scroll', 'immersive-exiting');
if (immersiveContainer) {
immersiveContainer.style.display = 'none';
immersiveContainer.style.transition = '';
immersiveContainer.style.opacity = '';
immersiveContainer.style.transform = '';
}
// 清理滚动容器标记 class
if (mainPageContainer) {
const tabContent = mainPageContainer.querySelector('.tab-content');
if (tabContent) {
tabContent.classList.remove('js-scroll-container');
console.log("[ImmersiveLayout] 已移除 tab-content 的 js-scroll-container 标记");
}
}
if (toggleBtn) {
toggleBtn.innerHTML = '';
toggleBtn.classList.remove('immersive-exit-btn-active');
toggleBtn.title = '进入沉浸式布局';
}
// 其他退出逻辑保持不变...
if (typeof window.refreshTocList === 'function') {
window.refreshTocList();
}
if (typeof window.docIdForLocalStorage !== 'undefined' && window.docIdForLocalStorage) {
const savedChatbotOpenState = localStorage.getItem(`chatbotOpenState_${window.docIdForLocalStorage}`);
if (savedChatbotOpenState === 'true') {
window.isChatbotOpen = true;
} else if (savedChatbotOpenState === 'false') {
window.isChatbotOpen = false;
}
}
if (window.ChatbotUI && typeof window.ChatbotUI.updateChatbotUI === 'function') {
window.ChatbotUI.updateChatbotUI();
}
if (window.DockLogic && typeof window.DockLogic.updateStats === 'function' && window.data && window.currentVisibleTabId) {
dockElement.style.display = '';
window.DockLogic.updateStats(window.data, window.currentVisibleTabId);
}
setTimeout(() => {
if (window.DockLogic) {
if (typeof window.DockLogic.unbindScrollForCurrentScrollable === 'function') {
console.log("[ImmersiveLayout] 退出沉浸模式前,先解绑旧的滚动事件");
window.DockLogic.unbindScrollForCurrentScrollable();
}
if (typeof window.DockLogic.forceUpdateReadingProgress === 'function') {
console.log("[ImmersiveLayout] 退出沉浸模式后,延迟调用 forceUpdateReadingProgress");
window.DockLogic.forceUpdateReadingProgress();
}
}
}, 300);
localStorage.setItem(LS_IMMERSIVE_KEY, 'false');
document.dispatchEvent(new CustomEvent('immersiveModeExited'));
}, 300);
}
function initResizeHandles() {
const handles = document.querySelectorAll('.immersive-resize-handle');
let activeHandle = null;
let startX, startWidthPrev, startWidthNext;
handles.forEach(handle => {
handle.addEventListener('mousedown', function(e) {
activeHandle = this;
startX = e.clientX;
const prevPanelId = activeHandle.dataset.targetPrev;
const nextPanelId = activeHandle.dataset.targetNext;
const prevPanel = document.getElementById(prevPanelId);
const nextPanel = document.getElementById(nextPanelId);
if (!prevPanel || !nextPanel) {
console.warn(`Resize panels not found: ${prevPanelId} or ${nextPanelId}`);
activeHandle = null;
return;
}
startWidthPrev = prevPanel.offsetWidth;
startWidthNext = nextPanel.offsetWidth;
document.body.classList.add('immersive-dragging');
document.body.style.userSelect = 'none';
document.body.style.cursor = 'col-resize';
e.preventDefault();
});
});
document.addEventListener('mousemove', function(e) {
if (!activeHandle) return;
const dx = e.clientX - startX;
const prevPanel = document.getElementById(activeHandle.dataset.targetPrev);
const nextPanel = document.getElementById(activeHandle.dataset.targetNext);
if (!prevPanel || !nextPanel) return;
const newWidthPrev = startWidthPrev + dx;
const newWidthNext = startWidthNext - dx;
const minPanelWidth = parseFloat(getComputedStyle(document.documentElement).getPropertyValue('--immersive-panel-min-width')) || 80;
if (newWidthPrev >= minPanelWidth && newWidthNext >= minPanelWidth) {
prevPanel.style.width = newWidthPrev + 'px';
nextPanel.style.width = newWidthNext + 'px';
// 平滑的过渡动画
prevPanel.style.transition = 'none';
nextPanel.style.transition = 'none';
}
});
document.addEventListener('mouseup', function() {
if (activeHandle) {
savePanelSizes();
// 恢复样式
document.body.classList.remove('immersive-dragging');
document.body.style.userSelect = '';
document.body.style.cursor = '';
// 恢复过渡动画
const prevPanel = document.getElementById(activeHandle.dataset.targetPrev);
const nextPanel = document.getElementById(activeHandle.dataset.targetNext);
if (prevPanel) prevPanel.style.transition = '';
if (nextPanel) nextPanel.style.transition = '';
activeHandle = null;
}
});
}
function mainInit() {
if (!initializeDomElements()) {
console.warn('Immersive layout core static elements not found on DOMContentLoaded. Retrying shortly...');
setTimeout(mainInit, 500);
return;
}
reQueryDynamicElements();
// 标准沉浸模式切换按钮
const standardToggleBtn = document.getElementById('toggle-immersive-btn');
// 简单沉浸模式切换按钮
const simpleToggleBtn = document.getElementById('toggle-simple-immersive-btn');
// 标准沉浸模式功能
if (standardToggleBtn) {
standardToggleBtn.addEventListener('click', () => {
// 检查是否为移动端设备(屏幕宽度小于等于700px)
if (window.innerWidth <= 700) {
console.warn('沉浸式布局在移动端(≤700px)不可用');
// 可选:显示提示消息
if (window.showToast) {
window.showToast('沉浸式布局在手机端不可用', 'warning');
} else {
alert('沉浸式布局在手机端不可用,请在更大的屏幕上使用');
}
return;
}
if (isImmersiveActive) {
exitImmersiveMode();
} else {
enterImmersiveMode();
}
});
}
// 简单沉浸模式功能
if (simpleToggleBtn) {
simpleToggleBtn.addEventListener('click', () => {
isSimpleImmersiveActive = !isSimpleImmersiveActive;
// 检查是否在"原始文件"标签页(PDF查看器)
const isOriginalFileTab = window.currentVisibleTabId === 'original-file';
const pdfIframeWrapper = document.getElementById('pdf-iframe-wrapper');
const pdfIframe = document.getElementById('pdf-viewer-iframe');
const mainContainer = document.querySelector('.container');
if (isSimpleImmersiveActive) {
// 如果是PDF查看器标签页,进行特殊处理
if (isOriginalFileTab && pdfIframeWrapper && mainContainer) {
// 添加特殊类用于PDF全屏模式
document.body.classList.add('simple-immersive-pdf-mode');
// 移除container的padding
mainContainer.dataset.originalPadding = mainContainer.style.padding || '';
mainContainer.style.padding = '0 !important';
// 让iframe wrapper充满container(接近全屏)
pdfIframeWrapper.style.cssText = `
width: 100%;
height: calc(100vh - 20px);
min-height: calc(100vh - 20px);
position: relative;
background: #525659;
`;
if (pdfIframe) {
pdfIframe.style.cssText = `
width: 100%;
height: 100%;
border: none;
`;
}
// 隐藏其他UI元素
const elementsToHide = [
{ selector: '.tabs-container', el: document.querySelector('.tabs-container') },
{ selector: '.history-export-controls', el: document.querySelector('.history-export-controls') },
{ selector: '#bottom-left-dock', el: document.getElementById('bottom-left-dock') },
{ selector: '#toc-popup', el: document.getElementById('toc-popup') },
{ selector: '#fileName', el: document.getElementById('fileName') },
{ selector: '#fileMeta', el: document.getElementById('fileMeta') }
];
elementsToHide.forEach(item => {
if (item.el) {
item.el.dataset.originalDisplay = item.el.style.display || '';
item.el.style.display = 'none';
}
});
// 隐藏loading指示器
const loading = document.getElementById('pdf-viewer-loading');
if (loading) loading.style.display = 'none';
// 确保iframe显示
if (pdfIframe) pdfIframe.style.display = 'block';
} else {
// 非PDF查看器标签页,使用原有的简单沉浸模式
document.body.classList.add('simple-immersive-pdf-mode');
}
simpleToggleBtn.innerHTML = '';
simpleToggleBtn.title = '退出简单沉浸模式';
localStorage.setItem(LS_SIMPLE_IMMERSIVE_KEY, 'true');
} else {
// 退出简单沉浸模式
document.body.classList.remove('simple-immersive-pdf-mode');
document.body.classList.remove('simple-immersive-pdf-mode');
// 恢复container的padding
if (mainContainer && mainContainer.dataset.originalPadding !== undefined) {
mainContainer.style.padding = mainContainer.dataset.originalPadding;
delete mainContainer.dataset.originalPadding;
}
// 恢复所有被隐藏的元素
const elementsToRestore = [
{ selector: '.tabs-container', el: document.querySelector('.tabs-container') },
{ selector: '.history-export-controls', el: document.querySelector('.history-export-controls') },
{ selector: '#bottom-left-dock', el: document.getElementById('bottom-left-dock') },
{ selector: '#toc-popup', el: document.getElementById('toc-popup') },
{ selector: '#fileName', el: document.getElementById('fileName') },
{ selector: '#fileMeta', el: document.getElementById('fileMeta') }
];
elementsToRestore.forEach(item => {
if (item.el && item.el.dataset.originalDisplay !== undefined) {
item.el.style.display = item.el.dataset.originalDisplay;
delete item.el.dataset.originalDisplay;
}
});
// 恢复iframe wrapper的原始样式
if (pdfIframeWrapper) {
pdfIframeWrapper.style.cssText = `
width: 100%;
height: 100%;
min-height: 500px;
position: relative;
background: #525659;
`;
}
simpleToggleBtn.innerHTML = '';
simpleToggleBtn.title = '进入简单沉浸模式';
localStorage.setItem(LS_SIMPLE_IMMERSIVE_KEY, 'false');
}
});
}
initResizeHandles();
// 监听窗口大小变化,如果变成移动端尺寸则自动退出沉浸模式
function handleWindowResize() {
if (window.innerWidth <= 700 && isImmersiveActive) {
console.log('检测到屏幕缩小到移动端尺寸,自动退出沉浸式布局');
exitImmersiveMode();
}
}
// 添加窗口大小变化监听器
window.addEventListener('resize', handleWindowResize);
// Restore immersive state from localStorage
const savedImmersiveState = localStorage.getItem(LS_IMMERSIVE_KEY);
if (savedImmersiveState === 'true') {
// 检查是否为移动端,如果是则不恢复沉浸模式
if (window.innerWidth <= 700) {
console.log('检测到移动端设备,不恢复沉浸式布局状态');
localStorage.setItem(LS_IMMERSIVE_KEY, 'false'); // 清除保存的状态
return;
}
// Slight delay to ensure other initializations (like TOC, Chatbot) can occur first
// especially if they also interact with elements moved by immersive mode.
setTimeout(() => {
if (!isImmersiveActive) { // Check again in case of race conditions or manual toggle
enterImmersiveMode();
}
}, 200); // Adjust delay if needed
}
// Restore simple immersive state from localStorage
const savedSimpleImmersiveState = localStorage.getItem(LS_SIMPLE_IMMERSIVE_KEY);
if (savedSimpleImmersiveState === 'true') {
// 检查是否为移动端,如果是则不启用简单沉浸模式
if (window.innerWidth <= 700) {
console.log('检测到移动端设备,不启用简单沉浸式布局状态');
localStorage.setItem(LS_SIMPLE_IMMERSIVE_KEY, 'false'); // 清除保存的状态
} else {
// 如果不在标准沉浸模式下,才启用简单沉浸模式
if (!isImmersiveActive) {
setTimeout(() => {
if (!isSimpleImmersiveActive) {
document.body.classList.add('simple-immersive-pdf-mode');
isSimpleImmersiveActive = true;
if (toggleBtn) {
toggleBtn.innerHTML = '';
toggleBtn.title = '退出简单沉浸模式';
}
}
}, 200);
}
}
}
console.log('Immersive layout logic initialized.');
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', mainInit);
} else {
mainInit();
}
global.ImmersiveLayout = {
isActive: () => isImmersiveActive,
isSimpleActive: () => isSimpleImmersiveActive, // 新增:简单沉浸模式状态查询
enter: enterImmersiveMode,
exit: exitImmersiveMode
};
})(window);