// LinkSync Popup Script // Handles bookmark management and sync operations (function() { 'use strict'; const Popup = { // API Configuration API_BASE_URL: '', API_KEY: '', // Initialize popup async init() { console.log('LinkSync: Popup initialized'); // Load settings await this.loadSettings(); // Setup event listeners this.setupEventListeners(); // Load bookmarks await this.loadBookmarks(); // Load collections await this.loadCollections(); // Update sync status this.updateSyncStatus(); }, // Load settings from storage async loadSettings() { this.API_BASE_URL = await this.getSetting('url') || 'http://localhost:5000'; this.API_KEY = await this.getSetting('apiKey') || ''; // Update form this.updateFormState(); }, // Get setting from storage async getSetting(key) { return new Promise(resolve => { browser.storage.local.get(key, result => resolve(result[key])); }); }, // Setup event listeners setupEventListeners() { // Form submission document.getElementById('bookmark-form').addEventListener('submit', async (e) => { e.preventDefault(); await this.addBookmark(); }); // Search filter document.getElementById('search').addEventListener('input', async (e) => { await this.filterBookmarks(e.target.value); }); // Sync button document.getElementById('sync-btn').addEventListener('click', async () => { await this.syncBookmarks(); }); // Settings button document.getElementById('settings-btn').addEventListener('click', () => { this.openSettings(); }); }, // Update form state (edit mode) updateFormState(isEdit = false) { const form = document.getElementById('bookmark-form'); if (isEdit) { form.style.display = 'block'; } else { form.style.display = 'none'; } }, // Load bookmarks from server async loadBookmarks() { try { const response = await fetch(`${this.API_BASE_URL}/api/links/`, { headers: { 'Authorization': `Token ${this.API_KEY}` } }); if (response.ok) { const data = await response.json(); this.renderBookmarks(data.links || []); } } catch (error) { console.error('LinkSync: Failed to load bookmarks:', error); this.renderError('Unable to connect to server. Check your settings.'); } }, // Render bookmarks to list renderBookmarks(bookmarks) { const container = document.getElementById('bookmarks-container'); container.innerHTML = ''; if (!bookmarks || bookmarks.length === 0) { container.innerHTML = '
No bookmarks
'; return; } bookmarks.forEach(bookmark => { const item = document.createElement('div'); item.className = 'bookmark-item'; item.innerHTML = ` ${bookmark.url}No collections
'; return; } collections.forEach(collection => { const item = document.createElement('div'); item.className = 'collection-item'; item.innerHTML = `${collection.description || ''}
Type: ${collection.query_type || 'dynamic'}
`; container.appendChild(item); }); }, // Sync bookmarks async syncBookmarks() { const indicator = document.getElementById('sync-indicator'); indicator.className = 'syncing'; try { const response = await fetch(`${this.API_BASE_URL}/api/sync/`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Token ${this.API_KEY}` }, body: JSON.stringify({ bookmarks: [], mode: await this.getSetting('mode') || 'bi-directional', deletions: await this.getSetting('deletions') || false }) }); if (response.ok) { const data = await response.json(); indicator.className = 'synced'; document.getElementById('last-sync').textContent = `Last sync: ${new Date().toLocaleTimeString()}`; this.showNotification('Sync completed', 'success'); } else { this.showNotification('Sync failed', 'error'); } } catch (error) { console.error('LinkSync: Sync error:', error); this.showNotification('Sync error', 'error'); } finally { setTimeout(() => indicator.className = '', 2000); } }, // Update sync status updateSyncStatus() { const indicator = document.getElementById('sync-indicator'); const lastSync = document.getElementById('last-sync'); const lastSyncTime = new Date(await this.getSetting('lastSync') || Date.now()); const minutesAgo = Math.floor((Date.now() - lastSyncTime.getTime()) / 60000); if (minutesAgo < 5) { indicator.className = 'synced'; lastSync.textContent = `Synced ${minutesAgo} min ago`; } else { indicator.className = 'error'; lastSync.textContent = `Last sync: ${lastSyncTime.toLocaleString()}`; } }, // Open settings modal openSettings() { // TODO: Open settings modal console.log('Open settings'); }, // Show notification showNotification(message, type) { // TODO: Show toast notification console.log(`[LinkSync] ${message}`); }, // Get setting async getSetting(key) { return new Promise(resolve => { browser.storage.local.get(key, result => resolve(result[key])); }); } }; // Initialize when page loads window.addEventListener('load', () => Popup.init()); // Expose to window window.Popup = Popup; })();