Explorar o código

greyed-out any video that was already watched (in order)

Brandon Wong hai 1 ano
pai
achega
fa221f4c67
Modificáronse 3 ficheiros con 272 adicións e 8 borrados
  1. 233 4
      2025-04-18-12-claude-mark-current-video.md
  2. 10 1
      popup/popup.css
  3. 29 3
      popup/popup.js

+ 233 - 4
2025-04-18-12-claude-mark-current-video.md

@@ -553,9 +553,238 @@ Need any adjustments to the styling or logic? You could also add an icon or addi
 ## Me
 
 > Sharing:
-> - <buf>popup/popup.html</buf>
-> - <buf>popup/popup.js</buf>
+> - 👀 <buf>popup/popup.html</buf>
+> - 👀 <buf>popup/popup.js</buf>
 > - <tool>files</tool>
-> - <buf>popup/popup.css</buf>
+> - 👀 <buf>popup/popup.css</buf>
+
+grey-out all the videos that are consecutively "done" from the beginning of the playlist. in other words, if there are any videos that are "done", but any of the videos before it are not "done", then leave it as normal.
+
+## CodeCompanion (Anthropic)
+
+### Reasoning
+
+I need to modify the code to grey-out all the videos that are consecutively "done" from the beginning of the playlist. Here's my plan:
+
+1. Create a new method in the Alpine.js component to determine if a video is part of the "consecutively done" videos from the beginning of the playlist.
+
+2. Add a new CSS class binding to each video item based on this determination.
+
+3. Add the CSS for the "done-video" styling.
+
+Let me work through this:
+
+First, the isConsecutivelyDone method logic:
+- For a video to be "consecutively done", it must:
+  - Be marked as "done"
+  - All videos BEFORE it in the playlist must also be "done"
+
+This means that we need to check all videos from index 0 up to (but not including) the current video's index.
+
+Here's the JavaScript function I'll add:
+
+```javascript
+isConsecutivelyDone(playlistName, index) {
+  const playlist = this.playlists[playlistName];
+  if (!playlist || !Array.isArray(playlist)) return false;
+  
+  // Current video must be "done" first
+  if (!playlist[index]?.status || playlist[index].status !== "done") {
+    return false;
+  }
+  
+  // Check all previous videos
+  for (let i = 0; i < index; i++) {
+    if (!playlist[i]?.status || playlist[i].status !== "done") {
+      return false; // Found a non-done video before the current one
+    }
+  }
+  
+  return true; // Current video is done, and all videos before it are done
+}
+```
+
+Then, I'll add this to the videoItemClass binding:
+
+```javascript
+videoItemClass: {
+  [":class"]() {
+    return {
+      'current-video': this.isCurrentVideo(
+        this.$el.dataset.playlistName,
+        parseInt(this.$el.dataset.playlistIndex)
+      ),
+      'done-video': this.isConsecutivelyDone(
+        this.$el.dataset.playlistName,
+        parseInt(this.$el.dataset.playlistIndex)
+      )
+    };
+  }
+}
+```
+
+And finally, add the CSS for the done-video class:
+
+```css
+.done-video {
+  color: #999;
+  text-decoration: line-through;
+  opacity: 0.7;
+}
+```
+
+I need to be careful that this styling doesn't conflict with the current-video styling in case there's some edge case. The most important thing is that this logic correctly identifies the consecutively done videos from the start of the playlist.
+
+### Response
+
+I'll implement the greying-out of consecutively "done" videos from the beginning of the playlist. Here's the approach:
+
+1. First, let's add the logic to identify consecutively done videos:
+
+```xml
+<tools>
+  <tool name="files">
+    <action type="edit">
+      <path>/home/brwong/projects/experiments/playlist/popup/popup.js</path>
+      <search><![CDATA[isCurrentVideo(playlistName, index) {
+        const playlist = this.playlists[playlistName];
+        if (!playlist || !Array.isArray(playlist)) return false;
+        
+        // Find the index of the first video that is not "done"
+        const currentIndex = playlist.findIndex(video => {
+          // Consider a video as not done if:
+          // 1. It has no status property, or
+          // 2. The status is not "done" (could be a number for partially watched)
+          return !video.status || video.status !== "done";
+        });
+        
+        // If no "current" video found (all are done) or current index doesn't match, return false
+        return currentIndex === index && currentIndex !== -1;
+      },]]></search>
+      <replace><![CDATA[isCurrentVideo(playlistName, index) {
+        const playlist = this.playlists[playlistName];
+        if (!playlist || !Array.isArray(playlist)) return false;
+        
+        // Find the index of the first video that is not "done"
+        const currentIndex = playlist.findIndex(video => {
+          // Consider a video as not done if:
+          // 1. It has no status property, or
+          // 2. The status is not "done" (could be a number for partially watched)
+          return !video.status || video.status !== "done";
+        });
+        
+        // If no "current" video found (all are done) or current index doesn't match, return false
+        return currentIndex === index && currentIndex !== -1;
+      },
+      
+      isConsecutivelyDone(playlistName, index) {
+        const playlist = this.playlists[playlistName];
+        if (!playlist || !Array.isArray(playlist)) return false;
+        
+        // Current video must be "done" first
+        if (!playlist[index]?.status || playlist[index].status !== "done") {
+          return false;
+        }
+        
+        // Check all previous videos - they must ALL be done
+        for (let i = 0; i < index; i++) {
+          if (!playlist[i]?.status || playlist[i].status !== "done") {
+            return false; // Found a non-done video before the current one
+          }
+        }
+        
+        return true; // Current video is done, and all videos before it are done
+      },]]></replace>
+    </action>
+  </tool>
+</tools>
+```
+
+2. Now update the videoItemClass binding to include the done-video class:
+
+```xml
+<tools>
+  <tool name="files">
+    <action type="edit">
+      <path>/home/brwong/projects/experiments/playlist/popup/popup.js</path>
+      <search><![CDATA[videoItemClass: {
+        [":class"]() {
+          return {
+            'current-video': this.isCurrentVideo(
+              this.$el.dataset.playlistName,
+              parseInt(this.$el.dataset.playlistIndex)
+            )
+          };
+        }
+      },]]></search>
+      <replace><![CDATA[videoItemClass: {
+        [":class"]() {
+          return {
+            'current-video': this.isCurrentVideo(
+              this.$el.dataset.playlistName,
+              parseInt(this.$el.dataset.playlistIndex)
+            ),
+            'done-video': this.isConsecutivelyDone(
+              this.$el.dataset.playlistName,
+              parseInt(this.$el.dataset.playlistIndex)
+            )
+          };
+        }
+      },]]></replace>
+    </action>
+  </tool>
+</tools>
+```
+
+3. Finally, add the CSS for the done-video class:
+
+```xml
+<tools>
+  <tool name="files">
+    <action type="edit">
+      <path>/home/brwong/projects/experiments/playlist/popup/popup.css</path>
+      <search><![CDATA[.current-video {
+    background-color: #e3f2fd;
+    border-left: 3px solid #4285f4;
+    padding-left: 5px;
+    font-weight: bold;
+}]]></search>
+      <replace><![CDATA[.current-video {
+    background-color: #e3f2fd;
+    border-left: 3px solid #4285f4;
+    padding-left: 5px;
+    font-weight: bold;
+}
+
+.done-video {
+    color: #999;
+    opacity: 0.6;
+}
+
+.done-video .video-title {
+    text-decoration: line-through;
+}]]></replace>
+    </action>
+  </tool>
+</tools>
+```
+
+These changes will:
+
+1. Add a method to identify videos that are "done" and have all previous videos also marked as "done"
+2. Update the class binding to apply the 'done-video' class to those videos
+3. Style the "done" videos with grey text, reduced opacity, and strikethrough for the title
+
+The current video highlighting will take precedence if somehow a video is both "current" and "done" (which shouldn't happen with your logic, but it's better to be safe).
+
+Would you like me to make any adjustments to the styling or logic?
+
+## Me
+
+> Sharing:
+> - 👀 <buf>popup/popup.html</buf>
+> - 👀 <buf>popup/popup.js</buf>
+> - <tool>files</tool>
+> - 👀 <buf>popup/popup.css</buf>
+
 
-I rejected the running of the files toolI rejected the running of the files toolI rejected the running of the files toolI rejected the running of the files toolI rejected the running of the files tool

+ 10 - 1
popup/popup.css

@@ -103,4 +103,13 @@ button:hover, a.play-btn:hover {
     border-left: 3px solid #4285f4;
     padding-left: 8px;
     font-weight: bold;
-}
+}
+
+.done-video {
+    color: #999;
+    opacity: 0.6;
+}
+
+.done-video .video-title {
+    text-decoration: line-through;
+}

+ 29 - 3
popup/popup.js

@@ -176,14 +176,36 @@ document.addEventListener("alpine:init", () => {
       if (!playlist || !Array.isArray(playlist)) return false;
 
       // Find the index of the first video that is not "done"
-      const currentIndex = playlist.findIndex(
-        (video) => video.status !== "done",
-      );
+      const currentIndex = playlist.findIndex((video) => {
+        // Consider a video as not done if:
+        // 1. It has no status property, or
+        // 2. The status is not "done" (could be a number for partially watched)
+        return !video.status || video.status !== "done";
+      });
 
       // If no "current" video found (all are done) or current index doesn't match, return false
       return currentIndex === index && currentIndex !== -1;
     },
 
+    isConsecutivelyDone(playlistName, index) {
+      const playlist = this.playlists[playlistName];
+      if (!playlist || !Array.isArray(playlist)) return false;
+
+      // Current video must be "done" first
+      if (!playlist[index]?.status || playlist[index].status !== "done") {
+        return false;
+      }
+
+      // Check all previous videos - they must ALL be done
+      for (let i = 0; i < index; i++) {
+        if (!playlist[i]?.status || playlist[i].status !== "done") {
+          return false; // Found a non-done video before the current one
+        }
+      }
+
+      return true; // Current video is done, and all videos before it are done
+    },
+
     videoItemClass: {
       [":class"]() {
         return {
@@ -191,6 +213,10 @@ document.addEventListener("alpine:init", () => {
             this.$el.dataset.playlistName,
             parseInt(this.$el.dataset.playlistIndex),
           ),
+          "done-video": this.isConsecutivelyDone(
+            this.$el.dataset.playlistName,
+            parseInt(this.$el.dataset.playlistIndex),
+          ),
         };
       },
     },