// Global variables to store session data let sessionData = { deploymentUrl: '', cookies: null, isConnected: false }; // DOM elements const connectBtn = document.getElementById('connectBtn'); const connectionStatus = document.getElementById('connectionStatus'); const deviceStatus = document.getElementById('deviceStatus'); const deviceList = document.getElementById('deviceList'); const deviceDetails = document.getElementById('deviceDetails'); const statusIndicator = document.getElementById('statusIndicator'); const deviceUUID = document.getElementById('deviceUUID'); const deviceSearch = document.getElementById('deviceSearch'); // New buttons for the layout const testConnectionBtn = document.getElementById('testConnectionBtn'); const disconnectBtn = document.getElementById('disconnectBtn'); const startProxyBtn = document.getElementById('startProxyBtn'); const checkVersionBtn = document.getElementById('checkVersionBtn'); const stopProxyBtn = document.getElementById('stopProxyBtn'); // Cookie proxy elements const cookieDeviceUUID = document.getElementById('cookieDeviceUUID'); const cookieKey = document.getElementById('cookieKey'); const startCookieProxyBtn = document.getElementById('startCookieProxyBtn'); const stopCookieProxyBtn = document.getElementById('stopCookieProxyBtn'); // Profile management elements const profileSelect = document.getElementById('profileSelect'); const addProfileBtn = document.getElementById('addProfileBtn'); const manageProfilesBtn = document.getElementById('manageProfilesBtn'); const addProfileModal = document.getElementById('addProfileModal'); const manageProfilesModal = document.getElementById('manageProfilesModal'); const addProfileForm = document.getElementById('addProfileForm'); const profilesList = document.getElementById('profilesList'); // Track selected device and profiles let selectedDevice = null; let currentProfiles = []; let selectedProfile = null; let activeProxyConnections = new Map(); // Track multiple active connections let activeCookieProxyConnections = new Map(); // Track cookie-based proxy connections const MAX_PROXY_CONNECTIONS = 2; // Limit to 2 simultaneous connections let allDevices = []; // Store all devices for search functionality // Event listeners connectBtn.addEventListener('click', handleConnection); testConnectionBtn.addEventListener('click', handleTestConnection); disconnectBtn.addEventListener('click', handleDisconnect); startProxyBtn.addEventListener('click', handleStartProxy); checkVersionBtn.addEventListener('click', handleCheckVersion); stopProxyBtn.addEventListener('click', handleStopProxy); // Cookie proxy event listeners startCookieProxyBtn.addEventListener('click', handleStartCookieProxy); stopCookieProxyBtn.addEventListener('click', handleStopCookieProxy); // Cookie key input listener to update button states cookieKey.addEventListener('input', updateCookieProxyButtonStates); // Device search event listener deviceSearch.addEventListener('input', handleDeviceSearch); // Cookie section collapsible header document.getElementById('cookieSectionHeader').addEventListener('click', toggleCookieSection); // Profile management event listeners profileSelect.addEventListener('change', handleProfileSelection); addProfileBtn.addEventListener('click', showAddProfileModal); manageProfilesBtn.addEventListener('click', showManageProfilesModal); addProfileForm.addEventListener('submit', handleAddProfile); // Modal event listeners document.getElementById('closeAddProfile').addEventListener('click', hideAddProfileModal); document.getElementById('cancelAddProfile').addEventListener('click', hideAddProfileModal); document.getElementById('closeManageProfiles').addEventListener('click', hideManageProfilesModal); document.getElementById('closeManageProfilesBtn').addEventListener('click', hideManageProfilesModal); // Close modals when clicking outside addProfileModal.addEventListener('click', (e) => { if (e.target === addProfileModal) hideAddProfileModal(); }); manageProfilesModal.addEventListener('click', (e) => { if (e.target === manageProfilesModal) hideManageProfilesModal(); }); // Handle connection button click async function handleConnection() { if (!selectedProfile) { showStatus(connectionStatus, 'Please select a profile to connect', 'error'); return; } // Disable button during connection setConnectButtonEnabled(false); showStatus(connectionStatus, 'Connecting to Alta API...', 'info'); try { const result = await window.electronAPI.login({ deploymentUrl: selectedProfile.deploymentUrl, username: selectedProfile.username, password: selectedProfile.password }); if (result.success) { // Store session data sessionData.deploymentUrl = selectedProfile.deploymentUrl; sessionData.cookies = result.cookies; sessionData.isConnected = true; showStatus(connectionStatus, 'Connected successfully!', 'success'); updateConnectionStatus(true); updateButtonStates(); // Auto-retrieve devices when connected try { await handleGetDevices(); } catch (deviceError) { console.error('Failed to auto-fetch devices:', deviceError); showStatus(deviceStatus, 'Connected, but failed to load devices. Try selecting a profile and reconnecting.', 'warning'); } } else { showStatus(connectionStatus, `Connection failed: ${result.message}`, 'error'); setConnectButtonEnabled(true); } } catch (error) { console.error('Connection error:', error); showStatus(connectionStatus, `Connection error: ${error.message}`, 'error'); setConnectButtonEnabled(true); } } // Handle test connection async function handleTestConnection() { if (!sessionData.isConnected) { showStatus(connectionStatus, 'Please connect to API first', 'error'); return; } showStatus(connectionStatus, 'Testing connection...', 'info'); try { const result = await window.electronAPI.getAuthInfo({ deploymentUrl: sessionData.deploymentUrl, cookies: sessionData.cookies }); if (result.success) { showStatus(connectionStatus, 'Connection test successful!', 'success'); } else { showStatus(connectionStatus, `Connection test failed: ${result.message}`, 'error'); } } catch (error) { console.error('Test connection error:', error); showStatus(connectionStatus, `Test failed: ${error.message}`, 'error'); } } // Handle disconnect function handleDisconnect() { sessionData.isConnected = false; sessionData.cookies = null; sessionData.deploymentUrl = ''; selectedDevice = null; activeProxyConnections.clear(); activeCookieProxyConnections.clear(); allDevices = []; // Clear stored devices updateConnectionStatus(false); updateButtonStates(); clearDeviceList(); deviceUUID.value = ''; cookieDeviceUUID.value = ''; cookieKey.value = ''; deviceSearch.value = ''; // Clear search input // Clear device status message deviceStatus.style.display = 'none'; deviceStatus.textContent = ''; // Reset connect button text if it was stuck connectBtn.textContent = 'Connect to API'; connectBtn.disabled = !selectedProfile; // Reset proxy buttons startProxyBtn.disabled = true; stopProxyBtn.disabled = true; showStatus(connectionStatus, 'Disconnected from API', 'info'); } // Handle start proxy async function handleStartProxy() { if (!selectedDevice) { showStatus(connectionStatus, 'Please select a device first', 'error'); return; } if (!selectedProfile) { showStatus(connectionStatus, 'Please select a profile first', 'error'); return; } // Check connection limit if (activeProxyConnections.size >= MAX_PROXY_CONNECTIONS) { showStatus(connectionStatus, `Maximum of ${MAX_PROXY_CONNECTIONS} camera proxy connections allowed. Stop an existing connection first.`, 'warning'); return; } // Check if this device already has an active connection const deviceId = selectedDevice.guid || selectedDevice.id; if (activeProxyConnections.has(deviceId)) { showStatus(connectionStatus, `Camera proxy already running for device ${selectedDevice.name}`, 'warning'); return; } // Check if camera proxy executable exists try { const checkResult = await window.electronAPI.checkCameraProxy(); if (!checkResult.exists) { showStatus(connectionStatus, 'Camera proxy executable (aware-cam-proxy-win.exe) not found in application directory', 'error'); return; } } catch (error) { showStatus(connectionStatus, 'Failed to check camera proxy executable', 'error'); return; } // Disable button during launch startProxyBtn.disabled = true; showStatus(connectionStatus, `Starting camera proxy for device ${selectedDevice.name}...`, 'info'); try { const result = await window.electronAPI.launchCameraProxy({ deploymentUrl: selectedProfile.deploymentUrl, username: selectedProfile.username, password: selectedProfile.password, deviceUuid: deviceId }); if (result.success) { // Track this connection activeProxyConnections.set(deviceId, { processId: result.processId, deviceName: selectedDevice.name, deviceId: deviceId, startTime: Date.now() }); updateProxyButtonStates(); showStatus(connectionStatus, `${result.message} (${activeProxyConnections.size}/${MAX_PROXY_CONNECTIONS} connections active)`, 'success'); } else { showStatus(connectionStatus, `Failed to start camera proxy: ${result.message}`, 'error'); } } catch (error) { console.error('Camera proxy launch error:', error); showStatus(connectionStatus, `Error launching camera proxy: ${error.message}`, 'error'); } finally { startProxyBtn.disabled = false; } } // Handle check version async function handleCheckVersion() { showStatus(connectionStatus, 'Checking camera proxy version...', 'info'); try { const result = await window.electronAPI.getCameraProxyVersion(); if (result.success) { showStatus(connectionStatus, `Camera Proxy Version: ${result.version}`, 'info'); } else { showStatus(connectionStatus, `Failed to get version: ${result.message}`, 'error'); } } catch (error) { console.error('Version check error:', error); showStatus(connectionStatus, `Error checking version: ${error.message}`, 'error'); } } // Handle stop proxy async function handleStopProxy() { if (activeProxyConnections.size === 0) { showStatus(connectionStatus, 'No active camera proxy connections found', 'warning'); return; } showStatus(connectionStatus, 'Stopping all camera proxy connections...', 'info'); try { const result = await window.electronAPI.stopCameraProxy(null); // Stop all processes if (result.success) { activeProxyConnections.clear(); showStatus(connectionStatus, 'All camera proxy connections stopped successfully', 'success'); // Update visual indicators for all devices const deviceItems = deviceList.querySelectorAll('.device-item'); deviceItems.forEach(item => { item.classList.remove('proxy-active'); }); } else { showStatus(connectionStatus, `Failed to stop camera proxy: ${result.message}`, 'warning'); } } catch (error) { console.error('Stop proxy error:', error); showStatus(connectionStatus, 'Error stopping camera proxy', 'error'); } updateProxyButtonStates(); updateCookieProxyButtonStates(); } // Handle start cookie proxy async function handleStartCookieProxy() { if (!selectedDevice) { showStatus(connectionStatus, 'Please select a device first', 'error'); return; } const cookieKeyValue = cookieKey.value.trim(); if (!cookieKeyValue) { showStatus(connectionStatus, 'Please enter a cookie key', 'error'); return; } if (!sessionData.deploymentUrl) { showStatus(connectionStatus, 'Please connect to API first to get deployment URL', 'error'); return; } // Check if this device already has an active cookie connection const deviceId = selectedDevice.guid || selectedDevice.id; if (activeCookieProxyConnections.has(deviceId)) { showStatus(connectionStatus, `Cookie proxy already running for device ${selectedDevice.name}`, 'warning'); return; } // Disable button during launch startCookieProxyBtn.disabled = true; showStatus(connectionStatus, `Starting cookie proxy for device ${selectedDevice.name}...`, 'info'); try { const result = await window.electronAPI.launchCookieCameraProxy({ deploymentUrl: sessionData.deploymentUrl, cookieKey: cookieKeyValue, deviceUuid: deviceId }); if (result.success) { // Track this connection activeCookieProxyConnections.set(deviceId, { processId: result.processId, deviceName: selectedDevice.name, deviceId: deviceId, startTime: Date.now(), type: 'cookie' }); updateCookieProxyButtonStates(); showStatus(connectionStatus, `${result.message} (Cookie proxy active for ${selectedDevice.name})`, 'success'); } else { showStatus(connectionStatus, `Failed to start cookie proxy: ${result.message}`, 'error'); } } catch (error) { console.error('Cookie proxy launch error:', error); showStatus(connectionStatus, `Error launching cookie proxy: ${error.message}`, 'error'); } finally { startCookieProxyBtn.disabled = false; } } // Handle stop cookie proxy async function handleStopCookieProxy() { if (activeCookieProxyConnections.size === 0) { showStatus(connectionStatus, 'No active cookie proxy connections found', 'warning'); return; } showStatus(connectionStatus, 'Stopping cookie proxy connections...', 'info'); try { const result = await window.electronAPI.stopCameraProxy(null); // Stop all processes if (result.success) { activeCookieProxyConnections.clear(); showStatus(connectionStatus, 'Cookie proxy connections stopped successfully', 'success'); // Update visual indicators for all devices const deviceItems = deviceList.querySelectorAll('.device-item'); deviceItems.forEach(item => { item.classList.remove('cookie-proxy-active'); }); } else { showStatus(connectionStatus, `Failed to stop cookie proxy: ${result.message}`, 'warning'); } } catch (error) { console.error('Stop cookie proxy error:', error); showStatus(connectionStatus, 'Error stopping cookie proxy', 'error'); } updateCookieProxyButtonStates(); } // Update cookie proxy button states function updateCookieProxyButtonStates() { const hasSelectedDevice = selectedDevice !== null; const hasCookieKey = cookieKey.value.trim().length > 0; const hasActiveConnection = activeCookieProxyConnections.size > 0; if (sessionData.isConnected && hasSelectedDevice && hasCookieKey) { const deviceId = selectedDevice.guid || selectedDevice.id; const isThisDeviceActive = activeCookieProxyConnections.has(deviceId); startCookieProxyBtn.disabled = isThisDeviceActive; stopCookieProxyBtn.disabled = !hasActiveConnection; } else { startCookieProxyBtn.disabled = true; stopCookieProxyBtn.disabled = !hasActiveConnection; } } // Update connection status indicator function updateConnectionStatus(connected) { const statusDot = statusIndicator.querySelector('.status-dot'); const statusText = statusIndicator.querySelector('.status-text'); if (connected) { statusDot.className = 'status-dot online'; statusText.textContent = 'Connected'; } else { statusDot.className = 'status-dot offline'; statusText.textContent = 'Disconnected'; } } // Update button states based on connection status function updateButtonStates() { if (sessionData.isConnected) { connectBtn.style.display = 'none'; // Hide connect button when connected testConnectionBtn.disabled = false; disconnectBtn.disabled = false; checkVersionBtn.disabled = false; updateProxyButtonStates(); // Update proxy buttons when connected } else { connectBtn.style.display = 'inline-block'; // Show connect button when disconnected connectBtn.disabled = !selectedProfile; testConnectionBtn.disabled = true; disconnectBtn.disabled = true; startProxyBtn.disabled = true; checkVersionBtn.disabled = true; stopProxyBtn.disabled = true; startCookieProxyBtn.disabled = true; stopCookieProxyBtn.disabled = true; } // Always update cookie proxy button states updateCookieProxyButtonStates(); } // Handle get devices (now called automatically) async function handleGetDevices() { if (!sessionData.isConnected) { showStatus(deviceStatus, 'Please connect to the API first', 'error'); return; } showStatus(deviceStatus, 'Fetching devices...', 'info'); clearDeviceList(); try { const result = await window.electronAPI.getDevices({ deploymentUrl: sessionData.deploymentUrl, cookies: sessionData.cookies }); if (result.success) { // Filter devices to only show non-cloud cameras (localStorage = false) const filteredDevices = result.devices.filter(device => { // Check if device has capabilities and localStorage property if (device.capabilities && device.capabilities.localStorage !== undefined) { // Only show devices where localStorage is false (non-cloud cameras) return device.capabilities.localStorage === false; } // If no capabilities or localStorage property, include the device (fallback) return true; }); const totalDevices = result.devices.length; const filteredCount = filteredDevices.length; const cloudDevicesHidden = totalDevices - filteredCount; let statusMessage = `Found ${filteredCount} local camera${filteredCount !== 1 ? 's' : ''}`; if (cloudDevicesHidden > 0) { statusMessage += ` (${cloudDevicesHidden} cloud camera${cloudDevicesHidden !== 1 ? 's' : ''} hidden)`; } showStatus(deviceStatus, statusMessage, 'success'); // Store all devices for search functionality allDevices = filteredDevices; displayDevices(filteredDevices); } else { showStatus(deviceStatus, `Failed to get devices: ${result.message}`, 'error'); } } catch (error) { console.error('Get devices error:', error); showStatus(deviceStatus, `Error getting devices: ${error.message}`, 'error'); } } // Helper function to determine device status from API data function getDeviceStatus(device) { // Check for live.display_status first (Alta API standard) if (device.live && device.live.display_status) { const status = device.live.display_status.toLowerCase(); // Handle color-based status responses from Alta API if (status === 'green') { return { isOnline: true, statusText: 'Online' }; } else if (status === 'red') { return { isOnline: false, statusText: 'Offline' }; } else if (status === 'yellow' || status === 'orange') { return { isOnline: false, statusText: 'Warning' }; } // Handle text-based status responses return { isOnline: status === 'online' || status === 'live' || status === 'connected', statusText: status === 'online' || status === 'live' || status === 'connected' ? 'Online' : 'Offline' }; } // Fallback to other possible status fields if (device.online !== undefined) { return { isOnline: device.online, statusText: device.online ? 'Online' : 'Offline' }; } if (device.status) { const status = device.status.toLowerCase(); // Handle color-based status in other fields if (status === 'green') { return { isOnline: true, statusText: 'Online' }; } else if (status === 'red') { return { isOnline: false, statusText: 'Offline' }; } return { isOnline: status === 'online' || status === 'live' || status === 'connected', statusText: status === 'online' || status === 'live' || status === 'connected' ? 'Online' : 'Offline' }; } // Default to offline if no status information available return { isOnline: false, statusText: 'Offline' }; } // Handle device search function handleDeviceSearch() { const searchTerm = deviceSearch.value.toLowerCase().trim(); if (!searchTerm) { // Show all devices if search is empty displayDevices(allDevices); return; } // Filter devices based on search term const filteredDevices = allDevices.filter(device => { const deviceName = (device.name || '').toLowerCase(); const deviceId = (device.guid || device.id || '').toLowerCase(); const deviceType = (device.type || '').toLowerCase(); const deviceModel = (device.model || '').toLowerCase(); const deviceIp = (device.ipAddress || '').toLowerCase(); return deviceName.includes(searchTerm) || deviceId.includes(searchTerm) || deviceType.includes(searchTerm) || deviceModel.includes(searchTerm) || deviceIp.includes(searchTerm); }); displayDevices(filteredDevices); } // Display devices in the UI function displayDevices(devices) { clearDeviceList(); if (!devices || devices.length === 0) { const searchTerm = deviceSearch.value.toLowerCase().trim(); const message = searchTerm ? 'No devices match your search' : 'No devices found'; deviceList.innerHTML = `

${message}

`; return; } devices.forEach((device, index) => { const deviceItem = document.createElement('div'); deviceItem.className = 'device-item'; deviceItem.dataset.deviceIndex = index; deviceItem.dataset.deviceId = device.guid || device.id; const deviceStatus = getDeviceStatus(device); const deviceId = device.guid || device.id; const isProxyActive = activeProxyConnections.has(deviceId); // Add proxy-active class if this device has an active connection if (isProxyActive) { deviceItem.classList.add('proxy-active'); } deviceItem.innerHTML = `
${escapeHtml(device.name || 'Unnamed Device')}
`; // Add click handler for device selection deviceItem.addEventListener('click', () => selectDevice(device, deviceItem)); deviceList.appendChild(deviceItem); }); // Update proxy button states after displaying devices updateProxyButtonStates(); } // Handle device selection function selectDevice(device, deviceElement) { // Remove previous selection const previousSelected = deviceList.querySelector('.device-item.selected'); if (previousSelected) { previousSelected.classList.remove('selected'); } // Select current device deviceElement.classList.add('selected'); selectedDevice = device; // Auto-populate device UUID fields const uuid = device.guid || device.id || ''; deviceUUID.value = uuid; cookieDeviceUUID.value = uuid; // Also populate cookie proxy UUID field // Show device selection feedback with connection status if (uuid) { const isActive = activeProxyConnections.has(uuid); const isCookieActive = activeCookieProxyConnections.has(uuid); const statusText = isActive ? ' (PROXY ACTIVE)' : ''; const cookieStatusText = isCookieActive ? ' (COOKIE PROXY ACTIVE)' : ''; showStatus(connectionStatus, `Selected device: ${device.name || 'Unnamed Device'} (UUID: ${uuid})${statusText}${cookieStatusText}`, 'info'); } updateProxyButtonStates(); updateCookieProxyButtonStates(); } // Display detailed device information function displayDeviceDetails(device) { const deviceStatus = getDeviceStatus(device); const detailsHtml = `

${escapeHtml(device.name || 'Unnamed Device')}

${escapeHtml(deviceStatus.statusText)}
Device ID
${escapeHtml(device.guid || device.id || 'N/A')}
Device Type
${escapeHtml(device.type || 'Unknown')}
Model
${escapeHtml(device.model || 'Unknown')}
IP Address
${escapeHtml(device.ipAddress || 'N/A')}
MAC Address
${escapeHtml(device.macAddress || 'N/A')}
Firmware Version
${escapeHtml(device.firmwareVersion || 'N/A')}
Serial Number
${escapeHtml(device.serialNumber || 'N/A')}
Location
${escapeHtml(device.location || 'N/A')}
`; deviceDetails.innerHTML = detailsHtml; } // Utility functions function showStatus(element, message, type) { element.textContent = message; element.className = `status-message ${type}`; element.style.display = 'block'; } function setConnectButtonEnabled(enabled) { connectBtn.disabled = !enabled; connectBtn.textContent = enabled ? 'Connect to Alta API' : 'Connecting...'; } function clearDeviceList() { deviceList.innerHTML = '

Connect to API to load devices

'; selectedDevice = null; deviceUUID.value = ''; } // New function to update proxy button states based on active connections function updateProxyButtonStates() { if (!sessionData.isConnected) { startProxyBtn.disabled = true; stopProxyBtn.disabled = true; return; } const hasActiveConnections = activeProxyConnections.size > 0; const atMaxConnections = activeProxyConnections.size >= MAX_PROXY_CONNECTIONS; const selectedDeviceActive = selectedDevice && activeProxyConnections.has(selectedDevice.guid || selectedDevice.id); // Enable start button if: connected, device selected, not at max connections, and device not already active startProxyBtn.disabled = !selectedDevice || atMaxConnections || selectedDeviceActive; // Enable stop button if there are active connections stopProxyBtn.disabled = !hasActiveConnections; // Update button text to show connection count if (hasActiveConnections) { stopProxyBtn.textContent = `Stop All Proxies (${activeProxyConnections.size})`; } else { stopProxyBtn.textContent = 'Stop Proxy'; } } function escapeHtml(text) { if (typeof text !== 'string') return text; const div = document.createElement('div'); div.textContent = text; return div.innerHTML; } // Profile Management Functions async function loadProfiles() { try { const result = await window.electronAPI.loadProfiles(); if (result.success) { currentProfiles = result.profiles; updateProfileDropdown(); } else { console.error('Failed to load profiles:', result.message); } } catch (error) { console.error('Error loading profiles:', error); } } function updateProfileDropdown() { // Clear existing options except the first one profileSelect.innerHTML = ''; currentProfiles.forEach(profile => { const option = document.createElement('option'); option.value = profile.id; option.textContent = `${profile.name} (${profile.username})`; profileSelect.appendChild(option); }); } async function handleProfileSelection() { const selectedProfileId = profileSelect.value; if (!selectedProfileId) { selectedProfile = null; updateButtonStates(); return; } try { const result = await window.electronAPI.getProfile(selectedProfileId); if (result.success) { selectedProfile = result.profile; updateButtonStates(); } else { showStatus(connectionStatus, `Failed to load profile: ${result.message}`, 'error'); } } catch (error) { console.error('Error loading profile:', error); showStatus(connectionStatus, 'Error loading profile', 'error'); } } function showAddProfileModal() { // Clear the form for new profile addProfileForm.reset(); addProfileModal.style.display = 'block'; document.getElementById('profileName').focus(); } function hideAddProfileModal() { addProfileModal.style.display = 'none'; addProfileForm.reset(); } async function handleAddProfile(event) { event.preventDefault(); const name = document.getElementById('profileName').value.trim(); const deploymentUrl = document.getElementById('profileUrl').value.trim(); const username = document.getElementById('profileUsername').value.trim(); const password = document.getElementById('profilePassword').value; if (!name || !deploymentUrl || !username || !password) { alert('Please fill in all fields'); return; } // Check if profile name already exists if (currentProfiles.some(p => p.name.toLowerCase() === name.toLowerCase())) { alert('A profile with this name already exists'); return; } try { const result = await window.electronAPI.saveProfile({ name: name, deploymentUrl: deploymentUrl.replace(/\/$/, ''), // Remove trailing slash username: username, password: password }); if (result.success) { hideAddProfileModal(); await loadProfiles(); // Reload profiles // Select the newly created profile profileSelect.value = result.profile.id; await handleProfileSelection(); showStatus(connectionStatus, 'Profile saved successfully!', 'success'); } else { alert(`Failed to save profile: ${result.message}`); } } catch (error) { console.error('Error saving profile:', error); alert('Error saving profile'); } } function showManageProfilesModal() { updateProfilesList(); manageProfilesModal.style.display = 'block'; } function hideManageProfilesModal() { manageProfilesModal.style.display = 'none'; } function updateProfilesList() { profilesList.innerHTML = ''; if (currentProfiles.length === 0) { profilesList.innerHTML = '
No profiles saved
'; return; } currentProfiles.forEach(profile => { const profileItem = document.createElement('div'); profileItem.className = 'profile-item'; profileItem.innerHTML = `

${escapeHtml(profile.name)}

${escapeHtml(profile.username)} @ ${escapeHtml(profile.deploymentUrl)}

`; profileItem.querySelector('.edit').addEventListener('click', () => editProfile(profile.id)); profileItem.querySelector('.delete').addEventListener('click', () => deleteProfile(profile.id)); profilesList.appendChild(profileItem); }); } async function editProfile(profileId) { try { const result = await window.electronAPI.getProfile(profileId); if (result.success) { const profile = result.profile; const newName = prompt('Enter new profile name:', profile.name); if (newName && newName.trim() !== profile.name) { const updateResult = await window.electronAPI.updateProfile(profileId, { name: newName.trim(), deploymentUrl: profile.deploymentUrl, username: profile.username, password: profile.password }); if (updateResult.success) { await loadProfiles(); updateProfilesList(); showStatus(connectionStatus, 'Profile updated successfully!', 'success'); } else { alert(`Failed to update profile: ${updateResult.message}`); } } } } catch (error) { console.error('Error editing profile:', error); alert('Error editing profile'); } } async function deleteProfile(profileId) { const profile = currentProfiles.find(p => p.id === profileId); if (!profile) return; if (confirm(`Are you sure you want to delete the profile "${profile.name}"?`)) { try { const result = await window.electronAPI.deleteProfile(profileId); if (result.success) { await loadProfiles(); updateProfilesList(); // Clear selection if deleted profile was selected if (profileSelect.value === profileId) { profileSelect.value = ''; await handleProfileSelection(); } showStatus(connectionStatus, 'Profile deleted successfully!', 'success'); } else { alert(`Failed to delete profile: ${result.message}`); } } catch (error) { console.error('Error deleting profile:', error); alert('Error deleting profile'); } } } // toggleCookieSection is attached via addEventListener in the event listeners section above // Handle cookie received from Chrome extension via local HTTP bridge async function handleExtensionCookie(data) { const { deploymentUrl, cookies, cookieValue } = data; // If already connected, disconnect first if (sessionData.isConnected) { handleDisconnect(); } // Set session state from extension cookie sessionData.deploymentUrl = deploymentUrl; sessionData.cookies = cookies; sessionData.isConnected = true; showStatus(connectionStatus, `Connected via Chrome extension to ${deploymentUrl}`, 'success'); updateConnectionStatus(true); updateButtonStates(); // Auto-populate cookie key and expand cookie proxy section cookieKey.value = cookieValue; const cookieContent = document.getElementById('cookieProxyContent'); const cookieIcon = document.getElementById('cookieCollapseIcon'); if (cookieContent.style.display === 'none') { cookieContent.style.display = 'block'; cookieIcon.textContent = '\u25B2'; cookieIcon.classList.add('expanded'); } updateCookieProxyButtonStates(); // Fetch devices try { await handleGetDevices(); } catch (err) { console.error('Failed to fetch devices after extension cookie:', err); showStatus(deviceStatus, 'Connected, but failed to load devices.', 'warning'); } } // Initialize the app document.addEventListener('DOMContentLoaded', async () => { console.log('Alta Video Camera Proxy loaded'); // Initialize connection status updateConnectionStatus(false); updateButtonStates(); // Listen for cookies pushed from Chrome extension window.electronAPI.onExtensionCookie(handleExtensionCookie); // Load saved profiles await loadProfiles(); // Check camera proxy executable availability await checkCameraProxyAvailability(); }); // Check if camera proxy executable is available async function checkCameraProxyAvailability() { try { const result = await window.electronAPI.checkCameraProxy(); if (!result.exists) { showStatus(connectionStatus, 'Warning: aware-cam-proxy-win.exe not found. Camera proxy functionality will not work.', 'warning'); // Disable proxy-related buttons startProxyBtn.disabled = true; checkVersionBtn.disabled = true; // Add a tooltip or visual indicator startProxyBtn.title = 'Camera proxy executable not found'; checkVersionBtn.title = 'Camera proxy executable not found'; } else { console.log('Camera proxy executable found at:', result.path); // Optionally get version info try { const versionResult = await window.electronAPI.getCameraProxyVersion(); if (versionResult.success) { console.log('Camera proxy version:', versionResult.version); } } catch (error) { console.log('Could not get camera proxy version:', error); } } } catch (error) { console.error('Error checking camera proxy availability:', error); showStatus(connectionStatus, 'Error checking camera proxy availability', 'warning'); } } // Toggle cookie section visibility function toggleCookieSection() { const content = document.getElementById('cookieProxyContent'); const icon = document.getElementById('cookieCollapseIcon'); if (content.style.display === 'none') { content.style.display = 'block'; icon.textContent = '▲'; icon.classList.add('expanded'); } else { content.style.display = 'none'; icon.textContent = '▼'; icon.classList.remove('expanded'); } }