Просмотр исходного кода

ui: Improve playlist modal and main app layout

Playlist Modal Improvements:
- Remove thumbnails (not needed, metadata fetched after adding)
- Uncheck private/unavailable videos by default
- Rename "Download Selected" → "Add to Queue" (more accurate)

Main Layout Improvements:
- Make header and footer sticky
- Make video list scrollable independently
- Use flexbox with overflow control for proper layout
- Header/input section/footer stay fixed while video list scrolls

Changes:
- index.html: Layout structure + button text
- scripts/app.js: Playlist rendering logic

Result: Better UX with clearer actions and improved scrolling behavior.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
jopa79 3 месяцев назад
Родитель
Сommit
a2907dd9c6
2 измененных файлов с 16 добавлено и 9 удалено
  1. 7 7
      index.html
  2. 9 2
      scripts/app.js

+ 7 - 7
index.html

@@ -10,7 +10,7 @@
     <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
     <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
 </head>
 </head>
 
 
-<body class="bg-[#1d293d] text-white min-h-screen flex flex-col font-['Inter']">
+<body class="bg-[#1d293d] text-white h-screen overflow-hidden flex flex-col font-['Inter']">
     <!-- Header - macOS Title Bar Style -->
     <!-- Header - macOS Title Bar Style -->
     <header class="bg-[#0f172b] h-[41px] flex items-center justify-center border-b border-[#314158] shrink-0 relative"
     <header class="bg-[#0f172b] h-[41px] flex items-center justify-center border-b border-[#314158] shrink-0 relative"
         role="banner" aria-label="GrabZilla application header" style="-webkit-app-region: drag;">
         role="banner" aria-label="GrabZilla application header" style="-webkit-app-region: drag;">
@@ -128,13 +128,13 @@
     </section>
     </section>
 
 
     <!-- Video List - Flex grow to fill remaining space -->
     <!-- Video List - Flex grow to fill remaining space -->
-    <main class="flex-1 overflow-hidden" role="main" aria-label="Video download queue"
+    <main class="flex-1 overflow-hidden flex flex-col" role="main" aria-label="Video download queue"
         aria-describedby="main-content-help">
         aria-describedby="main-content-help">
         <div id="main-content-help" class="sr-only">
         <div id="main-content-help" class="sr-only">
             Video download queue. Use arrow keys to navigate, Enter or Space to select videos, Delete to remove videos.
             Video download queue. Use arrow keys to navigate, Enter or Space to select videos, Delete to remove videos.
         </div>
         </div>
-        <!-- Table Header -->
-        <div class="grid grid-cols-[40px_40px_1fr_120px_100px_120px_100px] gap-4 px-4 py-4 text-sm font-medium text-[#90a1b9] tracking-[-0.1504px]"
+        <!-- Table Header (Sticky) -->
+        <div class="shrink-0 grid grid-cols-[40px_40px_1fr_120px_100px_120px_100px] gap-4 px-4 py-4 text-sm font-medium text-[#90a1b9] tracking-[-0.1504px]"
             role="row" aria-label="Video list column headers">
             role="row" aria-label="Video list column headers">
             <div role="columnheader" aria-label="Selection checkbox"></div>
             <div role="columnheader" aria-label="Selection checkbox"></div>
             <div role="columnheader" aria-label="Drag handle"></div>
             <div role="columnheader" aria-label="Drag handle"></div>
@@ -145,8 +145,8 @@
             <div role="columnheader">Status</div>
             <div role="columnheader">Status</div>
         </div>
         </div>
 
 
-        <!-- Video Items Container -->
-        <div id="videoList" class="px-4 pt-2 pb-4 space-y-2 overflow-y-auto h-full" role="grid"
+        <!-- Video Items Container (Scrollable) -->
+        <div id="videoList" class="flex-1 px-4 pt-2 pb-4 space-y-2 overflow-y-auto" role="grid"
             aria-label="Video download queue" aria-describedby="video-list-instructions" tabindex="0">
             aria-label="Video download queue" aria-describedby="video-list-instructions" tabindex="0">
             <div id="video-list-instructions" class="sr-only">
             <div id="video-list-instructions" class="sr-only">
                 Use arrow keys to navigate between videos. Press Enter or Space to select videos. Press Delete to remove
                 Use arrow keys to navigate between videos. Press Enter or Space to select videos. Press Delete to remove
@@ -675,7 +675,7 @@
                         Cancel
                         Cancel
                     </button>
                     </button>
                     <button id="downloadSelectedPlaylistBtn" class="bg-[#155dfc] text-white px-4 py-2 rounded-lg text-sm font-medium">
                     <button id="downloadSelectedPlaylistBtn" class="bg-[#155dfc] text-white px-4 py-2 rounded-lg text-sm font-medium">
-                        Download Selected
+                        Add to Queue
                     </button>
                     </button>
                 </div>
                 </div>
             </div>
             </div>

+ 9 - 2
scripts/app.js

@@ -575,9 +575,16 @@ class GrabZillaApp {
         playlistData.videos.forEach((video, index) => {
         playlistData.videos.forEach((video, index) => {
             const videoItem = document.createElement('label');
             const videoItem = document.createElement('label');
             videoItem.className = 'flex items-center gap-3 p-2 hover:bg-[#45556c]/30 rounded cursor-pointer';
             videoItem.className = 'flex items-center gap-3 p-2 hover:bg-[#45556c]/30 rounded cursor-pointer';
+
+            // Check if video is private/unavailable (deselect by default)
+            const isPrivate = video.title.includes('[Private') ||
+                            video.title.includes('Private video') ||
+                            video.title.includes('[Deleted') ||
+                            video.title.includes('Unavailable');
+            const checkedAttr = isPrivate ? '' : 'checked';
+
             videoItem.innerHTML = `
             videoItem.innerHTML = `
-                <input type="checkbox" class="playlist-video-checkbox w-4 h-4" data-index="${index}" checked>
-                <img src="${video.thumbnail || 'assets/icons/video-placeholder.svg'}" alt="" class="w-16 h-12 object-cover rounded">
+                <input type="checkbox" class="playlist-video-checkbox w-4 h-4" data-index="${index}" ${checkedAttr}>
                 <div class="flex-1 min-w-0">
                 <div class="flex-1 min-w-0">
                     <p class="text-sm text-white truncate">${video.title}</p>
                     <p class="text-sm text-white truncate">${video.title}</p>
                     <p class="text-xs text-[#90a1b9]">${video.duration ? this.formatDuration(video.duration) : 'Unknown duration'}</p>
                     <p class="text-xs text-[#90a1b9]">${video.duration ? this.formatDuration(video.duration) : 'Unknown duration'}</p>