/** * Version Fetcher - Automatically fetches and displays latest pyserveX version * from Gitea releases page */ (function() { 'use strict'; const RELEASES_URL = 'https://git.pyserve.org/Shifty/pyserveX/releases/latest'; const VERSION_ELEMENT_ID = 'current-version'; const CACHE_KEY = 'pyserve_version_cache'; const CACHE_DURATION = 3600000; // 1 hour const FALLBACK_VERSION = 'offline'; async function fetchLatestVersion() { try { const response = await fetch(RELEASES_URL, { method: 'GET', mode: 'cors', headers: { 'Accept': 'text/html' } }); if (!response.ok) { console.warn(`Failed to fetch: ${response.status}`); return null; } const html = await response.text(); const patterns = [ /PyServeX\s+v([\d.]+)/i, /releases\/tag\/v([\d.]+)/, /aria-label="PyServeX\s+v([\d.]+)/i, /<h4[^>]*>.*?v([\d.]+).*?<\/h4>/i ]; for (const pattern of patterns) { const match = html.match(pattern); if (match && match[1]) { console.log(`✓ Version found: ${match[1]}`); return match[1]; } } console.warn('Version not found in HTML'); return null; } catch (error) { console.warn('Fetch error:', error.message); return null; } } function getCachedVersion() { try { const cached = localStorage.getItem(CACHE_KEY); if (!cached) return null; const data = JSON.parse(cached); const now = Date.now(); if (now - data.timestamp < CACHE_DURATION) { return data.version; } localStorage.removeItem(CACHE_KEY); return null; } catch (error) { console.error('Cache read error:', error); return null; } } function cacheVersion(version) { try { const data = { version: version, timestamp: Date.now() }; localStorage.setItem(CACHE_KEY, JSON.stringify(data)); } catch (error) { console.error('Cache write error:', error); } } function updateVersionDisplay(version) { const element = document.getElementById(VERSION_ELEMENT_ID); if (!element) { console.warn('Version element not found'); return; } const versionLink = document.createElement('a'); versionLink.href = 'https://git.pyserve.org/Shifty/pyserveX/releases/tag/v' + version; versionLink.textContent = version; versionLink.target = '_blank'; versionLink.rel = 'noopener noreferrer'; versionLink.className = 'version-link'; element.innerHTML = ''; element.appendChild(versionLink); const badge = document.createElement('span'); badge.textContent = 'latest'; badge.className = 'version-badge'; badge.title = 'Fetched from Git repository'; element.appendChild(document.createTextNode(' ')); element.appendChild(badge); element.style.opacity = '1'; } function showLoadingState() { const element = document.getElementById(VERSION_ELEMENT_ID); if (element) { element.style.opacity = '0.6'; } } async function init() { showLoadingState(); const cachedVersion = getCachedVersion(); if (cachedVersion) { updateVersionDisplay(cachedVersion); } const latestVersion = await fetchLatestVersion(); if (latestVersion) { cacheVersion(latestVersion); updateVersionDisplay(latestVersion); } else if (!cachedVersion) { const element = document.getElementById(VERSION_ELEMENT_ID); if (element) { element.textContent = FALLBACK_VERSION; element.style.opacity = '1'; element.style.color = '#c9c9c9'; element.title = 'Version fetch failed (CORS or network issue)'; } } } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } })();