diff --git a/GUI/index.html b/GUI/index.html index 0f22cf8..8a041e2 100644 --- a/GUI/index.html +++ b/GUI/index.html @@ -35,6 +35,10 @@ Play + + +
@@ -880,6 +918,7 @@
+ diff --git a/GUI/js/featured.js b/GUI/js/featured.js new file mode 100644 index 0000000..9e44cc1 --- /dev/null +++ b/GUI/js/featured.js @@ -0,0 +1,165 @@ +// Featured Servers Management +const FEATURED_SERVERS_API = 'https://assets.authbp.xyz/featured.json'; + +/** + * Load and display featured servers + */ +async function loadFeaturedServers() { + const featuredContainer = document.getElementById('featuredServersList'); + const myServersContainer = document.getElementById('myServersList'); + + try { + console.log('[FeaturedServers] Fetching from', FEATURED_SERVERS_API); + + // Fetch featured servers from API (no cache) + const response = await fetch(FEATURED_SERVERS_API, { + cache: 'no-store', + headers: { + 'Cache-Control': 'no-cache', + 'Pragma': 'no-cache' + } + }); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + const data = await response.json(); + const featuredServers = data.featuredServers || []; + + console.log('[FeaturedServers] Loaded', featuredServers.length, 'featured servers'); + + // Render featured servers + if (featuredServers.length === 0) { + featuredContainer.innerHTML = ` +
+ +

No featured servers

+
+ `; + } else { + const featuredHTML = featuredServers.map((server, index) => { + console.log(`[FeaturedServers] Building featured card ${index + 1}:`, server.Name); + + const escapedName = (server.Name || 'Unknown Server').replace(/"/g, '"').replace(/'/g, ''').replace(//g, '>'); + const escapedAddress = (server.Address || '').replace(/"/g, '"').replace(/'/g, '''); + const bannerUrl = server.img_Banner || 'https://via.placeholder.com/400x240/1e293b/ffffff?text=Server+Banner'; + + return ` + + `; + }).join(''); + + featuredContainer.innerHTML = featuredHTML; + } + + // Show "Coming Soon" for my servers + myServersContainer.innerHTML = ` +
+

Coming Soon

+
+ `; + + } catch (error) { + console.error('[FeaturedServers] Error loading servers:', error); + featuredContainer.innerHTML = ` +
+ +

Failed to load servers

+

${error.message}

+
+ `; + myServersContainer.innerHTML = ` +
+

Coming Soon

+
+ `; + } +} + +/** + * Copy server address to clipboard + */ +async function copyServerAddress(address, button) { + try { + await navigator.clipboard.writeText(address); + + // Visual feedback + const originalHTML = button.innerHTML; + button.classList.add('copied'); + button.innerHTML = 'Copied!'; + + setTimeout(() => { + button.classList.remove('copied'); + button.innerHTML = originalHTML; + }, 2000); + + console.log('[FeaturedServers] Copied address:', address); + } catch (error) { + console.error('[FeaturedServers] Failed to copy address:', error); + + // Fallback for older browsers + const textArea = document.createElement('textarea'); + textArea.value = address; + textArea.style.position = 'fixed'; + textArea.style.left = '-999999px'; + document.body.appendChild(textArea); + textArea.select(); + + try { + document.execCommand('copy'); + const originalHTML = button.innerHTML; + button.classList.add('copied'); + button.innerHTML = 'Copied!'; + + setTimeout(() => { + button.classList.remove('copied'); + button.innerHTML = originalHTML; + }, 2000); + } catch (err) { + console.error('[FeaturedServers] Fallback copy also failed:', err); + } + + document.body.removeChild(textArea); + } +} + +// Load featured servers when the featured page becomes visible +document.addEventListener('DOMContentLoaded', () => { + const observer = new MutationObserver((mutations) => { + mutations.forEach((mutation) => { + if (mutation.type === 'attributes' && mutation.attributeName === 'class') { + const featuredPage = document.getElementById('featured-page'); + if (featuredPage && featuredPage.classList.contains('active')) { + loadFeaturedServers(); + } + } + }); + }); + + const featuredPage = document.getElementById('featured-page'); + if (featuredPage) { + observer.observe(featuredPage, { attributes: true }); + + // Load immediately if already visible + if (featuredPage.classList.contains('active')) { + loadFeaturedServers(); + } + } +}); diff --git a/GUI/style.css b/GUI/style.css index 8a6e826..e591e78 100644 --- a/GUI/style.css +++ b/GUI/style.css @@ -1107,6 +1107,216 @@ body { padding-bottom: 1rem; } +/* Featured Servers Styles */ +.featured-layout { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 2rem; + height: calc(100vh - 180px); + overflow: hidden; +} + +.featured-left, +.featured-right { + display: flex; + flex-direction: column; + overflow: hidden; + min-height: 0; +} + +.featured-header { + margin-bottom: 1.5rem; + flex-shrink: 0; +} + +.featured-title { + font-size: 1.5rem; + font-weight: 700; + color: white; + display: flex; + align-items: center; + gap: 0.5rem; +} + +.featured-list { + flex: 1; + overflow-y: auto; + overflow-x: hidden; + padding-right: 0.5rem; + display: flex; + flex-direction: column; + gap: 1.25rem; + min-height: 0; +} + +.featured-list::-webkit-scrollbar { + width: 8px; +} + +.featured-list::-webkit-scrollbar-track { + background: rgba(0, 0, 0, 0.3); + border-radius: 4px; +} + +.featured-list::-webkit-scrollbar-thumb { + background: rgba(147, 51, 234, 0.5); + border-radius: 4px; +} + +.featured-list::-webkit-scrollbar-thumb:hover { + background: rgba(147, 51, 234, 0.7); +} + +.featured-server-card { + position: relative; + background: rgba(0, 0, 0, 0.4); + backdrop-filter: blur(20px); + border: 1px solid rgba(255, 255, 255, 0.1); + border-radius: 12px; + overflow: hidden; + transition: all 0.3s ease; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3); + display: grid; + grid-template-columns: 200px 1fr; + min-height: 120px; + flex-shrink: 0; +} + +.featured-server-card:hover { + transform: translateX(4px); + border-color: rgba(147, 51, 234, 0.5); + box-shadow: 0 8px 40px rgba(147, 51, 234, 0.2); +} + +.featured-server-banner { + width: 200px; + height: 100%; + min-height: 120px; + object-fit: cover; + background: linear-gradient(135deg, #1e293b, #334155); + flex-shrink: 0; +} + +.featured-server-content { + padding: 1.25rem; + display: flex; + flex-direction: column; + justify-content: center; + gap: 0.75rem; +} + +.featured-server-name { + font-size: 1.15rem; + font-weight: 600; + color: white; + line-height: 1.4; + margin: 0; +} + +.featured-server-address { + display: flex; + align-items: center; + justify-content: space-between; + background: rgba(255, 255, 255, 0.05); + padding: 0.625rem 1rem; + border-radius: 6px; + border: 1px solid rgba(255, 255, 255, 0.1); +} + +.server-address-text { + font-family: 'JetBrains Mono', monospace; + color: #94a3b8; + font-size: 0.9rem; +} + +.copy-address-btn { + background: linear-gradient(135deg, #9333ea, #7c3aed); + color: white; + border: none; + padding: 0.5rem 1rem; + border-radius: 6px; + cursor: pointer; + font-size: 0.875rem; + font-weight: 500; + transition: all 0.2s ease; + display: flex; + align-items: center; + gap: 0.5rem; + white-space: nowrap; +} + +.copy-address-btn:hover { + background: linear-gradient(135deg, #7c3aed, #6d28d9); + transform: scale(1.05); +} + +.copy-address-btn:active { + transform: scale(0.95); +} + +.copy-address-btn.copied { + background: linear-gradient(135deg, #10b981, #059669); +} + +.loading-spinner { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 3rem; + color: #94a3b8; + gap: 1rem; +} + +.loading-spinner i { + color: #9333ea; +} + +/* My server card - without banner */ +.my-server-card { + position: relative; + background: rgba(0, 0, 0, 0.4); + backdrop-filter: blur(20px); + border: 1px solid rgba(255, 255, 255, 0.1); + border-radius: 12px; + overflow: hidden; + transition: all 0.3s ease; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3); + padding: 1.25rem; + flex-shrink: 0; +} + +.my-server-card:hover { + transform: translateX(4px); + border-color: rgba(147, 51, 234, 0.5); + box-shadow: 0 8px 40px rgba(147, 51, 234, 0.2); +} + +.my-server-content { + display: flex; + flex-direction: column; + gap: 0.75rem; +} + +.my-server-name { + font-size: 1.15rem; + font-weight: 600; + color: white; + line-height: 1.4; + margin: 0; +} + +.my-server-address { + display: flex; + align-items: center; + justify-content: space-between; + background: rgba(255, 255, 255, 0.05); + padding: 0.625rem 1rem; + border-radius: 6px; + border: 1px solid rgba(255, 255, 255, 0.1); +} + + .news-view-all:hover { color: white; } @@ -1770,252 +1980,252 @@ body { animation: shimmer 2s infinite; } -@keyframes shimmer { - 0% { - left: -100%; - } - - 100% { - left: 100%; - } -} - -/* Progress Error and Retry Styles */ -.progress-error-container { - margin-top: 0.75rem; - padding-top: 0.75rem; - border-top: 1px solid rgba(239, 68, 68, 0.3); - animation: errorSlideIn 0.3s ease-out; -} - -@keyframes errorSlideIn { - from { - opacity: 0; - transform: translateY(-10px); - } - to { - opacity: 1; - transform: translateY(0); - } -} - -.progress-error-message { - color: #f87171; - font-family: 'JetBrains Mono', monospace; - font-size: 0.75rem; - margin-bottom: 0.5rem; - text-shadow: 0 0 8px rgba(248, 113, 113, 0.4); - line-height: 1.4; -} - -.progress-retry-section { - display: flex; - justify-content: space-between; - align-items: center; - gap: 0.75rem; -} - -.progress-retry-buttons { - display: flex; - gap: 0.5rem; - flex-wrap: wrap; -} - -.progress-retry-info { - color: #fbbf24; - font-family: 'JetBrains Mono', monospace; - font-size: 0.7rem; - flex: 1; -} - -.progress-retry-btn { - background: linear-gradient(135deg, #dc2626, #ef4444); - color: white; - border: none; - padding: 0.5rem 1rem; - border-radius: 6px; - font-family: 'JetBrains Mono', monospace; - font-size: 0.75rem; - font-weight: 600; - cursor: pointer; - transition: all 0.2s ease; - box-shadow: 0 2px 8px rgba(220, 38, 38, 0.3); - white-space: nowrap; - min-width: 120px; -} - -.progress-retry-btn:hover { - background: linear-gradient(135deg, #b91c1c, #dc2626); - transform: translateY(-1px); - box-shadow: 0 4px 12px rgba(220, 38, 38, 0.4); -} - -.progress-retry-btn:active { - transform: translateY(0); - box-shadow: 0 2px 6px rgba(220, 38, 38, 0.3); -} - -.progress-retry-btn:disabled { - background: linear-gradient(135deg, #4b5563, #6b7280); - cursor: not-allowed; - transform: none; - box-shadow: none; - opacity: 0.6; -} - -/* Progress overlay error state */ -.progress-overlay.error-state { - border-color: rgba(239, 68, 68, 0.5); - box-shadow: - 0 4px 16px rgba(0, 0, 0, 0.5), - 0 0 30px rgba(239, 68, 68, 0.2), - inset 0 1px 0 rgba(255, 255, 255, 0.05); -} - -.progress-overlay.error-state #progressBarFill { - background: linear-gradient(90deg, #dc2626, #ef4444); - animation: errorPulse 1.5s ease-in-out infinite; -} - -@keyframes errorPulse { - 0%, 100% { - opacity: 0.8; - } - 50% { - opacity: 1; - } -} - -/* Error type specific styling */ -.progress-error-container.error-network { - border-top-color: rgba(59, 130, 246, 0.5); -} - -.progress-error-container.error-network .progress-error-message { - color: #60a5fa; - text-shadow: 0 0 8px rgba(96, 165, 250, 0.4); -} - -.progress-error-container.error-stall { - border-top-color: rgba(245, 158, 11, 0.5); -} - -.progress-error-container.error-stall .progress-error-message { - color: #fbbf24; - text-shadow: 0 0 8px rgba(251, 191, 36, 0.4); -} - -.progress-error-container.error-file { - border-top-color: rgba(239, 68, 68, 0.5); -} - -.progress-error-container.error-file .progress-error-message { - color: #f87171; - text-shadow: 0 0 8px rgba(248, 113, 113, 0.4); -} - -.progress-error-container.error-permission { - border-top-color: rgba(168, 85, 247, 0.5); -} - -.progress-error-container.error-permission .progress-error-message { - color: #a855f7; - text-shadow: 0 0 8px rgba(168, 85, 247, 0.4); -} - -.progress-error-container.error-server { - border-top-color: rgba(236, 72, 153, 0.5); -} - -.progress-error-container.error-server .progress-error-message { - color: #ec4899; - text-shadow: 0 0 8px rgba(236, 72, 153, 0.4); -} - -.progress-error-container.error-corruption { - border-top-color: rgba(220, 38, 38, 0.8); -} - -.progress-error-container.error-corruption .progress-error-message { - color: #dc2626; - text-shadow: 0 0 8px rgba(220, 38, 38, 0.6); - font-weight: 600; -} - -.progress-error-container.error-butler { - border-top-color: rgba(245, 158, 11, 0.5); -} - -.progress-error-container.error-butler .progress-error-message { - color: #f59e0b; - text-shadow: 0 0 8px rgba(245, 158, 11, 0.4); -} - -.progress-error-container.error-space { - border-top-color: rgba(168, 85, 247, 0.5); -} - -.progress-error-container.error-space .progress-error-message { - color: #a855f7; - text-shadow: 0 0 8px rgba(168, 85, 247, 0.4); -} - -.progress-error-container.error-conflict { - border-top-color: rgba(6, 182, 212, 0.5); -} - -.progress-error-container.error-conflict .progress-error-message { - color: #06b6d4; - text-shadow: 0 0 8px rgba(6, 182, 212, 0.4); -} - -/* Connection quality indicators */ -.progress-details { - transition: all 0.3s ease; -} - -.progress-details #progressSize { - transition: color 0.5s ease; -} - -/* Enhanced retry button states */ -.progress-retry-btn.retrying { - background: linear-gradient(135deg, #059669, #10b981); - animation: retryingPulse 1s ease-in-out infinite; -} - -@keyframes retryingPulse { - 0%, 100% { - transform: scale(1); - box-shadow: 0 2px 8px rgba(5, 150, 105, 0.3); - } - 50% { - transform: scale(1.05); - box-shadow: 0 4px 12px rgba(5, 150, 105, 0.4); - } -} - -/* Network status indicator (optional future enhancement) */ -.network-status { - position: absolute; - top: 5px; - right: 5px; - width: 8px; - height: 8px; - border-radius: 50%; - background: #10b981; - box-shadow: 0 0 6px rgba(16, 185, 129, 0.6); -} - -.network-status.poor { - background: #f87171; - box-shadow: 0 0 6px rgba(248, 113, 113, 0.6); -} - -.network-status.fair { - background: #fbbf24; - box-shadow: 0 0 6px rgba(251, 191, 36, 0.6); -} +@keyframes shimmer { + 0% { + left: -100%; + } + + 100% { + left: 100%; + } +} + +/* Progress Error and Retry Styles */ +.progress-error-container { + margin-top: 0.75rem; + padding-top: 0.75rem; + border-top: 1px solid rgba(239, 68, 68, 0.3); + animation: errorSlideIn 0.3s ease-out; +} + +@keyframes errorSlideIn { + from { + opacity: 0; + transform: translateY(-10px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.progress-error-message { + color: #f87171; + font-family: 'JetBrains Mono', monospace; + font-size: 0.75rem; + margin-bottom: 0.5rem; + text-shadow: 0 0 8px rgba(248, 113, 113, 0.4); + line-height: 1.4; +} + +.progress-retry-section { + display: flex; + justify-content: space-between; + align-items: center; + gap: 0.75rem; +} + +.progress-retry-buttons { + display: flex; + gap: 0.5rem; + flex-wrap: wrap; +} + +.progress-retry-info { + color: #fbbf24; + font-family: 'JetBrains Mono', monospace; + font-size: 0.7rem; + flex: 1; +} + +.progress-retry-btn { + background: linear-gradient(135deg, #dc2626, #ef4444); + color: white; + border: none; + padding: 0.5rem 1rem; + border-radius: 6px; + font-family: 'JetBrains Mono', monospace; + font-size: 0.75rem; + font-weight: 600; + cursor: pointer; + transition: all 0.2s ease; + box-shadow: 0 2px 8px rgba(220, 38, 38, 0.3); + white-space: nowrap; + min-width: 120px; +} + +.progress-retry-btn:hover { + background: linear-gradient(135deg, #b91c1c, #dc2626); + transform: translateY(-1px); + box-shadow: 0 4px 12px rgba(220, 38, 38, 0.4); +} + +.progress-retry-btn:active { + transform: translateY(0); + box-shadow: 0 2px 6px rgba(220, 38, 38, 0.3); +} + +.progress-retry-btn:disabled { + background: linear-gradient(135deg, #4b5563, #6b7280); + cursor: not-allowed; + transform: none; + box-shadow: none; + opacity: 0.6; +} + +/* Progress overlay error state */ +.progress-overlay.error-state { + border-color: rgba(239, 68, 68, 0.5); + box-shadow: + 0 4px 16px rgba(0, 0, 0, 0.5), + 0 0 30px rgba(239, 68, 68, 0.2), + inset 0 1px 0 rgba(255, 255, 255, 0.05); +} + +.progress-overlay.error-state #progressBarFill { + background: linear-gradient(90deg, #dc2626, #ef4444); + animation: errorPulse 1.5s ease-in-out infinite; +} + +@keyframes errorPulse { + 0%, 100% { + opacity: 0.8; + } + 50% { + opacity: 1; + } +} + +/* Error type specific styling */ +.progress-error-container.error-network { + border-top-color: rgba(59, 130, 246, 0.5); +} + +.progress-error-container.error-network .progress-error-message { + color: #60a5fa; + text-shadow: 0 0 8px rgba(96, 165, 250, 0.4); +} + +.progress-error-container.error-stall { + border-top-color: rgba(245, 158, 11, 0.5); +} + +.progress-error-container.error-stall .progress-error-message { + color: #fbbf24; + text-shadow: 0 0 8px rgba(251, 191, 36, 0.4); +} + +.progress-error-container.error-file { + border-top-color: rgba(239, 68, 68, 0.5); +} + +.progress-error-container.error-file .progress-error-message { + color: #f87171; + text-shadow: 0 0 8px rgba(248, 113, 113, 0.4); +} + +.progress-error-container.error-permission { + border-top-color: rgba(168, 85, 247, 0.5); +} + +.progress-error-container.error-permission .progress-error-message { + color: #a855f7; + text-shadow: 0 0 8px rgba(168, 85, 247, 0.4); +} + +.progress-error-container.error-server { + border-top-color: rgba(236, 72, 153, 0.5); +} + +.progress-error-container.error-server .progress-error-message { + color: #ec4899; + text-shadow: 0 0 8px rgba(236, 72, 153, 0.4); +} + +.progress-error-container.error-corruption { + border-top-color: rgba(220, 38, 38, 0.8); +} + +.progress-error-container.error-corruption .progress-error-message { + color: #dc2626; + text-shadow: 0 0 8px rgba(220, 38, 38, 0.6); + font-weight: 600; +} + +.progress-error-container.error-butler { + border-top-color: rgba(245, 158, 11, 0.5); +} + +.progress-error-container.error-butler .progress-error-message { + color: #f59e0b; + text-shadow: 0 0 8px rgba(245, 158, 11, 0.4); +} + +.progress-error-container.error-space { + border-top-color: rgba(168, 85, 247, 0.5); +} + +.progress-error-container.error-space .progress-error-message { + color: #a855f7; + text-shadow: 0 0 8px rgba(168, 85, 247, 0.4); +} + +.progress-error-container.error-conflict { + border-top-color: rgba(6, 182, 212, 0.5); +} + +.progress-error-container.error-conflict .progress-error-message { + color: #06b6d4; + text-shadow: 0 0 8px rgba(6, 182, 212, 0.4); +} + +/* Connection quality indicators */ +.progress-details { + transition: all 0.3s ease; +} + +.progress-details #progressSize { + transition: color 0.5s ease; +} + +/* Enhanced retry button states */ +.progress-retry-btn.retrying { + background: linear-gradient(135deg, #059669, #10b981); + animation: retryingPulse 1s ease-in-out infinite; +} + +@keyframes retryingPulse { + 0%, 100% { + transform: scale(1); + box-shadow: 0 2px 8px rgba(5, 150, 105, 0.3); + } + 50% { + transform: scale(1.05); + box-shadow: 0 4px 12px rgba(5, 150, 105, 0.4); + } +} + +/* Network status indicator (optional future enhancement) */ +.network-status { + position: absolute; + top: 5px; + right: 5px; + width: 8px; + height: 8px; + border-radius: 50%; + background: #10b981; + box-shadow: 0 0 6px rgba(16, 185, 129, 0.6); +} + +.network-status.poor { + background: #f87171; + box-shadow: 0 0 6px rgba(248, 113, 113, 0.6); +} + +.network-status.fair { + background: #fbbf24; + box-shadow: 0 0 6px rgba(251, 191, 36, 0.6); +} .progress-bar-fill { height: 100%; @@ -5990,167 +6200,167 @@ select.settings-input option { to { opacity: 1; } -} -/* Launcher Update Modal Styles */ -.update-modal-overlay { - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; - background: rgba(0, 0, 0, 0.85); - backdrop-filter: blur(10px); - display: flex; - align-items: center; - justify-content: center; - z-index: 100000; - animation: fadeIn 0.3s ease; -} - -.update-modal { - background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%); - border: 2px solid rgba(147, 51, 234, 0.3); - border-radius: 16px; - padding: 2rem; - max-width: 500px; - width: 90%; - box-shadow: 0 20px 60px rgba(147, 51, 234, 0.3); - animation: slideUp 0.3s ease; -} - -@keyframes slideUp { - from { - transform: translateY(30px); - opacity: 0; - } - to { - transform: translateY(0); - opacity: 1; - } -} - -.update-header { - display: flex; - align-items: center; - gap: 1rem; - margin-bottom: 1.5rem; - color: #9333ea; -} - -.update-header i { - font-size: 2rem; -} - -.update-header h2 { - margin: 0; - font-size: 1.5rem; - color: #fff; -} - -.update-content { - color: #e0e0e0; - margin-bottom: 1.5rem; -} - -.update-version { - font-size: 1.2rem; - font-weight: 600; - color: #9333ea; - margin-bottom: 0.5rem; -} - -.current-version { - color: #888; - font-size: 0.9rem; - margin-bottom: 1rem; -} - -.release-notes { - background: rgba(0, 0, 0, 0.3); - border-left: 3px solid #9333ea; - padding: 1rem; - border-radius: 8px; - max-height: 200px; - overflow-y: auto; - font-size: 0.9rem; - line-height: 1.6; -} - -.update-progress { - margin-bottom: 1.5rem; -} - -.progress-bar-container { - background: rgba(0, 0, 0, 0.3); - border-radius: 10px; - height: 20px; - overflow: hidden; - margin-bottom: 0.5rem; -} - -.progress-bar { - height: 100%; - background: linear-gradient(90deg, #9333ea 0%, #7c3aed 100%); - width: 0%; - transition: width 0.3s ease; - border-radius: 10px; -} - -.progress-text { - color: #aaa; - font-size: 0.9rem; - text-align: center; - margin: 0; -} - -.update-note { - background: rgba(147, 51, 234, 0.1); - border: 1px solid rgba(147, 51, 234, 0.3); - padding: 0.75rem; - border-radius: 8px; - font-size: 0.9rem; - margin-top: 1rem; -} - -.update-actions { - display: flex; - gap: 1rem; - justify-content: flex-end; -} - -.update-actions button { - padding: 0.75rem 1.5rem; - border: none; - border-radius: 8px; - font-weight: 600; - cursor: pointer; - transition: all 0.2s; - display: flex; - align-items: center; - gap: 0.5rem; -} - -.update-actions .btn-primary { - background: linear-gradient(135deg, #9333ea 0%, #7c3aed 100%); - color: white; -} - -.update-actions .btn-primary:hover:not(:disabled) { - transform: translateY(-2px); - box-shadow: 0 5px 15px rgba(147, 51, 234, 0.4); -} - -.update-actions .btn-secondary { - background: rgba(255, 255, 255, 0.1); - color: #e0e0e0; - border: 1px solid rgba(255, 255, 255, 0.2); -} - -.update-actions .btn-secondary:hover:not(:disabled) { - background: rgba(255, 255, 255, 0.15); -} - -.update-actions button:disabled { - opacity: 0.5; - cursor: not-allowed; +} +/* Launcher Update Modal Styles */ +.update-modal-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.85); + backdrop-filter: blur(10px); + display: flex; + align-items: center; + justify-content: center; + z-index: 100000; + animation: fadeIn 0.3s ease; +} + +.update-modal { + background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%); + border: 2px solid rgba(147, 51, 234, 0.3); + border-radius: 16px; + padding: 2rem; + max-width: 500px; + width: 90%; + box-shadow: 0 20px 60px rgba(147, 51, 234, 0.3); + animation: slideUp 0.3s ease; +} + +@keyframes slideUp { + from { + transform: translateY(30px); + opacity: 0; + } + to { + transform: translateY(0); + opacity: 1; + } +} + +.update-header { + display: flex; + align-items: center; + gap: 1rem; + margin-bottom: 1.5rem; + color: #9333ea; +} + +.update-header i { + font-size: 2rem; +} + +.update-header h2 { + margin: 0; + font-size: 1.5rem; + color: #fff; +} + +.update-content { + color: #e0e0e0; + margin-bottom: 1.5rem; +} + +.update-version { + font-size: 1.2rem; + font-weight: 600; + color: #9333ea; + margin-bottom: 0.5rem; +} + +.current-version { + color: #888; + font-size: 0.9rem; + margin-bottom: 1rem; +} + +.release-notes { + background: rgba(0, 0, 0, 0.3); + border-left: 3px solid #9333ea; + padding: 1rem; + border-radius: 8px; + max-height: 200px; + overflow-y: auto; + font-size: 0.9rem; + line-height: 1.6; +} + +.update-progress { + margin-bottom: 1.5rem; +} + +.progress-bar-container { + background: rgba(0, 0, 0, 0.3); + border-radius: 10px; + height: 20px; + overflow: hidden; + margin-bottom: 0.5rem; +} + +.progress-bar { + height: 100%; + background: linear-gradient(90deg, #9333ea 0%, #7c3aed 100%); + width: 0%; + transition: width 0.3s ease; + border-radius: 10px; +} + +.progress-text { + color: #aaa; + font-size: 0.9rem; + text-align: center; + margin: 0; +} + +.update-note { + background: rgba(147, 51, 234, 0.1); + border: 1px solid rgba(147, 51, 234, 0.3); + padding: 0.75rem; + border-radius: 8px; + font-size: 0.9rem; + margin-top: 1rem; +} + +.update-actions { + display: flex; + gap: 1rem; + justify-content: flex-end; +} + +.update-actions button { + padding: 0.75rem 1.5rem; + border: none; + border-radius: 8px; + font-weight: 600; + cursor: pointer; + transition: all 0.2s; + display: flex; + align-items: center; + gap: 0.5rem; +} + +.update-actions .btn-primary { + background: linear-gradient(135deg, #9333ea 0%, #7c3aed 100%); + color: white; +} + +.update-actions .btn-primary:hover:not(:disabled) { + transform: translateY(-2px); + box-shadow: 0 5px 15px rgba(147, 51, 234, 0.4); +} + +.update-actions .btn-secondary { + background: rgba(255, 255, 255, 0.1); + color: #e0e0e0; + border: 1px solid rgba(255, 255, 255, 0.2); +} + +.update-actions .btn-secondary:hover:not(:disabled) { + background: rgba(255, 255, 255, 0.15); +} + +.update-actions button:disabled { + opacity: 0.5; + cursor: not-allowed; } diff --git a/backend/utils/serverListSync.js b/backend/utils/serverListSync.js index 59e7e47..52ef6c6 100644 --- a/backend/utils/serverListSync.js +++ b/backend/utils/serverListSync.js @@ -90,7 +90,8 @@ async function syncServerList() { Id: uuidv4(), Name: "@ " + remoteServer.Name, Address: remoteServer.Address, - DateSaved: currentDate + DateSaved: currentDate, + img_Banner: remoteServer.img_Banner || null // Copy banner if exists }; apiServers.push(serverToAdd); console.log('[ServerListSync] Added/Updated server with new ID:', remoteServer.Name);