diff --git a/retro-refresh.css b/retro-refresh.css new file mode 100644 index 0000000..9e987ff --- /dev/null +++ b/retro-refresh.css @@ -0,0 +1,369 @@ +/* Retro Floating Refresh Bar Styles */ +:root { + --terminal-bg: #000000; + --terminal-border: #f7931a; + --terminal-text: #f7931a; + --terminal-glow: rgba(247, 147, 26, 0.7); + --terminal-width: 300px; +} + +/* Adjust width for desktop */ +@media (min-width: 768px) { + :root { + --terminal-width: 340px; + } +} + +/* Remove the existing refresh timer container styles */ +#refreshUptime { + visibility: hidden !important; + height: 0 !important; + overflow: hidden !important; + margin: 0 !important; + padding: 0 !important; +} + +/* Add padding to the bottom of the page to prevent floating bar from covering content +body { + padding-bottom: 100px !important; +} +*/ +/* Floating Retro Terminal Container */ +#retro-terminal-bar { + position: fixed; + bottom: 20px; + left: 50%; + transform: translateX(-50%); + width: var(--terminal-width); + background-color: var(--terminal-bg); + border: 2px solid var(--terminal-border); + /* box-shadow: 0 0 15px var(--terminal-glow); */ + z-index: 1000; + font-family: 'VT323', monospace; + overflow: hidden; + padding: 5px; +} + +/* Desktop positioning (bottom right) */ +@media (min-width: 768px) { + #retro-terminal-bar { + left: auto; + right: 20px; + transform: none; + } +} + +/* Terminal header with control buttons */ +/* Update the terminal title to match card headers */ +.terminal-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 5px; + border-bottom: 1px solid var(--terminal-border); + padding-bottom: 3px; + background-color: #000; /* Match card header background */ +} + +.terminal-title { + color: var(--primary-color); + font-weight: bold; + font-size: 1.1rem; /* Match card header font size */ + border-bottom: none; + text-shadow: 0 0 5px var(--primary-color); + animation: flicker 4s infinite; /* Add flicker animation from card headers */ + font-family: var(--header-font); /* Use the same font variable */ + padding: 0.3rem 0; /* Match card header padding */ + letter-spacing: 1px; +} + +/* Make sure we're using the flicker animation defined in the main CSS */ +@keyframes flicker { + 0% { opacity: 0.97; } + 5% { opacity: 0.95; } + 10% { opacity: 0.97; } + 15% { opacity: 0.94; } + 20% { opacity: 0.98; } + 50% { opacity: 0.95; } + 80% { opacity: 0.96; } + 90% { opacity: 0.94; } + 100% { opacity: 0.98; } +} + +.terminal-controls { + display: flex; + gap: 5px; +} + +.terminal-dot { + width: 8px; + height: 8px; + border-radius: 50%; + background-color: #555; + transition: background-color 0.3s; +} + +.terminal-dot:hover { + background-color: #999; + cursor: pointer; +} + +.terminal-dot.minimize:hover { + background-color: #ffcc00; +} + +.terminal-dot.close:hover { + background-color: #ff3b30; +} + +/* Terminal content area */ +.terminal-content { + position: relative; + color: #ffffff; + padding: 5px 0; +} + +/* Scanline effect for authentic CRT look */ +.terminal-content::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: repeating-linear-gradient( + 0deg, + rgba(0, 0, 0, 0.15), + rgba(0, 0, 0, 0.15) 1px, + transparent 1px, + transparent 2px + ); + pointer-events: none; + z-index: 1; + animation: flicker 0.15s infinite; +} + +@keyframes flicker { + 0% { opacity: 1.0; } + 50% { opacity: 0.98; } + 100% { opacity: 1.0; } +} + +/* Enhanced Progress Bar with tick marks */ +#retro-terminal-bar .bitcoin-progress-container { + width: 100%; + height: 20px; + background-color: #111; + border: 1px solid var(--terminal-border); + margin-bottom: 10px; + position: relative; + overflow: hidden; + box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.8); +} + +/* Tick marks on progress bar */ +.progress-ticks { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + display: flex; + justify-content: space-between; + padding: 0 5px; + color: rgba(255, 255, 255, 0.6); + font-size: 10px; + pointer-events: none; + z-index: 3; +} + +.progress-ticks span { + display: flex; + align-items: flex-end; + height: 100%; + padding-bottom: 2px; +} + +.tick-mark { + position: absolute; + top: 0; + width: 1px; + height: 5px; + background-color: rgba(255, 255, 255, 0.4); +} + +.tick-mark.major { + height: 8px; + background-color: rgba(255, 255, 255, 0.6); +} + +/* The actual progress bar */ +#retro-terminal-bar #bitcoin-progress-inner { + height: 100%; + width: 0; + background: linear-gradient(90deg, #f7931a, #ffa500); + position: relative; + transition: width 1s linear; +} + +/* Position the original inner container correctly */ +#retro-terminal-bar #refreshContainer { + display: block; + width: 100%; +} + +/* Blinking scan line animation */ +.scan-line { + position: absolute; + height: 2px; + width: 100%; + background-color: rgba(255, 255, 255, 0.7); + animation: scan 3s linear infinite; + box-shadow: 0 0 8px 1px rgba(255, 255, 255, 0.5); + z-index: 2; +} + +@keyframes scan { + 0% { top: -2px; } + 100% { top: 22px; } +} + +/* Text styling */ +#retro-terminal-bar #progress-text { + font-size: 16px; + color: var(--terminal-text); + text-shadow: 0 0 5px var(--terminal-text); + margin-top: 5px; + text-align: center; + position: relative; + z-index: 2; +} + +#retro-terminal-bar #uptimeTimer { + font-size: 16px; + color: var(--terminal-text); + text-shadow: 0 0 5px var(--terminal-text); + text-align: center; + position: relative; + z-index: 2; + border-top: 1px solid rgba(247, 147, 26, 0.3); + padding-top: 5px; + margin-top: 5px; +} + +/* Terminal cursor */ +#retro-terminal-bar #terminal-cursor { + display: inline-block; + width: 8px; + height: 14px; + background-color: var(--terminal-text); + margin-left: 2px; + animation: blink 1s step-end infinite; + box-shadow: 0 0 8px var(--terminal-text); +} + +/* Glowing effect during the last few seconds */ +#retro-terminal-bar #bitcoin-progress-inner.glow-effect { + box-shadow: 0 0 15px #f7931a, 0 0 25px #f7931a; +} + +#retro-terminal-bar .waiting-for-update { + animation: waitingPulse 2s infinite !important; +} + +@keyframes waitingPulse { + 0%, 100% { box-shadow: 0 0 10px #f7931a, 0 0 15px #f7931a; opacity: 0.8; } + 50% { box-shadow: 0 0 20px #f7931a, 0 0 35px #f7931a; opacity: 1; } +} + +/* Status indicators */ +.status-indicators { + display: flex; + justify-content: space-between; + margin-bottom: 5px; + font-size: 12px; + color: #aaa; +} + +.status-indicator { + display: flex; + align-items: center; +} + +.status-dot { + width: 6px; + height: 6px; + border-radius: 50%; + margin-right: 4px; +} + +.status-dot.connected { + background-color: #32CD32; + box-shadow: 0 0 5px #32CD32; + animation: pulse 2s infinite; +} + +@keyframes pulse { + 0% { opacity: 0.8; } + 50% { opacity: 1; } + 100% { opacity: 0.8; } +} + +/* Collapse/expand functionality */ +#retro-terminal-bar.collapsed .terminal-content { + display: none; +} + +#retro-terminal-bar.collapsed { + width: 180px; +} + +/* On desktop, move the collapsed bar to bottom right */ +@media (min-width: 768px) { + #retro-terminal-bar.collapsed { + right: 20px; + transform: none; + } +} + +/* Show button */ +#show-terminal-button { + position: fixed; + bottom: 10px; + right: 10px; + z-index: 1000; + background-color: #f7931a; + color: #000; + border: none; + padding: 8px 12px; + cursor: pointer; + font-family: 'VT323', monospace; + font-size: 14px; + box-shadow: 0 0 10px rgba(247, 147, 26, 0.5); +} + +#show-terminal-button:hover { + background-color: #ffaa33; +} + +/* Mobile responsiveness */ +@media (max-width: 576px) { + #retro-terminal-bar { + width: 280px; + bottom: 10px; + } + + .terminal-title { + font-size: 14px; + } + + .terminal-dot { + width: 6px; + height: 6px; + } + + #show-terminal-button { + padding: 6px 10px; + font-size: 12px; + } +} \ No newline at end of file diff --git a/retro-refresh.js b/retro-refresh.js new file mode 100644 index 0000000..af5b2e4 --- /dev/null +++ b/retro-refresh.js @@ -0,0 +1,238 @@ +// This script integrates the retro floating refresh bar +// with the existing dashboard and workers page functionality + +(function() { + // Wait for DOM to be ready + document.addEventListener('DOMContentLoaded', function() { + // Create the retro terminal bar if it doesn't exist yet + if (!document.getElementById('retro-terminal-bar')) { + createRetroTerminalBar(); + } + + // Hide the original refresh container + const originalRefreshUptime = document.getElementById('refreshUptime'); + if (originalRefreshUptime) { + originalRefreshUptime.style.visibility = 'hidden'; + originalRefreshUptime.style.height = '0'; + originalRefreshUptime.style.overflow = 'hidden'; + + // Important: We keep the original elements and just hide them + // This ensures all existing JavaScript functions still work + } + + // Add extra space at the bottom of the page to prevent the floating bar from covering content + const extraSpace = document.createElement('div'); + extraSpace.style.height = '100px'; + document.body.appendChild(extraSpace); + }); + + // Function to create the retro terminal bar + function createRetroTerminalBar() { + // Get the HTML content from the shared CSS/HTML + const html = ` +
+
+
SYSTEM MONITOR v0.1
+
+
+
+
+
+
+
+
+
+ LIVE +
+
+ 00:00:00 +
+
+ +
+ +
+
+
+
+
+ 0s + 15s + 30s + 45s + 60s +
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
60s to next update
+
Uptime: 0h 0m 0s
+
+
+ `; + + // Create a container for the HTML + const container = document.createElement('div'); + container.innerHTML = html; + + // Append to the body + document.body.appendChild(container.firstElementChild); + + // Start the clock update + updateTerminalClock(); + setInterval(updateTerminalClock, 1000); + + // Check if terminal should be collapsed based on previous state + const isCollapsed = localStorage.getItem('terminalCollapsed') === 'true'; + if (isCollapsed) { + document.getElementById('retro-terminal-bar').classList.add('collapsed'); + } + } + + // Function to update the terminal clock + function updateTerminalClock() { + const clockElement = document.getElementById('data-refresh-time'); + if (clockElement) { + const now = new Date(); + const hours = String(now.getHours()).padStart(2, '0'); + const minutes = String(now.getMinutes()).padStart(2, '0'); + const seconds = String(now.getSeconds()).padStart(2, '0'); + clockElement.textContent = `${hours}:${minutes}:${seconds}`; + } + } + + // Expose these functions globally for the onclick handlers + window.toggleTerminal = function() { + const terminal = document.getElementById('retro-terminal-bar'); + terminal.classList.toggle('collapsed'); + + // Store state in localStorage + localStorage.setItem('terminalCollapsed', terminal.classList.contains('collapsed')); + }; + + window.hideTerminal = function() { + document.getElementById('retro-terminal-bar').style.display = 'none'; + + // Create a show button that appears at the bottom right + const showButton = document.createElement('button'); + showButton.id = 'show-terminal-button'; + showButton.textContent = 'Show Monitor'; + showButton.style.position = 'fixed'; + showButton.style.bottom = '10px'; + showButton.style.right = '10px'; + showButton.style.zIndex = '1000'; + showButton.style.backgroundColor = '#f7931a'; + showButton.style.color = '#000'; + showButton.style.border = 'none'; + showButton.style.padding = '8px 12px'; + showButton.style.cursor = 'pointer'; + showButton.style.fontFamily = "'VT323', monospace"; + showButton.style.fontSize = '14px'; + showButton.onclick = function() { + document.getElementById('retro-terminal-bar').style.display = 'block'; + this.remove(); + }; + document.body.appendChild(showButton); + }; + + // Redirect original progress bar updates to our new floating bar + // This Observer will listen for changes to the original #bitcoin-progress-inner + // and replicate them to our new floating bar version + const initProgressObserver = function() { + // Setup a MutationObserver to watch for style changes on the original progress bar + const originalProgressBar = document.querySelector('#refreshUptime #bitcoin-progress-inner'); + const newProgressBar = document.querySelector('#retro-terminal-bar #bitcoin-progress-inner'); + + if (originalProgressBar && newProgressBar) { + const observer = new MutationObserver(function(mutations) { + mutations.forEach(function(mutation) { + if (mutation.attributeName === 'style') { + // Get the width from the original progress bar + const width = originalProgressBar.style.width; + if (width) { + // Apply it to our new progress bar + newProgressBar.style.width = width; + + // Also copy any classes (like glow-effect) + if (originalProgressBar.classList.contains('glow-effect') && + !newProgressBar.classList.contains('glow-effect')) { + newProgressBar.classList.add('glow-effect'); + } else if (!originalProgressBar.classList.contains('glow-effect') && + newProgressBar.classList.contains('glow-effect')) { + newProgressBar.classList.remove('glow-effect'); + } + + // Copy waiting-for-update class + if (originalProgressBar.classList.contains('waiting-for-update') && + !newProgressBar.classList.contains('waiting-for-update')) { + newProgressBar.classList.add('waiting-for-update'); + } else if (!originalProgressBar.classList.contains('waiting-for-update') && + newProgressBar.classList.contains('waiting-for-update')) { + newProgressBar.classList.remove('waiting-for-update'); + } + } + } + }); + }); + + // Start observing + observer.observe(originalProgressBar, { attributes: true }); + } + + // Also watch for changes to the progress text + const originalProgressText = document.querySelector('#refreshUptime #progress-text'); + const newProgressText = document.querySelector('#retro-terminal-bar #progress-text'); + + if (originalProgressText && newProgressText) { + const textObserver = new MutationObserver(function(mutations) { + mutations.forEach(function(mutation) { + if (mutation.type === 'childList') { + // Update the text in our new bar + newProgressText.textContent = originalProgressText.textContent; + } + }); + }); + + // Start observing + textObserver.observe(originalProgressText, { childList: true, subtree: true }); + } + + // Watch for changes to the uptime timer + const originalUptimeTimer = document.querySelector('#refreshUptime #uptimeTimer'); + const newUptimeTimer = document.querySelector('#retro-terminal-bar #uptimeTimer'); + + if (originalUptimeTimer && newUptimeTimer) { + const uptimeObserver = new MutationObserver(function(mutations) { + mutations.forEach(function(mutation) { + if (mutation.type === 'childList') { + // Update the text in our new bar + newUptimeTimer.innerHTML = originalUptimeTimer.innerHTML; + } + }); + }); + + // Start observing + uptimeObserver.observe(originalUptimeTimer, { childList: true, subtree: true }); + } + }; + + // Start the observer once the page is fully loaded + window.addEventListener('load', function() { + // Give a short delay to ensure all elements are rendered + setTimeout(initProgressObserver, 500); + }); +})(); \ No newline at end of file