// Speed test functionality class MediaFlowSpeedTest { constructor() { this.config = null; this.results = { proxy: {}, direct: {} }; this.servers = []; this.currentTestIndex = 0; this.totalTests = 0; this.charts = {}; this.testCancelled = false; this.selectedCdns = new Set(); this.activeAbortControllers = new Set(); this.initializeEventListeners(); this.initializeForm(); this.setupResizeHandler(); } initializeEventListeners() { document.getElementById('configForm').addEventListener('submit', (e) => { e.preventDefault(); this.startSpeedTest(); }); document.getElementById('provider').addEventListener('change', (e) => { const apiKeySection = document.getElementById('apiKeySection'); if (e.target.value === 'all_debrid') { apiKeySection.classList.remove('hidden'); } else { apiKeySection.classList.add('hidden'); } // Clear CDN selection when provider changes this.config = null; this.selectedCdns.clear(); this.showPlaceholderCdnSelection(); this.updateCdnButtonStates(); }); document.getElementById('addServerBtn').addEventListener('click', () => { this.addServerInput(); }); document.getElementById('runAgainBtn').addEventListener('click', () => { this.resetTest(); }); document.getElementById('cancelTestBtn').addEventListener('click', () => { this.cancelTest(); }); document.getElementById('selectAllCdn').addEventListener('click', () => { this.selectAllCdns(true); }); document.getElementById('selectNoneCdn').addEventListener('click', () => { this.selectAllCdns(false); }); document.getElementById('refreshCdnBtn').addEventListener('click', async () => { await this.refreshCdnLocations(); }); // Handle server removal document.addEventListener('click', (e) => { if (e.target.classList.contains('remove-server')) { e.target.closest('.server-input').remove(); this.updateRemoveButtons(); } }); } initializeForm() { // Set current URL as default MediaFlow URL const currentUrl = new URL(window.location.href); const baseUrl = `${currentUrl.protocol}//${currentUrl.host}`; const firstServerUrl = document.querySelector('.server-url'); firstServerUrl.value = baseUrl; firstServerUrl.placeholder = `${baseUrl} (Current Instance)`; // The top "MediaFlow API Password" (#currentApiPassword) is the // source of truth; hydrate from localStorage (shared with the URL // generator) and persist edits back. Per-server fields are treated // as optional overrides (see collectServerConfigurations). const topPw = document.getElementById('currentApiPassword'); const saved = localStorage.getItem('mediaflow_api_password'); if (topPw) { if (saved && !topPw.value) topPw.value = saved; topPw.addEventListener('input', () => { const v = topPw.value.trim(); if (v) localStorage.setItem('mediaflow_api_password', v); else localStorage.removeItem('mediaflow_api_password'); }); } // Relabel the per-server field so users realise it's an override // rather than a second required field. document.querySelectorAll('.server-password').forEach(el => { el.placeholder = 'Override password (blank = use main)'; }); // Show placeholder CDN selection initially this.showPlaceholderCdnSelection(); this.updateCdnButtonStates(); } showPlaceholderCdnSelection() { const cdnStatusContainer = document.getElementById('cdnStatusContainer'); const cdnContainer = document.getElementById('cdnSelection'); // Clear status container cdnStatusContainer.innerHTML = ''; // Show placeholder in main CDN container cdnContainer.innerHTML = `
Configure your debrid provider settings above, then click "🔄 Refresh CDNs" to load available locations.
Loading CDN locations...