티스토리 수익 글 보기

티스토리 수익 글 보기

// theme-selector.js import { db } from ‘./dbInstance.js’ import { fetchDefaults } from ‘./defaults.js’ import { defaultLightTheme } from ‘./default-theme.js’ // Import the default light theme class ThemeSelector extends HTMLElement { constructor () { super() this.attachShadow({ mode: ‘open’ }) this.selectElement = document.createElement(‘select’) this.selectElement.id = ‘theme-select’ this.selectElement.addEventListener(‘change’, this.changeTheme.bind(this)) const style = document.createElement(‘style’) style.textContent = ` select { padding: 2px; margin: 6px 0; border: 1px solid var(–rdp-border-color); border-radius: 4px; width: 120px; } ` this.shadowRoot.appendChild(this.selectElement) this.shadowRoot.appendChild(style) } async connectedCallback () { // Append colorblind filters to the main document document.body.appendChild(this.createColorBlindFilters()) const defaults = await fetchDefaults() const customTheme = defaults.theme || {} const isCustomDifferent = this.isThemeDifferent(customTheme, defaultLightTheme) // Build the select options based on theme comparison this.buildOptions(isCustomDifferent) // Get the current theme from the database const currentTheme = await db.getTheme() || (isCustomDifferent ? ‘custom’ : ‘light’) this.selectElement.value = currentTheme // Apply the current theme if (currentTheme === ‘custom’ && isCustomDifferent) { this.applyCustomTheme(customTheme) } else { this.applyTheme(currentTheme) } } isThemeDifferent (custom, defaultTheme) { // Compare each property; return true if any property differs for (const key in defaultTheme) { if (custom[key] !== defaultTheme[key]) { return true } } // Additionally, check if custom has extra properties for (const key in custom) { if (!(key in defaultTheme)) { return true } } return false } buildOptions (includeCustom) { // Clear existing options this.selectElement.innerHTML = ” // Standard Themes const standardGroup = document.createElement(‘optgroup’) standardGroup.label = ‘Standard Themes’; [‘light’, ‘dark’].forEach(text => { const option = document.createElement(‘option’) option.value = text option.textContent = text.charAt(0).toUpperCase() + text.slice(1) standardGroup.appendChild(option) }) // Conditionally add ‘Custom’ option if (includeCustom) { const customOption = document.createElement(‘option’) customOption.value = ‘custom’ customOption.textContent = ‘Custom’ standardGroup.appendChild(customOption) } this.selectElement.appendChild(standardGroup) // Color Blind Themes const colorBlindGroup = document.createElement(‘optgroup’) colorBlindGroup.label = ‘Color Blind Themes’; [ { value: ‘deuteranomaly’, text: ‘Deuteranomaly (Green-Weak)’ }, { value: ‘protanomaly’, text: ‘Protanomaly (Red-Weak)’ }, { value: ‘deuteranopia’, text: ‘Deuteranopia (Green-Blind)’ }, { value: ‘protanopia’, text: ‘Protanopia (Red-Blind)’ }, { value: ‘tritanopia’, text: ‘Tritanopia (Blue-Blind)’ }, { value: ‘tritanomaly’, text: ‘Tritanomaly (Blue-Weak)’ }, { value: ‘achromatopsia’, text: ‘Achromatopsia (All-Color-Blind)’ } ].forEach(({ value, text }) => { const option = document.createElement(‘option’) option.value = value option.textContent = text colorBlindGroup.appendChild(option) }) this.selectElement.appendChild(colorBlindGroup) } async changeTheme (event) { const newTheme = event.target.value await db.setTheme(newTheme) const defaults = await fetchDefaults() const customTheme = defaults.theme || {} const isCustomDifferent = this.isThemeDifferent(customTheme, defaultLightTheme) if (newTheme === ‘custom’ && isCustomDifferent) { this.applyCustomTheme(customTheme) } else { this.removeCustomTheme() this.applyTheme(newTheme) } } applyTheme (themeName) { document.documentElement.setAttribute(‘data-theme’, themeName) } async applyCustomTheme (theme) { document.documentElement.setAttribute(‘data-theme’, ‘custom’) // Create or update a