Browse Source

feat: modify playlist import to append and filter

regarding the playlist import functionality, rather than parsing the json content and replacing the in-memory playlist data, I want to: filter out any playlist items that are already marked as "done", add them to the end of the playlists without overriding the items that are already there, and not add any that are already currently in a playlist (that is already the current behaviour for adding an individual video).

```git-revs
23c3ef4  (Base revision)
3c012a0  Modify validateAndImportPlaylists to filter done videos and merge with existing playlists
03d874f  Replace updatePlaylists with appendToPlaylists that merges imported videos with existing ones
HEAD     Save conversation context
```

codemcp-id: 17-feat-modify-playlist-import-to-append-and-filter
Brandon Wong 7 months ago
parent
commit
4b39ec2da7
2 changed files with 75 additions and 7 deletions
  1. 42 0
      2025-11-07-codemcp-modify-playlist-import-to-append-and-filter.md
  2. 33 7
      popup/popup.js

+ 42 - 0
2025-11-07-codemcp-modify-playlist-import-to-append-and-filter.md

@@ -0,0 +1,42 @@
+# 2025-11-07 CodeMCP: Modify Playlist Import to Append and Filter
+
+## User Request
+
+regarding the playlist import functionality, rather than parsing the json content and replacing the in-memory playlist data, I want to: filter out any playlist items that are already marked as "done", add them to the end of the playlists without overriding the items that are already there, and not add any that are already currently in a playlist (that is already the current behaviour for adding an individual video).
+
+## Changes Made
+
+### Modified `validateAndImportPlaylists()` in popup/popup.js
+
+1. Added filtering logic to exclude videos marked as "done":
+   ```javascript
+   if (video.status === "done") {
+     return false;
+   }
+   ```
+
+2. Changed the final call from `this.updatePlaylists(validPlaylists)` to `this.appendToPlaylists(validPlaylists)`
+
+### Replaced `updatePlaylists()` with `appendToPlaylists()` in popup/popup.js
+
+Created a new method that:
+1. Creates a copy of current playlists
+2. Iterates through imported playlists and videos
+3. Uses `PlaylistUtils.findPlaylist()` to check if each video already exists in any playlist
+4. Only adds videos that don't already exist (deduplication)
+5. Appends videos to the end of their respective playlists
+6. Shows user feedback with counts of added and skipped videos
+
+Key implementation details:
+- Uses the existing `PlaylistUtils.findPlaylist()` utility which checks videos by their YouTube video ID
+- Maintains the same duplicate-checking behavior as adding individual videos
+- Creates new playlists if they don't exist yet
+- Provides informative user feedback: "Import complete! Added X video(s), skipped Y duplicate(s)."
+
+## Behavior Summary
+
+The import functionality now:
+1. ✅ Filters out videos marked as "done"
+2. ✅ Appends videos to end of playlists (doesn't replace existing items)
+3. ✅ Skips duplicates using the same logic as adding individual videos
+4. ✅ Provides clear feedback about what was added/skipped

+ 33 - 7
popup/popup.js

@@ -898,7 +898,7 @@ document.addEventListener("alpine:init", () => {
           continue;
         }
 
-        // Validate each video in the playlist
+        // Validate each video in the playlist and filter out done videos
         const validVideos = videos.filter((video) => {
           if (!video || typeof video !== "object") {
             console.error(`Invalid video object in '${playlistName}'`);
@@ -917,6 +917,10 @@ document.addEventListener("alpine:init", () => {
             return false;
           }
 
+          if (video.status === "done") {
+            return false;
+          }
+
           return true;
         });
 
@@ -939,18 +943,40 @@ document.addEventListener("alpine:init", () => {
       }
 
       // Update storage and state
-      this.updatePlaylists(validPlaylists);
+      this.appendToPlaylists(validPlaylists);
     },
 
-    async updatePlaylists(playlists) {
+    async appendToPlaylists(importedPlaylists) {
       try {
-        await browser.storage.local.set({ playlists });
-        this.playlists = playlists;
+        const currentPlaylists = JSON.parse(JSON.stringify(this.playlists));
+        let addedCount = 0;
+        let skippedCount = 0;
+
+        for (const [playlistName, importedVideos] of Object.entries(importedPlaylists)) {
+          if (!currentPlaylists[playlistName]) {
+            currentPlaylists[playlistName] = [];
+          }
+
+          for (const video of importedVideos) {
+            const alreadyExists = PlaylistUtils.findPlaylist(currentPlaylists, video.url);
+
+            if (!alreadyExists) {
+              currentPlaylists[playlistName].push(video);
+              addedCount++;
+            } else {
+              skippedCount++;
+            }
+          }
+        }
+
+        await browser.storage.local.set({ playlists: currentPlaylists });
+        this.playlists = currentPlaylists;
         this.updatePlaylistsForDisplay();
         this.updateCurrentPlaylistVideos();
-        alert("Playlists imported successfully!");
+
+        alert(`Import complete! Added ${addedCount} video(s), skipped ${skippedCount} duplicate(s).`);
       } catch (error) {
-        console.error("Error updating playlists:", error);
+        console.error("Error appending playlists:", error);
         alert("Error importing playlists: " + error.message);
       }
     },