logo

pleroma-fe

My custom branche(s) on git.pleroma.social/pleroma/pleroma-fe git clone https://anongit.hacktivis.me/git/pleroma-fe.git/
commit: aa7a3361833f4c88ec685c4a92ff7727ed7249a7
parent 2b9968eacd6f45dc5ad39796f1b2f488e2a22cbb
Author: Henry Jameson <me@hjkos.com>
Date:   Thu, 12 Sep 2024 19:31:19 +0300

Updated shadow control to be able to handle "absolute null" situation

Diffstat:

Msrc/components/settings_modal/tabs/theme_tab/theme_tab.js14+++++++++++++-
Msrc/components/settings_modal/tabs/theme_tab/theme_tab.vue46++++------------------------------------------
Msrc/components/shadow_control/shadow_control.js122++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Msrc/components/shadow_control/shadow_control.scss17++++++++++++++++-
Msrc/components/shadow_control/shadow_control.vue103++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------
Msrc/i18n/en.json1+
Msrc/services/theme_data/theme_data.service.js2+-
7 files changed, 179 insertions(+), 126 deletions(-)

diff --git a/src/components/settings_modal/tabs/theme_tab/theme_tab.js b/src/components/settings_modal/tabs/theme_tab/theme_tab.js @@ -314,7 +314,18 @@ export default { }, set (val) { if (val) { - this.shadowsLocal[this.shadowSelected] = this.currentShadowFallback.map(_ => Object.assign({}, _)) + this.shadowsLocal[this.shadowSelected] = (this.currentShadowFallback || []) + .map(s => ({ + name: null, + x: 0, + y: 0, + blur: 0, + spread: 0, + inset: false, + color: '#000000', + alpha: 1, + ...s + })) } else { delete this.shadowsLocal[this.shadowSelected] } @@ -328,6 +339,7 @@ export default { return this.shadowsLocal[this.shadowSelected] }, set (v) { + console.log('TT', v) this.shadowsLocal[this.shadowSelected] = v } }, diff --git a/src/components/settings_modal/tabs/theme_tab/theme_tab.vue b/src/components/settings_modal/tabs/theme_tab/theme_tab.vue @@ -937,24 +937,14 @@ </Select> </div> <div class="override"> - <label - for="override" - class="label" - > - {{ $t('settings.style.shadows.override') }} - </label> - {{ ' ' }} - <input + <Checkbox id="override" v-model="currentShadowOverriden" name="override" class="input-override" - type="checkbox" > - <label - class="checkbox-label" - for="override" - /> + {{ $t('settings.style.shadows.override') }} + </Checkbox> </div> <button class="btn button-default" @@ -965,38 +955,10 @@ </div> <ShadowControl v-model="currentShadow" - :ready="!!currentShadowFallback" + :separate-inset="shadowSelected === 'avatar' || shadowSelected === 'avatarStatus'" :fallback="currentShadowFallback" /> - <div v-if="shadowSelected === 'avatar' || shadowSelected === 'avatarStatus'"> - <i18n-t - scope="global" - keypath="settings.style.shadows.filter_hint.always_drop_shadow" - tag="p" - > - <code>filter: drop-shadow()</code> - </i18n-t> - <p>{{ $t('settings.style.shadows.filter_hint.avatar_inset') }}</p> - <i18n-t - scope="global" - keypath="settings.style.shadows.filter_hint.drop_shadow_syntax" - tag="p" - > - <code>drop-shadow</code> - <code>spread-radius</code> - <code>inset</code> - </i18n-t> - <i18n-t - scope="global" - keypath="settings.style.shadows.filter_hint.inset_classic" - tag="p" - > - <code>box-shadow</code> - </i18n-t> - <p>{{ $t('settings.style.shadows.filter_hint.spread_zero') }}</p> - </div> </div> - <div :label="$t('settings.style.fonts._tab_label')" class="fonts-container" diff --git a/src/components/shadow_control/shadow_control.js b/src/components/shadow_control/shadow_control.js @@ -1,8 +1,9 @@ -import ColorInput from '../color_input/color_input.vue' -import OpacityInput from '../opacity_input/opacity_input.vue' -import Select from '../select/select.vue' -import Checkbox from '../checkbox/checkbox.vue' -import { getCssShadow } from '../../services/theme_data/theme_data.service.js' +import ColorInput from 'src/components/color_input/color_input.vue' +import OpacityInput from 'src/components/opacity_input/opacity_input.vue' +import Select from 'src/components/select/select.vue' +import Checkbox from 'src/components/checkbox/checkbox.vue' +import Popover from 'src/components/popover/popover.vue' +import { getCssShadow, getCssShadowFilter } from '../../services/theme_data/theme_data.service.js' import { hex2rgb } from '../../services/color_convert/color_convert.js' import { library } from '@fortawesome/fontawesome-svg-core' import { @@ -31,12 +32,8 @@ const toModel = (object = {}) => ({ }) export default { - // 'modelValue' and 'Fallback' can be undefined, but if they are - // initially vue won't detect it when they become something else - // therefore i'm using "ready" which should be passed as true when - // data becomes available props: [ - 'modelValue', 'fallback', 'ready' + 'modelValue', 'fallback', 'separateInset' ], emits: ['update:modelValue'], data () { @@ -51,75 +48,86 @@ export default { ColorInput, OpacityInput, Select, - Checkbox - }, - methods: { - add () { - this.cValue.push(toModel(this.selected)) - this.selectedId = this.cValue.length - 1 - }, - del () { - this.cValue.splice(this.selectedId, 1) - this.selectedId = this.cValue.length === 0 ? undefined : Math.max(this.selectedId - 1, 0) - }, - moveUp () { - const movable = this.cValue.splice(this.selectedId, 1)[0] - this.cValue.splice(this.selectedId - 1, 0, movable) - this.selectedId -= 1 - }, - moveDn () { - const movable = this.cValue.splice(this.selectedId, 1)[0] - this.cValue.splice(this.selectedId + 1, 0, movable) - this.selectedId += 1 - } + Checkbox, + Popover }, beforeUpdate () { - this.cValue = this.modelValue || this.fallback + this.cValue = (this.modelValue || this.fallback || []).map(toModel) }, computed: { + selected () { + const selected = this.cValue[this.selectedId] + if (selected) { + return { ...selected } + } + return null + }, + present () { + return this.selected != null && !this.usingFallback + }, + shadowsAreNull () { + return this.modelValue == null + }, anyShadows () { return this.cValue.length > 0 }, anyShadowsFallback () { return this.fallback.length > 0 }, - selected () { - if (this.ready && this.anyShadows) { - return this.cValue[this.selectedId] - } else { - return toModel({}) - } - }, currentFallback () { - if (this.ready && this.anyShadowsFallback) { - return this.fallback[this.selectedId] - } else { - return toModel({}) - } + return this.fallback?.[this.selectedId] }, moveUpValid () { - return this.ready && this.selectedId > 0 + return this.selectedId > 0 }, moveDnValid () { - return this.ready && this.selectedId < this.cValue.length - 1 - }, - present () { - return this.ready && - typeof this.cValue[this.selectedId] !== 'undefined' && - !this.usingFallback + return this.selectedId < this.cValue.length - 1 }, usingFallback () { - return typeof this.modelValue === 'undefined' + return this.modelValue == null }, rgb () { return hex2rgb(this.selected.color) }, style () { - return this.ready - ? { - boxShadow: getCssShadow(this.fallback) - } - : {} + if (!this.ready) return {} + if (this.separateInset) { + return { + filter: getCssShadowFilter(this.fallback), + boxShadow: getCssShadow(this.fallback, true) + } + } + return { + boxShadow: getCssShadow(this.fallback) + } + } + }, + methods: { + updateProperty (prop, value) { + this.cValue[this.selectedId][prop] = value + this.$emit('update:modelValue', this.cValue) + }, + add () { + this.cValue.push(toModel(this.selected)) + this.selectedId = Math.max(this.cValue.length - 1, 0) + this.$emit('update:modelValue', this.cValue) + }, + del () { + this.cValue.splice(this.selectedId, 1) + this.selectedId = this.cValue.length === 0 ? undefined : Math.max(this.selectedId - 1, 0) + this.$emit('update:modelValue', this.cValue) + }, + moveUp () { + const movable = this.cValue.splice(this.selectedId, 1)[0] + this.cValue.splice(this.selectedId - 1, 0, movable) + this.selectedId -= 1 + this.$emit('update:modelValue', this.cValue) + }, + moveDn () { + const movable = this.cValue.splice(this.selectedId, 1)[0] + this.cValue.splice(this.selectedId + 1, 0, movable) + this.selectedId += 1 + this.$emit('update:modelValue', this.cValue) } } } diff --git a/src/components/shadow_control/shadow_control.scss b/src/components/shadow_control/shadow_control.scss @@ -69,6 +69,16 @@ } } + .inset-alert { + padding: 0.25em 0.5em; + } + + &.disabled { + .inset-alert { + opacity: 0.2; + } + } + .shadow-preview { order: 2; flex: 3 3 15em; @@ -94,7 +104,7 @@ .input-light-grid { grid-area: options; - justify-self: end; + justify-self: center; } .input-number { @@ -176,3 +186,8 @@ } } } + +.inset-tooltip { + padding: 0.5em; + max-width: 30em; +} diff --git a/src/components/shadow_control/shadow_control.vue b/src/components/shadow_control/shadow_control.vue @@ -11,20 +11,22 @@ {{ $t('settings.style.shadows.offset') }} </label> <input - v-model="selected.y" + :value="selected?.y" :disabled="!present" :class="{ disabled: !present }" class="input input-number y-shift-number" type="number" + @input="e => updateProperty('y', e.target.value)" > <input - v-model="selected.y" + :value="selected?.y" :disabled="!present" :class="{ disabled: !present }" class="input input-range y-shift-slider" type="range" max="20" min="-20" + @input="e => updateProperty('y', e.target.value)" > <div class="preview-window" @@ -36,20 +38,22 @@ /> </div> <input - v-model="selected.x" + :value="selected?.x" :disabled="!present" :class="{ disabled: !present }" class="input input-number x-shift-number" type="number" + @input="e => updateProperty('x', e.target.value)" > <input - v-model="selected.x" + :value="selected?.x" :disabled="!present" :class="{ disabled: !present }" class="input input-range x-shift-slider" type="range" max="20" min="-20" + @input="e => updateProperty('x', e.target.value)" > <Checkbox id="inset" @@ -67,7 +71,7 @@ v-model="selectedId" class="shadow-list" size="10" - :disabled="!ready || usingFallback" + :disabled="shadowsAreNull" > <option v-for="(shadow, index) in cValue" @@ -75,28 +79,26 @@ :value="index" :class="{ '-active': index === Number(selectedId) }" > - {{ shadow.name ?? $t('settings.style.shadows.shadow_id', { value: index }) }} + {{ shadow?.name ?? $t('settings.style.shadows.shadow_id', { value: index }) }} </option> </Select> <div - :disabled="usingFallback" class="id-control arrange-buttons" > <button class="btn button-default" - :disabled="!ready || !present" - :class="{ disabled: !present }" - @click="del" + :disabled="shadowsAreNull" + @click="add" > <FAIcon fixed-width - icon="times" + icon="plus" /> </button> <button class="btn button-default" :disabled="!moveUpValid" - :class="{ disabled: !present }" + :class="{ disabled: !moveUpValid }" @click="moveUp" > <FAIcon @@ -107,6 +109,7 @@ <button class="btn button-default" :disabled="!moveDnValid" + :class="{ disabled: !moveDnValid }" @click="moveDn" > <FAIcon @@ -116,12 +119,13 @@ </button> <button class="btn button-default" - :disabled="usingFallback || !present" - @click="add" + :disabled="!present" + :class="{ disabled: !present }" + @click="del" > <FAIcon fixed-width - icon="plus" + icon="times" /> </button> </div> @@ -141,11 +145,12 @@ </label> <input id="name" - v-model="selected.name" + :value="selected?.name" :disabled="!present" :class="{ disabled: !present }" name="name" class="input input-string" + @input="e => updateProperty('name', e.target.value)" > </div> <div @@ -154,10 +159,11 @@ > <Checkbox id="inset" - v-model="selected.inset" + :value="selected?.inset" :disabled="!present" name="inset" class="input-inset input-boolean" + @input="e => updateProperty('inset', e.target.value)" > <template #before> {{ $t('settings.style.shadows.inset') }} @@ -178,7 +184,7 @@ </label> <input id="blur" - v-model="selected.blur" + :value="selected?.blur" :disabled="!present" :class="{ disabled: !present }" name="blur" @@ -186,14 +192,16 @@ type="range" max="20" min="0" + @input="e => updateProperty('blur', e.target.value)" > <input - v-model="selected.blur" + :value="selected?.blur" :disabled="!present" :class="{ disabled: !present }" class="input input-number" type="number" min="0" + @input="e => updateProperty('blur', e.target.value)" > </div> <div @@ -210,7 +218,7 @@ </label> <input id="spread" - v-model="selected.spread" + :value="selected?.spread" :disabled="!present" :class="{ disabled: !present }" name="spread" @@ -218,26 +226,30 @@ type="range" max="20" min="-20" + @input="e => updateProperty('spread', e.target.value)" > <input - v-model="selected.spread" + :value="selected?.spread" :disabled="!present" :class="{ disabled: !present }" class="input input-number" type="number" + @input="e => updateProperty('spread', e.target.value)" > </div> <ColorInput - v-model="selected.color" + :modelValue="selected?.color" :disabled="!present" :label="$t('settings.style.common.color')" - :fallback="currentFallback.color" + :fallback="currentFallback?.color" :show-optional-tickbox="false" name="shadow" + @update:modelValue="e => updateProperty('color', e.target.value)" /> <OpacityInput - v-model="selected.alpha" + :modelValue="selected?.alpha" :disabled="!present" + @update:modelValue="e => updateProperty('alpha', e.target.value)" /> <i18n-t scope="global" @@ -247,6 +259,49 @@ > <code>--variable,mod</code> </i18n-t> + <Popover + trigger="hover" + v-if="separateInset" + > + <template #trigger> + <div + class="inset-alert alert warning" + > + <FAIcon icon="exclamation-triangle" /> + &nbsp; + {{ $t('settings.style.shadows.filter_hint.avatar_inset_short') }} + </div> + </template> + <template #content> + <div class="inset-tooltip"> + <i18n-t + scope="global" + keypath="settings.style.shadows.filter_hint.always_drop_shadow" + tag="p" + > + <code>filter: drop-shadow()</code> + </i18n-t> + <p>{{ $t('settings.style.shadows.filter_hint.avatar_inset') }}</p> + <i18n-t + scope="global" + keypath="settings.style.shadows.filter_hint.drop_shadow_syntax" + tag="p" + > + <code>drop-shadow</code> + <code>spread-radius</code> + <code>inset</code> + </i18n-t> + <i18n-t + scope="global" + keypath="settings.style.shadows.filter_hint.inset_classic" + tag="p" + > + <code>box-shadow</code> + </i18n-t> + <p>{{ $t('settings.style.shadows.filter_hint.spread_zero') }}</p> + </div> + </template> + </Popover> </div> </div> </template> diff --git a/src/i18n/en.json b/src/i18n/en.json @@ -880,6 +880,7 @@ "filter_hint": { "always_drop_shadow": "Warning, this shadow always uses {0} when browser supports it.", "drop_shadow_syntax": "{0} does not support {1} parameter and {2} keyword.", + "avatar_inset_short": "Separate inset shadow", "avatar_inset": "Please note that combining both inset and non-inset shadows on avatars might give unexpected results with transparent avatars.", "spread_zero": "Shadows with spread > 0 will appear as if it was set to zero", "inset_classic": "Inset shadows will be using {0}" diff --git a/src/services/theme_data/theme_data.service.js b/src/services/theme_data/theme_data.service.js @@ -452,7 +452,7 @@ export const getCssShadow = (input, usesDropShadow) => { ]).join(' ')).join(', ') } -const getCssShadowFilter = (input) => { +export const getCssShadowFilter = (input) => { if (input.length === 0) { return 'none' }