티스토리 수익 글 보기
// 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