239 lines
7.9 KiB
JavaScript
239 lines
7.9 KiB
JavaScript
// Theme management functionality
|
|
|
|
class ThemeManager {
|
|
constructor() {
|
|
this.currentTheme = this.getStoredTheme() || this.getPreferredTheme();
|
|
this.init();
|
|
}
|
|
|
|
init() {
|
|
this.applyTheme(this.currentTheme);
|
|
this.setupEventListeners();
|
|
}
|
|
|
|
getStoredTheme() {
|
|
return localStorage.getItem('theme');
|
|
}
|
|
|
|
setStoredTheme(theme) {
|
|
localStorage.setItem('theme', theme);
|
|
}
|
|
|
|
getPreferredTheme() {
|
|
if (this.getStoredTheme()) {
|
|
return this.getStoredTheme();
|
|
}
|
|
|
|
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
|
}
|
|
|
|
applyTheme(theme) {
|
|
document.body.className = document.body.className.replace(/theme-\w+/, '');
|
|
document.body.classList.add(`theme-${theme}`);
|
|
this.currentTheme = theme;
|
|
this.setStoredTheme(theme);
|
|
|
|
// Update theme toggle button
|
|
this.updateThemeToggleButton();
|
|
|
|
// Dispatch theme change event
|
|
window.dispatchEvent(new CustomEvent('themeChanged', {
|
|
detail: { theme: theme }
|
|
}));
|
|
}
|
|
|
|
toggleTheme() {
|
|
const newTheme = this.currentTheme === 'light' ? 'dark' : 'light';
|
|
this.applyTheme(newTheme);
|
|
|
|
// Update user preference via API if logged in
|
|
if (typeof ScriptsManager !== 'undefined') {
|
|
ScriptsManager.updateUserPreferences({ theme: newTheme })
|
|
.catch(error => console.error('Failed to update theme preference:', error));
|
|
}
|
|
}
|
|
|
|
updateThemeToggleButton() {
|
|
const toggleButton = document.getElementById('theme-toggle');
|
|
if (!toggleButton) return;
|
|
|
|
const darkIcon = toggleButton.querySelector('.theme-icon-dark');
|
|
const lightIcon = toggleButton.querySelector('.theme-icon-light');
|
|
|
|
if (this.currentTheme === 'dark') {
|
|
if (darkIcon) darkIcon.style.display = 'none';
|
|
if (lightIcon) lightIcon.style.display = 'inline';
|
|
} else {
|
|
if (darkIcon) darkIcon.style.display = 'inline';
|
|
if (lightIcon) lightIcon.style.display = 'none';
|
|
}
|
|
}
|
|
|
|
setupEventListeners() {
|
|
// Theme toggle button
|
|
const toggleButton = document.getElementById('theme-toggle');
|
|
if (toggleButton) {
|
|
toggleButton.addEventListener('click', () => this.toggleTheme());
|
|
}
|
|
|
|
// Listen for system theme changes
|
|
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
|
|
if (!this.getStoredTheme()) {
|
|
this.applyTheme(e.matches ? 'dark' : 'light');
|
|
}
|
|
});
|
|
|
|
// Listen for custom theme change events
|
|
window.addEventListener('setTheme', (e) => {
|
|
this.applyTheme(e.detail.theme);
|
|
});
|
|
}
|
|
|
|
getCurrentTheme() {
|
|
return this.currentTheme;
|
|
}
|
|
|
|
setTheme(theme) {
|
|
if (['light', 'dark'].includes(theme)) {
|
|
this.applyTheme(theme);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Theme-specific component adjustments
|
|
class ThemeComponentManager {
|
|
constructor(themeManager) {
|
|
this.themeManager = themeManager;
|
|
this.init();
|
|
}
|
|
|
|
init() {
|
|
// Listen for theme changes
|
|
window.addEventListener('themeChanged', (e) => {
|
|
this.adjustComponents(e.detail.theme);
|
|
});
|
|
|
|
// Initial adjustment
|
|
this.adjustComponents(this.themeManager.getCurrentTheme());
|
|
}
|
|
|
|
adjustComponents(theme) {
|
|
this.adjustBootstrapComponents(theme);
|
|
this.adjustCustomComponents(theme);
|
|
this.adjustCharts(theme);
|
|
}
|
|
|
|
adjustBootstrapComponents(theme) {
|
|
// Adjust modal backdrop
|
|
const modals = document.querySelectorAll('.modal');
|
|
modals.forEach(modal => {
|
|
if (theme === 'dark') {
|
|
modal.classList.add('modal-dark');
|
|
} else {
|
|
modal.classList.remove('modal-dark');
|
|
}
|
|
});
|
|
|
|
// Adjust tooltips
|
|
const tooltips = document.querySelectorAll('.tooltip');
|
|
tooltips.forEach(tooltip => {
|
|
if (theme === 'dark') {
|
|
tooltip.classList.add('tooltip-dark');
|
|
} else {
|
|
tooltip.classList.remove('tooltip-dark');
|
|
}
|
|
});
|
|
}
|
|
|
|
adjustCustomComponents(theme) {
|
|
// Adjust log containers
|
|
const logContainers = document.querySelectorAll('.log-container');
|
|
logContainers.forEach(container => {
|
|
if (theme === 'dark') {
|
|
container.style.backgroundColor = '#000000';
|
|
container.style.color = '#ffffff';
|
|
} else {
|
|
container.style.backgroundColor = '#f8f9fa';
|
|
container.style.color = '#212529';
|
|
}
|
|
});
|
|
|
|
// Adjust code blocks
|
|
const codeBlocks = document.querySelectorAll('.code-block');
|
|
codeBlocks.forEach(block => {
|
|
if (theme === 'dark') {
|
|
block.style.backgroundColor = '#2d2d2d';
|
|
block.style.color = '#e9ecef';
|
|
block.style.borderColor = '#495057';
|
|
} else {
|
|
block.style.backgroundColor = '#f8f9fa';
|
|
block.style.color = '#212529';
|
|
block.style.borderColor = '#e9ecef';
|
|
}
|
|
});
|
|
}
|
|
|
|
adjustCharts(theme) {
|
|
// Adjust any charts or graphs based on theme
|
|
// This would be implemented when charts are added
|
|
const chartContainers = document.querySelectorAll('.chart-container');
|
|
chartContainers.forEach(container => {
|
|
const event = new CustomEvent('themeChanged', {
|
|
detail: { theme: theme }
|
|
});
|
|
container.dispatchEvent(event);
|
|
});
|
|
}
|
|
}
|
|
|
|
// Utility functions for theme-aware styling
|
|
function getThemeAwareColor(lightColor, darkColor) {
|
|
const theme = window.themeManager ? window.themeManager.getCurrentTheme() : 'light';
|
|
return theme === 'dark' ? darkColor : lightColor;
|
|
}
|
|
|
|
function getThemeAwareCSS(lightCSS, darkCSS) {
|
|
const theme = window.themeManager ? window.themeManager.getCurrentTheme() : 'light';
|
|
return theme === 'dark' ? darkCSS : lightCSS;
|
|
}
|
|
|
|
// CSS custom properties for theme-aware components
|
|
function updateThemeCustomProperties(theme) {
|
|
const root = document.documentElement;
|
|
|
|
if (theme === 'dark') {
|
|
root.style.setProperty('--theme-bg', '#1a1a1a');
|
|
root.style.setProperty('--theme-fg', '#e9ecef');
|
|
root.style.setProperty('--theme-border', '#495057');
|
|
root.style.setProperty('--theme-muted', '#adb5bd');
|
|
root.style.setProperty('--theme-card-bg', '#2d2d2d');
|
|
} else {
|
|
root.style.setProperty('--theme-bg', '#ffffff');
|
|
root.style.setProperty('--theme-fg', '#212529');
|
|
root.style.setProperty('--theme-border', '#dee2e6');
|
|
root.style.setProperty('--theme-muted', '#6c757d');
|
|
root.style.setProperty('--theme-card-bg', '#ffffff');
|
|
}
|
|
}
|
|
|
|
// Initialize theme management when DOM is loaded
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Create global theme manager instance
|
|
window.themeManager = new ThemeManager();
|
|
window.themeComponentManager = new ThemeComponentManager(window.themeManager);
|
|
|
|
// Update CSS custom properties
|
|
window.addEventListener('themeChanged', (e) => {
|
|
updateThemeCustomProperties(e.detail.theme);
|
|
});
|
|
|
|
// Initial update
|
|
updateThemeCustomProperties(window.themeManager.getCurrentTheme());
|
|
});
|
|
|
|
// Export for use in other modules
|
|
window.ThemeManager = {
|
|
getThemeAwareColor,
|
|
getThemeAwareCSS,
|
|
updateThemeCustomProperties
|
|
}; |