From fdb2be1d8b0f3c1e20331ed1420e8f5453bc9840 Mon Sep 17 00:00:00 2001 From: StellarStoic Date: Sat, 7 Sep 2024 23:07:21 +0200 Subject: [PATCH] add: toggle button for switching on/off live BTC price updates with time info of the stored price age --- converter.css | 125 ++++++++++++++++++++++++++++++++++++++++++++- converter.html | 12 +++++ sintraWebSocket.js | 116 +++++++++++++++++++++++++++++++++++++---- 3 files changed, 241 insertions(+), 12 deletions(-) diff --git a/converter.css b/converter.css index 8889b87..fafb29e 100644 --- a/converter.css +++ b/converter.css @@ -151,4 +151,127 @@ .description-modal a:hover { color: #f2a900; /* Even brighter on hover for emphasis */ -} \ No newline at end of file +} + +#toggle-btn-space { + font-family: monospace, Courier, "Courier New"; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + overflow-y: auto; + } + + #toggle-btn-box { + position: sticky; + top: 33px; + left: 50%; + transform: translateX(-0%); + width: 52px; + margin: 0; + } + + #toggle-button { + width: 16px; + height: 33px; + background-color: #2d2c2c; + border-radius: 100px; + cursor: pointer; + position: relative; + z-index: 2; + } + + #toggle-button:before { + content: ""; + position: absolute; + top: 18px; + bottom: 2px; + left: 2px; + width: 12px; + opacity: 1; + background-color: #bcbcbc; + border-radius: 100px; + transition: 0.3s linear all; + } + + #toggle-button.moveup:before { + top: 2px; + bottom: 18px; + background-color: #f2a900; + animation: moveup-1 0.3s linear forwards, moveup-2 0.3s linear 0.6s forwards, + blink 1s ease-in-out 0.9s infinite; + } + + #toggle-button.movedown:before { + top: 18px; + bottom: 2px; + background-color: #bcbcbc; + animation: movedown-1 0.3s linear 0s forwards, + movedown-2 0.3s linear 0.6s forwards; + } + + @keyframes moveup-1 { + 0% { top: 18px; } + 100% { top: 2px; } + } + + @keyframes moveup-2 { + 0% { bottom: 2px; } + 100% { bottom: 18px; } + } + + @keyframes movedown-1 { + 0% { bottom: 18px; } + 100% { bottom: 2px; } + } + + @keyframes movedown-2 { + 0% { top: 2px; } + 100% { top: 18px; } + } + + @keyframes blink { + 0% { opacity: 1; } + 75% { opacity: 0; } + 100% { opacity: 1; } + } + + #live-data { + position: fixed; + top: 50%; + right: -90px; + width: 120px; + margin-top: -44px; + } + + .live-data-text { + color: #88888856; + font-size: 10px; + line-height: 1; + margin-top: 70px; + margin: 0; + transition: 0.3s ease color; + cursor: pointer; + visibility: hidden; + } + + .live-data-text.active { + visibility: visible; + color: #8888886f; + } + + #active-text { + font-size: 10px; + margin-top: 13px; + margin-left: -50px; + } + + #stop-text { + margin-top: 40px; + margin-left: -74px; + } + + #active-text.lspace { + letter-spacing: 2px; + } \ No newline at end of file diff --git a/converter.html b/converter.html index fec293e..4ddadd7 100644 --- a/converter.html +++ b/converter.html @@ -28,7 +28,19 @@ + +
+
+
+
+
Live BTC Price
+
BTC Price from Cache
+
+
+
+
+
BTC diff --git a/sintraWebSocket.js b/sintraWebSocket.js index d44c20a..8a3ff7c 100644 --- a/sintraWebSocket.js +++ b/sintraWebSocket.js @@ -1,12 +1,20 @@ -// Function to connect to Sintra WebSocket and handle live BTC price -function connectToSintraAPI() { - const socket = new WebSocket('wss://api.sintra.fi/ws'); +let sintraWebSocket = null; // Declare WebSocket globally +let isManuallyClosed = false; // Flag to control automatic reconnect - socket.onopen = function () { +// Function to start Sintra WebSocket connection +function startSintraWebSocket() { + if (sintraWebSocket) { + sintraWebSocket.close(); // Close existing connection before starting a new one + } + + sintraWebSocket = new WebSocket('wss://api.sintra.fi/ws'); + isManuallyClosed = false; // Reset manual close flag when starting WebSocket + + sintraWebSocket.onopen = function () { // consol.log("WebSocket connection to Sintra established."); }; - socket.onmessage = function (event) { + sintraWebSocket.onmessage = function (event) { const data = JSON.parse(event.data); if (data.event === "data") { const btcPrice = data.data.prices.usd; // BTC price in USD @@ -18,21 +26,107 @@ function connectToSintraAPI() { if (cachedRates) { cachedRates['BTC'] = 1 / btcPrice; // Update BTC exchange rate (BTC per USD) localStorage.setItem('exchangeRatesCache', JSON.stringify(cachedRates)); + + // Store the current time when BTC price is cached + const cacheTimestamp = Date.now(); + localStorage.setItem('btcCacheTimestamp', cacheTimestamp); // Store cache timestamp // Call updateAllCurrencies to recalculate based on the new BTC price - updateAllCurrencies(); + if (typeof updateAllCurrencies === 'function') { + updateAllCurrencies(); + } } } }; - socket.onerror = function (error) { + sintraWebSocket.onerror = function (error) { console.error("WebSocket error with Sintra:", error); }; - socket.onclose = function () { - // consol.log("WebSocket connection to Sintra closed, reconnecting..."); - setTimeout(connectToSintraAPI, 1000); // Reconnect after 1 second + sintraWebSocket.onclose = function () { + // consol.log("WebSocket connection to Sintra closed."); + if (!isManuallyClosed) { + setTimeout(startSintraWebSocket, 1000); // Reconnect after 1 second only if not manually closed + } }; } -connectToSintraAPI(); +// Function to stop Sintra WebSocket connection +function stopSintraWebSocket() { + if (sintraWebSocket) { + isManuallyClosed = true; // Set flag to prevent automatic reconnect + sintraWebSocket.close(); + sintraWebSocket = null; // Reset WebSocket reference + // consol.log("WebSocket connection to Sintra stopped."); + } +} + +// Function to calculate and format the age of the cached BTC price +function getCachedBtcAge() { + const cachedTimestamp = localStorage.getItem('btcCacheTimestamp'); // Retrieve timestamp + if (cachedTimestamp) { + const now = Date.now(); + const ageMs = now - cachedTimestamp; // Time difference in milliseconds + const ageMinutes = Math.floor(ageMs / (1000 * 60)); // Convert milliseconds to minutes + + if (ageMinutes < 60) { + return `${ageMinutes}m`; // Show in minutes if less than an hour + } else { + const ageHours = Math.floor(ageMinutes / 60); // Convert minutes to hours + return `${ageHours}h`; // Show in hours if more than 60 minutes + } + } + return null; +} + +// Function to handle toggle between live and cached BTC prices +function handleBtcToggle() { + const toggleButton = document.getElementById('toggle-button'); + const btcPriceStatus = document.getElementById('active-text'); + const stopText = document.getElementById('stop-text'); + + toggleButton.addEventListener('click', function () { + if (!toggleButton.classList.contains('moveup')) { + // Switch to "Live BTC Price" + toggleButton.classList.remove('movedown'); + toggleButton.classList.add('moveup'); + stopText.classList.remove('active'); + btcPriceStatus.classList.add('active'); + startSintraWebSocket(); // Start WebSocket for live price + } else { + // Switch to "BTC Price from Cache" + toggleButton.classList.remove('moveup'); + toggleButton.classList.add('movedown'); + stopSintraWebSocket(); // Stop WebSocket for live price + + const btcAge = getCachedBtcAge(); + stopText.classList.add('active'); + btcPriceStatus.classList.remove('active'); + stopText.textContent = btcAge !== null ? `BTC Price from ${btcAge} ago` : "BTC Price (cache unavailable)"; + } + }); +} + +// Initialize the WebSocket and toggle state +document.addEventListener('DOMContentLoaded', function () { + handleBtcToggle(); + + const cachedRates = JSON.parse(localStorage.getItem('exchangeRatesCache')); + const toggleButton = document.getElementById('toggle-button'); + const btcPriceStatus = document.getElementById('active-text'); + const stopText = document.getElementById('stop-text'); + + if (cachedRates && cachedRates['BTC']) { + const btcAge = getCachedBtcAge(); + if (btcAge !== null) { + stopText.textContent = `BTC Price from ${btcAge} ago`; + } else { + stopText.textContent = "BTC Price (cache unavailable)"; + } + toggleButton.classList.add('movedown'); + } else { + btcPriceStatus.textContent = "Live BTC Price"; + toggleButton.classList.add('moveup'); + startSintraWebSocket(); + } +});