// Software Upgrade System - Frontend Functions // Requires: jQuery or modern fetch API class UpgradeManager { constructor(apiBase = '/api.php') { this.apiBase = apiBase; this.serviceToken = ''; this.init(); } init() { // Get service token from DOM if available const tokenElement = document.getElementById('servicetoken'); if (tokenElement) { this.serviceToken = tokenElement.innerHTML || ''; } } async makeAPICall(endpoint, method = 'GET', data = null) { const url = this.apiBase + endpoint; const bearer = 'Bearer ' + this.serviceToken; const options = { method: method, headers: { 'Authorization': bearer, 'Content-Type': 'application/json' }, credentials: 'include' }; if (data && (method === 'POST' || method === 'PUT')) { options.body = JSON.stringify(data); } const response = await fetch(url, options); if (!response.ok) { const errorData = await response.json().catch(() => ({ error: 'Network error' })); throw new Error(errorData.error || `HTTP ${response.status}`); } return await response.json(); } async getAvailableVersions() { try { const data = await this.makeAPICall('/v2/get/software?available'); return data; } catch (error) { console.error('Error fetching available versions:', error); throw error; } } async downloadVersion(versionId, onProgress = null) { try { // Step 1: Request download token const downloadRequest = await this.makeAPICall('/v2/post/software', 'POST', { action: 'download', version_id: parseInt(versionId) }); if (!downloadRequest.download_url) { throw new Error('No download URL received'); } // Step 2: Download file using temporary URL await this.downloadFile(downloadRequest.download_url, onProgress); } catch (error) { console.error('Download error:', error); throw error; } } async downloadFile(url, onProgress) { const response = await fetch(url, { credentials: 'include' }); if (!response.ok) { throw new Error('Download failed'); } const contentLength = response.headers.get('Content-Length'); const total = parseInt(contentLength, 10); let loaded = 0; const reader = response.body.getReader(); const chunks = []; while (true) { const { done, value } = await reader.read(); if (done) break; chunks.push(value); loaded += value.length; if (onProgress && total) { onProgress(loaded, total); } } // Create blob from chunks const blob = new Blob(chunks); // Trigger download const downloadUrl = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.href = downloadUrl; a.download = 'software_upgrade.zip'; // Filename will be set by server document.body.appendChild(a); a.click(); window.URL.revokeObjectURL(downloadUrl); document.body.removeChild(a); } async purchaseVersion(versionId, transactionId = null) { try { const purchaseData = { action: 'purchase', version_id: parseInt(versionId) }; if (transactionId) { purchaseData.transaction_id = transactionId; } const result = await this.makeAPICall('/v2/post/software', 'POST', purchaseData); return result; } catch (error) { console.error('Purchase error:', error); throw error; } } formatBytes(bytes) { if (bytes === 0) return '0 Bytes'; const k = 1024; const sizes = ['Bytes', 'KB', 'MB', 'GB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return Math.round(bytes / Math.pow(k, i) * 100) / 100 + ' ' + sizes[i]; } formatPrice(price, currency = 'USD') { return new Intl.NumberFormat('en-US', { style: 'currency', currency: currency }).format(price); } } // Global upgrade manager instance let upgradeManager; // Initialize upgrade system function initUpgradeSystem() { upgradeManager = new UpgradeManager(); } // Display upgrade options in UI async function showUpgradeOptions(containerId = 'upgrade-container') { const container = document.getElementById(containerId); if (!container) { console.error('Container element not found:', containerId); return; } try { const data = await upgradeManager.getAvailableVersions(); container.innerHTML = ''; // Show current version info if (data.current_version) { const currentDiv = document.createElement('div'); currentDiv.className = 'current-version-info'; currentDiv.innerHTML = `
Owned versions: ${data.owned_versions.map(v => v.version).join(', ')}
`; container.appendChild(currentDiv); } // Show available versions if (data.available_versions && data.available_versions.length > 0) { const versionsDiv = document.createElement('div'); versionsDiv.className = 'available-versions'; data.available_versions.forEach(version => { const versionCard = document.createElement('div'); versionCard.className = 'version-card'; versionCard.dataset.versionId = version.id; let buttonHTML = ''; let priceHTML = ''; let statusHTML = ''; if (version.is_accessible) { statusHTML = 'Owned'; buttonHTML = ``; } else if (version.requires_payment) { if (version.is_upgrade) { priceHTML = `No software versions available at this time.
'; } } catch (error) { container.innerHTML = ``; console.error('Error showing upgrade options:', error); } } // Download version with progress async function downloadVersion(versionId) { const button = event.target; const originalText = button.innerHTML; try { button.disabled = true; button.innerHTML = 'Preparing Download...'; // Create progress indicator const progressContainer = document.createElement('div'); progressContainer.className = 'download-progress'; progressContainer.innerHTML = `