Parcourir la source

added an export button

Brandon Wong il y a 1 an
Parent
commit
1d8807c557
3 fichiers modifiés avec 270 ajouts et 0 suppressions
  1. 216 0
      2025-04-09-9-claude-export-button.md
  2. 7 0
      popup/popup.html
  3. 47 0
      popup/popup.js

+ 216 - 0
2025-04-09-9-claude-export-button.md

@@ -0,0 +1,216 @@
+## Me
+
+> Sharing:
+> - 👀 <buf>popup/popup.html</buf>
+> - 👀 <buf>popup/popup.js</buf>
+> - <tool>files</tool>
+
+@files this is the html and js code of a firefox browser extension popup window, implemented with alpine.js (using the CSP-friendly mode). add a button at the bottom of the window that will export the playlists and the playback history and download it as a json file.
+
+## CodeCompanion (Anthropic)
+
+### Reasoning
+
+I need to add a button to the popup HTML and implement JavaScript functionality to export playlists and playback history as a JSON file. Let's break down the task:
+
+1. Add an export button to the HTML at the bottom of the popup window
+2. Implement a JavaScript function to:
+   - Gather playlist data (already in the `this.playlists` object)
+   - Gather playback history (doesn't seem to be implemented yet, so I'll add it)
+   - Combine them into a JSON object
+   - Create and trigger a download for this JSON data
+
+Let's start by modifying the HTML file to add the export button:
+
+For the HTML (`popup.html`), I'll add a button at the bottom, after the playlists container but still within the app div:
+
+```html
+<div id="app" x-data="playlistManager">
+  <!-- existing header and playlists content -->
+  
+  <div class="playlists-container">
+    <!-- existing playlist template -->
+  </div>
+  
+  <!-- New export button -->
+  <div class="actions-container">
+    <button class="export-btn" x-bind="exportButton">Export Playlists</button>
+  </div>
+</div>
+```
+
+Now for the JavaScript (`popup.js`), I need to add:
+1. An `exportButton` binding similar to the existing button bindings
+2. An `exportPlaylists` function that does the actual export work
+
+Here's what I'll add to the Alpine data object:
+
+```javascript
+exportButton: {
+  ["@click"]() {
+    this.exportPlaylists();
+  },
+},
+
+async exportPlaylists() {
+  try {
+    // Get current playlists from our data
+    const playlists = this.playlists;
+    
+    // Get playback history if it exists (or use empty object)
+    const result = await browser.storage.local.get("playbackHistory");
+    const playbackHistory = result.playbackHistory || {};
+    
+    // Combine into a single export object
+    const exportData = {
+      playlists: playlists,
+      playbackHistory: playbackHistory,
+      exportDate: new Date().toISOString()
+    };
+    
+    // Convert to JSON string
+    const jsonString = JSON.stringify(exportData, null, 2);
+    
+    // Create a download link
+    const blob = new Blob([jsonString], { type: 'application/json' });
+    const url = URL.createObjectURL(blob);
+    
+    // Create a temporary link element and trigger download
+    const a = document.createElement('a');
+    a.href = url;
+    a.download = `playlists-export-${new Date().toISOString().split('T')[0]}.json`;
+    document.body.appendChild(a);
+    a.click();
+    
+    // Clean up
+    setTimeout(() => {
+      document.body.removeChild(a);
+      URL.revokeObjectURL(url);
+    }, 100);
+    
+  } catch (error) {
+    console.error("Error exporting playlists:", error);
+  }
+}
+```
+
+Now I'll put this all together to create the changes needed.
+
+For `popup.html`, I'll add the export button at the bottom, after line 59 (the closing of the playlists-container) but before line 60 (the closing of the app div).
+
+For `popup.js`, I'll add the new methods to the Alpine data object before the final closing braces.
+
+Let me create the XML response for the tools:
+
+### Response
+
+Looking at your files, I'll add an export button at the bottom of the popup window to export playlists and playback history as a JSON file.
+
+First, let's add the button to the HTML and then implement the JavaScript functionality:
+
+```xml
+<tools>
+  <tool name="files">
+    <action type="edit">
+      <path>/home/brwong/projects/experiments/playlist/popup/popup.html</path>
+      <search><![CDATA[        </div>
+      </div>
+    </body>]]></search>
+      <replace><![CDATA[        </div>
+        
+        <!-- Export button -->
+        <div class="export-container">
+          <button class="export-btn" x-bind="exportButton">Export Playlists</button>
+        </div>
+      </div>
+    </body>]]></replace>
+    </action>
+  </tool>
+</tools>
+```
+
+Now let's add the JavaScript functionality to handle the export:
+
+```xml
+<tools>
+  <tool name="files">
+    <action type="edit">
+      <path>/home/brwong/projects/experiments/playlist/popup/popup.js</path>
+      <search><![CDATA[      removeVideoButton: {
+        ["@click"]() {
+          this.removeVideo(
+            this.$el.dataset.playlistName,
+            this.$el.dataset.playlistIndex,
+          );
+        },
+      },]]></search>
+      <replace><![CDATA[      removeVideoButton: {
+        ["@click"]() {
+          this.removeVideo(
+            this.$el.dataset.playlistName,
+            this.$el.dataset.playlistIndex,
+          );
+        },
+      },
+      
+      exportButton: {
+        ["@click"]() {
+          this.exportPlaylists();
+        },
+      },
+      
+      async exportPlaylists() {
+        try {
+          // Get current playlists
+          const playlists = this.playlists;
+          
+          // Get playback history if it exists
+          const result = await browser.storage.local.get("playbackHistory");
+          const playbackHistory = result.playbackHistory || {};
+          
+          // Create export data object
+          const exportData = {
+            playlists: playlists,
+            playbackHistory: playbackHistory,
+            exportDate: new Date().toISOString()
+          };
+          
+          // Convert to JSON
+          const jsonString = JSON.stringify(exportData, null, 2);
+          
+          // Create download
+          const blob = new Blob([jsonString], { type: 'application/json' });
+          const url = URL.createObjectURL(blob);
+          
+          // Trigger download
+          const a = document.createElement('a');
+          a.href = url;
+          a.download = `playlists-export-${new Date().toISOString().split('T')[0]}.json`;
+          document.body.appendChild(a);
+          a.click();
+          
+          // Clean up
+          setTimeout(() => {
+            document.body.removeChild(a);
+            URL.revokeObjectURL(url);
+          }, 100);
+          
+        } catch (error) {
+          console.error("Error exporting playlists:", error);
+        }
+      },]]></replace>
+    </action>
+  </tool>
+</tools>
+```
+
+Now we should also add some basic styling for the export button. Would you like me to create or modify a CSS file for this as well?
+
+## Me
+
+> Sharing:
+> - 👀 <buf>popup/popup.html</buf>
+> - 👀 <buf>popup/popup.js</buf>
+> - <tool>files</tool>
+
+

+ 7 - 0
popup/popup.html

@@ -57,6 +57,13 @@
           </div>
         </template>
       </div>
+
+      <!-- Export button -->
+      <div class="export-container">
+        <button class="export-btn" x-bind="exportButton">
+          Export Playlists
+        </button>
+      </div>
     </div>
   </body>
 </html>

+ 47 - 0
popup/popup.js

@@ -60,6 +60,47 @@ document.addEventListener("alpine:init", () => {
       }
     },
 
+    async exportPlaylists() {
+      try {
+        // Get current playlists
+        const playlistResult = await browser.storage.local.get("playlists");
+        const playlists = playlistResult.playlists || {};
+
+        // Get playback history
+        const historyResult = await browser.storage.local.get("history");
+        const playbackHistory = historyResult.history || {};
+
+        // Create export data object
+        const exportData = {
+          playlists,
+          playbackHistory,
+          exportDate: new Date().toISOString(),
+        };
+
+        // Convert to JSON
+        const jsonString = JSON.stringify(exportData, null, 2);
+
+        // Create download
+        const blob = new Blob([jsonString], { type: "application/json" });
+        const url = URL.createObjectURL(blob);
+
+        // Trigger download
+        const a = document.createElement("a");
+        a.href = url;
+        a.download = `playlists-export-${new Date().toISOString().split("T")[0]}.json`;
+        document.body.appendChild(a);
+        a.click();
+
+        // Clean up
+        setTimeout(() => {
+          document.body.removeChild(a);
+          URL.revokeObjectURL(url);
+        }, 100);
+      } catch (error) {
+        console.error("Error exporting playlists:", error);
+      }
+    },
+
     videotitle: {
       ["@click"]() {
         console.log("TITLE CLICK", this.$el);
@@ -80,5 +121,11 @@ document.addEventListener("alpine:init", () => {
         );
       },
     },
+
+    exportButton: {
+      ["@click"]() {
+        this.exportPlaylists();
+      },
+    },
   }));
 });