diff --git a/src/components/shadow_control/shadow_control.js b/src/components/shadow_control/shadow_control.js index 44e4a22f..653d5a9b 100644 --- a/src/components/shadow_control/shadow_control.js +++ b/src/components/shadow_control/shadow_control.js @@ -61,6 +61,21 @@ export default { } } }, + currentFallback () { + if (this.ready && this.fallback.length > 0) { + return this.fallback[this.selectedId] + } else { + return { + x: 0, + y: 0, + blur: 0, + spread: 0, + inset: false, + color: '#000000', + alpha: 1 + } + } + }, moveUpValid () { return this.ready && this.selectedId > 0 }, diff --git a/src/components/shadow_control/shadow_control.vue b/src/components/shadow_control/shadow_control.vue index de8a42d1..efbb980e 100644 --- a/src/components/shadow_control/shadow_control.vue +++ b/src/components/shadow_control/shadow_control.vue @@ -191,6 +191,8 @@ v-model="selected.color" :disabled="!present" :label="$t('settings.style.common.color')" + :fallback="currentFallback.color" + :showOptionalTickbox="false" name="shadow" /> ({ ...acc, [ key + 'ColorLocal' ]: val }), {}), ...Object.keys(OPACITIES) - .map(key => console.log(key) || [key, '']) + .map(key => [key, '']) .reduce((acc, [key, val]) => ({ ...acc, [ key + 'OpacityLocal' ]: val }), {}), shadowSelected: undefined, @@ -134,7 +135,7 @@ export default { }, currentOpacity () { return Object.keys(OPACITIES) - .map(key => console.log(key) || [key, this[key + 'OpacityLocal']]) + .map(key => [key, this[key + 'OpacityLocal']]) .reduce((acc, [key, val]) => ({ ...acc, [ key ]: val }), {}) }, currentRadii () { @@ -224,7 +225,7 @@ export default { ].join(';') }, shadowsAvailable () { - return Object.keys(this.previewTheme.shadows).sort() + return Object.keys(DEFAULT_SHADOWS).sort() }, currentShadowOverriden: { get () { @@ -239,7 +240,7 @@ export default { } }, currentShadowFallback () { - return this.previewTheme.shadows[this.shadowSelected] + return (this.previewTheme.shadows || {})[this.shadowSelected] }, currentShadow: { get () { @@ -314,6 +315,17 @@ export default { } }) }, + updatePreviewColorsAndShadows () { + this.previewColors = generateColors({ + opacity: this.currentOpacity, + colors: this.currentColors + }) + this.previewShadows = generateShadows( + { shadows: this.shadowsLocal }, + this.previewColors.theme.colors, + this.previewColors.mod + ) + }, onImport (parsed) { if (parsed._pleroma_theme_version === 1) { this.normalizeLocalState(parsed, 1) @@ -435,6 +447,14 @@ export default { }) } + if (opacity && !this.keepOpacity) { + this.clearOpacity() + Object.entries(opacity).forEach(([k, v]) => { + if (typeof v === 'undefined' || v === null || Number.isNaN(v)) return + this[k + 'OpacityLocal'] = v + }) + } + if (!this.keepRoundness) { this.clearRoundness() Object.entries(radii).forEach(([k, v]) => { @@ -454,14 +474,6 @@ export default { this.clearFonts() this.fontsLocal = fonts } - - if (opacity && !this.keepOpacity) { - this.clearOpacity() - Object.entries(opacity).forEach(([k, v]) => { - if (typeof v === 'undefined' || v === null || Number.isNaN(v)) return - this[k + 'OpacityLocal'] = v - }) - } } }, watch: { @@ -476,8 +488,9 @@ export default { }, shadowsLocal: { handler () { + if (Object.getOwnPropertyNames(this.previewColors).length === 1) return try { - this.previewShadows = generateShadows({ shadows: this.shadowsLocal }) + this.updatePreviewColorsAndShadows() this.shadowsInvalid = false } catch (e) { this.shadowsInvalid = true @@ -500,10 +513,7 @@ export default { }, currentColors () { try { - this.previewColors = generateColors({ - opacity: this.currentOpacity, - colors: this.currentColors - }) + this.updatePreviewColorsAndShadows() this.colorsInvalid = false } catch (e) { this.colorsInvalid = true @@ -512,10 +522,7 @@ export default { }, currentOpacity () { try { - this.previewColors = generateColors({ - opacity: this.currentOpacity, - colors: this.currentColors - }) + this.updatePreviewColorsAndShadows() } catch (e) { console.warn(e) } diff --git a/src/components/style_switcher/style_switcher.vue b/src/components/style_switcher/style_switcher.vue index c8c02b8d..287d31b7 100644 --- a/src/components/style_switcher/style_switcher.vue +++ b/src/components/style_switcher/style_switcher.vue @@ -691,7 +691,7 @@ {{ $t('settings.style.switcher.clear_all') }} - { theme: { colors: htmlColors.solid, opacity - } + }, + mod } } @@ -211,83 +212,99 @@ export const generateFonts = (input) => { } } -export const generateShadows = (input) => { - const border = (top, shadow) => ({ - x: 0, - y: top ? 1 : -1, - blur: 0, +const border = (top, shadow) => ({ + x: 0, + y: top ? 1 : -1, + blur: 0, + spread: 0, + color: shadow ? '#000000' : '#FFFFFF', + alpha: 0.2, + inset: true +}) +const buttonInsetFakeBorders = [border(true, false), border(false, true)] +const inputInsetFakeBorders = [border(true, true), border(false, false)] +const hoverGlow = { + x: 0, + y: 0, + blur: 4, + spread: 0, + color: '--faint', + alpha: 1 +} + +export const DEFAULT_SHADOWS = { + panel: [{ + x: 1, + y: 1, + blur: 4, spread: 0, - color: shadow ? '#000000' : '#FFFFFF', - alpha: 0.2, - inset: true - }) - const buttonInsetFakeBorders = [border(true, false), border(false, true)] - const inputInsetFakeBorders = [border(true, true), border(false, false)] - const hoverGlow = { + color: '#000000', + alpha: 0.6 + }], + topBar: [{ x: 0, y: 0, blur: 4, spread: 0, - color: '--faint', + color: '#000000', + alpha: 0.6 + }], + popup: [{ + x: 2, + y: 2, + blur: 3, + spread: 0, + color: '#000000', + alpha: 0.5 + }], + avatar: [{ + x: 0, + y: 1, + blur: 8, + spread: 0, + color: '#000000', + alpha: 0.7 + }], + avatarStatus: [], + panelHeader: [], + button: [{ + x: 0, + y: 0, + blur: 2, + spread: 0, + color: '#000000', alpha: 1 - } - - const shadows = { - panel: [{ - x: 1, - y: 1, - blur: 4, - spread: 0, - color: '#000000', - alpha: 0.6 - }], - topBar: [{ - x: 0, - y: 0, - blur: 4, - spread: 0, - color: '#000000', - alpha: 0.6 - }], - popup: [{ - x: 2, - y: 2, - blur: 3, - spread: 0, - color: '#000000', - alpha: 0.5 - }], - avatar: [{ - x: 0, - y: 1, - blur: 8, - spread: 0, - color: '#000000', - alpha: 0.7 - }], - avatarStatus: [], - panelHeader: [], - button: [{ - x: 0, - y: 0, - blur: 2, - spread: 0, - color: '#000000', - alpha: 1 - }, ...buttonInsetFakeBorders], - buttonHover: [hoverGlow, ...buttonInsetFakeBorders], - buttonPressed: [hoverGlow, ...inputInsetFakeBorders], - input: [...inputInsetFakeBorders, { - x: 0, - y: 0, - blur: 2, - inset: true, - spread: 0, - color: '#000000', - alpha: 1 - }], + }, ...buttonInsetFakeBorders], + buttonHover: [hoverGlow, ...buttonInsetFakeBorders], + buttonPressed: [hoverGlow, ...inputInsetFakeBorders], + input: [...inputInsetFakeBorders, { + x: 0, + y: 0, + blur: 2, + inset: true, + spread: 0, + color: '#000000', + alpha: 1 + }] +} +export const generateShadows = (input, colors, mod) => { + const shadows = Object.entries({ + ...DEFAULT_SHADOWS, ...(input.shadows || {}) - } + }).reduce((shadowsAcc, [slotName, shadowdefs]) => { + const newShadow = shadowdefs.reduce((shadowAcc, def) => [ + ...shadowAcc, + { + ...def, + color: rgb2hex(computeDynamicColor( + def.color, + (variableSlot) => convert(colors[variableSlot]).rgb, + mod + )) + } + ], []) + return { ...shadowsAcc, [slotName]: newShadow } + }, {}) return { rules: { @@ -325,12 +342,15 @@ export const composePreset = (colors, radii, shadows, fonts) => { } } -export const generatePreset = (input) => composePreset( - generateColors(input), - generateRadii(input), - generateShadows(input), - generateFonts(input) -) +export const generatePreset = (input) => { + const colors = generateColors(input) + return composePreset( + colors, + generateRadii(input), + generateShadows(input, colors.theme.colors, colors.mod), + generateFonts(input) + ) +} export const getThemes = () => { return window.fetch('/static/styles.json') @@ -362,7 +382,7 @@ export const getThemes = () => { export const setPreset = (val, commit) => { return getThemes() - .then((themes) => console.log(themes) || themes[val] ? themes[val] : themes['pleroma-dark']) + .then((themes) => themes[val] ? themes[val] : themes['pleroma-dark']) .then((theme) => { const isV1 = Array.isArray(theme) const data = isV1 ? {} : theme.theme diff --git a/src/services/theme_data/theme_data.service.js b/src/services/theme_data/theme_data.service.js index 9f010fdf..e4456b29 100644 --- a/src/services/theme_data/theme_data.service.js +++ b/src/services/theme_data/theme_data.service.js @@ -697,6 +697,22 @@ export const OPACITIES = Object.entries(SLOT_INHERITANCE).reduce((acc, [k, v]) = } }, {}) +/** + * Handle dynamic color + */ +export const computeDynamicColor = (sourceColor, getColor, mod) => { + if (typeof sourceColor !== 'string' || !sourceColor.startsWith('--')) return sourceColor + let targetColor = null + // Color references other color + const [variable, modifier] = sourceColor.split(/,/g).map(str => str.trim()) + const variableSlot = variable.substring(2) + targetColor = getColor(variableSlot) + if (modifier) { + targetColor = brightness(Number.parseFloat(modifier) * mod, targetColor).rgb + } + return targetColor +} + /** * THE function you want to use. Takes provided colors and opacities, mod * value and uses inheritance data to figure out color needed for the slot. @@ -728,13 +744,11 @@ export const getColors = (sourceColors, sourceOpacity, mod) => SLOT_ORDERED.redu a: 0 } } else if (typeof sourceColor === 'string' && sourceColor.startsWith('--')) { - // Color references other color - const [variable, modifier] = sourceColor.split(/,/g).map(str => str.trim()) - const variableSlot = variable.substring(2) - targetColor = colors[variableSlot] || sourceColors[variableSlot] - if (modifier) { - targetColor = brightness(Number.parseFloat(modifier) * mod, targetColor).rgb - } + targetColor = computeDynamicColor( + sourceColor, + variableSlot => colors[variableSlot] || sourceColors[variableSlot], + mod + ) } else if (typeof sourceColor === 'string' && sourceColor.startsWith('#')) { targetColor = convert(targetColor).rgb }