Bläddra i källkod

Update index.html

Toby Chui 3 veckor sedan
förälder
incheckning
b605dba5d4
1 ändrade filer med 101 tillägg och 8 borttagningar
  1. 101 8
      src/web/Movie/index.html

+ 101 - 8
src/web/Movie/index.html

@@ -1371,7 +1371,7 @@ img.ctx-icon { height: 16px; opacity: 0.85; display: block; }
 }
 
 /* ─── Video info modal ───────────────────────────────────────────────────────── */
-#video-info-modal {
+#video-info-modal, #adv-settings-modal {
     display: none;
     position: absolute;
     top: 50%; left: 50%;
@@ -1385,17 +1385,29 @@ img.ctx-icon { height: 16px; opacity: 0.85; display: block; }
     width: 340px;
     box-shadow: 0 8px 40px rgba(0,0,0,0.8), 0 0 0 1px rgba(255,255,255,0.1);
 }
-#video-info-modal h3 {
+#video-info-modal h3, #adv-settings-modal h3 {
     font-size: 14px; font-weight: 600;
     margin-bottom: 12px;
     display: flex; align-items: center; justify-content: space-between;
 }
-#video-info-close {
+#video-info-close, #adv-settings-close {
     background: none; border: none; cursor: pointer;
     color: var(--text-sub); font-size: 17px; line-height: 1; padding: 0; outline: none;
 }
-#video-info-close img { width: 14px; height: 14px; display: block; opacity: 0.55; transition: opacity var(--transition); }
-#video-info-close:hover img { opacity: 1; }
+#video-info-close img, #adv-settings-close img { width: 14px; height: 14px; display: block; opacity: 0.55; transition: opacity var(--transition); }
+#video-info-close:hover img, #adv-settings-close:hover img { opacity: 1; }
+
+/* Advanced settings modal rows — same switch as the Settings tab, tighter */
+#adv-settings-modal { width: 380px; max-height: 70%; overflow-y: auto; }
+.adv-row {
+    display: flex; align-items: center; gap: 14px;
+    padding: 10px 0;
+    border-top: 1px solid rgba(255,255,255,0.06);
+}
+.adv-row:first-child { border-top: none; }
+.adv-row-text  { flex: 1; min-width: 0; }
+.adv-row-label { font-size: 13px; font-weight: 600; margin-bottom: 3px; }
+.adv-row-desc  { font-size: 11px; color: var(--text-sub); line-height: 1.45; }
 #video-info-tabs {
     display: flex; gap: 3px;
     background: var(--surface2);
@@ -1795,6 +1807,26 @@ img.ctx-icon { height: 16px; opacity: 0.85; display: block; }
                 <div id="video-info-body"></div>
             </div>
 
+            <!-- Advanced settings modal -->
+            <div id="adv-settings-modal">
+                <h3><span>Advanced Settings</span><button id="adv-settings-close" title="Close" onclick="closeAdvancedSettings()"><img src="img/icons/close_white.svg" alt=""></button></h3>
+                <div id="adv-settings-body">
+                    <div class="adv-row">
+                        <div class="adv-row-text">
+                            <div class="adv-row-label">Disable playlist show when change episode</div>
+                            <div class="adv-row-desc">
+                                Keep the playlist hidden when you skip to another episode. When this is
+                                off, a hidden playlist peeks open for 2 seconds and closes again.
+                            </div>
+                        </div>
+                        <label class="settings-switch" title="Disable playlist show when change episode">
+                            <input type="checkbox" id="adv-no-playlist-peek">
+                            <span class="settings-switch-track"></span>
+                        </label>
+                    </div>
+                </div>
+            </div>
+
             <!-- Playback settings popup -->
             <div id="settings-popup">
                 <div class="set-section">
@@ -1833,6 +1865,9 @@ img.ctx-icon { height: 16px; opacity: 0.85; display: block; }
                     <div class="set-link" id="set-video-props">
                         <img src="img/icons/menu_white.svg" alt="">Video properties
                     </div>
+                    <div class="set-link" id="set-advanced">
+                        <img src="img/icons/settings_white.svg" alt="">Advanced settings
+                    </div>
                 </div>
             </div>
 
@@ -1978,6 +2013,13 @@ var libraryCacheTs   = 0;   // timestamp of the index currently in memory
 // stop auto-managing it until the next playback starts.
 var playlistUserToggled = false;
 
+// Skipping between episodes must not reshuffle the layout. A playlist that is
+// already open stays open; a closed one only peeks open for this long before
+// tucking itself away again (unless the user disabled the peek entirely).
+var PLAYLIST_PEEK_MS   = 2000;
+var playlistPeekTimer  = null;
+var disablePlaylistPeek = (localStorage.getItem('movie_no_playlist_peek') === '1');
+
 // ─── Arozcast cast state ──────────────────────────────────────────────────────
 var castWs          = null;
 var castCode        = null;
@@ -3487,6 +3529,9 @@ function isWebPlayable(ext) {
     return ['mp4', 'webm', 'ogg'].includes(ext);
 }
 function startPlayback(index) {
+    // Coming from inside the player means this is an episode change rather than
+    // a fresh playback, and the playlist is handled differently (see below).
+    var isEpisodeChange = $('#view-player').hasClass('active');
     cancelCountdown();
     hideSeekFreeze();   // never carry a frozen frame across to a different episode
     resetSubtitleSeekFloor();   // a fresh episode starts unsuppressed
@@ -3540,9 +3585,14 @@ function startPlayback(index) {
 
     renderSidebar(currentEpisodes, index);
 
-    // New playback — drop any manual show/hide the user applied to the last one
-    playlistUserToggled = false;
-    applyPlaylistVisibility();
+    if (isEpisodeChange) {
+        peekPlaylistForEpisodeChange();
+    } else {
+        // New playback — drop any manual show/hide the user applied to the last one
+        cancelPlaylistPeek();
+        playlistUserToggled = false;
+        applyPlaylistVisibility();
+    }
 
     highlightPlayingEpisode(index);
 
@@ -3669,6 +3719,7 @@ function closePlayer() {
     }
     saveWatchPosition();
     cancelCountdown();
+    cancelPlaylistPeek();
     hideSeekFreeze();
     resetStoryboard();
     resetEmbeddedTracks();
@@ -3931,10 +3982,34 @@ function toggleFullscreen() {
 }
 
 function toggleSidebar() {
+    cancelPlaylistPeek();         // a manual toggle outranks a pending auto-close
     playlistUserToggled = true;   // stop auto-management until the next playback
     $('#playlist-sidebar').toggleClass('collapsed');
 }
 
+function cancelPlaylistPeek() {
+    if (playlistPeekTimer) { clearTimeout(playlistPeekTimer); playlistPeekTimer = null; }
+}
+
+// Skipping to another episode used to re-run applyPlaylistVisibility(), which
+// popped the sidebar open and left it there. Instead: leave an open playlist
+// alone, and let a closed one peek open just long enough to show what is playing
+// now — or not at all, when disabled in Advanced settings.
+function peekPlaylistForEpisodeChange() {
+    cancelPlaylistPeek();
+    var $sidebar = $('#playlist-sidebar');
+    if (!$sidebar.hasClass('collapsed')) { return; }   // already open — nothing to do
+    if (disablePlaylistPeek) { return; }
+    if (!currentEpisodes || currentEpisodes.length <= 1) { return; }
+    $sidebar.removeClass('collapsed');
+    playlistPeekTimer = setTimeout(function () {
+        playlistPeekTimer = null;
+        $('#playlist-sidebar').addClass('collapsed');
+        // The peek is transient — keep a later resize from re-opening it
+        playlistUserToggled = true;
+    }, PLAYLIST_PEEK_MS);
+}
+
 // The playlist sidebar eats a lot of width, so it is only opened automatically
 // where there is room for it: a wide (desktop/laptop) viewport, or any device
 // held in landscape. A phone/tablet in portrait starts with it collapsed — the
@@ -4230,6 +4305,13 @@ function initSettingsPopup() {
     });
 
     $('#set-video-props').on('click', function () { closeSettingsPopup(); openVideoInfo('props'); });
+    $('#set-advanced').on('click',    function () { closeSettingsPopup(); openAdvancedSettings(); });
+
+    $('#adv-no-playlist-peek').on('change', function () {
+        disablePlaylistPeek = $(this).is(':checked');
+        localStorage.setItem('movie_no_playlist_peek', disablePlaylistPeek ? '1' : '0');
+        if (disablePlaylistPeek) { cancelPlaylistPeek(); }
+    });
 
     // Apply persisted values to the video element
     setRepeatSingle(repeatSingle);
@@ -4246,6 +4328,7 @@ function initSettingsPopup() {
 
 function openVideoInfo(tab) {
     currentInfoTab = tab || 'props';
+    closeAdvancedSettings();
     $('#video-info-modal').show();
     $('.info-tab').removeClass('active').eq(currentInfoTab === 'props' ? 0 : 1).addClass('active');
     $('#video-info-title').text(currentInfoTab === 'props' ? 'Video Properties' : 'Streaming Stats');
@@ -4261,6 +4344,14 @@ function closeVideoInfo() {
     if (infoRefreshTimer) { clearInterval(infoRefreshTimer); infoRefreshTimer = null; }
 }
 
+function openAdvancedSettings() {
+    closeVideoInfo();
+    $('#adv-no-playlist-peek').prop('checked', disablePlaylistPeek);
+    $('#adv-settings-modal').show();
+}
+
+function closeAdvancedSettings() { $('#adv-settings-modal').hide(); }
+
 function showInfoTab(tab) {
     currentInfoTab = tab;
     $('.info-tab').removeClass('active').eq(tab === 'props' ? 0 : 1).addClass('active');
@@ -4403,11 +4494,13 @@ function initKeyboard() {
                         $('#subtitle-popup').hasClass('active') ||
                         $('#player-ctx').is(':visible') ||
                         $('#video-info-modal').is(':visible') ||
+                        $('#adv-settings-modal').is(':visible') ||
                         $('#subtitle-settings-modal').is(':visible')) {
                         closeSettingsPopup();
                         closeSubtitlePopup();
                         $('#player-ctx').hide();
                         closeVideoInfo();
+                        closeAdvancedSettings();
                         closeSubtitleSettings();
                     } else {
                         closePlayer();