2024-02-21 12:23:10 +02:00
|
|
|
import { hex2rgb } from '../color_convert/color_convert.js'
|
|
|
|
|
import { generatePreset } from '../theme_data/theme_data.service.js'
|
2024-02-19 19:59:38 +02:00
|
|
|
import { init } from '../theme_data/theme_data_3.service.js'
|
2024-02-19 20:47:27 +02:00
|
|
|
import { convertTheme2To3 } from '../theme_data/theme2_to_theme3.js'
|
2024-02-19 19:59:38 +02:00
|
|
|
import { getCssRules } from '../theme_data/css_utils.js'
|
2022-06-05 17:10:44 +03:00
|
|
|
import { defaultState } from '../../modules/config.js'
|
2024-02-27 00:07:45 +02:00
|
|
|
import { chunk } from 'lodash'
|
2020-01-06 22:55:14 +02:00
|
|
|
|
2024-02-26 21:37:40 +02:00
|
|
|
export const applyTheme = async (input) => {
|
2024-02-21 22:18:56 +02:00
|
|
|
let extraRules
|
2024-02-27 17:03:39 +02:00
|
|
|
if (input.themeFileVersion === 1) {
|
|
|
|
|
extraRules = convertTheme2To3(input)
|
|
|
|
|
} else {
|
2024-02-22 18:04:28 +02:00
|
|
|
const { theme } = generatePreset(input)
|
2024-02-21 22:18:56 +02:00
|
|
|
extraRules = convertTheme2To3(theme)
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-27 22:02:44 +02:00
|
|
|
// Assuming that "worst case scenario background" is panel background since it's the most likely one
|
|
|
|
|
const themes3 = init(extraRules, extraRules[0].directives['--bg'].split('|')[1].trim())
|
2017-11-17 17:24:42 +02:00
|
|
|
const head = document.head
|
|
|
|
|
const body = document.body
|
2019-08-27 12:17:10 -04:00
|
|
|
body.classList.add('hidden')
|
2017-11-14 01:37:49 +02:00
|
|
|
|
2017-11-17 17:24:42 +02:00
|
|
|
const styleEl = document.createElement('style')
|
|
|
|
|
head.appendChild(styleEl)
|
|
|
|
|
const styleSheet = styleEl.sheet
|
2017-11-17 02:17:36 +02:00
|
|
|
|
2024-02-19 20:47:27 +02:00
|
|
|
getCssRules(themes3.eager, themes3.staticVars).forEach(rule => {
|
2024-02-18 20:11:06 +02:00
|
|
|
// Hack to support multiple selectors on same component
|
|
|
|
|
if (rule.match(/::-webkit-scrollbar-button/)) {
|
|
|
|
|
const parts = rule.split(/[{}]/g)
|
|
|
|
|
const newRule = [
|
|
|
|
|
parts[0],
|
|
|
|
|
', ',
|
|
|
|
|
parts[0].replace(/button/, 'thumb'),
|
|
|
|
|
' {',
|
|
|
|
|
parts[1],
|
|
|
|
|
'}'
|
|
|
|
|
].join('')
|
|
|
|
|
styleSheet.insertRule(newRule, 'index-max')
|
|
|
|
|
} else {
|
|
|
|
|
styleSheet.insertRule(rule, 'index-max')
|
|
|
|
|
}
|
2024-01-31 17:39:51 +02:00
|
|
|
})
|
2024-02-26 21:37:40 +02:00
|
|
|
|
2019-08-27 12:17:10 -04:00
|
|
|
body.classList.remove('hidden')
|
2024-02-26 21:37:40 +02:00
|
|
|
|
2024-02-27 00:07:45 +02:00
|
|
|
// Optimization - instead of processing all lazy rules in one go, process them in small chunks
|
|
|
|
|
// so that UI can do other things and be somewhat responsive while less important rules are being
|
|
|
|
|
// processed
|
|
|
|
|
chunk(themes3.lazy, 5).forEach(chunk => {
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
Promise.all(chunk.map(x => x())).then(result => {
|
|
|
|
|
getCssRules(result.filter(x => x), themes3.staticVars).forEach(rule => {
|
|
|
|
|
styleSheet.insertRule(rule, 'index-max')
|
|
|
|
|
})
|
2024-02-26 21:37:40 +02:00
|
|
|
})
|
2024-02-27 22:02:44 +02:00
|
|
|
}, 200)
|
2024-02-15 20:20:27 +02:00
|
|
|
})
|
2024-02-26 21:37:40 +02:00
|
|
|
|
|
|
|
|
return Promise.resolve()
|
2017-11-17 17:24:42 +02:00
|
|
|
}
|
|
|
|
|
|
2023-03-17 23:30:46 +03:00
|
|
|
const configColumns = ({ sidebarColumnWidth, contentColumnWidth, notifsColumnWidth, emojiReactionsScale }) =>
|
|
|
|
|
({ sidebarColumnWidth, contentColumnWidth, notifsColumnWidth, emojiReactionsScale })
|
2022-06-05 17:10:44 +03:00
|
|
|
|
|
|
|
|
const defaultConfigColumns = configColumns(defaultState)
|
|
|
|
|
|
|
|
|
|
export const applyConfig = (config) => {
|
|
|
|
|
const columns = configColumns(config)
|
|
|
|
|
|
|
|
|
|
if (columns === defaultConfigColumns) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const head = document.head
|
|
|
|
|
const body = document.body
|
|
|
|
|
body.classList.add('hidden')
|
|
|
|
|
|
|
|
|
|
const rules = Object
|
|
|
|
|
.entries(columns)
|
|
|
|
|
.filter(([k, v]) => v)
|
|
|
|
|
.map(([k, v]) => `--${k}: ${v}`).join(';')
|
|
|
|
|
|
|
|
|
|
const styleEl = document.createElement('style')
|
|
|
|
|
head.appendChild(styleEl)
|
|
|
|
|
const styleSheet = styleEl.sheet
|
|
|
|
|
|
|
|
|
|
styleSheet.toString()
|
|
|
|
|
styleSheet.insertRule(`:root { ${rules} }`, 'index-max')
|
|
|
|
|
body.classList.remove('hidden')
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-12 04:00:41 +02:00
|
|
|
export const getThemes = () => {
|
2020-02-11 10:42:15 +02:00
|
|
|
const cache = 'no-store'
|
|
|
|
|
|
|
|
|
|
return window.fetch('/static/styles.json', { cache })
|
2017-11-17 17:24:42 +02:00
|
|
|
.then((data) => data.json())
|
|
|
|
|
.then((themes) => {
|
2020-01-17 00:27:46 +02:00
|
|
|
return Object.entries(themes).map(([k, v]) => {
|
|
|
|
|
let promise = null
|
2018-12-11 01:38:20 +03:00
|
|
|
if (typeof v === 'object') {
|
2020-01-17 00:27:46 +02:00
|
|
|
promise = Promise.resolve(v)
|
2018-12-11 01:38:20 +03:00
|
|
|
} else if (typeof v === 'string') {
|
2020-02-11 10:42:15 +02:00
|
|
|
promise = window.fetch(v, { cache })
|
2018-12-11 01:38:20 +03:00
|
|
|
.then((data) => data.json())
|
|
|
|
|
.catch((e) => {
|
|
|
|
|
console.error(e)
|
2020-01-17 00:27:46 +02:00
|
|
|
return null
|
2018-12-11 01:38:20 +03:00
|
|
|
})
|
|
|
|
|
}
|
2020-01-17 00:27:46 +02:00
|
|
|
return [k, promise]
|
|
|
|
|
})
|
2018-12-11 01:38:20 +03:00
|
|
|
})
|
|
|
|
|
.then((promises) => {
|
|
|
|
|
return promises
|
|
|
|
|
.reduce((acc, [k, v]) => {
|
|
|
|
|
acc[k] = v
|
|
|
|
|
return acc
|
|
|
|
|
}, {})
|
|
|
|
|
})
|
|
|
|
|
}
|
2020-01-20 01:31:54 +02:00
|
|
|
|
2020-01-22 00:37:19 +02:00
|
|
|
export const getPreset = (val) => {
|
2020-01-17 00:27:46 +02:00
|
|
|
return getThemes()
|
2020-01-20 00:34:49 +02:00
|
|
|
.then((themes) => themes[val] ? themes[val] : themes['pleroma-dark'])
|
2020-01-17 00:27:46 +02:00
|
|
|
.then((theme) => {
|
|
|
|
|
const isV1 = Array.isArray(theme)
|
2024-02-27 17:03:39 +02:00
|
|
|
const data = isV1 ? {} : theme.theme
|
2020-01-17 00:27:46 +02:00
|
|
|
|
|
|
|
|
if (isV1) {
|
|
|
|
|
const bg = hex2rgb(theme[1])
|
|
|
|
|
const fg = hex2rgb(theme[2])
|
|
|
|
|
const text = hex2rgb(theme[3])
|
|
|
|
|
const link = hex2rgb(theme[4])
|
|
|
|
|
|
|
|
|
|
const cRed = hex2rgb(theme[5] || '#FF0000')
|
|
|
|
|
const cGreen = hex2rgb(theme[6] || '#00FF00')
|
|
|
|
|
const cBlue = hex2rgb(theme[7] || '#0000FF')
|
|
|
|
|
const cOrange = hex2rgb(theme[8] || '#E3FF00')
|
|
|
|
|
|
|
|
|
|
data.colors = { bg, fg, text, link, cRed, cBlue, cGreen, cOrange }
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-22 01:10:24 +02:00
|
|
|
return { theme: data, source: theme.source }
|
2020-01-17 00:27:46 +02:00
|
|
|
})
|
2017-01-16 17:44:26 +01:00
|
|
|
}
|
2020-01-22 00:37:19 +02:00
|
|
|
|
2024-02-21 22:18:56 +02:00
|
|
|
export const setPreset = (val) => getPreset(val).then(data => applyTheme(data))
|