Add responsive theme toggle and dynamic styling

Introduces a responsive theme toggle button with styles for desktop and mobile views in `theme-toggle.css`. Updates `BitcoinProgressBar.js` to support dynamic theme changes and adds a new `updateTheme` method. Enhances `main.js` for theme management based on user preferences in `localStorage`. Modifies `base.html` and other HTML files to include the theme toggle button and necessary scripts. Introduces `theme.js` for managing theme constants and applying the DeepSea theme.
This commit is contained in:
DJObleezy 2025-04-22 17:43:46 -07:00
parent 2142a7d2af
commit 0d0a707019
10 changed files with 1500 additions and 169 deletions

146
static/css/theme-toggle.css Normal file
View File

@ -0,0 +1,146 @@
/* Responsive Theme Toggle Button Styles */
/* Common styles for the theme toggle button regardless of device */
#themeToggle,
.theme-toggle-btn {
position: fixed;
z-index: 1000;
background: transparent;
border-width: 1px;
border-style: solid;
font-family: 'VT323', monospace;
transition: all 0.3s ease;
cursor: pointer;
white-space: nowrap;
text-transform: uppercase;
outline: none;
display: flex;
align-items: center;
justify-content: center;
}
/* Default positioning and styling for desktop */
@media screen and (min-width: 768px) {
#themeToggle,
.theme-toggle-btn {
top: 15px;
left: 15px;
padding: 6px 12px;
font-size: 14px;
border-radius: 3px;
letter-spacing: 0.5px;
}
/* Add theme icon for desktop view */
#themeToggle:before,
.theme-toggle-btn:before {
content: "☀/☾";
margin-right: 5px;
font-size: 14px;
}
/* Hover effects for desktop */
#themeToggle:hover,
.theme-toggle-btn:hover {
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
}
}
/* Mobile-specific styling - MODIFIED to keep left positioning */
@media screen and (max-width: 767px) {
#themeToggle,
.theme-toggle-btn {
top: 60px;
left: 10px; /* Keep on left side */
padding: 8px;
font-size: 12px;
border-radius: 50%;
width: 40px;
height: 40px;
}
/* Use just icon for mobile to save space */
#themeToggle:before,
.theme-toggle-btn:before {
content: "☀/☾";
margin-right: 0;
font-size: 16px;
}
/* Hide text on mobile */
#themeToggle span,
.theme-toggle-btn span {
display: none;
}
/* Adjust position when in portrait mode on very small screens */
@media screen and (max-height: 500px) {
#themeToggle,
.theme-toggle-btn {
top: 5px;
left: 5px; /* Keep on left side */
width: 35px;
height: 35px;
font-size: 10px;
}
}
}
/* The rest of the CSS remains unchanged */
/* Active state for the button */
#themeToggle:active,
.theme-toggle-btn:active {
transform: translateY(1px);
box-shadow: 0 0 2px rgba(0, 0, 0, 0.3);
}
/* Bitcoin theme specific styling (orange) */
body:not(.deepsea-theme) #themeToggle,
body:not(.deepsea-theme) .theme-toggle-btn {
color: #f2a900;
border-color: #f2a900;
}
body:not(.deepsea-theme) #themeToggle:hover,
body:not(.deepsea-theme) .theme-toggle-btn:hover {
background-color: rgba(242, 169, 0, 0.1);
box-shadow: 0 4px 8px rgba(242, 169, 0, 0.3);
}
/* DeepSea theme specific styling (blue) */
body.deepsea-theme #themeToggle,
body.deepsea-theme .theme-toggle-btn {
color: #0088cc;
border-color: #0088cc;
}
body.deepsea-theme #themeToggle:hover,
body.deepsea-theme .theme-toggle-btn:hover {
background-color: rgba(0, 136, 204, 0.1);
box-shadow: 0 4px 8px rgba(0, 136, 204, 0.3);
}
/* Transition effect for smoother theme switching */
#themeToggle,
.theme-toggle-btn,
#themeToggle:before,
.theme-toggle-btn:before {
transition: all 0.3s ease;
}
/* Accessibility improvements */
#themeToggle:focus,
.theme-toggle-btn:focus {
box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.3);
outline: none;
}
body:not(.deepsea-theme) #themeToggle:focus,
body:not(.deepsea-theme) .theme-toggle-btn:focus {
box-shadow: 0 0 0 3px rgba(242, 169, 0, 0.3);
}
body.deepsea-theme #themeToggle:focus,
body.deepsea-theme .theme-toggle-btn:focus {
box-shadow: 0 0 0 3px rgba(0, 136, 204, 0.3);
}

View File

@ -2,11 +2,14 @@
* BitcoinMinuteRefresh.js - Simplified Bitcoin-themed floating uptime monitor
*
* This module creates a Bitcoin-themed terminal that shows server uptime.
* Now includes DeepSea theme support.
*/
const BitcoinMinuteRefresh = (function () {
// Constants
const STORAGE_KEY = 'bitcoin_last_refresh_time'; // For cross-page sync
const BITCOIN_COLOR = '#f7931a';
const DEEPSEA_COLOR = '#0088cc';
// Private variables
let terminalElement = null;
@ -16,6 +19,117 @@ const BitcoinMinuteRefresh = (function () {
let uptimeInterval = null;
let isInitialized = false;
let refreshCallback = null;
let currentThemeColor = BITCOIN_COLOR; // Default Bitcoin color
/**
* Apply the current theme color
*/
function applyThemeColor() {
// Check if theme toggle is set to DeepSea
const isDeepSeaTheme = localStorage.getItem('useDeepSeaTheme') === 'true';
currentThemeColor = isDeepSeaTheme ? DEEPSEA_COLOR : BITCOIN_COLOR;
// Don't try to update DOM elements if they don't exist yet
if (!terminalElement) return;
// Update terminal colors
if (isDeepSeaTheme) {
terminalElement.style.borderColor = DEEPSEA_COLOR;
terminalElement.style.color = DEEPSEA_COLOR;
terminalElement.style.boxShadow = `0 0 5px rgba(0, 136, 204, 0.3)`;
// Update header border
const headerElement = terminalElement.querySelector('.terminal-header');
if (headerElement) {
headerElement.style.borderColor = DEEPSEA_COLOR;
}
// Update terminal title
const titleElement = terminalElement.querySelector('.terminal-title');
if (titleElement) {
titleElement.style.color = DEEPSEA_COLOR;
titleElement.style.textShadow = '0 0 5px rgba(0, 136, 204, 0.8)';
}
// Update uptime timer border
const uptimeTimer = terminalElement.querySelector('.uptime-timer');
if (uptimeTimer) {
uptimeTimer.style.borderColor = `rgba(0, 136, 204, 0.5)`;
}
// Update uptime separators
const separators = terminalElement.querySelectorAll('.uptime-separator');
separators.forEach(sep => {
sep.style.textShadow = '0 0 8px rgba(0, 136, 204, 0.8)';
});
// Update uptime title
const uptimeTitle = terminalElement.querySelector('.uptime-title');
if (uptimeTitle) {
uptimeTitle.style.textShadow = '0 0 5px rgba(0, 136, 204, 0.8)';
}
// Update minimized view
const miniLabel = terminalElement.querySelector('.mini-uptime-label');
if (miniLabel) {
miniLabel.style.color = DEEPSEA_COLOR;
}
} else {
// Reset to Bitcoin theme
terminalElement.style.borderColor = BITCOIN_COLOR;
terminalElement.style.color = BITCOIN_COLOR;
terminalElement.style.boxShadow = `0 0 5px rgba(247, 147, 26, 0.3)`;
// Update header border
const headerElement = terminalElement.querySelector('.terminal-header');
if (headerElement) {
headerElement.style.borderColor = BITCOIN_COLOR;
}
// Update terminal title
const titleElement = terminalElement.querySelector('.terminal-title');
if (titleElement) {
titleElement.style.color = BITCOIN_COLOR;
titleElement.style.textShadow = '0 0 5px rgba(247, 147, 26, 0.8)';
}
// Update uptime timer border
const uptimeTimer = terminalElement.querySelector('.uptime-timer');
if (uptimeTimer) {
uptimeTimer.style.borderColor = `rgba(247, 147, 26, 0.5)`;
}
// Update uptime separators
const separators = terminalElement.querySelectorAll('.uptime-separator');
separators.forEach(sep => {
sep.style.textShadow = '0 0 8px rgba(247, 147, 26, 0.8)';
});
// Update uptime title
const uptimeTitle = terminalElement.querySelector('.uptime-title');
if (uptimeTitle) {
uptimeTitle.style.textShadow = '0 0 5px rgba(247, 147, 26, 0.8)';
}
// Update minimized view
const miniLabel = terminalElement.querySelector('.mini-uptime-label');
if (miniLabel) {
miniLabel.style.color = BITCOIN_COLOR;
}
}
}
/**
* Listen for theme changes
*/
function setupThemeChangeListener() {
// Listen for theme change events from localStorage
window.addEventListener('storage', function (e) {
if (e.key === 'useDeepSeaTheme') {
applyThemeColor();
}
});
}
/**
* Add dragging functionality to the terminal
@ -200,6 +314,7 @@ const BitcoinMinuteRefresh = (function () {
* Add CSS styles for the terminal
*/
function addStyles() {
// Use the currentThemeColor variable instead of hardcoded colors
const styleElement = document.createElement('style');
styleElement.id = 'bitcoin-terminal-styles';
styleElement.textContent = `
@ -210,14 +325,14 @@ const BitcoinMinuteRefresh = (function () {
right: 20px;
width: 230px;
background-color: #000000;
border: 1px solid #f7931a;
color: #f7931a;
border: 1px solid ${currentThemeColor};
color: ${currentThemeColor};
font-family: 'VT323', monospace;
z-index: 9999;
overflow: hidden;
padding: 8px;
transition: all 0.3s ease;
box-shadow: 0 0 5px rgba(247, 147, 26, 0.3);
box-shadow: 0 0 5px rgba(${currentThemeColor === DEEPSEA_COLOR ? '0, 136, 204' : '247, 147, 26'}, 0.3);
}
/* Terminal Header */
@ -616,6 +731,9 @@ const BitcoinMinuteRefresh = (function () {
// Store the refresh callback
refreshCallback = refreshFunc;
// Get current theme status
applyThemeColor();
// Create the terminal element if it doesn't exist
if (!document.getElementById('bitcoin-terminal')) {
createTerminalElement();
@ -623,8 +741,14 @@ const BitcoinMinuteRefresh = (function () {
// Get references to existing elements
terminalElement = document.getElementById('bitcoin-terminal');
uptimeElement = document.getElementById('uptime-timer');
// Apply theme to existing element
applyThemeColor();
}
// Set up listener for theme changes
setupThemeChangeListener();
// Try to get stored server time information
try {
serverTimeOffset = parseFloat(localStorage.getItem('serverTimeOffset') || '0');
@ -766,11 +890,12 @@ const BitcoinMinuteRefresh = (function () {
updateServerTime: updateServerTime,
toggleTerminal: toggleTerminal,
hideTerminal: hideTerminal,
showTerminal: showTerminal
showTerminal: showTerminal,
updateTheme: applyThemeColor // <-- Add this new method
};
})();
// Auto-initialize when document is ready if a refresh function is available in the global scope
// Auto-initialize when document is ready
document.addEventListener('DOMContentLoaded', function () {
// Check if manualRefresh function exists in global scope
if (typeof window.manualRefresh === 'function') {
@ -778,4 +903,7 @@ document.addEventListener('DOMContentLoaded', function () {
} else {
console.log("BitcoinMinuteRefresh: No refresh function found, will need to be initialized manually");
}
// Update theme based on current setting
setTimeout(() => BitcoinMinuteRefresh.updateTheme(), 100);
});

View File

@ -1,4 +1,7 @@
"use strict";
// Add this flag at the top of your file, outside the function
let isApplyingTheme = false;
"use strict";
/**
* ArrowIndicator - A clean implementation for managing metric value change indicators
@ -176,6 +179,11 @@ class ArrowIndicator {
});
}
// Current theme affects arrow colors
const theme = getCurrentTheme();
const upArrowColor = THEME.SHARED.GREEN;
const downArrowColor = THEME.SHARED.RED;
// Get normalized values and compare with previous metrics
for (const key of metricKeys) {
if (newMetrics[key] === undefined) continue;
@ -714,15 +722,16 @@ function handleVisibilityChange() {
// Helper function to show connection issues to the user
function showConnectionIssue(message) {
const theme = getCurrentTheme();
let $connectionStatus = $("#connectionStatus");
if (!$connectionStatus.length) {
$("body").append('<div id="connectionStatus" style="position: fixed; top: 10px; right: 10px; background: rgba(255,0,0,0.7); color: white; padding: 10px; border-radius: 5px; z-index: 9999;"></div>');
$("body").append(`<div id="connectionStatus" style="position: fixed; top: 10px; right: 10px; background: rgba(255,0,0,0.7); color: white; padding: 10px; border-radius: 5px; z-index: 9999;"></div>`);
$connectionStatus = $("#connectionStatus");
}
$connectionStatus.html(`<i class="fas fa-exclamation-triangle"></i> ${message}`).show();
// Show manual refresh button when there are connection issues
$("#refreshButton").show();
// Show manual refresh button with theme color
$("#refreshButton").css('background-color', theme.PRIMARY).show();
}
// Helper function to hide connection issue message
@ -766,7 +775,7 @@ function manualRefresh() {
});
}
// Initialize Chart.js with Unit Normalization
// Modify the initializeChart function to use blue colors for the chart
function initializeChart() {
try {
const ctx = document.getElementById('trendGraph').getContext('2d');
@ -780,10 +789,12 @@ function initializeChart() {
return null;
}
// Get the current theme colors
const theme = getCurrentTheme();
// Check if Chart.js plugin is available
const hasAnnotationPlugin = window['chartjs-plugin-annotation'] !== undefined;
// Inside the initializeChart function, modify the dataset configuration:
return new Chart(ctx, {
type: 'line',
data: {
@ -796,29 +807,29 @@ function initializeChart() {
const chart = context.chart;
const { ctx, chartArea } = chart;
if (!chartArea) {
return '#f7931a';
return theme.PRIMARY;
}
// Create gradient for line
const gradient = ctx.createLinearGradient(0, 0, 0, chartArea.bottom);
gradient.addColorStop(0, '#ffa64d'); // Lighter orange
gradient.addColorStop(1, '#f7931a'); // Bitcoin orange
gradient.addColorStop(0, theme.CHART.GRADIENT_START);
gradient.addColorStop(1, theme.CHART.GRADIENT_END);
return gradient;
},
backgroundColor: function (context) {
const chart = context.chart;
const { ctx, chartArea } = chart;
if (!chartArea) {
return 'rgba(247,147,26,0.1)';
return `rgba(${theme.PRIMARY_RGB}, 0.1)`;
}
// Create gradient for fill
const gradient = ctx.createLinearGradient(0, 0, 0, chartArea.bottom);
gradient.addColorStop(0, 'rgba(255, 166, 77, 0.3)'); // Lighter orange with transparency
gradient.addColorStop(0.5, 'rgba(247, 147, 26, 0.2)'); // Bitcoin orange with medium transparency
gradient.addColorStop(1, 'rgba(247, 147, 26, 0.05)'); // Bitcoin orange with high transparency
gradient.addColorStop(0, `rgba(${theme.PRIMARY_RGB}, 0.3)`);
gradient.addColorStop(0.5, `rgba(${theme.PRIMARY_RGB}, 0.2)`);
gradient.addColorStop(1, `rgba(${theme.PRIMARY_RGB}, 0.05)`);
return gradient;
},
fill: true,
tension: 0.3, // Slightly increase tension for smoother curves
tension: 0.3,
}]
},
options: {
@ -848,10 +859,10 @@ function initializeChart() {
y: {
title: {
display: true,
text: 'HASHRATE (TH/S)', // Already uppercase
color: '#f7931a', // Bitcoin orange
text: 'HASHRATE (TH/S)',
color: theme.PRIMARY,
font: {
family: "'VT323', monospace", // Terminal font
family: "'VT323', monospace",
size: 16,
weight: 'bold'
}
@ -905,7 +916,7 @@ function initializeChart() {
plugins: {
tooltip: {
backgroundColor: 'rgba(0, 0, 0, 0.8)',
titleColor: '#f7931a',
titleColor: theme.PRIMARY,
bodyColor: '#FFFFFF',
titleFont: {
family: "'VT323', monospace",
@ -937,10 +948,10 @@ function initializeChart() {
type: 'line',
yMin: 0,
yMax: 0,
borderColor: '#ffd700', // Gold color
borderColor: theme.CHART.ANNOTATION,
borderWidth: 3,
borderDash: [8, 4],
shadowColor: 'rgba(255, 215, 0, 0.5)',
shadowColor: `rgba(${theme.PRIMARY_RGB}, 0.5)`,
shadowBlur: 8,
shadowOffsetX: 0,
shadowOffsetY: 0,
@ -948,7 +959,7 @@ function initializeChart() {
enabled: true,
content: '24HR AVG: 0 TH/S',
backgroundColor: 'rgba(0,0,0,0.8)',
color: '#ffd700',
color: theme.CHART.ANNOTATION,
font: {
family: "'VT323', monospace",
size: 16,
@ -1237,20 +1248,21 @@ function updateChartWithNormalizedData(chart, data) {
chart.data.datasets[0].data = [normalizedValue];
}
// If using 3hr average due to low hashrate device detection, add visual indicator
// In updateChartWithNormalizedData function
if (useHashrate3hr) {
// Add indicator text to the chart
if (!chart.lowHashrateIndicator) {
// Create the indicator element if it doesn't exist
const graphContainer = document.getElementById('graphContainer');
if (graphContainer) {
const theme = getCurrentTheme();
const indicator = document.createElement('div');
indicator.id = 'lowHashrateIndicator';
indicator.style.position = 'absolute';
indicator.style.bottom = '10px';
indicator.style.right = '10px';
indicator.style.background = 'rgba(0,0,0,0.7)';
indicator.style.color = '#f7931a';
indicator.style.color = theme.PRIMARY;
indicator.style.padding = '5px 10px';
indicator.style.borderRadius = '3px';
indicator.style.fontSize = '12px';
@ -1261,6 +1273,8 @@ function updateChartWithNormalizedData(chart, data) {
chart.lowHashrateIndicator = indicator;
}
} else {
// Update color based on current theme
chart.lowHashrateIndicator.style.color = getCurrentTheme().PRIMARY;
// Show the indicator if it already exists
chart.lowHashrateIndicator.style.display = 'block';
}
@ -1902,8 +1916,512 @@ function resetDashboardChart() {
}
}
// Document ready initialization
// Replace your entire function with this version
function applyDeepSeaTheme() {
// Check if we're already applying the theme to prevent recursion
if (isApplyingTheme) {
console.log("Theme application already in progress, avoiding recursion");
return;
}
// Set the guard flag
isApplyingTheme = true;
try {
console.log("Applying DeepSea theme...");
// Create or update CSS variables for the DeepSea theme
const styleElement = document.createElement('style');
styleElement.id = 'deepSeaThemeStyles'; // Give it an ID so we can check if it exists
// Enhanced CSS with your requested changes
styleElement.textContent = `
/* Base theme variables */
:root {
--primary-color: #0088cc !important;
--bitcoin-orange: #0088cc !important;
--bitcoin-orange-rgb: 0, 136, 204 !important;
--bg-gradient: linear-gradient(135deg, #0a0a0a, #131b20) !important;
--accent-color: #00b3ff !important;
--header-bg: linear-gradient(to right, #0088cc, #005580) !important;
--card-header-bg: linear-gradient(to right, #0088cc, #006699) !important;
--progress-bar-color: #0088cc !important;
--link-color: #0088cc !important;
--link-hover-color: #00b3ff !important;
/* Standardized text shadow values */
--blue-text-shadow: 0 0 10px rgba(0, 136, 204, 0.8), 0 0 5px rgba(0, 136, 204, 0.5);
--yellow-text-shadow: 0 0 10px rgba(255, 215, 0, 0.8), 0 0 5px rgba(255, 215, 0, 0.5);
--green-text-shadow: 0 0 10px rgba(50, 205, 50, 0.8), 0 0 5px rgba(50, 205, 50, 0.5);
--red-text-shadow: 0 0 10px rgba(255, 85, 85, 0.8), 0 0 5px rgba(255, 85, 85, 0.5);
--white-text-shadow: 0 0 10px rgba(255, 255, 255, 0.8), 0 0 5px rgba(255, 255, 255, 0.5);
--cyan-text-shadow: 0 0 10px rgba(0, 255, 255, 0.8), 0 0 5px rgba(0, 255, 255, 0.5);
}
/* Blue elements - main theme elements */
.card-header, .card > .card-header,
.container-fluid .card > .card-header {
background: linear-gradient(to right, #0088cc, #006699) !important;
border-bottom: 1px solid #0088cc !important;
text-shadow: var(--blue-text-shadow) !important;
color: #fff !important;
}
.card {
border: 1px solid #0088cc !important;
box-shadow: 0 0 5px rgba(0, 136, 204, 0.3) !important;
}
/* Navigation and interface elements */
.nav-link {
border: 1px solid #0088cc !important;
color: #0088cc !important;
}
.nav-link:hover, .nav-link.active {
background-color: #0088cc !important;
color: #fff !important;
box-shadow: 0 0 10px rgba(0, 136, 204, 0.5) !important;
}
#terminal-cursor {
background-color: #0088cc !important;
box-shadow: 0 0 5px rgba(0, 136, 204, 0.8) !important;
}
#lastUpdated {
color: #0088cc !important;
}
/* Chart and progress elements */
.bitcoin-progress-inner {
background: linear-gradient(90deg, #0088cc, #00b3ff) !important;
}
.bitcoin-progress-container {
border: 1px solid #0088cc !important;
box-shadow: 0 0 8px rgba(0, 136, 204, 0.5) !important;
}
h1, .text-center h1 {
color: #0088cc !important;
text-shadow: var(--blue-text-shadow) !important;
}
.nav-badge {
background-color: #0088cc !important;
}
/* ===== COLOR SPECIFIC STYLING ===== */
/* YELLOW - SATOSHI EARNINGS & BTC PRICE */
/* All Satoshi earnings in yellow with consistent text shadow */
#daily_mined_sats,
#monthly_mined_sats,
#estimated_earnings_per_day_sats,
#estimated_earnings_next_block_sats,
#estimated_rewards_in_window_sats,
#btc_price, /* BTC Price in yellow */
.card:contains('SATOSHI EARNINGS') span.metric-value {
color: #ffd700 !important; /* Bitcoin gold/yellow */
text-shadow: var(--yellow-text-shadow) !important;
}
/* More specific selectors for Satoshi values */
span.metric-value[id$="_sats"] {
color: #ffd700 !important;
text-shadow: var(--yellow-text-shadow) !important;
}
/* Retaining original yellow for specific elements */
.est_time_to_payout:not(.green):not(.red) {
color: #ffd700 !important;
text-shadow: var(--yellow-text-shadow) !important;
}
/* GREEN - POSITIVE USD VALUES */
/* USD earnings that are positive should be green */
.metric-value.green,
span.green,
#daily_revenue:not([style*="color: #ff"]),
#monthly_profit_usd:not([style*="color: #ff"]),
#daily_profit_usd:not([style*="color: #ff"]) {
color: #32CD32 !important; /* Lime green */
text-shadow: var(--green-text-shadow) !important;
}
/* Status indicators remain green */
.status-green {
color: #32CD32 !important;
text-shadow: var(--green-text-shadow) !important;
}
.online-dot {
background: #32CD32 !important;
box-shadow: 0 0 10px #32CD32, 0 0 20px #32CD32 !important;
}
/* RED - NEGATIVE USD VALUES & WARNINGS */
/* Red for negative values and warnings */
.metric-value.red,
span.red,
.status-red,
#daily_power_cost {
color: #ff5555 !important;
text-shadow: var(--red-text-shadow) !important;
}
.offline-dot {
background: #ff5555 !important;
box-shadow: 0 0 10px #ff5555, 0 0 20px #ff5555 !important;
}
/* WHITE - Network stats and worker data */
#block_number,
#difficulty,
#network_hashrate,
#pool_fees_percentage,
#workers_hashing,
#last_share,
#blocks_found,
#last_block_height {
color: #ffffff !important;
text-shadow: var(--white-text-shadow) !important;
}
/* CYAN - Time ago in last block */
#last_block_time {
color: #00ffff !important; /* Cyan */
text-shadow: var(--cyan-text-shadow) !important;
}
/* BLUE - Pool statistics */
#pool_total_hashrate {
color: #0088cc !important;
text-shadow: var(--blue-text-shadow) !important;
}
/* Hashrate values are white */
#hashrate_24hr,
#hashrate_3hr,
#hashrate_10min,
#hashrate_60sec {
color: white !important;
text-shadow: var(--white-text-shadow) !important;
}
/* Pool luck/efficiency colors - PRESERVE EXISTING */
#pool_luck.very-lucky {
color: #32CD32 !important; /* Very lucky - bright green */
text-shadow: var(--green-text-shadow) !important;
}
#pool_luck.lucky {
color: #90EE90 !important; /* Lucky - light green */
text-shadow: 0 0 10px rgba(144, 238, 144, 0.8), 0 0 5px rgba(144, 238, 144, 0.5) !important;
}
#pool_luck.normal-luck {
color: #F0E68C !important; /* Normal - khaki */
text-shadow: 0 0 10px rgba(240, 230, 140, 0.8), 0 0 5px rgba(240, 230, 140, 0.5) !important;
}
#pool_luck.unlucky {
color: #ff5555 !important; /* Unlucky - red */
text-shadow: var(--red-text-shadow) !important;
}
/* Congrats message */
#congratsMessage {
background: #0088cc !important;
box-shadow: 0 0 15px rgba(0, 136, 204, 0.7) !important;
}
/* Animations */
@keyframes waitingPulse {
0%, 100% { box-shadow: 0 0 10px #0088cc, 0 0 15px #0088cc !important; opacity: 0.8; }
50% { box-shadow: 0 0 20px #0088cc, 0 0 35px #0088cc !important; opacity: 1; }
}
@keyframes glow {
0%, 100% { box-shadow: 0 0 10px #0088cc, 0 0 15px #0088cc !important; }
50% { box-shadow: 0 0 15px #0088cc, 0 0 25px #0088cc !important; }
}
`;
// Check if our style element already exists
const existingStyle = document.getElementById('deepSeaThemeStyles');
if (existingStyle) {
existingStyle.parentNode.removeChild(existingStyle);
}
// Add our new style element to the head
document.head.appendChild(styleElement);
// Update page title
document.title = document.title.replace("BTC-OS", "DeepSea");
document.title = document.title.replace("Bitcoin", "DeepSea");
// Update header text
const headerElement = document.querySelector('h1');
if (headerElement) {
headerElement.innerHTML = headerElement.innerHTML.replace("BTC-OS", "DeepSea");
headerElement.innerHTML = headerElement.innerHTML.replace("BITCOIN", "DEEPSEA");
}
console.log("DeepSea theme applied with color adjustments");
} finally {
// Always reset the guard flag when done, even if there's an error
isApplyingTheme = false;
}
}
// Make the function accessible globally so main.js can check for it
window.applyDeepSeaTheme = applyDeepSeaTheme;
$(document).ready(function () {
// Apply theme based on stored preference - moved to beginning for better initialization
try {
const useDeepSea = localStorage.getItem('useDeepSeaTheme') === 'true';
if (useDeepSea) {
applyDeepSeaTheme();
}
// Setup theme change listener
setupThemeChangeListener();
} catch (e) {
console.error("Error handling theme:", e);
}
// Modify the initializeChart function to use blue colors for the chart
function initializeChart() {
try {
const ctx = document.getElementById('trendGraph').getContext('2d');
if (!ctx) {
console.error("Could not find trend graph canvas");
return null;
}
if (!window.Chart) {
console.error("Chart.js not loaded");
return null;
}
// Get the current theme colors
const theme = getCurrentTheme();
// Check if Chart.js plugin is available
const hasAnnotationPlugin = window['chartjs-plugin-annotation'] !== undefined;
return new Chart(ctx, {
type: 'line',
data: {
labels: [],
datasets: [{
label: 'HASHRATE TREND (TH/s)',
data: [],
borderWidth: 2,
borderColor: function (context) {
const chart = context.chart;
const { ctx, chartArea } = chart;
if (!chartArea) {
return theme.PRIMARY;
}
// Create gradient for line
const gradient = ctx.createLinearGradient(0, 0, 0, chartArea.bottom);
gradient.addColorStop(0, theme.CHART.GRADIENT_START);
gradient.addColorStop(1, theme.CHART.GRADIENT_END);
return gradient;
},
backgroundColor: function (context) {
const chart = context.chart;
const { ctx, chartArea } = chart;
if (!chartArea) {
return `rgba(${theme.PRIMARY_RGB}, 0.1)`;
}
// Create gradient for fill
const gradient = ctx.createLinearGradient(0, 0, 0, chartArea.bottom);
gradient.addColorStop(0, `rgba(${theme.PRIMARY_RGB}, 0.3)`);
gradient.addColorStop(0.5, `rgba(${theme.PRIMARY_RGB}, 0.2)`);
gradient.addColorStop(1, `rgba(${theme.PRIMARY_RGB}, 0.05)`);
return gradient;
},
fill: true,
tension: 0.3,
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
animation: {
duration: 0 // Disable animations for better performance
},
scales: {
x: {
display: true,
ticks: {
maxTicksLimit: 8, // Limit number of x-axis labels
maxRotation: 0, // Don't rotate labels
autoSkip: true, // Automatically skip some labels
color: '#FFFFFF',
font: {
family: "'VT323', monospace", // Terminal font
size: 14
}
},
grid: {
color: '#333333',
lineWidth: 0.5
}
},
y: {
title: {
display: true,
text: 'HASHRATE (TH/S)',
color: theme.PRIMARY,
font: {
family: "'VT323', monospace",
size: 16,
weight: 'bold'
}
},
ticks: {
color: '#FFFFFF',
maxTicksLimit: 6, // Limit total number of ticks
precision: 1, // Control decimal precision
autoSkip: true, // Skip labels to prevent overcrowding
autoSkipPadding: 10, // Padding between skipped labels
font: {
family: "'VT323', monospace", // Terminal font
size: 14
},
callback: function (value) {
// For zero, just return 0
if (value === 0) return '0';
// For very large values (1M+)
if (value >= 1000000) {
return (value / 1000000).toFixed(1) + 'M';
}
// For large values (1K+)
else if (value >= 1000) {
return (value / 1000).toFixed(1) + 'K';
}
// For values between 10 and 1000
else if (value >= 10) {
return Math.round(value);
}
// For small values, limit decimal places
else if (value >= 1) {
return value.toFixed(1);
}
// For tiny values, use appropriate precision
else {
return value.toPrecision(2);
}
}
},
grid: {
color: '#333333',
lineWidth: 0.5,
drawBorder: false,
zeroLineColor: '#555555',
zeroLineWidth: 1,
drawTicks: false
}
}
},
plugins: {
tooltip: {
backgroundColor: 'rgba(0, 0, 0, 0.8)',
titleColor: theme.PRIMARY,
bodyColor: '#FFFFFF',
titleFont: {
family: "'VT323', monospace",
size: 16,
weight: 'bold'
},
bodyFont: {
family: "'VT323', monospace",
size: 14
},
padding: 10,
cornerRadius: 0,
displayColors: false,
callbacks: {
title: function (tooltipItems) {
return tooltipItems[0].label.toUpperCase();
},
label: function (context) {
// Format tooltip values with appropriate unit
const value = context.raw;
return 'HASHRATE: ' + formatHashrateForDisplay(value).toUpperCase();
}
}
},
legend: { display: false },
annotation: hasAnnotationPlugin ? {
annotations: {
averageLine: {
type: 'line',
yMin: 0,
yMax: 0,
borderColor: theme.CHART.ANNOTATION,
borderWidth: 3,
borderDash: [8, 4],
shadowColor: `rgba(${theme.PRIMARY_RGB}, 0.5)`,
shadowBlur: 8,
shadowOffsetX: 0,
shadowOffsetY: 0,
label: {
enabled: true,
content: '24HR AVG: 0 TH/S',
backgroundColor: 'rgba(0,0,0,0.8)',
color: theme.CHART.ANNOTATION,
font: {
family: "'VT323', monospace",
size: 16,
weight: 'bold'
},
padding: { top: 4, bottom: 4, left: 8, right: 8 },
borderRadius: 0,
position: 'start'
}
}
}
} : {}
}
}
});
} catch (error) {
console.error("Error initializing chart:", error);
return null;
}
}
// Add this function to the document ready section
function setupThemeChangeListener() {
// Listen for storage events to detect theme changes from other tabs/windows
window.addEventListener('storage', function (event) {
if (event.key === 'useDeepSeaTheme') {
// Update chart with new theme colors
if (trendChart) {
// Trigger chart update with new colors
trendChart.destroy();
trendChart = initializeChart();
updateChartWithNormalizedData(trendChart, latestMetrics);
}
// Update other UI elements that depend on theme colors
updateRefreshButtonColor();
// Trigger a custom event that other components can listen to
$(document).trigger('themeChanged');
}
});
}
setupThemeChangeListener();
// Remove the existing refreshUptime container to avoid duplicates
$('#refreshUptime').hide();
@ -2046,6 +2564,14 @@ $(document).ready(function () {
}
}
// Update BitcoinProgressBar theme when theme changes
$(document).on('themeChanged', function () {
if (typeof BitcoinMinuteRefresh !== 'undefined' &&
typeof BitcoinMinuteRefresh.updateTheme === 'function') {
BitcoinMinuteRefresh.updateTheme();
}
});
// Set up event source for SSE
setupEventSource();
@ -2053,8 +2579,8 @@ $(document).ready(function () {
updateServerTime();
setInterval(updateServerTime, 30000);
// Add a manual refresh button for fallback
$("body").append('<button id="refreshButton" style="position: fixed; bottom: 20px; left: 20px; z-index: 1000; background: #f7931a; color: black; border: none; padding: 8px 16px; display: none; border-radius: 4px; cursor: pointer;">Refresh Data</button>');
// Update the manual refresh button color
$("body").append('<button id="refreshButton" style="position: fixed; bottom: 20px; left: 20px; z-index: 1000; background: #0088cc; color: white; border: none; padding: 8px 16px; display: none; border-radius: 4px; cursor: pointer;">Refresh Data</button>');
$("#refreshButton").on("click", function () {
$(this).text("Refreshing...");

404
static/js/theme.js Normal file
View File

@ -0,0 +1,404 @@
// Bitcoin Orange theme (default)
const BITCOIN_THEME = {
PRIMARY: '#f2a900',
PRIMARY_RGB: '242, 169, 0',
SHARED: {
GREEN: '#32CD32',
RED: '#ff5555',
YELLOW: '#ffd700'
},
CHART: {
GRADIENT_START: '#f2a900',
GRADIENT_END: 'rgba(242, 169, 0, 0.2)',
ANNOTATION: '#ffd700'
}
};
// DeepSea theme (blue alternative)
const DEEPSEA_THEME = {
PRIMARY: '#0088cc',
PRIMARY_RGB: '0, 136, 204',
SHARED: {
GREEN: '#32CD32',
RED: '#ff5555',
YELLOW: '#ffd700'
},
CHART: {
GRADIENT_START: '#0088cc',
GRADIENT_END: 'rgba(0, 136, 204, 0.2)',
ANNOTATION: '#00b3ff'
}
};
// Global theme constants
const THEME = {
BITCOIN: BITCOIN_THEME,
DEEPSEA: DEEPSEA_THEME,
SHARED: BITCOIN_THEME.SHARED
};
// Function to get the current theme based on localStorage setting
function getCurrentTheme() {
const useDeepSea = localStorage.getItem('useDeepSeaTheme') === 'true';
return useDeepSea ? DEEPSEA_THEME : BITCOIN_THEME;
}
// Make globals available
window.THEME = THEME;
window.getCurrentTheme = getCurrentTheme;
// Use window-scoped variable to prevent conflicts
window.themeProcessing = false;
// Fixed applyDeepSeaTheme function with recursion protection
function applyDeepSeaTheme() {
// Check if we're already applying the theme to prevent recursion
if (window.themeProcessing) {
console.log("Theme application already in progress, avoiding recursion");
return;
}
// Set the guard flag
window.themeProcessing = true;
try {
console.log("Applying DeepSea theme...");
// Create or update CSS variables for the DeepSea theme
const styleElement = document.createElement('style');
styleElement.id = 'deepSeaThemeStyles'; // Give it an ID so we can check if it exists
// Enhanced CSS with your requested changes
styleElement.textContent = `
/* Base theme variables */
:root {
--primary-color: #0088cc !important;
--bitcoin-orange: #0088cc !important;
--bitcoin-orange-rgb: 0, 136, 204 !important;
--bg-gradient: linear-gradient(135deg, #0a0a0a, #131b20) !important;
--accent-color: #00b3ff !important;
--header-bg: linear-gradient(to right, #0088cc, #005580) !important;
--card-header-bg: linear-gradient(to right, #0088cc, #006699) !important;
--progress-bar-color: #0088cc !important;
--link-color: #0088cc !important;
--link-hover-color: #00b3ff !important;
/* Standardized text shadow values */
--blue-text-shadow: 0 0 10px rgba(0, 136, 204, 0.8), 0 0 5px rgba(0, 136, 204, 0.5);
--yellow-text-shadow: 0 0 10px rgba(255, 215, 0, 0.8), 0 0 5px rgba(255, 215, 0, 0.5);
--green-text-shadow: 0 0 10px rgba(50, 205, 50, 0.8), 0 0 5px rgba(50, 205, 50, 0.5);
--red-text-shadow: 0 0 10px rgba(255, 85, 85, 0.8), 0 0 5px rgba(255, 85, 85, 0.5);
--white-text-shadow: 0 0 10px rgba(255, 255, 255, 0.8), 0 0 5px rgba(255, 255, 255, 0.5);
--cyan-text-shadow: 0 0 10px rgba(0, 255, 255, 0.8), 0 0 5px rgba(0, 255, 255, 0.5);
}
/* Blue elements - main theme elements */
.card-header, .card > .card-header,
.container-fluid .card > .card-header {
background: linear-gradient(to right, #0088cc, #006699) !important;
border-bottom: 1px solid #0088cc !important;
text-shadow: var(--blue-text-shadow) !important;
color: #fff !important;
}
.card {
border: 1px solid #0088cc !important;
box-shadow: 0 0 5px rgba(0, 136, 204, 0.3) !important;
}
/* Navigation and interface elements */
.nav-link {
border: 1px solid #0088cc !important;
color: #0088cc !important;
}
.nav-link:hover, .nav-link.active {
background-color: #0088cc !important;
color: #fff !important;
box-shadow: 0 0 10px rgba(0, 136, 204, 0.5) !important;
}
#terminal-cursor {
background-color: #0088cc !important;
box-shadow: 0 0 5px rgba(0, 136, 204, 0.8) !important;
}
#lastUpdated {
color: #0088cc !important;
}
/* Chart and progress elements */
.bitcoin-progress-inner {
background: linear-gradient(90deg, #0088cc, #00b3ff) !important;
}
.bitcoin-progress-container {
border: 1px solid #0088cc !important;
box-shadow: 0 0 8px rgba(0, 136, 204, 0.5) !important;
}
h1, .text-center h1 {
color: #0088cc !important;
text-shadow: var(--blue-text-shadow) !important;
}
.nav-badge {
background-color: #0088cc !important;
}
/* Theme toggle button styling */
#themeToggle,
button.theme-toggle,
.toggle-theme-btn {
background: transparent !important;
border: 1px solid #0088cc !important;
color: #0088cc !important;
transition: all 0.3s ease !important;
}
#themeToggle:hover,
button.theme-toggle:hover,
.toggle-theme-btn:hover {
background-color: rgba(0, 136, 204, 0.1) !important;
box-shadow: 0 0 10px rgba(0, 136, 204, 0.3) !important;
}
/* ===== COLOR SPECIFIC STYLING ===== */
/* YELLOW - SATOSHI EARNINGS & BTC PRICE */
/* All Satoshi earnings in yellow with consistent text shadow */
#daily_mined_sats,
#monthly_mined_sats,
#estimated_earnings_per_day_sats,
#estimated_earnings_next_block_sats,
#estimated_rewards_in_window_sats,
#btc_price, /* BTC Price in yellow */
.card:contains('SATOSHI EARNINGS') span.metric-value {
color: #ffd700 !important; /* Bitcoin gold/yellow */
text-shadow: var(--yellow-text-shadow) !important;
}
/* More specific selectors for Satoshi values */
span.metric-value[id$="_sats"] {
color: #ffd700 !important;
text-shadow: var(--yellow-text-shadow) !important;
}
/* Retaining original yellow for specific elements */
.est_time_to_payout:not(.green):not(.red) {
color: #ffd700 !important;
text-shadow: var(--yellow-text-shadow) !important;
}
/* GREEN - POSITIVE USD VALUES */
/* USD earnings that are positive should be green */
.metric-value.green,
span.green,
#daily_revenue:not([style*="color: #ff"]),
#monthly_profit_usd:not([style*="color: #ff"]),
#daily_profit_usd:not([style*="color: #ff"]) {
color: #32CD32 !important; /* Lime green */
text-shadow: var(--green-text-shadow) !important;
}
/* Status indicators remain green */
.status-green {
color: #32CD32 !important;
text-shadow: var(--green-text-shadow) !important;
}
.online-dot {
background: #32CD32 !important;
box-shadow: 0 0 10px #32CD32, 0 0 20px #32CD32 !important;
}
/* RED - NEGATIVE USD VALUES & WARNINGS */
/* Red for negative values and warnings */
.metric-value.red,
span.red,
.status-red,
#daily_power_cost {
color: #ff5555 !important;
text-shadow: var(--red-text-shadow) !important;
}
.offline-dot {
background: #ff5555 !important;
box-shadow: 0 0 10px #ff5555, 0 0 20px #ff5555 !important;
}
/* WHITE - Network stats and worker data */
#block_number,
#difficulty,
#network_hashrate,
#pool_fees_percentage,
#workers_hashing,
#last_share,
#blocks_found,
#last_block_height {
color: #ffffff !important;
text-shadow: var(--white-text-shadow) !important;
}
/* CYAN - Time ago in last block */
#last_block_time {
color: #00ffff !important; /* Cyan */
text-shadow: var(--cyan-text-shadow) !important;
}
/* BLUE - Pool statistics */
#pool_total_hashrate {
color: #0088cc !important;
text-shadow: var(--blue-text-shadow) !important;
}
/* Hashrate values are white */
#hashrate_24hr,
#hashrate_3hr,
#hashrate_10min,
#hashrate_60sec {
color: white !important;
text-shadow: var(--white-text-shadow) !important;
}
/* Pool luck/efficiency colors - PRESERVE EXISTING */
#pool_luck.very-lucky {
color: #32CD32 !important; /* Very lucky - bright green */
text-shadow: var(--green-text-shadow) !important;
}
#pool_luck.lucky {
color: #90EE90 !important; /* Lucky - light green */
text-shadow: 0 0 10px rgba(144, 238, 144, 0.8), 0 0 5px rgba(144, 238, 144, 0.5) !important;
}
#pool_luck.normal-luck {
color: #F0E68C !important; /* Normal - khaki */
text-shadow: 0 0 10px rgba(240, 230, 140, 0.8), 0 0 5px rgba(240, 230, 140, 0.5) !important;
}
#pool_luck.unlucky {
color: #ff5555 !important; /* Unlucky - red */
text-shadow: var(--red-text-shadow) !important;
}
/* Congrats message */
#congratsMessage {
background: #0088cc !important;
box-shadow: 0 0 15px rgba(0, 136, 204, 0.7) !important;
}
/* Animations */
@keyframes waitingPulse {
0%, 100% { box-shadow: 0 0 10px #0088cc, 0 0 15px #0088cc !important; opacity: 0.8; }
50% { box-shadow: 0 0 20px #0088cc, 0 0 35px #0088cc !important; opacity: 1; }
}
@keyframes glow {
0%, 100% { box-shadow: 0 0 10px #0088cc, 0 0 15px #0088cc !important; }
50% { box-shadow: 0 0 15px #0088cc, 0 0 25px #0088cc !important; }
}
`;
// Check if our style element already exists
const existingStyle = document.getElementById('deepSeaThemeStyles');
if (existingStyle) {
existingStyle.parentNode.removeChild(existingStyle);
}
// Add our new style element to the head
document.head.appendChild(styleElement);
// Update page title
document.title = document.title.replace("BTC-OS", "DeepSea");
document.title = document.title.replace("Bitcoin", "DeepSea");
// Update header text
const headerElement = document.querySelector('h1');
if (headerElement) {
headerElement.innerHTML = headerElement.innerHTML.replace("BTC-OS", "DeepSea");
headerElement.innerHTML = headerElement.innerHTML.replace("BITCOIN", "DEEPSEA");
}
// Update theme toggle button
const themeToggle = document.getElementById('themeToggle');
if (themeToggle) {
themeToggle.style.borderColor = '#0088cc';
themeToggle.style.color = '#0088cc';
}
console.log("DeepSea theme applied with color adjustments");
} finally {
// Always reset the guard flag when done, even if there's an error
window.themeProcessing = false;
}
}
// Make the function accessible globally
window.applyDeepSeaTheme = applyDeepSeaTheme;
// Toggle theme with hard page refresh
function toggleTheme() {
const useDeepSea = localStorage.getItem('useDeepSeaTheme') !== 'true';
// Save the new theme preference
saveThemePreference(useDeepSea);
// Show a brief loading message to indicate theme change is happening
const loadingMessage = document.createElement('div');
loadingMessage.style.position = 'fixed';
loadingMessage.style.top = '0';
loadingMessage.style.left = '0';
loadingMessage.style.width = '100%';
loadingMessage.style.height = '100%';
loadingMessage.style.backgroundColor = 'rgba(0, 0, 0, 0.5)';
loadingMessage.style.display = 'flex';
loadingMessage.style.justifyContent = 'center';
loadingMessage.style.alignItems = 'center';
loadingMessage.style.zIndex = '9999';
loadingMessage.style.color = useDeepSea ? '#0088cc' : '#f2a900';
loadingMessage.style.fontFamily = "'VT323', monospace";
loadingMessage.style.fontSize = '24px';
loadingMessage.innerHTML = '<div style="background-color: rgba(0, 0, 0, 0.8); padding: 20px; border-radius: 5px;">APPLYING ' + (useDeepSea ? 'DEEPSEA' : 'BITCOIN') + ' THEME...</div>';
document.body.appendChild(loadingMessage);
// Short delay before refreshing to allow the message to be seen
setTimeout(() => {
// Hard reload the page
window.location.reload();
}, 300);
}
// Set theme preference to localStorage
function saveThemePreference(useDeepSea) {
try {
localStorage.setItem('useDeepSeaTheme', useDeepSea);
} catch (e) {
console.error("Error saving theme preference:", e);
}
}
// Check for theme preference in localStorage
function loadThemePreference() {
try {
const themePreference = localStorage.getItem('useDeepSeaTheme');
if (themePreference === 'true') {
applyDeepSeaTheme();
} else {
// Make sure the toggle button is styled correctly for Bitcoin theme
const themeToggle = document.getElementById('themeToggle');
if (themeToggle) {
themeToggle.style.borderColor = '#f2a900';
themeToggle.style.color = '#f2a900';
}
}
} catch (e) {
console.error("Error loading theme preference:", e);
}
}
// Apply theme on page load
document.addEventListener('DOMContentLoaded', loadThemePreference);
// For pages that load content dynamically, also check when the window loads
window.addEventListener('load', loadThemePreference);

View File

@ -17,8 +17,25 @@
<!-- Common CSS -->
<link rel="stylesheet" href="/static/css/common.css">
<!-- Custom CSS -->
<link rel="stylesheet" href="/static/css/theme-toggle.css">
<!-- Theme JS (added to ensure consistent application of theme) -->
<script src="/static/js/theme.js"></script>
<!-- Page-specific CSS -->
{% block css %}{% endblock %}
<style>
.footer {
margin-top: 30px;
padding: 10px 0;
color: grey;
font-size: 0.9rem;
text-shadow: 0 0 5px rgba(100, 100, 100, 0.3);
border-top: 1px solid rgba(128, 128, 128, 0.2);
}
</style>
</head>
<body>
<div class="container-fluid">
@ -34,6 +51,11 @@
<!-- Top right link -->
<a href="https://x.com/DJObleezy" id="topRightLink" target="_blank" rel="noopener noreferrer">MADE BY @DJO₿LEEZY</a>
<!-- Theme toggle button (new) -->
<button id="themeToggle" class="theme-toggle-btn">
<span>Toggle Theme</span>
</button>
{% block last_updated %}
<p class="text-center" id="lastUpdated" style="color: #f7931a; text-transform: uppercase;"><strong>LAST UPDATED:</strong> {{ current_time }}<span id="terminal-cursor"></span></p>
{% endblock %}
@ -57,6 +79,11 @@
{% block congrats_message %}
<div id="congratsMessage" style="display:none; position: fixed; top: 20px; left: 50%; transform: translateX(-50%); z-index: 1000; background: #f7931a; color: #000; padding: 10px; border-radius: 5px; box-shadow: 0 0 15px rgba(247, 147, 26, 0.7);"></div>
{% endblock %}
<!-- Footer -->
<footer class="footer text-center">
<p>Not affiliated with Ocean.xyz</p>
</footer>
</div>
<!-- External JavaScript libraries -->
@ -64,6 +91,32 @@
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-annotation@1.1.0"></script>
<!-- Theme toggle initialization -->
<script>
document.addEventListener('DOMContentLoaded', function () {
// Initialize theme toggle button based on current theme
const themeToggle = document.getElementById('themeToggle');
if (themeToggle) {
// Check current theme
const isDeepSea = localStorage.getItem('useDeepSeaTheme') === 'true';
// Update button style based on theme
if (isDeepSea) {
themeToggle.style.borderColor = '#0088cc';
themeToggle.style.color = '#0088cc';
} else {
themeToggle.style.borderColor = '#f2a900';
themeToggle.style.color = '#f2a900';
}
// Add click event listener
themeToggle.addEventListener('click', function () {
toggleTheme(); // This will now trigger a page refresh
});
}
});
</script>
<!-- Page-specific JavaScript -->
{% block javascript %}{% endblock %}

View File

@ -4,6 +4,7 @@
{% block css %}
<link rel="stylesheet" href="/static/css/blocks.css">
<link rel="stylesheet" href="/static/css/theme-toggle.css">
{% endblock %}
{% block header %}BLOCKCHAIN MONITOR v 0.1{% endblock %}

View File

@ -6,25 +6,122 @@
<title>Ocean.xyz Pool Miner - Initializing...</title>
<link href="https://fonts.googleapis.com/css2?family=VT323&display=swap" rel="stylesheet">
<link rel="stylesheet" href="/static/css/boot.css">
<link rel="stylesheet" href="/static/css/theme-toggle.css">
<!-- Add Theme JS -->
<script src="/static/js/theme.js"></script>
<style>
/* Added styles for configuration form */
/* Config form styling - fixed width and hidden by default */
#config-form {
display: none;
margin-top: 20px;
background-color: rgba(0, 0, 0, 0.7);
width: 500px;
max-width: 90%;
margin: 30px auto;
padding: 20px;
background-color: #0d0d0d;
border: 1px solid #f7931a;
padding: 15px;
max-width: 600px;
margin-left: auto;
margin-right: auto;
box-shadow: 0 0 10px rgba(247, 147, 26, 0.5);
border-radius: 4px;
}
.config-title {
/* Boot text color - updated with theme toggling */
body:not(.deepsea-theme) #terminal,
body:not(.deepsea-theme) #output,
body:not(.deepsea-theme) #prompt-container,
body:not(.deepsea-theme) #prompt-text,
body:not(.deepsea-theme) #user-input,
body:not(.deepsea-theme) #loading-message {
color: #f7931a;
font-size: 22px;
text-shadow: 0 0 5px rgba(247, 147, 26, 0.4);
}
/* DeepSea theme text color */
body.deepsea-theme #terminal,
body.deepsea-theme #output,
body.deepsea-theme #prompt-container,
body.deepsea-theme #prompt-text,
body.deepsea-theme #user-input,
body.deepsea-theme #loading-message {
color: #0088cc;
text-shadow: 0 0 5px rgba(0, 136, 204, 0.4);
}
/* DeepSea cursor color */
body.deepsea-theme .cursor,
body.deepsea-theme .prompt-cursor {
background-color: #0088cc;
box-shadow: 0 0 5px rgba(0, 136, 204, 0.8);
}
/* Boot-specific DeepSea theme adjustments */
body.deepsea-theme #bitcoin-logo {
color: #0088cc;
border-color: #0088cc;
text-shadow: 0 0 10px rgba(0, 136, 204, 0.5);
box-shadow: 0 0 15px rgba(0, 136, 204, 0.5);
}
body.deepsea-theme #config-form {
border: 1px solid #0088cc;
box-shadow: 0 0 10px rgba(0, 136, 204, 0.5);
}
body.deepsea-theme .config-title {
color: #0088cc;
text-shadow: 0 0 8px rgba(0, 136, 204, 0.8);
}
body.deepsea-theme .form-group label {
color: #0088cc;
}
body.deepsea-theme .form-group input,
body.deepsea-theme .form-group select {
border: 1px solid #0088cc;
}
body.deepsea-theme .form-group input:focus,
body.deepsea-theme .form-group select:focus {
box-shadow: 0 0 5px #0088cc;
}
body.deepsea-theme .btn {
background-color: #0088cc;
}
body.deepsea-theme .btn:hover {
background-color: #00b3ff;
}
body.deepsea-theme .btn-secondary {
background-color: #333;
color: #0088cc;
}
body.deepsea-theme .tooltip .tooltip-text {
border: 1px solid #0088cc;
}
body.deepsea-theme .form-group select {
background-image: linear-gradient(45deg, transparent 50%, #0088cc 50%), linear-gradient(135deg, #0088cc 50%, transparent 50%);
}
/* DeepSea skip button */
body.deepsea-theme #skip-button {
background-color: #0088cc;
box-shadow: 0 0 8px rgba(0, 136, 204, 0.5);
}
body.deepsea-theme #skip-button:hover {
background-color: #00b3ff;
box-shadow: 0 0 12px rgba(0, 136, 204, 0.7);
}
/* Original Bitcoin styling preserved by default */
.config-title {
font-size: 24px;
text-align: center;
margin-bottom: 15px;
margin-bottom: 20px;
color: #f7931a;
text-shadow: 0 0 8px rgba(247, 147, 26, 0.8);
}
@ -38,17 +135,19 @@
color: #f7931a;
}
.form-group input {
.form-group input,
.form-group select {
width: 100%;
background-color: #111;
border: 1px solid #f7931a;
padding: 8px;
color: white;
background-color: #0d0d0d;
border: 1px solid #f7931a;
color: #fff;
font-family: 'VT323', monospace;
font-size: 18px;
}
.form-group input:focus {
.form-group input:focus,
.form-group select:focus {
outline: none;
box-shadow: 0 0 5px #f7931a;
}
@ -60,19 +159,17 @@
}
.btn {
padding: 8px 16px;
background-color: #f7931a;
color: #000;
border: none;
color: black;
padding: 8px 15px;
cursor: pointer;
font-family: 'VT323', monospace;
font-size: 18px;
cursor: pointer;
min-width: 120px;
text-align: center;
}
.btn:hover {
background-color: #ffa642;
background-color: #ffa32e;
}
.btn-secondary {
@ -80,79 +177,10 @@
color: #f7931a;
}
.btn-secondary:hover {
background-color: #444;
}
/* Make skip button more mobile-friendly */
#skip-button {
position: fixed;
bottom: 20px;
right: 20px;
z-index: 1000;
padding: 12px 20px;
font-size: 18px;
border-radius: 8px;
}
@media (max-width: 768px) {
#skip-button {
bottom: 10px;
right: 10px;
padding: 15px 25px;
font-size: 20px; /* Larger font size for better tap targets */
border-radius: 10px;
width: auto;
}
.form-actions {
flex-direction: column;
gap: 10px;
}
.btn {
width: 100%;
padding: 12px;
font-size: 20px;
}
}
/* Tooltip styles */
.tooltip {
position: relative;
display: inline-block;
margin-left: 5px;
cursor: help;
}
.tooltip .tooltip-text {
visibility: hidden;
width: 200px;
background-color: #000;
color: #fff;
text-align: center;
border: 1px solid #f7931a;
padding: 5px;
position: absolute;
z-index: 1;
bottom: 125%;
left: 50%;
margin-left: -100px;
opacity: 0;
transition: opacity 0.3s;
font-size: 14px;
}
.tooltip:hover .tooltip-text {
visibility: visible;
opacity: 1;
}
/* Form success/error message */
#form-message {
margin-top: 10px;
padding: 8px;
text-align: center;
margin-top: 15px;
padding: 10px;
border-radius: 3px;
display: none;
}
@ -168,60 +196,63 @@
color: #ff0000;
}
/* Add these styles to match the timezone dropdown with your other inputs */
.tooltip {
position: relative;
display: inline-block;
margin-left: 5px;
width: 14px;
height: 14px;
background-color: #333;
color: #fff;
border-radius: 50%;
text-align: center;
line-height: 14px;
font-size: 10px;
cursor: help;
}
.tooltip .tooltip-text {
visibility: hidden;
width: 200px;
background-color: #000;
color: #fff;
text-align: center;
border-radius: 3px;
padding: 5px;
position: absolute;
z-index: 1;
bottom: 125%;
left: 50%;
margin-left: -100px;
opacity: 0;
transition: opacity 0.3s;
font-size: 14px;
border: 1px solid #f7931a;
}
.tooltip:hover .tooltip-text {
visibility: visible;
opacity: 1;
}
/* Style the select dropdown with custom arrow */
.form-group select {
width: 100%;
background-color: #111;
border: 1px solid #f7931a;
padding: 8px;
color: white;
font-family: 'VT323', monospace;
font-size: 18px;
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
cursor: pointer;
}
/* Add a custom dropdown arrow */
.form-group select {
background-image: linear-gradient(45deg, transparent 50%, #f7931a 50%), linear-gradient(135deg, #f7931a 50%, transparent 50%);
background-position: calc(100% - 15px) 50%, calc(100% - 10px) 50%;
background-position: calc(100% - 15px) calc(1em + 0px), calc(100% - 10px) calc(1em + 0px);
background-size: 5px 5px, 5px 5px;
background-repeat: no-repeat;
padding-right: 25px; /* Space for the arrow */
}
.form-group select:focus {
outline: none;
box-shadow: 0 0 5px #f7931a;
}
/* Style the option groups */
.form-group select optgroup {
background-color: #111;
color: #f7931a;
font-family: 'VT323', monospace;
}
/* Style the options */
.form-group select option {
background-color: #222;
color: white;
padding: 8px;
}
/* Improve mobile appearance */
@media (max-width: 768px) {
.form-group select {
padding: 12px;
padding-right: 30px; /* More space for the dropdown arrow */
font-size: 20px;
}
padding-right: 30px;
}
</style>
</head>
<body>
<!-- Theme toggle button (new) -->
<button id="themeToggle" class="theme-toggle-btn">
<span>Toggle Theme</span>
</button>
<button id="skip-button">SKIP</button>
<div id="debug-info"></div>
<div id="loading-message">Loading mining data...</div>
@ -232,7 +263,7 @@
██╔══██╗ ██║ ██║ ██║ ██║╚════██║
██████╔╝ ██║ ╚██████╗ ╚██████╔╝███████║
╚═════╝ ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝
v.21
v.21
</div>
<div id="terminal">
<div id="terminal-content">
@ -322,6 +353,45 @@
</div>
<script>
// Theme toggle initialization
document.addEventListener('DOMContentLoaded', function () {
// Initialize theme toggle button based on current theme
const themeToggle = document.getElementById('themeToggle');
if (themeToggle) {
// Check current theme
const isDeepSea = localStorage.getItem('useDeepSeaTheme') === 'true';
// Update button style based on theme
if (isDeepSea) {
document.body.classList.add('deepsea-theme');
themeToggle.style.borderColor = '#0088cc';
themeToggle.style.color = '#0088cc';
} else {
document.body.classList.remove('deepsea-theme');
themeToggle.style.borderColor = '#f2a900';
themeToggle.style.color = '#f2a900';
}
// Add click event listener
themeToggle.addEventListener('click', function () {
toggleTheme(); // This will now trigger a page refresh
});
}
// Update terminal colors based on theme (boot.html specific)
function updateTerminalColors() {
const isDeepSeaTheme = localStorage.getItem('useDeepSeaTheme') === 'true';
if (isDeepSeaTheme) {
document.body.classList.add('deepsea-theme');
} else {
document.body.classList.remove('deepsea-theme');
}
}
// Initialize terminal colors
updateTerminalColors();
});
// Add a function to populate all available timezones
function populateTimezones() {
const otherTimezones = document.getElementById('other-timezones');

View File

@ -4,6 +4,7 @@
{% block css %}
<link rel="stylesheet" href="/static/css/dashboard.css">
<link rel="stylesheet" href="/static/css/theme-toggle.css">
{% endblock %}
{% block dashboard_active %}active{% endblock %}

View File

@ -4,6 +4,7 @@
{% block css %}
<link rel="stylesheet" href="/static/css/notifications.css">
<link rel="stylesheet" href="/static/css/theme-toggle.css">
{% endblock %}
{% block header %}NOTIFICATION CENTER v 0.1{% endblock %}

View File

@ -4,6 +4,7 @@
{% block css %}
<link rel="stylesheet" href="/static/css/workers.css">
<link rel="stylesheet" href="/static/css/theme-toggle.css">
{% endblock %}
{% block header %}WORKERS OVERVIEW{% endblock %}