瀏覽代碼

增加全屏按钮

sequoia00 1 月之前
父節點
當前提交
b7557aff89
共有 1 個文件被更改,包括 182 次插入70 次删除
  1. 182 70
      static/web/viewer.html

+ 182 - 70
static/web/viewer.html

@@ -192,20 +192,47 @@
             min-height: 0;
         }
 
-        #readerControls.collapsed {
-            padding: 10px 8px;
-            gap: 6px;
-        }
-
+        #readerControls.collapsed {
+            padding: 10px 8px;
+            gap: 6px;
+        }
+
         body.reader-position-left #readerControls.collapsed,
         body.reader-position-right #readerControls.collapsed {
-            width: calc(var(--reader-controls-size) + var(--reader-controls-padding) * 2);
+            width: 0;
+            padding: 0;
+            border: 0;
+            box-shadow: none;
+            overflow: visible;
+        }
+
+        #readerControls.collapsed .reader-tool:not(.reader-tool-collapse),
+        #readerControls.collapsed .reader-settings-launcher {
+            display: none;
+        }
+
+        #readerControls.collapsed #readerControlsSpacer,
+        #readerControls.collapsed .reader-tools,
+        #readerControls.collapsed .reader-settings-anchor {
+            display: none;
+        }
+
+        #readerControls.collapsed .reader-tool-collapse {
+            position: fixed;
+            top: 0;
+            left: 0;
+            z-index: 30;
+            display: inline-flex;
+            box-shadow: 0 8px 24px rgba(15, 23, 42, 0.18);
+        }
+
+        body.reader-controls-collapsed #sidebarContainer {
+            display: none;
+        }
+
+        body.reader-controls-collapsed #outerContainer.sidebarOpen #viewerContainer:not(.pdfPresentationMode) {
+            inset-inline-start: 0;
         }
-
-        #readerControls.collapsed .reader-tool:not(.reader-tool-collapse),
-        #readerControls.collapsed .reader-settings-launcher {
-            display: none;
-        }
 
         .reader-tools {
             display: flex;
@@ -312,8 +339,13 @@
             order: 2;
             border-right: none;
             border-left: 1px solid var(--reader-controls-border);
-            box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.7);
-        }
+            box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.7);
+        }
+
+        body.reader-position-right #readerControls.collapsed .reader-tool-collapse {
+            left: auto;
+            right: 0;
+        }
 
         .reader-settings-panel {
             display: none;
@@ -1140,24 +1172,30 @@
                                 <span class="reader-tool-label">整页</span>
                             </span>
                         </button>
-                        <button id="pause-play-button" class="reader-tool" type="button" title="暂停播放" aria-label="暂停播放">
-                            <span class="reader-tool-stack">
-                                <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M9 5v14"/><path d="M15 5v14"/></svg>
-                                <span class="reader-tool-label">暂停</span>
-                            </span>
-                        </button>
-                        <button id="stop-play-button" class="reader-tool reader-tool-danger" type="button" title="停止播放" aria-label="停止播放">
-                            <span class="reader-tool-stack">
-                                <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M7 7h10v10H7z"/></svg>
-                                <span class="reader-tool-label">停止</span>
-                            </span>
-                        </button>
-                        <button id="toggle-text-select" class="reader-tool reader-tool-accent" type="button" title="文本选择" aria-label="文本选择">
-                            <span class="reader-tool-stack">
-                                <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 7V4h3"/><path d="M20 7V4h-3"/><path d="M4 17v3h3"/><path d="M20 17v3h-3"/><path d="M8 12h8"/></svg>
-                                <span class="reader-tool-label">选读</span>
-                            </span>
-                        </button>
+                        <button id="pause-play-button" class="reader-tool" type="button" title="暂停播放" aria-label="暂停播放">
+                            <span class="reader-tool-stack">
+                                <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M9 5v14"/><path d="M15 5v14"/></svg>
+                                <span class="reader-tool-label">暂停</span>
+                            </span>
+                        </button>
+                        <button id="stop-play-button" class="reader-tool reader-tool-danger" type="button" title="停止播放" aria-label="停止播放">
+                            <span class="reader-tool-stack">
+                                <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M7 7h10v10H7z"/></svg>
+                                <span class="reader-tool-label">停止</span>
+                            </span>
+                        </button>
+                        <button id="toggle-text-select" class="reader-tool reader-tool-accent" type="button" title="文本选择" aria-label="文本选择">
+                            <span class="reader-tool-stack">
+                                <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M6 5h12"/><path d="M12 5v14"/></svg>
+                                <span class="reader-tool-label">选读</span>
+                            </span>
+                        </button>
+                        <button id="toggle-browser-fullscreen" class="reader-tool" type="button" title="浏览器全屏" aria-label="浏览器全屏">
+                            <span class="reader-tool-stack">
+                                <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 7V4h3"/><path d="M20 7V4h-3"/><path d="M4 17v3h3"/><path d="M20 17v3h-3"/><path d="M8 12h8"/></svg>
+                                <span class="reader-tool-label">全屏</span>
+                            </span>
+                        </button>
                     </div>
                     <div id="readerControlsSpacer"></div>
                     <div class="reader-settings-anchor">
@@ -1522,22 +1560,25 @@
                 const userMenuTrigger = document.getElementById('userMenuTrigger');
                 const userMenuPanel = document.getElementById('userMenuPanel');
                 const userLogoutBtn = document.getElementById('userLogoutBtn');
-                const userAdminBtn = document.getElementById('userAdminBtn');
-                const readerControls = document.getElementById('readerControls');
-                const readerControlsCollapse = document.getElementById('readerControlsCollapse');
-                const readerSettingsButton = document.getElementById('readerSettingsButton');
-                const readerSettingsPanel = document.getElementById('readerSettingsPanel');
-
-                let selectedFile = null;
-                let currentPage = 1;
-                const itemsPerPage = 10;
-                let allFiles = [];
-                let selectedStartContext = null;
-                const currentFilePath = new URLSearchParams(window.location.search).get('file') || '';
-                let isRestoringProgress = false;
-                const NIGHT_MODE_STORAGE_KEY = 'reader_pro.night_mode';
-                const READER_SIZE_STORAGE_KEY = 'reader_pro.controls.size';
-                const READER_COLLAPSED_STORAGE_KEY = 'reader_pro.controls.collapsed';
+                const userAdminBtn = document.getElementById('userAdminBtn');
+                const readerControls = document.getElementById('readerControls');
+                const readerControlsCollapse = document.getElementById('readerControlsCollapse');
+                const readerSettingsButton = document.getElementById('readerSettingsButton');
+                const readerSettingsPanel = document.getElementById('readerSettingsPanel');
+                const sidebarToggleButton = document.getElementById('sidebarToggleButton');
+                const browserFullscreenButton = document.getElementById('toggle-browser-fullscreen');
+
+                let selectedFile = null;
+                let currentPage = 1;
+                const itemsPerPage = 10;
+                let allFiles = [];
+                let selectedStartContext = null;
+                let sidebarWasOpenBeforeReaderCollapse = false;
+                const currentFilePath = new URLSearchParams(window.location.search).get('file') || '';
+                let isRestoringProgress = false;
+                const NIGHT_MODE_STORAGE_KEY = 'reader_pro.night_mode';
+                const READER_SIZE_STORAGE_KEY = 'reader_pro.controls.size';
+                const READER_COLLAPSED_STORAGE_KEY = 'reader_pro.controls.collapsed';
 
                 function updateReaderToggleIcon() {
                     const icon = readerControlsCollapse.querySelector('svg path');
@@ -1552,12 +1593,24 @@
                     icon.setAttribute('d', directionMap[position] || directionMap.left);
                 }
 
-                function setReaderControlsCollapsed(collapsed) {
-                    readerControls.classList.toggle('collapsed', collapsed);
-                    readerControlsCollapse.setAttribute('aria-expanded', String(!collapsed));
-                    localStorage.setItem(READER_COLLAPSED_STORAGE_KEY, collapsed ? '1' : '0');
-                    updateReaderToggleIcon();
-                }
+                function setReaderControlsCollapsed(collapsed) {
+                    readerControls.classList.toggle('collapsed', collapsed);
+                    readerControlsCollapse.setAttribute('aria-expanded', String(!collapsed));
+                    document.body.classList.toggle('reader-controls-collapsed', collapsed);
+
+                    if (collapsed) {
+                        sidebarWasOpenBeforeReaderCollapse = sidebarToggleButton.getAttribute('aria-expanded') === 'true';
+                        if (sidebarWasOpenBeforeReaderCollapse) {
+                            sidebarToggleButton.click();
+                        }
+                    } else if (sidebarWasOpenBeforeReaderCollapse &&
+                        sidebarToggleButton.getAttribute('aria-expanded') !== 'true') {
+                        sidebarToggleButton.click();
+                    }
+
+                    localStorage.setItem(READER_COLLAPSED_STORAGE_KEY, collapsed ? '1' : '0');
+                    updateReaderToggleIcon();
+                }
 
                 function setReaderControlsPosition(position) {
                     const normalized = ['left', 'right'].includes(position) ? position : 'left';
@@ -1613,10 +1666,61 @@
                     localStorage.setItem(pdfjsPreferencesKey, JSON.stringify(preferences));
                 }
 
-                function initNightMode() {
-                    const enabled = localStorage.getItem(NIGHT_MODE_STORAGE_KEY) === '1';
-                    setNightMode(enabled);
-                }
+                function initNightMode() {
+                    const enabled = localStorage.getItem(NIGHT_MODE_STORAGE_KEY) === '1';
+                    setNightMode(enabled);
+                }
+
+                function getFullscreenElement() {
+                    return document.fullscreenElement ||
+                        document.webkitFullscreenElement ||
+                        document.mozFullScreenElement ||
+                        document.msFullscreenElement ||
+                        null;
+                }
+
+                function updateBrowserFullscreenButton() {
+                    const isFullscreen = !!getFullscreenElement();
+                    browserFullscreenButton.classList.toggle('is-active', isFullscreen);
+                    browserFullscreenButton.title = isFullscreen ? '退出浏览器全屏' : '浏览器全屏';
+                    browserFullscreenButton.setAttribute('aria-label', isFullscreen ? '退出浏览器全屏' : '浏览器全屏');
+                }
+
+                async function toggleBrowserFullscreen() {
+                    const target = document.documentElement;
+                    const isFullscreen = !!getFullscreenElement();
+
+                    try {
+                        if (isFullscreen) {
+                            if (document.exitFullscreen) {
+                                await document.exitFullscreen();
+                            } else if (document.webkitExitFullscreen) {
+                                document.webkitExitFullscreen();
+                            } else if (document.mozCancelFullScreen) {
+                                document.mozCancelFullScreen();
+                            } else if (document.msExitFullscreen) {
+                                document.msExitFullscreen();
+                            }
+                            return;
+                        }
+
+                        if (target.requestFullscreen) {
+                            await target.requestFullscreen({ navigationUI: 'hide' });
+                        } else if (target.webkitRequestFullscreen) {
+                            target.webkitRequestFullscreen();
+                        } else if (target.mozRequestFullScreen) {
+                            target.mozRequestFullScreen();
+                        } else if (target.msRequestFullscreen) {
+                            target.msRequestFullscreen();
+                        } else {
+                            alert('当前浏览器不支持网页全屏');
+                        }
+                    } catch (error) {
+                        console.warn('切换浏览器全屏失败:', error);
+                    } finally {
+                        setTimeout(updateBrowserFullscreenButton, 0);
+                    }
+                }
 
                 async function ensureLoggedIn() {
                     try {
@@ -1658,16 +1762,20 @@
                 userAdminBtn.addEventListener('click', function () {
                     window.location.href = '/admin';
                 });
-                initNightMode();
-                initReaderControls();
-                nightModeButton.addEventListener('click', function () {
-                    const nextEnabled = !document.body.classList.contains('night-reading-mode');
-                    setNightMode(nextEnabled);
-                    window.location.reload();
-                });
-                readerControlsCollapse.addEventListener('click', () => {
-                    setReaderControlsCollapsed(!readerControls.classList.contains('collapsed'));
-                });
+                initNightMode();
+                initReaderControls();
+                updateBrowserFullscreenButton();
+                nightModeButton.addEventListener('click', function () {
+                    const nextEnabled = !document.body.classList.contains('night-reading-mode');
+                    setNightMode(nextEnabled);
+                    window.location.reload();
+                });
+                browserFullscreenButton.addEventListener('click', () => {
+                    toggleBrowserFullscreen();
+                });
+                readerControlsCollapse.addEventListener('click', () => {
+                    setReaderControlsCollapsed(!readerControls.classList.contains('collapsed'));
+                });
                 readerSettingsButton.addEventListener('click', event => {
                     event.stopPropagation();
                     const nextOpen = !readerControls.classList.contains('settings-open');
@@ -1680,9 +1788,13 @@
                         readerSettingsButton.setAttribute('aria-expanded', 'false');
                     }
                 });
-                readerSettingsPanel.querySelectorAll('[data-size]').forEach(button => {
-                    button.addEventListener('click', () => setReaderControlsSize(button.dataset.size));
-                });
+                readerSettingsPanel.querySelectorAll('[data-size]').forEach(button => {
+                    button.addEventListener('click', () => setReaderControlsSize(button.dataset.size));
+                });
+                document.addEventListener('fullscreenchange', updateBrowserFullscreenButton);
+                document.addEventListener('webkitfullscreenchange', updateBrowserFullscreenButton);
+                document.addEventListener('mozfullscreenchange', updateBrowserFullscreenButton);
+                document.addEventListener('MSFullscreenChange', updateBrowserFullscreenButton);
 
                 async function saveReadingProgress(pageNumber) {
                     if (!currentFilePath || !Number.isInteger(pageNumber) || pageNumber < 1) return;