|
|
@@ -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>
|
|
|
+
|
|
|
+
|