diff --git a/index.html b/index.html index 3c9ff17..3eff8cb 100644 --- a/index.html +++ b/index.html @@ -68,6 +68,10 @@ 🌍 Live-Map + @@ -361,6 +365,19 @@ + +
+
+
+

📋 Updates & Changelog

+

Versionshistorie und neue Features

+
+
+
⏳ Lade Changelog...
+
+
+
+
diff --git a/script.js b/script.js index 912ee16..538da55 100644 --- a/script.js +++ b/script.js @@ -1990,3 +1990,172 @@ } }); + +// ========================================== +// UPDATES VIEW - CHANGELOG LOADER +// ========================================== + +async function loadChangelog() { + const container = document.getElementById('changelogContent'); + + try { + const response = await fetch('CHANGELOG.md'); + if (!response.ok) throw new Error('CHANGELOG nicht gefunden'); + + const markdown = await response.text(); + const html = parseChangelog(markdown); + container.innerHTML = html; + + // Accordion-Funktionalität + document.querySelectorAll('.version-header').forEach(header => { + header.addEventListener('click', () => { + const versionBox = header.parentElement; + versionBox.classList.toggle('open'); + + // Vibration Feedback + if (navigator.vibrate) navigator.vibrate(5); + }); + }); + + } catch (error) { + console.error('Changelog Fehler:', error); + container.innerHTML = ` +
+

⚠️ Changelog konnte nicht geladen werden

+

${error.message}

+
+ `; + } +} + +function parseChangelog(markdown) { + const lines = markdown.split('\n'); + let html = ''; + let currentVersion = null; + let currentCategory = null; + let changes = {}; + + // Parse Markdown + for (let i = 0; i < lines.length; i++) { + const line = lines[i].trim(); + + // Version Header: ## [30.0.0] - 2026-02-10 + if (line.match(/^## \[(\d+\.\d+\.\d+)\] - (.+)$/)) { + // Speichere vorherige Version + if (currentVersion) { + html += renderVersion(currentVersion, changes); + changes = {}; + } + + const match = line.match(/^## \[(\d+\.\d+\.\d+)\] - (.+)$/); + currentVersion = { + number: match[1], + date: match[2] + }; + } + + // Kategorie: ### Added + else if (line.match(/^### (.+)$/)) { + const match = line.match(/^### (.+)$/); + currentCategory = match[1]; + if (!changes[currentCategory]) { + changes[currentCategory] = []; + } + } + + // Change Item: - Feature xyz + else if (line.match(/^[-*] (.+)$/) && currentCategory) { + const match = line.match(/^[-*] (.+)$/); + changes[currentCategory].push(match[1]); + } + } + + // Speichere letzte Version + if (currentVersion) { + html += renderVersion(currentVersion, changes); + } + + // GitHub Link Button + html += ` + + 💻 Alle Updates & Code auf GitHub + + `; + + return html; +} + +function renderVersion(version, changes) { + const categoryIcons = { + 'Added': '✨', + 'Changed': '🔄', + 'Fixed': '🐛', + 'Removed': '🗑️', + 'Deprecated': '⚠️', + 'Security': '🔒' + }; + + let categoriesHtml = ''; + + for (const [category, items] of Object.entries(changes)) { + if (items.length === 0) continue; + + const icon = categoryIcons[category] || '📝'; + const itemsHtml = items.map(item => `
  • ${item}
  • `).join(''); + + categoriesHtml += ` +
    +
    ${icon} ${category}
    +
      + ${itemsHtml} +
    +
    + `; + } + + return ` +
    +
    +
    + v${version.number} + ${version.date} +
    + ▼ +
    +
    +
    + ${categoriesHtml} +
    +
    +
    + `; +} + +// Changelog laden wenn Updates-View geöffnet wird +document.addEventListener('DOMContentLoaded', () => { + // Wenn direkt Updates-View aktiv ist + if (document.getElementById('view-updates')?.classList.contains('active')) { + loadChangelog(); + } + + // Beim View-Wechsel + const observer = new MutationObserver((mutations) => { + mutations.forEach((mutation) => { + if (mutation.target.id === 'view-updates' && + mutation.target.classList.contains('active')) { + // Nur laden wenn noch nicht geladen + const content = document.getElementById('changelogContent'); + if (content.innerHTML.includes('Lade Changelog')) { + loadChangelog(); + } + } + }); + }); + + const updatesView = document.getElementById('view-updates'); + if (updatesView) { + observer.observe(updatesView, { attributes: true, attributeFilter: ['class'] }); + } +}); diff --git a/service-worker.js b/service-worker.js index 2953d82..0971b3e 100644 --- a/service-worker.js +++ b/service-worker.js @@ -5,6 +5,7 @@ const urlsToCache = [ '/styles.css', '/script.js', '/manifest.json', + '/CHANGELOG.md', '/DotMatrix.ttf', '/images/favicon.png' ]; diff --git a/styles.css b/styles.css index c2d7177..d83ce6a 100644 --- a/styles.css +++ b/styles.css @@ -1018,7 +1018,7 @@ @media (min-width: 768px) { .container { - max-width: 600px; + max-width: 900px; margin: 0 auto; padding: 20px; } @@ -1026,7 +1026,7 @@ .detail-modal { left: 50%; transform: translateX(-50%); - max-width: 600px; + max-width: 900px; } } @@ -1070,7 +1070,7 @@ /* Tablet & Desktop */ @media (min-width: 768px) { .container { - max-width: 1200px; + max-width: 900px; margin: 0 auto; padding: 20px 30px; } @@ -1123,28 +1123,28 @@ } .nav-menu { - width: 280px; + width: 320px; } /* Header größer auf Desktop */ .header h1 { - font-size: 36px; + font-size: 38px; letter-spacing: 3px; } .header .subtitle { - font-size: 14px; + font-size: 15px; } .header .author { - font-size: 11px; + font-size: 12px; } /* Controls größer */ .controls { - padding: 20px; - background-color: rgba(10, 10, 10, 0.5); - border-radius: 8px; + padding: 22px; + background-color: rgba(10, 10, 10, 0.6); + border-radius: 10px; } .search-input { @@ -1355,6 +1355,7 @@ /* Large Desktop - 2 Column Layout */ @media (min-width: 1200px) { .container { + max-width: 1100px; padding: 30px 40px; } @@ -1375,7 +1376,12 @@ } .journey-leg { - padding: 16px; + padding: 18px; + } + + /* Detail Modal größer */ + .detail-modal { + max-width: 1100px; } } @@ -1393,6 +1399,11 @@ .station-info { grid-column: 1 / -1; } + + /* Detail Modal noch größer */ + .detail-modal { + max-width: 1300px; + } } /* Mobile Optimierungen */ @@ -2312,3 +2323,367 @@ padding: 7px 14px; } } + + /* Desktop-Optimierungen für Live-Map */ + @media (min-width: 768px) { + .livemap-controls { + top: 20px; + left: 20px; + right: auto; + max-width: 400px; + gap: 12px; + } + + .livemap-info { + padding: 14px 20px; + font-size: 18px; + border-radius: 10px; + } + + .filter-btn { + padding: 10px 16px; + font-size: 15px; + border-radius: 8px; + } + + .filter-btn:hover { + background-color: rgba(255, 237, 0, 0.2); + border-color: #FFED00; + } + + .filter-btn.active:hover { + background-color: #FFED00; + } + + .vehicle-popup .popup-line { + font-size: 18px; + } + + .vehicle-popup .popup-direction { + font-size: 16px; + } + + .vehicle-popup .popup-delay { + font-size: 14px; + } + } + + /* Large Desktop Live-Map */ + @media (min-width: 1200px) { + .livemap-controls { + max-width: 450px; + } + + .livemap-info { + padding: 16px 24px; + font-size: 20px; + } + + .filter-btn { + padding: 12px 18px; + font-size: 16px; + } + } + + /* Desktop-Optimierungen für Home View */ + @media (min-width: 768px) { + .home-container { + max-width: 900px; + padding: 20px; + } + + .home-hero-combined { + padding: 30px; + margin: 30px 0; + border-radius: 14px; + } + + .home-hint-text { + font-size: 16px; + } + + .home-nav-buttons { + gap: 15px; + } + + .home-nav-btn { + padding: 20px; + min-height: 80px; + } + + .home-nav-btn .nav-icon { + font-size: 32px; + } + + .home-nav-btn .nav-label { + font-size: 18px; + } + + .home-nav-btn:hover { + background-color: rgba(255, 237, 0, 0.05); + transform: translateY(-3px); + box-shadow: 0 6px 20px rgba(255, 237, 0, 0.2); + } + } + + @media (min-width: 1200px) { + .home-container { + max-width: 1100px; + } + + .home-hero-combined { + padding: 40px; + } + + .home-nav-buttons { + grid-template-columns: repeat(3, 1fr); + } + } + + /* ========================================== + DESKTOP LAYOUT ZUSAMMENFASSUNG + ========================================== + + Mobile (bis 767px): + - Original Mobile-Styles bleiben unverändert + - Optimiert für Touch-Bedienung + + Tablet/Desktop (768px - 1199px): + - Container: 900px + - Single Column Layout + - Detail-Modal: 900px + - Größere Schrift und Abstände + + Large Desktop (1200px - 1599px): + - Container: 1100px + - 2 Spalten für Abfahrten + - Detail-Modal: 1100px + + Extra Large Desktop (1600px+): + - Container: 1400px + - 3 Spalten für Abfahrten + - Detail-Modal: 1300px + + ========================================== */ + + /* ========================================== + UPDATES VIEW STYLING + ========================================== */ + + .updates-header { + text-align: center; + padding: 30px 20px 20px; + border-bottom: 2px solid #FFED00; + margin-bottom: 20px; + } + + .updates-header h2 { + font-size: 28px; + margin-bottom: 8px; + color: #FFED00; + } + + .updates-subtitle { + font-size: 14px; + opacity: 0.7; + color: #fff; + } + + .changelog-container { + padding: 10px; + } + + /* Version Box - wie im Screenshot */ + .version-box { + background: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 100%); + border: 2px solid #FFED00; + border-radius: 10px; + margin-bottom: 20px; + overflow: hidden; + } + + .version-header { + background-color: #000; + border-bottom: 2px solid #FFED00; + padding: 15px 20px; + cursor: pointer; + display: flex; + justify-content: space-between; + align-items: center; + transition: background-color 0.2s; + } + + .version-header:hover { + background-color: #0a0a0a; + } + + .version-header:active { + background-color: #1a1a1a; + } + + .version-title { + display: flex; + align-items: center; + gap: 12px; + } + + .version-number { + background-color: #FFED00; + color: #000; + padding: 4px 12px; + border-radius: 6px; + font-size: 16px; + font-weight: bold; + } + + .version-date { + color: #fff; + opacity: 0.7; + font-size: 13px; + } + + .version-toggle { + font-size: 20px; + color: #FFED00; + transition: transform 0.3s; + } + + .version-box.open .version-toggle { + transform: rotate(180deg); + } + + .version-content { + max-height: 0; + overflow: hidden; + transition: max-height 0.3s ease-out; + } + + .version-box.open .version-content { + max-height: 2000px; + } + + .version-content-inner { + padding: 20px; + } + + /* Change Categories */ + .change-category { + margin-bottom: 20px; + } + + .change-category-title { + color: #FFED00; + font-size: 16px; + font-weight: bold; + margin-bottom: 10px; + display: flex; + align-items: center; + gap: 8px; + } + + .change-list { + list-style: none; + padding: 0; + } + + .change-item { + padding: 8px 0 8px 25px; + position: relative; + color: #fff; + font-size: 14px; + line-height: 1.5; + } + + .change-item:before { + content: "•"; + position: absolute; + left: 10px; + color: #FFED00; + font-size: 18px; + } + + /* GitHub Button - wie im Screenshot */ + .github-link-btn { + display: block; + width: 100%; + padding: 15px; + margin-top: 20px; + background: linear-gradient(135deg, #1a1a1a 0%, #0a0a0a 100%); + border: 2px solid #FFED00; + border-radius: 8px; + color: #FFED00; + text-decoration: none; + text-align: center; + font-size: 16px; + font-weight: bold; + transition: all 0.2s; + } + + .github-link-btn:hover { + background: #FFED00; + color: #000; + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(255, 237, 0, 0.3); + } + + .github-link-btn:active { + transform: translateY(0); + } + + /* Older Updates Button */ + .older-updates-btn { + display: block; + width: 100%; + padding: 12px; + margin-top: 15px; + background-color: #0a0a0a; + border: 1px solid #333; + border-radius: 6px; + color: #FFED00; + text-align: center; + font-size: 14px; + cursor: pointer; + transition: all 0.2s; + } + + .older-updates-btn:hover { + background-color: #1a1a1a; + border-color: #FFED00; + } + + .older-updates-btn:active { + background-color: #000; + } + + /* Desktop Optimierungen */ + @media (min-width: 768px) { + .updates-header h2 { + font-size: 36px; + } + + .updates-subtitle { + font-size: 16px; + } + + .version-number { + font-size: 18px; + padding: 6px 16px; + } + + .version-date { + font-size: 15px; + } + + .change-category-title { + font-size: 18px; + } + + .change-item { + font-size: 15px; + } + + .github-link-btn { + font-size: 18px; + padding: 18px; + } + }