/** * Popup script - handles UI interactions */ document.addEventListener('DOMContentLoaded', async () => { await init(); }); /** * Initialize the popup */ async function init() { // Check configuration const config = await browser.runtime.sendMessage({ type: 'GET_CONFIG' }); if (!config.apiUrl || !config.apiKey) { showSetupRequired(); return; } // Test connection const connectionStatus = await browser.runtime.sendMessage({ type: 'TEST_CONNECTION' }); updateConnectionIndicator(connectionStatus.connected); // Show main content document.getElementById('setup-required').classList.add('hidden'); document.getElementById('main-content').classList.remove('hidden'); if (!connectionStatus.connected) { showError(`Cannot connect to backend: ${connectionStatus.error}`); } // Load platform status await loadPlatformStatus(); // Setup event listeners setupEventListeners(); } /** * Show the setup required message */ function showSetupRequired() { document.getElementById('setup-required').classList.remove('hidden'); document.getElementById('main-content').classList.add('hidden'); document.getElementById('open-settings-btn').addEventListener('click', () => { browser.runtime.openOptionsPage(); }); } /** * Update the connection status indicator * @param {boolean} connected - Whether connected to backend */ function updateConnectionIndicator(connected) { const indicator = document.getElementById('connection-status'); indicator.classList.toggle('connected', connected); indicator.title = connected ? 'Connected to GallerySubscriber' : 'Disconnected'; } /** * Load and display platform status */ async function loadPlatformStatus() { const status = await browser.runtime.sendMessage({ type: 'GET_PLATFORM_STATUS' }); const container = document.getElementById('platforms-list'); container.innerHTML = ''; for (const [key, platform] of Object.entries(PLATFORMS)) { const platformStatus = status[key] || {}; const card = createPlatformCard(key, platform, platformStatus); container.appendChild(card); } } /** * Create a platform card element * @param {string} key - Platform key * @param {object} platform - Platform definition * @param {object} status - Platform status * @returns {HTMLElement} */ function createPlatformCard(key, platform, status) { const card = document.createElement('div'); card.className = 'platform-card'; card.dataset.platform = key; // Discord is clickable if we have a token captured // Other token-based platforms are disabled const isDisabled = platform.authType === 'token' && key !== 'discord'; const isDiscordWithoutToken = key === 'discord' && !status.hasToken; if (isDisabled || isDiscordWithoutToken) { card.classList.add('disabled'); } const statusText = getStatusText(status, platform, key); const statusClass = getStatusClass(status, platform, key); card.innerHTML = `
${platform.name.charAt(0)}
${platform.name}
${statusText}
`; if (!isDisabled && !isDiscordWithoutToken) { card.addEventListener('click', () => exportPlatformCookies(key, card)); } return card; } /** * Get status text for display * @param {object} status - Platform status * @param {object} platform - Platform definition * @param {string} key - Platform key * @returns {string} */ function getStatusText(status, platform, key) { // Special handling for Discord token-based auth if (key === 'discord') { if (status.hasToken) { return 'Token captured - ready to export'; } return 'Open Discord in browser to capture token'; } if (platform.authType === 'token') { return 'Manual token entry required'; } if (status.error) { return 'Error checking cookies'; } if (!status.hasCookies || status.cookieCount === 0) { return 'No cookies found - log in first'; } return `${status.cookieCount} cookies ready`; } /** * Get status CSS class * @param {object} status - Platform status * @param {object} platform - Platform definition * @param {string} key - Platform key * @returns {string} */ function getStatusClass(status, platform, key) { // Special handling for Discord if (key === 'discord') { return status.hasToken ? 'ready' : 'no-cookies'; } if (platform.authType === 'token') { return 'no-cookies'; } if (status.error) { return 'error'; } if (!status.hasCookies || status.cookieCount === 0) { return 'no-cookies'; } return 'ready'; } /** * Export cookies for a single platform * @param {string} platformKey - Platform key * @param {HTMLElement} cardElement - The card element */ async function exportPlatformCookies(platformKey, cardElement) { cardElement.classList.add('loading'); hideStatusMessage(); try { const result = await browser.runtime.sendMessage({ type: 'EXPORT_COOKIES', platform: platformKey }); if (result.error) { showError(result.error); } else { // Handle different response types (cookies vs token) const successMsg = result.cookieCount !== undefined ? `${PLATFORMS[platformKey].name}: ${result.cookieCount} cookies exported!` : `${PLATFORMS[platformKey].name}: Token exported successfully!`; showSuccess(successMsg); // Refresh status await loadPlatformStatus(); } } catch (error) { showError(error.message); } finally { cardElement.classList.remove('loading'); } } /** * Export cookies for all platforms */ async function exportAllCookies() { const btn = document.getElementById('export-all-btn'); btn.disabled = true; btn.textContent = 'Exporting...'; hideStatusMessage(); try { const results = await browser.runtime.sendMessage({ type: 'EXPORT_ALL_COOKIES' }); const successes = Object.values(results).filter(r => r.success).length; const skipped = Object.values(results).filter(r => r.skipped).length; const failures = Object.values(results).filter(r => !r.success && !r.skipped).length; if (failures === 0 && successes > 0) { showSuccess(`Exported ${successes} platform(s) successfully!`); } else if (successes > 0) { showWarning(`${successes} succeeded, ${failures} failed`); } else if (failures > 0) { showError('All exports failed. Are you logged in?'); } else { showWarning('No platforms to export'); } await loadPlatformStatus(); } catch (error) { showError(error.message); } finally { btn.disabled = false; btn.textContent = 'Export All Platforms'; } } /** * Setup event listeners */ function setupEventListeners() { document.getElementById('export-all-btn').addEventListener('click', exportAllCookies); document.getElementById('settings-btn').addEventListener('click', () => { browser.runtime.openOptionsPage(); }); } /** * Show success message * @param {string} message - Message to display */ function showSuccess(message) { showStatusMessage(message, 'success'); } /** * Show error message * @param {string} message - Message to display */ function showError(message) { showStatusMessage(message, 'error'); } /** * Show warning message * @param {string} message - Message to display */ function showWarning(message) { showStatusMessage(message, 'warning'); } /** * Show a status message * @param {string} message - Message text * @param {string} type - Message type (success, error, warning) */ function showStatusMessage(message, type) { const el = document.getElementById('status-message'); el.textContent = message; el.className = `status-message ${type}`; el.classList.remove('hidden'); } /** * Hide the status message */ function hideStatusMessage() { document.getElementById('status-message').classList.add('hidden'); }