fuzzyworld

tools / commit

adding export functionality

d981c94fbd99d3a14e0f1ca8e291aa233f58be86 · Pavel Safronov · 2025-07-21 22:21:34 -0700 · parents f86ea817ad75

adding export functionality
 separator-page/index.html | 112 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 111 insertions(+), 1 deletion(-)

diff --git a/separator-page/index.html b/separator-page/index.html
index 60f4c6f..35f9a21 100644
--- a/separator-page/index.html
+++ b/separator-page/index.html
@@ -198,7 +198,14 @@ This is a separator page!</textarea>
         <hr />
 
         <div class="previous-icons-container">
-            <h3>Previous Icons (shift-click to remove)</h3>
+            <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px;">
+                <h3 style="margin: 0;">Previous Icons (shift-click to remove)</h3>
+                <div style="display: flex; gap: 8px;">
+                    <button id="export-icons"
+                        style="padding: 4px 8px; font-size: 0.8em; background: #ddd; border: none; border-radius: 4px; cursor: pointer;">Export
+                        PNG</button>
+                </div>
+            </div>
             <div class="previous-icons" id="previous-icons">
                 <!-- Previous icons will be dynamically added here -->
             </div>
@@ -259,6 +266,9 @@ This is a separator page!</textarea>
         /** @type {HTMLDivElement} */
         const previousIconsContainer = document.getElementById("previous-icons");
 
+        /** @type {HTMLButtonElement} */
+        const exportIconsButton = document.getElementById("export-icons");
+
         // Global storage key for previous icons (shared across all tabs)
         const previousIconsKey = "separator-previous-icons";
         const maxPreviousIcons = 100; // Limit to 100 recent icons
@@ -336,6 +346,100 @@ This is a separator page!</textarea>
             });
         }
 
+        async function downloadImageAsFile(url, filename) {
+            try {
+                // If it's a data URL, we can download it directly
+                if (url.startsWith('data:')) {
+                    const link = document.createElement('a');
+                    link.href = url;
+                    link.download = filename;
+                    document.body.appendChild(link);
+                    link.click();
+                    document.body.removeChild(link);
+                    return true;
+                }
+
+                // For external URLs, we need to fetch and convert
+                const response = await fetch(url);
+                const blob = await response.blob();
+
+                // Convert to PNG if it's not already
+                const canvas = document.createElement('canvas');
+                const ctx = canvas.getContext('2d');
+                const img = new Image();
+
+                return new Promise((resolve) => {
+                    img.onload = () => {
+                        canvas.width = img.width;
+                        canvas.height = img.height;
+                        ctx.drawImage(img, 0, 0);
+
+                        canvas.toBlob((pngBlob) => {
+                            const link = document.createElement('a');
+                            link.href = URL.createObjectURL(pngBlob);
+                            link.download = filename;
+                            document.body.appendChild(link);
+                            link.click();
+                            document.body.removeChild(link);
+                            URL.revokeObjectURL(link.href);
+                            resolve(true);
+                        }, 'image/png');
+                    };
+
+                    img.onerror = () => {
+                        console.warn(`Failed to load image: ${url}`);
+                        resolve(false);
+                    };
+
+                    img.crossOrigin = 'anonymous';
+                    img.src = URL.createObjectURL(blob);
+                });
+            } catch (error) {
+                console.warn(`Failed to download ${url}:`, error);
+                return false;
+            }
+        }
+
+        async function exportIcons() {
+            const previousIcons = JSON.parse(localStorage.getItem(previousIconsKey) || "[]");
+
+            if (previousIcons.length === 0) {
+                alert('No icons to export!');
+                return;
+            }
+
+            // Update button to show progress
+            const originalText = exportIconsButton.textContent;
+            exportIconsButton.textContent = "Exporting...";
+            exportIconsButton.style.background = "#ffa500";
+            exportIconsButton.disabled = true;
+
+            let successCount = 0;
+
+            for (let i = 0; i < previousIcons.length; i++) {
+                const iconUrl = previousIcons[i];
+                const filename = `template-icon-${i + 1}.png`;
+
+                const success = await downloadImageAsFile(iconUrl, filename);
+                if (success) {
+                    successCount++;
+                }
+
+                // Small delay between downloads to prevent overwhelming the browser
+                await new Promise(resolve => setTimeout(resolve, 100));
+            }
+
+            // Show completion feedback
+            exportIconsButton.textContent = `Exported ${successCount}/${previousIcons.length}`;
+            exportIconsButton.style.background = successCount === previousIcons.length ? "#4CAF50" : "#ff9800";
+
+            setTimeout(() => {
+                exportIconsButton.textContent = originalText;
+                exportIconsButton.style.background = "#ddd";
+                exportIconsButton.disabled = false;
+            }, 3000);
+        }
+
         function saveTabData() {
             const data = {
                 id: tabId,
@@ -429,6 +533,12 @@ This is a separator page!</textarea>
             }
         });
 
+        // Export icons as PNG files
+        exportIconsButton.addEventListener("click", exportIcons);
+
+        // Import icons from JSON file
+        importIconsButton.addEventListener("click", importIcons);
+
         // Title and description event listeners
         titleElement.addEventListener("input", () => {
             console.debug('Title updated to:', titleElement.innerText);