/* global chrome, browser */ // Browser compatibility polyfill if (typeof browser === 'undefined' && typeof chrome !== 'undefined') { browser = chrome; } const apiBaseUrlInput = document.getElementById('trackeepApiUrl'); const apiKeyInput = document.getElementById('trackeepApiKey'); const testConnectionBtn = document.getElementById('testConnectionBtn'); const generateKeyBtn = document.getElementById('generateKeyBtn'); const saveBtn = document.getElementById('saveBtn'); const statusMessageEl = document.getElementById('statusMessage'); const connectionStatusEl = document.getElementById('connectionStatus'); const statusTitleEl = document.getElementById('statusTitle'); const statusTextEl = document.getElementById('statusMessage'); const installWelcomeEl = document.getElementById('installWelcome'); const mainOptionsEl = document.getElementById('mainOptions'); function showMessage(message, type = 'info', duration = 5000) { statusMessageEl.textContent = message; statusMessageEl.className = `status-message ${type}`; statusMessageEl.style.display = 'flex'; if (duration > 0) { setTimeout(() => { statusMessageEl.style.display = 'none'; }, duration); } } function hideMessage() { statusMessageEl.style.display = 'none'; } function showConnectionStatus(title, message, type = 'info') { connectionStatusEl.style.display = 'block'; statusTitleEl.textContent = title; statusTextEl.textContent = message; connectionStatusEl.className = `connection-status ${type}`; } function hideConnectionStatus() { connectionStatusEl.style.display = 'none'; } function setButtonLoading(button, loading = true) { if (loading) { button.disabled = true; const originalContent = button.innerHTML; button.dataset.originalContent = originalContent; button.innerHTML = ` Saving... `; } else { button.disabled = false; if (button.dataset.originalContent) { button.innerHTML = button.dataset.originalContent; delete button.dataset.originalContent; } } } function detectAndPrefillApiBaseUrl(callback) { browser.tabs.query({ active: true, currentWindow: true }, (tabs) => { const tab = tabs && tabs[0]; if (!tab || !tab.url) { if (callback) callback(); return; } try { const url = new URL(tab.url); const isTrackeepDomain = url.hostname.includes('trackeep') || url.hostname === 'localhost'; if (isTrackeepDomain && (url.protocol === 'https:' || url.protocol === 'http:')) { const candidate = `${url.origin}/api/v1`; browser.storage.sync.get(['trackeepApiBaseUrl'], (items) => { if (!items.trackeepApiBaseUrl) { apiBaseUrlInput.value = candidate; } if (callback) callback(); }); } else { // Fallback to localhost if nothing set browser.storage.sync.get(['trackeepApiBaseUrl'], (items) => { if (!items.trackeepApiBaseUrl) { apiBaseUrlInput.value = 'http://localhost:8080/api/v1'; } if (callback) callback(); }); } } catch (e) { if (callback) callback(); } }); } function loadSettings() { browser.storage.sync.get(['trackeepApiBaseUrl', 'trackeepApiKey', 'isFirstInstall'], (items) => { // Handle first-time install if (items.isFirstInstall) { installWelcomeEl.style.display = 'flex'; mainOptionsEl.style.display = 'none'; } else { installWelcomeEl.style.display = 'none'; mainOptionsEl.style.display = 'block'; } // Load saved settings if (items.trackeepApiBaseUrl) { apiBaseUrlInput.value = items.trackeepApiBaseUrl; } if (items.trackeepApiKey) { apiKeyInput.value = items.trackeepApiKey; } // Auto-detect API URL if empty if (!items.trackeepApiBaseUrl) { detectAndPrefillApiBaseUrl(); } }); } function saveSettings() { const apiBaseUrl = apiBaseUrlInput.value.trim(); const apiKey = apiKeyInput.value.trim(); if (!apiBaseUrl) { showMessage('API base URL is required.', 'error'); return; } if (!apiKey) { showMessage('API key is required.', 'error'); return; } if (!apiKey.startsWith('tk_')) { showMessage('API key should start with "tk_"', 'error'); return; } setButtonLoading(saveBtn, true); showMessage('Saving settings...', 'info', 0); browser.storage.sync.set({ trackeepApiBaseUrl: apiBaseUrl, trackeepApiKey: apiKey, isFirstInstall: false }, () => { setButtonLoading(saveBtn, false); showMessage('Settings saved successfully!', 'success'); }); } async function testConnection() { const apiBaseUrl = apiBaseUrlInput.value.trim(); const apiKey = apiKeyInput.value.trim(); if (!apiBaseUrl || !apiKey) { showConnectionStatus('Connection Failed', 'Please enter both URL and API key', 'error'); return; } showConnectionStatus('Testing Connection', 'Connecting to your Trackeep instance...', 'info'); try { const base = apiBaseUrl.replace(/\/$/, ''); const response = await fetch(`${base}/auth/me`, { method: 'GET', headers: { 'Authorization': `Bearer ${apiKey}`, 'Content-Type': 'application/json' } }); if (response.ok) { const data = await response.json(); showConnectionStatus('Connection Successful', `Connected as ${data.username || 'user'}. API key is valid!`, 'success'); // Hide success message after 3 seconds setTimeout(() => { hideConnectionStatus(); }, 3000); } else { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } } catch (error) { showConnectionStatus('Connection Failed', `Error: ${error.message}`, 'error'); } } async function generateApiKey() { const apiBaseUrl = apiBaseUrlInput.value.trim(); if (!apiBaseUrl) { showMessage('Please enter API URL first', 'error'); return; } showConnectionStatus('Generating API Key', 'Opening Trackeep to generate new API key...', 'info'); try { const base = apiBaseUrl.replace(/\/$/, ''); const response = await fetch(`${base}/auth/generate-key`, { method: 'POST', headers: { 'Content-Type': 'application/json' } }); if (response.ok) { const data = await response.json(); if (data.api_key) { apiKeyInput.value = data.api_key; showConnectionStatus('API Key Generated', 'New API key generated and copied to clipboard!', 'success'); // Copy to clipboard navigator.clipboard.writeText(data.api_key); // Hide success message after 3 seconds setTimeout(() => { hideConnectionStatus(); }, 3000); } else { throw new Error('No API key in response'); } } else { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } } catch (error) { showConnectionStatus('Generation Failed', `Error: ${error.message}`, 'error'); } } // Initialize everything when DOM is loaded document.addEventListener('DOMContentLoaded', () => { detectAndPrefillApiBaseUrl(() => { loadSettings(); }); // Event listeners for main options saveBtn.addEventListener('click', (e) => { e.preventDefault(); saveSettings(); }); testConnectionBtn.addEventListener('click', (e) => { e.preventDefault(); testConnection(); }); generateKeyBtn.addEventListener('click', (e) => { e.preventDefault(); generateApiKey(); }); // Event listeners for setup form const testSetupConnectionBtn = document.getElementById('testSetupConnectionBtn'); const completeSetupBtn = document.getElementById('completeSetupBtn'); const getStartedBtn = document.getElementById('getStartedBtn'); if (testSetupConnectionBtn) { testSetupConnectionBtn.addEventListener('click', (e) => { e.preventDefault(); testSetupConnection(); }); } if (completeSetupBtn) { completeSetupBtn.addEventListener('click', (e) => { e.preventDefault(); completeSetup(); }); } if (getStartedBtn) { getStartedBtn.addEventListener('click', (e) => { e.preventDefault(); // Hide welcome and show main options with setup form document.getElementById('installWelcome').style.display = 'none'; document.getElementById('mainOptions').style.display = 'block'; }); } }); // Test connection from setup form async function testSetupConnection() { const apiBaseUrl = document.getElementById('setupApiUrl').value.trim(); const apiKey = document.getElementById('setupApiKey').value.trim(); if (!apiBaseUrl || !apiKey) { showSetupConnectionStatus('Connection Failed', 'Please enter both URL and API key', 'error'); return; } showSetupConnectionStatus('Testing Connection', 'Connecting to your Trackeep instance...', 'info'); try { const base = apiBaseUrl.replace(/\/$/, ''); const response = await fetch(`${base}/auth/me`, { method: 'GET', headers: { 'Authorization': `Bearer ${apiKey}`, 'Content-Type': 'application/json' } }); if (response.ok) { const data = await response.json(); showSetupConnectionStatus('Connection Successful', `Connected as ${data.username || 'user'}. API key is valid!`, 'success'); // Copy values to main form document.getElementById('trackeepApiUrl').value = apiBaseUrl; document.getElementById('trackeepApiKey').value = apiKey; // Hide success message after 3 seconds setTimeout(() => { hideSetupConnectionStatus(); }, 3000); } else { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } } catch (error) { showSetupConnectionStatus('Connection Failed', `Error: ${error.message}`, 'error'); } } // Complete setup function completeSetup() { const apiBaseUrl = document.getElementById('setupApiUrl').value.trim(); const apiKey = document.getElementById('setupApiKey').value.trim(); if (!apiBaseUrl || !apiKey) { showMessage('Please fill in both URL and API key', 'error'); return; } // Save settings browser.storage.sync.set({ trackeepApiBaseUrl: apiBaseUrl, trackeepApiKey: apiKey, isFirstInstall: false }, () => { showMessage('Setup completed successfully!', 'success'); // Switch to main options view document.getElementById('installWelcome').style.display = 'none'; document.getElementById('mainOptions').style.display = 'block'; // Load settings in main form document.getElementById('trackeepApiUrl').value = apiBaseUrl; document.getElementById('trackeepApiKey').value = apiKey; }); } // Setup connection status functions function showSetupConnectionStatus(title, message, type = 'info') { const statusEl = document.getElementById('setupConnectionStatus'); const titleEl = document.getElementById('setupStatusTitle'); const messageEl = document.getElementById('setupStatusMessage'); statusEl.style.display = 'block'; titleEl.textContent = title; messageEl.textContent = message; statusEl.className = `connection-status ${type}`; } function hideSetupConnectionStatus() { document.getElementById('setupConnectionStatus').style.display = 'none'; }