"use strict"; // Dragon Wind Chrome Extension — Popup Script let config = { serverUrl: 'http://localhost:3000', username: 'Admin', password: '' }; let authToken = null; let uploadMode = 'http'; let selectedFiles = []; let folderList = []; let connected = false; // ==================== INIT ==================== (async function init() { const stored = await chrome.storage.local.get(['config', 'token', 'mode']); if (stored.config) config = { ...config, ...stored.config }; if (stored.token) authToken = stored.token; if (stored.mode) uploadMode = stored.mode; document.getElementById('cfg-server').value = config.serverUrl; document.getElementById('cfg-user').value = config.username; document.getElementById('conn-server').textContent = config.serverUrl.replace(/https?:\/\//, ''); setMode(uploadMode, false); await tryConnect(); })(); document.getElementById('settings-toggle').addEventListener('click', () => { const panel = document.getElementById('settings-panel'); panel.classList.toggle('open'); }); // ==================== CONNECTION ==================== async function tryConnect() { setConnStatus('grey', 'Connecting…'); if (!authToken) { if (!config.username || !config.password) { setConnStatus('red', 'Set credentials in settings'); return; } await login(); return; } try { const r = await apiFetch('GET', '/api/health'); if (r.status === 'ok') { setConnStatus('green', `Connected — ${r.s3Configured ? 'S3 ✓' : 'S3 not configured'}`); connected = true; await loadFolders(); } else { authToken = null; await chrome.storage.local.remove('token'); await login(); } } catch (e) { setConnStatus('red', `Cannot reach server`); } } async function login() { try { const r = await apiFetch('POST', '/api/login', { username: config.username, password: config.password }); if (r.success) { authToken = r.token; await chrome.storage.local.set({ token: authToken }); setConnStatus('green', `Connected as ${r.user}`); connected = true; await loadFolders(); } else { setConnStatus('red', r.error || 'Auth failed'); } } catch (e) { setConnStatus('red', 'Connection failed'); } } function setConnStatus(color, text) { const dot = document.getElementById('conn-dot'); dot.className = `conn-dot ${color}`; document.getElementById('conn-label').textContent = text; } // ==================== SETTINGS ==================== async function saveSettings() { const serverUrl = document.getElementById('cfg-server').value.trim().replace(/\/$/, ''); const username = document.getElementById('cfg-user').value.trim(); const password = document.getElementById('cfg-pass').value; if (!serverUrl) { showSettingsStatus('Server URL required', 'error'); return; } config = { serverUrl, username, password: password || config.password }; authToken = null; await chrome.storage.local.set({ config, token: null }); document.getElementById('conn-server').textContent = serverUrl.replace(/https?:\/\//, ''); showSettingsStatus('Saved — connecting…', 'loading'); connected = false; await tryConnect(); showSettingsStatus('Settings saved', 'success'); } function showSettingsStatus(msg, type) { const el = document.getElementById('settings-status'); el.className = `status-bar ${type}`; el.textContent = msg; } // ==================== FOLDERS ==================== async function loadFolders() { try { const d = await apiFetch('GET', '/api/folders'); folderList = []; flattenTree(d.tree || [], '', folderList); const sel = document.getElementById('folder-select'); const current = sel.value; sel.innerHTML = ''; folderList.forEach(f => { const opt = document.createElement('option'); opt.value = f.path; opt.textContent = f.display; sel.appendChild(opt); }); if (current) sel.value = current; } catch (_) {} } function flattenTree(nodes, prefix, out) { nodes.forEach(n => { const path = prefix ? `${prefix}/${n.name}` : n.name; const display = '\u00a0'.repeat(prefix.split('/').filter(Boolean).length * 2) + (prefix ? '↳ ' : '') + n.name; out.push({ path, display }); if (n.children.length) flattenTree(n.children, path, out); }); } // ==================== MODE ==================== function setMode(mode, save = true) { uploadMode = mode; document.getElementById('btn-http').className = `mode-btn${mode === 'http' ? ' active-http' : ''}`; document.getElementById('btn-udp').className = `mode-btn${mode === 'udp' ? ' active-udp' : ''}`; const btn = document.getElementById('upload-btn'); if (mode === 'http') { btn.className = 'upload-btn http'; btn.textContent = 'Upload Files'; } else { btn.className = 'upload-btn'; btn.textContent = '⚡ UDP Upload'; } if (save) chrome.storage.local.set({ mode }); } // ==================== FILES ==================== function onDrop(e) { e.preventDefault(); document.getElementById('drop-zone').classList.remove('over'); addFiles(Array.from(e.dataTransfer.files)); } function onFileInputChange(e) { addFiles(Array.from(e.target.files)); e.target.value = ''; } function addFiles(files) { files.forEach(f => { if (!selectedFiles.find(x => x.name === f.name && x.size === f.size)) { selectedFiles.push({ file: f, name: f.name, size: f.size, status: 'pending' }); } }); renderFileList(); updateBtn(); } function renderFileList() { const list = document.getElementById('file-list'); list.innerHTML = ''; selectedFiles.forEach((item, i) => { const el = document.createElement('div'); el.className = 'file-item'; el.innerHTML = `