Spaces:
Runtime error
Runtime error
File size: 5,069 Bytes
8fd7a1d |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
import {BLOCKS_CUSTOM, Theme} from '.';
import {customThemeManager, CustomTheme} from './custom-themes.js';
const matchMedia = query => (window.matchMedia ? window.matchMedia(query) : null);
const PREFERS_HIGH_CONTRAST_QUERY = matchMedia('(prefers-contrast: more)');
const PREFERS_DARK_QUERY = matchMedia('(prefers-color-scheme: dark)');
const STORAGE_KEY = 'tw:theme';
/**
* @returns {Theme} detected theme
*/
const systemPreferencesTheme = () => {
if (PREFERS_HIGH_CONTRAST_QUERY && PREFERS_HIGH_CONTRAST_QUERY.matches) {
return Theme.highContrast;
}
if (PREFERS_DARK_QUERY && PREFERS_DARK_QUERY.matches) {
return Theme.dark;
}
return Theme.light;
};
/**
* @param {function} onChange callback; no guarantees about arguments
* @returns {function} call to remove event listeners to prevent memory leak
*/
const onSystemPreferenceChange = onChange => {
if (
!PREFERS_HIGH_CONTRAST_QUERY ||
!PREFERS_DARK_QUERY ||
// Some old browsers don't support addEventListener on media queries
!PREFERS_HIGH_CONTRAST_QUERY.addEventListener ||
!PREFERS_DARK_QUERY.addEventListener
) {
return () => {};
}
PREFERS_HIGH_CONTRAST_QUERY.addEventListener('change', onChange);
PREFERS_DARK_QUERY.addEventListener('change', onChange);
return () => {
PREFERS_HIGH_CONTRAST_QUERY.removeEventListener('change', onChange);
PREFERS_DARK_QUERY.removeEventListener('change', onChange);
};
};
/**
* @returns {Theme} the theme
*/
const detectTheme = () => {
const systemPreferences = systemPreferencesTheme();
try {
const local = localStorage.getItem(STORAGE_KEY);
// Migrate legacy preferences
if (local === 'dark') {
return Theme.dark;
}
if (local === 'light') {
return Theme.light;
}
const parsed = JSON.parse(local);
// Check if this is a custom theme
if (parsed.isCustom && parsed.customThemeUuid) {
const customTheme = customThemeManager.getTheme(parsed.customThemeUuid);
if (customTheme) {
return customTheme;
}
// Fall back to system preferences if custom theme not found
console.warn(`Custom theme ${parsed.customThemeUuid} not found, falling back to system preferences`);
}
// Any invalid values in storage will be handled by Theme itself
const wallpaper = parsed.wallpaper || { url: '', opacity: 0.3, darkness: 0, gridVisible: true, history: [] };
// Add backward compatibility for gridVisible
if (typeof wallpaper.gridVisible === 'undefined') {
wallpaper.gridVisible = true;
}
return new Theme(
parsed.accent || systemPreferences.accent,
parsed.gui || systemPreferences.gui,
parsed.blocks || systemPreferences.blocks,
parsed.menuBarAlign || systemPreferences.menuBarAlign,
wallpaper,
parsed.fonts || { system: [], google: [], history: [] }
);
} catch (e) {
// ignore
}
return systemPreferences;
};
/**
* @param {Theme} theme the theme
*/
const persistTheme = theme => {
const systemPreferences = systemPreferencesTheme();
const nonDefaultSettings = {};
// Handle custom themes differently
if (theme instanceof CustomTheme) {
nonDefaultSettings.customThemeUuid = theme.uuid;
nonDefaultSettings.isCustom = true;
} else {
if (theme.accent !== systemPreferences.accent) {
nonDefaultSettings.accent = theme.accent;
}
if (theme.gui !== systemPreferences.gui) {
nonDefaultSettings.gui = theme.gui;
}
// custom blocks are managed by addon at runtime, don't save here
if (theme.blocks !== systemPreferences.blocks && theme.blocks !== BLOCKS_CUSTOM) {
nonDefaultSettings.blocks = theme.blocks;
}
if (theme.menuBarAlign !== systemPreferences.menuBarAlign) {
nonDefaultSettings.menuBarAlign = theme.menuBarAlign;
}
// Always save wallpaper settings if they exist
if (theme.wallpaper && (theme.wallpaper.url || theme.wallpaper.history.length > 0)) {
nonDefaultSettings.wallpaper = theme.wallpaper;
}
// Always save fonts settings if they exist
if (theme.fonts && (theme.fonts.system.length > 0 || theme.fonts.google.length > 0 || theme.fonts.history.length > 0)) {
nonDefaultSettings.fonts = theme.fonts;
}
}
if (Object.keys(nonDefaultSettings).length === 0) {
try {
localStorage.removeItem(STORAGE_KEY);
} catch (e) {
// ignore
}
} else {
try {
localStorage.setItem(STORAGE_KEY, JSON.stringify(nonDefaultSettings));
} catch (e) {
// ignore
}
}
};
export {
onSystemPreferenceChange,
detectTheme,
persistTheme
};
|