Browse Source

feat: add visual styling for non-contiguous done videos

in the popup menu, there may be videos that are marked as "done" that come after videos that are not marked as done. even though they are not truncated with the contiguous "done" videos, they should be visually marked somehow. grey them out (very slightly) in the main view and in the individual playlist view. leave everything else the same.

```git-revs
63eade0  (Base revision)
e1bf1b1  Add isNonContiguousDone property to visible videos in main view
cf8ba40  Add isNonContiguousDone property to current playlist videos
57ccfdc  Add isNonContiguousDone method to identify done videos after non-done videos
0e5a1f2  Update videoItemClass to include non-contiguous-done-video class
8afed70  Add CSS styling for non-contiguous done videos
HEAD     Create context log file for the feature implementation
```

codemcp-id: 9-feat-add-visual-styling-for-non-contiguous-done-vi
Brandon Wong 1 year ago
parent
commit
57a28fb71d

+ 36 - 0
2025-05-31-codemcp-feat-add-visual-styling-for-non-contiguous-done-vi.md

@@ -0,0 +1,36 @@
+# 2025-05-31 - Feature: Add visual styling for non-contiguous done videos
+
+## User Request
+> in the popup menu, there may be videos that are marked as "done" that come after videos that are not marked as done. even though they are not truncated with the contiguous "done" videos, they should be visually marked somehow. grey them out (very slightly) in the main view and in the individual playlist view. leave everything else the same.
+
+## Implementation Summary
+
+Added visual styling for videos that are marked as "done" but appear after non-done videos in the playlist. These non-contiguous done videos are now visually distinguished with subtle greying.
+
+### Changes Made
+
+1. **JavaScript Logic (`popup/popup.js`)**:
+   - Added `isNonContiguousDone(playlistName, videoIndex)` method to identify done videos that come after non-done videos
+   - Updated `updatePlaylistsForDisplay()` to include `isNonContiguousDone` property in visible videos
+   - Updated `updateCurrentPlaylistVideos()` to include `isNonContiguousDone` property in current playlist videos
+   - Modified `videoItemClass` binding to apply `non-contiguous-done-video` CSS class
+
+2. **CSS Styling (`popup/popup.css`)**:
+   - Added `.non-contiguous-done-video` class with subtle opacity reduction (0.7) and light grey background
+   - Added `.non-contiguous-done-video .video-title` with greyed text color (#666)
+
+### Technical Details
+
+The `isNonContiguousDone` method checks if:
+1. The video at the given index is marked as "done"
+2. There exists at least one non-done video before it in the playlist
+
+This ensures only truly non-contiguous done videos are styled, maintaining the existing behavior for contiguous done videos at the beginning of playlists.
+
+The styling is applied in both:
+- Main playlists view (truncated display)
+- Individual playlist view (full display)
+
+### Files Modified
+- `popup/popup.js` - Added logic for identifying non-contiguous done videos
+- `popup/popup.css` - Added subtle visual styling for non-contiguous done videos

+ 9 - 0
popup/popup.css

@@ -121,6 +121,15 @@ button:hover {
   text-decoration: line-through;
 }
 
+.non-contiguous-done-video {
+  opacity: 0.7;
+  background-color: rgba(128, 128, 128, 0.05);
+}
+
+.non-contiguous-done-video .video-title {
+  color: #666;
+}
+
 /* Truncated videos indicator */
 .truncated-videos {
   padding: 8px 0 12px 8px;

+ 20 - 1
popup/popup.js

@@ -88,6 +88,7 @@ document.addEventListener("alpine:init", () => {
               ...video,
               originalIndex: currentIndex + index,
               doneButtonText: video.status === "done" ? "Remove Done Status" : "Mark as Done",
+              isNonContiguousDone: this.isNonContiguousDone(playlistName, currentIndex + index),
             }));
 
           return {
@@ -108,9 +109,10 @@ document.addEventListener("alpine:init", () => {
       ) {
         this.currentPlaylistVideos = [];
       } else {
-        this.currentPlaylistVideos = this.playlists[this.currentPlaylistName].map((video) => ({
+        this.currentPlaylistVideos = this.playlists[this.currentPlaylistName].map((video, index) => ({
           ...video,
           doneButtonText: video.status === "done" ? "Remove Done Status" : "Mark as Done",
+          isNonContiguousDone: this.isNonContiguousDone(this.currentPlaylistName, index),
         }));
       }
     },
@@ -482,6 +484,22 @@ document.addEventListener("alpine:init", () => {
       },
     },
 
+    isNonContiguousDone(playlistName, videoIndex) {
+      const playlist = this.playlists[playlistName];
+      if (!playlist || !playlist[videoIndex] || playlist[videoIndex].status !== "done") {
+        return false;
+      }
+
+      // Check if there's any non-done video before this done video
+      for (let i = 0; i < videoIndex; i++) {
+        if (playlist[i].status !== "done") {
+          return true;
+        }
+      }
+
+      return false;
+    },
+
     isCurrentVideo(playlistName, index) {
       const currentIndex = this.currentIndices[playlistName];
       return currentIndex === index;
@@ -507,6 +525,7 @@ document.addEventListener("alpine:init", () => {
           "current-video": this.isCurrentVideo(playlistName, index),
           "done-video":
             this.isDoneVideo(playlistName, index) && video.status === "done",
+          "non-contiguous-done-video": this.isNonContiguousDone(playlistName, index),
         };
       },
     },