Merge remote-tracking branch 'origin/develop' into fix-develop-issues
This commit is contained in:
commit
e8d7d341f0
49 changed files with 1755 additions and 724 deletions
|
|
@ -120,6 +120,7 @@ const EmojiPicker = {
|
|||
groupRefs: {},
|
||||
emojiRefs: {},
|
||||
filteredEmojiGroups: [],
|
||||
emojiSize: 0,
|
||||
width: 0
|
||||
}
|
||||
},
|
||||
|
|
@ -130,6 +131,23 @@ const EmojiPicker = {
|
|||
Popover
|
||||
},
|
||||
methods: {
|
||||
updateEmojiSize () {
|
||||
const css = window.getComputedStyle(this.$refs.popover.$el)
|
||||
const emojiSize = css.getPropertyValue('--emojiSize')
|
||||
const emojiSizeUnit = emojiSize.replace(/[0-9,.]+/, '')
|
||||
const emojiSizeValue = Number(emojiSize.replace(/[^0-9,.]+/, ''))
|
||||
const fontSize = css.getPropertyValue('font-size').replace(/[^0-9,.]+/, '')
|
||||
|
||||
let emojiSizeReal
|
||||
if (emojiSizeUnit.endsWith('em')) {
|
||||
emojiSizeReal = emojiSizeValue * fontSize
|
||||
} else {
|
||||
emojiSizeReal = emojiSizeValue
|
||||
}
|
||||
|
||||
const fullEmojiSize = emojiSizeReal + (2 * 0.2 * fontSize)
|
||||
this.emojiSize = fullEmojiSize
|
||||
},
|
||||
showPicker () {
|
||||
this.$refs.popover.showPopover()
|
||||
this.onShowing()
|
||||
|
|
@ -224,6 +242,7 @@ const EmojiPicker = {
|
|||
},
|
||||
onShowing () {
|
||||
const oldContentLoaded = this.contentLoaded
|
||||
this.updateEmojiSize()
|
||||
this.recalculateItemPerRow()
|
||||
this.$nextTick(() => {
|
||||
this.$refs.search.focus()
|
||||
|
|
@ -266,16 +285,20 @@ const EmojiPicker = {
|
|||
},
|
||||
computed: {
|
||||
minItemSize () {
|
||||
return this.emojiHeight
|
||||
return this.emojiSize
|
||||
},
|
||||
// used to watch it
|
||||
fontSize () {
|
||||
this.$nextTick(() => {
|
||||
this.updateEmojiSize()
|
||||
})
|
||||
return this.$store.getters.mergedConfig.fontSize
|
||||
},
|
||||
emojiHeight () {
|
||||
return 32 + 4
|
||||
},
|
||||
emojiWidth () {
|
||||
return 32 + 4
|
||||
return this.emojiSize
|
||||
},
|
||||
itemPerRow () {
|
||||
return this.width ? Math.floor(this.width / this.emojiWidth - 1) : 6
|
||||
return this.width ? Math.floor(this.width / this.emojiSize) : 6
|
||||
},
|
||||
activeGroupView () {
|
||||
return this.showingStickers ? '' : this.activeGroup
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
$emoji-picker-header-height: 36px;
|
||||
$emoji-picker-header-picture-width: 32px;
|
||||
$emoji-picker-header-picture-height: 32px;
|
||||
$emoji-picker-emoji-size: 32px;
|
||||
|
||||
.emoji-picker {
|
||||
--__emoji-picker-header: 2.2em;
|
||||
|
||||
width: 25em;
|
||||
max-width: calc(100vw - 20px); // popover gives 10px margin from window edge
|
||||
display: flex;
|
||||
|
|
@ -13,24 +10,26 @@ $emoji-picker-emoji-size: 32px;
|
|||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: $emoji-picker-header-picture-width;
|
||||
max-width: $emoji-picker-header-picture-width;
|
||||
height: $emoji-picker-header-picture-height;
|
||||
max-height: $emoji-picker-header-picture-height;
|
||||
width: var(--__emoji-picker-header);
|
||||
max-width: var(--__emoji-picker-header);
|
||||
height: var(--__emoji-picker-header);
|
||||
max-height: var(--__emoji-picker-header);
|
||||
|
||||
.still-image {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
width: var(--__emoji-picker-header);
|
||||
max-width: var(--__emoji-picker-header);
|
||||
height: var(--__emoji-picker-header);
|
||||
max-height: var(--__emoji-picker-header);
|
||||
object-fit: contain;
|
||||
|
||||
--_still_image-label-scale: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
.keep-open,
|
||||
.too-many-emoji,
|
||||
.hide-custom-emoji {
|
||||
padding: 7px;
|
||||
padding: 0.5em;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
|
|
@ -44,13 +43,13 @@ $emoji-picker-emoji-size: 32px;
|
|||
}
|
||||
|
||||
.keep-open-label {
|
||||
padding: 0 7px;
|
||||
padding: 0 0.5em;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.heading {
|
||||
display: flex;
|
||||
padding: 10px 7px 5px;
|
||||
padding: 0.7em 0.5em 0;
|
||||
}
|
||||
|
||||
.content {
|
||||
|
|
@ -65,13 +64,14 @@ $emoji-picker-emoji-size: 32px;
|
|||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
.additional-tabs {
|
||||
display: flex;
|
||||
border-left: 1px solid;
|
||||
border-left-color: var(--border);
|
||||
padding-left: 7px;
|
||||
padding-left: 0.5em;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
|
|
@ -80,25 +80,29 @@ $emoji-picker-emoji-size: 32px;
|
|||
flex-basis: auto;
|
||||
display: flex;
|
||||
align-content: center;
|
||||
scrollbar-width: thin;
|
||||
|
||||
&-item {
|
||||
padding: 0 7px;
|
||||
padding: 0 0.5em;
|
||||
cursor: pointer;
|
||||
font-size: 1.85em;
|
||||
width: $emoji-picker-header-picture-width;
|
||||
max-width: $emoji-picker-header-picture-width;
|
||||
height: $emoji-picker-header-picture-height;
|
||||
max-height: $emoji-picker-header-picture-height;
|
||||
width: var(--__emoji-picker-header);
|
||||
max-width: var(--__emoji-picker-header);
|
||||
height: var(--__emoji-picker-header);
|
||||
max-height: var(--__emoji-picker-header);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.svg-inline--fa {
|
||||
font-size: 1.85em;
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
opacity: 0.5;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&.toggled {
|
||||
border-bottom: 4px solid;
|
||||
border-bottom: 0.2em solid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -125,7 +129,7 @@ $emoji-picker-emoji-size: 32px;
|
|||
|
||||
.emoji {
|
||||
&-search {
|
||||
padding: 5px;
|
||||
padding: 0.3em;
|
||||
flex: 0 0 auto;
|
||||
|
||||
input {
|
||||
|
|
@ -139,6 +143,7 @@ $emoji-picker-emoji-size: 32px;
|
|||
flex: 1 1 1px;
|
||||
position: relative;
|
||||
overflow: auto;
|
||||
scrollbar-gutter: stable both-edges;
|
||||
user-select: none;
|
||||
mask:
|
||||
linear-gradient(to top, white 0, transparent 100%) bottom no-repeat,
|
||||
|
|
@ -165,13 +170,13 @@ $emoji-picker-emoji-size: 32px;
|
|||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
padding-left: 5px;
|
||||
justify-content: left;
|
||||
|
||||
&-title {
|
||||
font-size: 0.85em;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding-left: 0.3em;
|
||||
|
||||
&.disabled {
|
||||
display: none;
|
||||
|
|
@ -180,24 +185,28 @@ $emoji-picker-emoji-size: 32px;
|
|||
}
|
||||
|
||||
&-item {
|
||||
width: $emoji-picker-emoji-size;
|
||||
height: $emoji-picker-emoji-size;
|
||||
width: var(--emoji-size);
|
||||
height: var(--emoji-size);
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
line-height: $emoji-picker-emoji-size;
|
||||
line-height: var(--emoji-size);
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 4px;
|
||||
margin: 0.2em;
|
||||
cursor: pointer;
|
||||
|
||||
.emoji-picker-emoji.-custom {
|
||||
object-fit: contain;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
width: var(--emoji-size);
|
||||
max-width: var(--emoji-size);
|
||||
height: var(--emoji-size);
|
||||
max-height: var(--emoji-size);
|
||||
|
||||
--_still_image-label-scale: 0.5;
|
||||
}
|
||||
|
||||
.emoji-picker-emoji.-unicode {
|
||||
font-size: 24px;
|
||||
font-size: 1.6em;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@
|
|||
margin-top: 0.25em;
|
||||
flex-wrap: wrap;
|
||||
|
||||
--emoji-size: calc(1.25em * var(--emojiReactionsScale, 1));
|
||||
--emoji-size: calc(var(--emojiSize, 1.25em) * var(--emojiReactionsScale, 1));
|
||||
|
||||
.emoji-reaction-container {
|
||||
display: flex;
|
||||
|
|
|
|||
|
|
@ -1,63 +1,59 @@
|
|||
import { set } from 'lodash'
|
||||
import Select from '../select/select.vue'
|
||||
import Checkbox from 'src/components/checkbox/checkbox.vue'
|
||||
import Popover from 'src/components/popover/popover.vue'
|
||||
|
||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||
import {
|
||||
faExclamationTriangle,
|
||||
faKeyboard,
|
||||
faFont
|
||||
} from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
library.add(
|
||||
faExclamationTriangle,
|
||||
faKeyboard,
|
||||
faFont
|
||||
)
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Select
|
||||
Select,
|
||||
Checkbox,
|
||||
Popover
|
||||
},
|
||||
props: [
|
||||
'name', 'label', 'modelValue', 'fallback', 'options', 'no-inherit'
|
||||
],
|
||||
mounted () {
|
||||
this.$store.dispatch('queryLocalFonts')
|
||||
},
|
||||
emits: ['update:modelValue'],
|
||||
data () {
|
||||
return {
|
||||
lValue: this.modelValue,
|
||||
manualEntry: false,
|
||||
availableOptions: [
|
||||
this.noInherit ? '' : 'inherit',
|
||||
'custom',
|
||||
...(this.options || []),
|
||||
'serif',
|
||||
'sans-serif',
|
||||
'monospace',
|
||||
'sans-serif'
|
||||
...(this.options || [])
|
||||
].filter(_ => _)
|
||||
}
|
||||
},
|
||||
beforeUpdate () {
|
||||
this.lValue = this.modelValue
|
||||
methods: {
|
||||
toggleManualEntry () {
|
||||
this.manualEntry = !this.manualEntry
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
present () {
|
||||
return typeof this.lValue !== 'undefined'
|
||||
return typeof this.modelValue !== 'undefined'
|
||||
},
|
||||
dValue () {
|
||||
return this.lValue || this.fallback || {}
|
||||
localFontsList () {
|
||||
return this.$store.state.interface.localFonts
|
||||
},
|
||||
family: {
|
||||
get () {
|
||||
return this.dValue.family
|
||||
},
|
||||
set (v) {
|
||||
set(this.lValue, 'family', v)
|
||||
this.$emit('update:modelValue', this.lValue)
|
||||
}
|
||||
},
|
||||
isCustom () {
|
||||
return this.preset === 'custom'
|
||||
},
|
||||
preset: {
|
||||
get () {
|
||||
if (this.family === 'serif' ||
|
||||
this.family === 'sans-serif' ||
|
||||
this.family === 'monospace' ||
|
||||
this.family === 'inherit') {
|
||||
return this.family
|
||||
} else {
|
||||
return 'custom'
|
||||
}
|
||||
},
|
||||
set (v) {
|
||||
this.family = v === 'custom' ? '' : v
|
||||
}
|
||||
localFontsSize () {
|
||||
return this.$store.state.interface.localFonts?.length
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div
|
||||
class="font-control style-control"
|
||||
class="font-control"
|
||||
:class="{ custom: isCustom }"
|
||||
>
|
||||
<label
|
||||
|
|
@ -10,43 +10,121 @@
|
|||
>
|
||||
{{ label }}
|
||||
</label>
|
||||
<input
|
||||
{{ ' ' }}
|
||||
<Checkbox
|
||||
v-if="typeof fallback !== 'undefined'"
|
||||
:id="name + '-o'"
|
||||
:aria-labelledby="name + '-label'"
|
||||
class="input -checkbox opt exlcude-disabled visible-for-screenreader-only"
|
||||
type="checkbox"
|
||||
:checked="present"
|
||||
:modelValue="present"
|
||||
@change="$emit('update:modelValue', typeof modelValue === 'undefined' ? fallback : undefined)"
|
||||
>
|
||||
<label
|
||||
v-if="typeof fallback !== 'undefined'"
|
||||
class="opt-l"
|
||||
:for="name + '-o'"
|
||||
:aria-hidden="true"
|
||||
/>
|
||||
{{ ' ' }}
|
||||
<Select
|
||||
:id="name + '-font-switcher'"
|
||||
v-model="preset"
|
||||
:disabled="!present"
|
||||
class="font-switcher"
|
||||
>
|
||||
<option
|
||||
v-for="option in availableOptions"
|
||||
:key="option"
|
||||
:value="option"
|
||||
{{ $t('settings.style.themes3.define') }}
|
||||
</Checkbox>
|
||||
<p v-if="modelValue?.family">
|
||||
<label
|
||||
v-if="manualEntry"
|
||||
:id="name + '-label'"
|
||||
:for="preset === 'custom' ? name : name + '-font-switcher'"
|
||||
class="label"
|
||||
>
|
||||
{{ option === 'custom' ? $t('settings.style.fonts.custom') : option }}
|
||||
</option>
|
||||
</Select>
|
||||
<input
|
||||
v-if="isCustom"
|
||||
:id="name"
|
||||
v-model="family"
|
||||
class="input custom-font"
|
||||
type="text"
|
||||
>
|
||||
<i18n-t
|
||||
keypath="settings.style.themes3.font.entry"
|
||||
tag="span"
|
||||
>
|
||||
<template #fontFamily>
|
||||
<code>font-family</code>
|
||||
</template>
|
||||
</i18n-t>
|
||||
</label>
|
||||
<label
|
||||
v-else
|
||||
:id="name + '-label'"
|
||||
:for="preset === 'custom' ? name : name + '-font-switcher'"
|
||||
class="label"
|
||||
>
|
||||
{{ $t('settings.style.themes3.font.select') }}
|
||||
</label>
|
||||
{{ ' ' }}
|
||||
<span
|
||||
v-if="manualEntry"
|
||||
class="btn-group"
|
||||
>
|
||||
<button
|
||||
class="btn button-default"
|
||||
@click="toggleManualEntry"
|
||||
:title="$t('settings.style.themes3.font.lookup_local_fonts')"
|
||||
>
|
||||
<FAIcon
|
||||
fixed-width
|
||||
icon="font"
|
||||
/>
|
||||
</button>
|
||||
<input
|
||||
:id="name"
|
||||
:model-value="modelValue.family"
|
||||
class="input custom-font"
|
||||
type="text"
|
||||
@update:modelValue="$emit('update:modelValue', { ...(modelValue || {}), family: $event.target.value })"
|
||||
>
|
||||
</span>
|
||||
<span
|
||||
v-else
|
||||
class="btn-group"
|
||||
>
|
||||
<button
|
||||
class="btn button-default"
|
||||
@click="toggleManualEntry"
|
||||
:title="$t('settings.style.themes3.font.enter_manually')"
|
||||
>
|
||||
<FAIcon
|
||||
fixed-width
|
||||
icon="keyboard"
|
||||
/>
|
||||
</button>
|
||||
<Select
|
||||
:id="name + '-local-font-switcher'"
|
||||
:model-value="modelValue?.family"
|
||||
class="custom-font"
|
||||
@update:modelValue="v => $emit('update:modelValue', { ...(modelValue || {}), family: v })"
|
||||
>
|
||||
<optgroup
|
||||
:label="$t('settings.style.themes3.font.group-builtin')"
|
||||
>
|
||||
<option
|
||||
v-for="option in availableOptions"
|
||||
:key="option"
|
||||
:value="option"
|
||||
:style="{ fontFamily: option === 'inherit' ? null : option }"
|
||||
>
|
||||
{{ $t('settings.style.themes3.font.builtin.' + option) }}
|
||||
</option>
|
||||
</optgroup>
|
||||
<optgroup
|
||||
v-if="localFontsSize > 0"
|
||||
:label="$t('settings.style.themes3.font.group-local')"
|
||||
>
|
||||
<option
|
||||
v-for="option in localFontsList"
|
||||
:key="option"
|
||||
:value="option"
|
||||
:style="{ fontFamily: option }"
|
||||
>
|
||||
{{ option }}
|
||||
</option>
|
||||
</optgroup>
|
||||
<optgroup
|
||||
v-else
|
||||
:label="$t('settings.style.themes3.font.group-local')"
|
||||
>
|
||||
<option disabled>
|
||||
{{ $t('settings.style.themes3.font.local-unavailable1') }}
|
||||
</option>
|
||||
<option disabled>
|
||||
{{ $t('settings.style.themes3.font.local-unavailable2') }}
|
||||
</option>
|
||||
</optgroup>
|
||||
</Select>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -54,21 +132,15 @@
|
|||
|
||||
<style lang="scss">
|
||||
.font-control {
|
||||
input.custom-font {
|
||||
min-width: 10em;
|
||||
}
|
||||
|
||||
&.custom {
|
||||
/* TODO Should make proper joiners... */
|
||||
.font-switcher {
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
.custom-font {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
.custom-font {
|
||||
min-width: 20em;
|
||||
max-width: 20em;
|
||||
}
|
||||
}
|
||||
|
||||
.invalid-tooltip {
|
||||
margin: 0.5em 1em;
|
||||
min-width: 10em;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@
|
|||
.mobile-nav {
|
||||
display: grid;
|
||||
line-height: var(--navbar-height);
|
||||
grid-template-rows: 50px;
|
||||
grid-template-rows: var(--navbar-height);
|
||||
grid-template-columns: 2fr auto;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
|
|
@ -190,8 +190,8 @@
|
|||
justify-content: space-between;
|
||||
z-index: calc(var(--ZI_navbar) + 100);
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
height: 3.5em;
|
||||
line-height: 3.5em;
|
||||
position: absolute;
|
||||
box-shadow: var(--shadow);
|
||||
|
||||
|
|
@ -214,7 +214,7 @@
|
|||
}
|
||||
|
||||
.mobile-notifications {
|
||||
margin-top: 50px;
|
||||
margin-top: 3.5em;
|
||||
width: 100vw;
|
||||
height: calc(100vh - var(--navbar-height));
|
||||
overflow-x: hidden;
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@
|
|||
}
|
||||
|
||||
&.toggled {
|
||||
margin-bottom: -4px;
|
||||
border-bottom: 4px solid;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@ export default {
|
|||
'RichContent',
|
||||
'Input',
|
||||
'Avatar',
|
||||
'Attachment'
|
||||
'Attachment',
|
||||
'PollGraph'
|
||||
],
|
||||
defaultRules: []
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,16 @@ export default {
|
|||
'Tab',
|
||||
'ListItem'
|
||||
],
|
||||
validInnerComponentsLite: [
|
||||
'Text',
|
||||
'Link',
|
||||
'Icon',
|
||||
'Border',
|
||||
'Button',
|
||||
'Input',
|
||||
'PanelHeader',
|
||||
'Alert'
|
||||
],
|
||||
defaultRules: [
|
||||
{
|
||||
directives: {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,11 @@ export default {
|
|||
'Alert',
|
||||
'Button' // mobile post button
|
||||
],
|
||||
validInnerComponentsLite: [
|
||||
'Underlay',
|
||||
'Scrollbar',
|
||||
'ScrollbarElement'
|
||||
],
|
||||
defaultRules: [
|
||||
{
|
||||
directives: {
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
</template>
|
||||
<slot v-else />
|
||||
</label>
|
||||
{{ ' ' }}
|
||||
<input
|
||||
:id="path"
|
||||
class="input number-input"
|
||||
|
|
|
|||
|
|
@ -48,6 +48,10 @@ export default {
|
|||
draftMode: {
|
||||
type: Boolean,
|
||||
default: undefined
|
||||
},
|
||||
timedApplyMode: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
inject: {
|
||||
|
|
@ -161,7 +165,11 @@ export default {
|
|||
case 'admin':
|
||||
return (k, v) => this.$store.dispatch('pushAdminSetting', { path: k, value: v })
|
||||
default:
|
||||
return (k, v) => this.$store.dispatch('setOption', { name: k, value: v })
|
||||
if (this.timedApplyMode) {
|
||||
return (k, v) => this.$store.dispatch('setOptionTemporarily', { name: k, value: v })
|
||||
} else {
|
||||
return (k, v) => this.$store.dispatch('setOption', { name: k, value: v })
|
||||
}
|
||||
}
|
||||
},
|
||||
defaultState () {
|
||||
|
|
|
|||
|
|
@ -21,15 +21,23 @@ export default {
|
|||
unitSet: {
|
||||
type: String,
|
||||
default: 'none'
|
||||
},
|
||||
step: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
resetDefault: {
|
||||
type: Object,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...Setting.computed,
|
||||
stateUnit () {
|
||||
return this.state.replace(/\d+/, '')
|
||||
return typeof this.state === 'string' ? this.state.replace(/[0-9,.]+/, '') : ''
|
||||
},
|
||||
stateValue () {
|
||||
return this.state.replace(/\D+/, '')
|
||||
return typeof this.state === 'string' ? this.state.replace(/[^0-9,.]+/, '') : ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
@ -39,10 +47,18 @@ export default {
|
|||
return this.$t(['settings', 'units', this.unitSet, value].join('.'))
|
||||
},
|
||||
updateValue (e) {
|
||||
this.configSink(this.path, parseInt(e.target.value) + this.stateUnit)
|
||||
this.configSink(this.path, parseFloat(e.target.value) + this.stateUnit)
|
||||
},
|
||||
updateUnit (e) {
|
||||
this.configSink(this.path, this.stateValue + e.target.value)
|
||||
let value = this.stateValue
|
||||
const newUnit = e.target.value
|
||||
if (this.resetDefault) {
|
||||
const replaceValue = this.resetDefault[newUnit]
|
||||
if (replaceValue != null) {
|
||||
value = replaceValue
|
||||
}
|
||||
}
|
||||
this.configSink(this.path, value + newUnit)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,11 +9,12 @@
|
|||
>
|
||||
<slot />
|
||||
</label>
|
||||
{{ ' ' }}
|
||||
<input
|
||||
:id="path"
|
||||
class="input number-input"
|
||||
type="number"
|
||||
step="1"
|
||||
:step="step"
|
||||
:disabled="disabled"
|
||||
:min="min || 0"
|
||||
:value="stateValue"
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import AsyncComponentError from 'src/components/async_component_error/async_comp
|
|||
import getResettableAsyncComponent from 'src/services/resettable_async_component.js'
|
||||
import Popover from '../popover/popover.vue'
|
||||
import Checkbox from 'src/components/checkbox/checkbox.vue'
|
||||
import ConfirmModal from 'src/components/confirm_modal/confirm_modal.vue'
|
||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||
import { cloneDeep, isEqual } from 'lodash'
|
||||
import {
|
||||
|
|
@ -53,6 +54,7 @@ const SettingsModal = {
|
|||
Modal,
|
||||
Popover,
|
||||
Checkbox,
|
||||
ConfirmModal,
|
||||
SettingsModalUserContent: getResettableAsyncComponent(
|
||||
() => import('./settings_modal_user_content.vue'),
|
||||
{
|
||||
|
|
@ -165,6 +167,7 @@ const SettingsModal = {
|
|||
},
|
||||
computed: {
|
||||
currentSaveStateNotice () {
|
||||
console.log(this.$store.state.interface.settings.currentSaveStateNotice)
|
||||
return this.$store.state.interface.settings.currentSaveStateNotice
|
||||
},
|
||||
modalActivated () {
|
||||
|
|
|
|||
|
|
@ -147,6 +147,18 @@
|
|||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<teleport to="#modal">
|
||||
<ConfirmModal
|
||||
v-if="$store.state.interface.temporaryChangesTimeoutId"
|
||||
:title="$t('settings.confirm_new_setting')"
|
||||
:cancel-text="$t('settings.revert')"
|
||||
:confirm-text="$t('settings.confirm')"
|
||||
@cancelled="$store.state.interface.temporaryChangesRevert"
|
||||
@accepted="$store.state.interface.temporaryChangesConfirm"
|
||||
>
|
||||
{{ $t('settings.confirm_new_question') }}
|
||||
</ConfirmModal>
|
||||
</teleport>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import FilteringTab from './tabs/filtering_tab.vue'
|
|||
import SecurityTab from './tabs/security_tab/security_tab.vue'
|
||||
import ProfileTab from './tabs/profile_tab.vue'
|
||||
import GeneralTab from './tabs/general_tab.vue'
|
||||
import AppearanceTab from './tabs/appearance_tab.vue'
|
||||
import VersionTab from './tabs/version_tab.vue'
|
||||
import ThemeTab from './tabs/theme_tab/theme_tab.vue'
|
||||
|
||||
|
|
@ -19,7 +20,8 @@ import {
|
|||
faBell,
|
||||
faDownload,
|
||||
faEyeSlash,
|
||||
faInfo
|
||||
faInfo,
|
||||
faWindowRestore
|
||||
} from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
library.add(
|
||||
|
|
@ -30,7 +32,8 @@ library.add(
|
|||
faBell,
|
||||
faDownload,
|
||||
faEyeSlash,
|
||||
faInfo
|
||||
faInfo,
|
||||
faWindowRestore
|
||||
)
|
||||
|
||||
const SettingsModalContent = {
|
||||
|
|
@ -44,6 +47,7 @@ const SettingsModalContent = {
|
|||
SecurityTab,
|
||||
ProfileTab,
|
||||
GeneralTab,
|
||||
AppearanceTab,
|
||||
VersionTab,
|
||||
ThemeTab
|
||||
},
|
||||
|
|
|
|||
|
|
@ -13,6 +13,20 @@
|
|||
>
|
||||
<GeneralTab />
|
||||
</div>
|
||||
<div
|
||||
:label="$t('settings.appearance')"
|
||||
icon="window-restore"
|
||||
data-tab-name="appearance"
|
||||
>
|
||||
<AppearanceTab />
|
||||
</div>
|
||||
<div
|
||||
:label="$t('settings.theme')"
|
||||
icon="paint-brush"
|
||||
data-tab-name="theme"
|
||||
>
|
||||
<ThemeTab />
|
||||
</div>
|
||||
<div
|
||||
v-if="isLoggedIn"
|
||||
:label="$t('settings.profile_tab')"
|
||||
|
|
@ -21,6 +35,14 @@
|
|||
>
|
||||
<ProfileTab />
|
||||
</div>
|
||||
<div
|
||||
v-if="isLoggedIn"
|
||||
:label="$t('settings.notifications')"
|
||||
icon="bell"
|
||||
data-tab-name="notifications"
|
||||
>
|
||||
<NotificationsTab />
|
||||
</div>
|
||||
<div
|
||||
v-if="isLoggedIn"
|
||||
:label="$t('settings.security_tab')"
|
||||
|
|
@ -36,20 +58,14 @@
|
|||
>
|
||||
<FilteringTab />
|
||||
</div>
|
||||
<div
|
||||
:label="$t('settings.theme')"
|
||||
icon="paint-brush"
|
||||
data-tab-name="theme"
|
||||
>
|
||||
<ThemeTab />
|
||||
</div>
|
||||
<div
|
||||
v-if="isLoggedIn"
|
||||
:label="$t('settings.notifications')"
|
||||
icon="bell"
|
||||
data-tab-name="notifications"
|
||||
:label="$t('settings.mutes_and_blocks')"
|
||||
:fullHeight="true"
|
||||
icon="eye-slash"
|
||||
data-tab-name="mutesAndBlocks"
|
||||
>
|
||||
<NotificationsTab />
|
||||
<MutesAndBlocksTab />
|
||||
</div>
|
||||
<div
|
||||
v-if="isLoggedIn"
|
||||
|
|
@ -59,15 +75,6 @@
|
|||
>
|
||||
<DataImportExportTab />
|
||||
</div>
|
||||
<div
|
||||
v-if="isLoggedIn"
|
||||
:label="$t('settings.mutes_and_blocks')"
|
||||
:fullHeight="true"
|
||||
icon="eye-slash"
|
||||
data-tab-name="mutesAndBlocks"
|
||||
>
|
||||
<MutesAndBlocksTab />
|
||||
</div>
|
||||
<div
|
||||
:label="$t('settings.version.title')"
|
||||
icon="info"
|
||||
|
|
|
|||
195
src/components/settings_modal/tabs/appearance_tab.js
Normal file
195
src/components/settings_modal/tabs/appearance_tab.js
Normal file
|
|
@ -0,0 +1,195 @@
|
|||
import BooleanSetting from '../helpers/boolean_setting.vue'
|
||||
import ChoiceSetting from '../helpers/choice_setting.vue'
|
||||
import IntegerSetting from '../helpers/integer_setting.vue'
|
||||
import FloatSetting from '../helpers/float_setting.vue'
|
||||
import UnitSetting, { defaultHorizontalUnits } from '../helpers/unit_setting.vue'
|
||||
|
||||
import FontControl from 'src/components/font_control/font_control.vue'
|
||||
|
||||
import { normalizeThemeData } from 'src/modules/interface'
|
||||
|
||||
import {
|
||||
getThemes
|
||||
} from 'src/services/style_setter/style_setter.js'
|
||||
import { convertTheme2To3 } from 'src/services/theme_data/theme2_to_theme3.js'
|
||||
import { init } from 'src/services/theme_data/theme_data_3.service.js'
|
||||
import {
|
||||
getCssRules,
|
||||
getScopedVersion
|
||||
} from 'src/services/theme_data/css_utils.js'
|
||||
|
||||
import SharedComputedObject from '../helpers/shared_computed_object.js'
|
||||
import ProfileSettingIndicator from '../helpers/profile_setting_indicator.vue'
|
||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||
import {
|
||||
faGlobe
|
||||
} from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
import Preview from './theme_tab/preview.vue'
|
||||
|
||||
library.add(
|
||||
faGlobe
|
||||
)
|
||||
|
||||
const AppearanceTab = {
|
||||
data () {
|
||||
return {
|
||||
availableStyles: [],
|
||||
intersectionObserver: null,
|
||||
thirdColumnModeOptions: ['none', 'notifications', 'postform'].map(mode => ({
|
||||
key: mode,
|
||||
value: mode,
|
||||
label: this.$t(`settings.third_column_mode_${mode}`)
|
||||
})),
|
||||
forcedRoundnessOptions: ['disabled', 'sharp', 'nonsharp', 'round'].map((mode, i) => ({
|
||||
key: mode,
|
||||
value: i - 1,
|
||||
label: this.$t(`settings.style.themes3.hacks.forced_roundness_mode_${mode}`)
|
||||
})),
|
||||
underlayOverrideModes: ['none', 'opaque', 'transparent'].map((mode, i) => ({
|
||||
key: mode,
|
||||
value: mode,
|
||||
label: this.$t(`settings.style.themes3.hacks.underlay_override_mode_${mode}`)
|
||||
}))
|
||||
}
|
||||
},
|
||||
components: {
|
||||
BooleanSetting,
|
||||
ChoiceSetting,
|
||||
IntegerSetting,
|
||||
FloatSetting,
|
||||
UnitSetting,
|
||||
ProfileSettingIndicator,
|
||||
FontControl,
|
||||
Preview
|
||||
},
|
||||
mounted () {
|
||||
getThemes()
|
||||
.then((promises) => {
|
||||
return Promise.all(
|
||||
Object.entries(promises)
|
||||
.map(([k, v]) => v.then(res => [k, res]))
|
||||
)
|
||||
})
|
||||
.then(themes => themes.reduce((acc, [k, v]) => {
|
||||
if (v) {
|
||||
return [
|
||||
...acc,
|
||||
{
|
||||
name: v.name || v[0],
|
||||
key: k,
|
||||
data: v
|
||||
}
|
||||
]
|
||||
} else {
|
||||
return acc
|
||||
}
|
||||
}, []))
|
||||
.then((themesComplete) => {
|
||||
this.availableStyles = themesComplete
|
||||
})
|
||||
|
||||
if (window.IntersectionObserver) {
|
||||
this.intersectionObserver = new IntersectionObserver((entries, observer) => {
|
||||
entries.forEach(({ target, isIntersecting }) => {
|
||||
if (!isIntersecting) return
|
||||
const theme = this.availableStyles.find(x => x.key === target.dataset.themeKey)
|
||||
this.$nextTick(() => {
|
||||
if (theme) theme.ready = true
|
||||
})
|
||||
observer.unobserve(target)
|
||||
})
|
||||
}, {
|
||||
root: this.$refs.themeList
|
||||
})
|
||||
}
|
||||
},
|
||||
updated () {
|
||||
this.$nextTick(() => {
|
||||
this.$refs.themeList.querySelectorAll('.theme-preview').forEach(node => {
|
||||
this.intersectionObserver.observe(node)
|
||||
})
|
||||
})
|
||||
},
|
||||
computed: {
|
||||
noIntersectionObserver () {
|
||||
return !window.IntersectionObserver
|
||||
},
|
||||
horizontalUnits () {
|
||||
return defaultHorizontalUnits
|
||||
},
|
||||
fontsOverride () {
|
||||
return this.$store.getters.mergedConfig.fontsOverride
|
||||
},
|
||||
columns () {
|
||||
const mode = this.$store.getters.mergedConfig.thirdColumnMode
|
||||
|
||||
const notif = mode === 'none' ? [] : ['notifs']
|
||||
|
||||
if (this.$store.getters.mergedConfig.sidebarRight || mode === 'postform') {
|
||||
return [...notif, 'content', 'sidebar']
|
||||
} else {
|
||||
return ['sidebar', 'content', ...notif]
|
||||
}
|
||||
},
|
||||
instanceSpecificPanelPresent () { return this.$store.state.instance.showInstanceSpecificPanel },
|
||||
instanceWallpaperUsed () {
|
||||
return this.$store.state.instance.background &&
|
||||
!this.$store.state.users.currentUser.background_image
|
||||
},
|
||||
instanceShoutboxPresent () { return this.$store.state.instance.shoutAvailable },
|
||||
language: {
|
||||
get: function () { return this.$store.getters.mergedConfig.interfaceLanguage },
|
||||
set: function (val) {
|
||||
this.$store.dispatch('setOption', { name: 'interfaceLanguage', value: val })
|
||||
}
|
||||
},
|
||||
isCustomThemeUsed () {
|
||||
const { theme } = this.mergedConfig
|
||||
return theme === 'custom' || theme === null
|
||||
},
|
||||
...SharedComputedObject()
|
||||
},
|
||||
methods: {
|
||||
updateFont (key, value) {
|
||||
console.log(key, value)
|
||||
this.$store.dispatch('setOption', {
|
||||
name: 'theme3hacks',
|
||||
value: {
|
||||
...this.mergedConfig.theme3hacks,
|
||||
fonts: {
|
||||
...this.mergedConfig.theme3hacks.fonts,
|
||||
[key]: value
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
isThemeActive (key) {
|
||||
const { theme } = this.mergedConfig
|
||||
return key === theme
|
||||
},
|
||||
setTheme (name) {
|
||||
this.$store.dispatch('setTheme', { themeName: name, saveData: true, recompile: true })
|
||||
},
|
||||
previewTheme (key, input) {
|
||||
const style = normalizeThemeData(input)
|
||||
const x = 2
|
||||
if (x === 1) return
|
||||
const theme2 = convertTheme2To3(style)
|
||||
const theme3 = init({
|
||||
inputRuleset: theme2,
|
||||
ultimateBackgroundColor: '#000000',
|
||||
liteMode: true,
|
||||
debug: true,
|
||||
onlyNormalState: true
|
||||
})
|
||||
|
||||
return getScopedVersion(
|
||||
getCssRules(theme3.eager),
|
||||
'#theme-preview-' + key
|
||||
).join('\n')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default AppearanceTab
|
||||
313
src/components/settings_modal/tabs/appearance_tab.vue
Normal file
313
src/components/settings_modal/tabs/appearance_tab.vue
Normal file
|
|
@ -0,0 +1,313 @@
|
|||
<template>
|
||||
<div class="appearance-tab" :label="$t('settings.general')">
|
||||
<div class="setting-item">
|
||||
<h2>{{ $t('settings.theme') }}</h2>
|
||||
<ul
|
||||
class="theme-list"
|
||||
ref="themeList"
|
||||
>
|
||||
<button
|
||||
v-if="isCustomThemeUsed"
|
||||
disabled
|
||||
class="button-default theme-preview"
|
||||
>
|
||||
<preview />
|
||||
<h4 class="theme-name">{{ $t('settings.style.custom_theme_used') }}</h4>
|
||||
</button>
|
||||
<button
|
||||
v-for="style in availableStyles"
|
||||
:data-theme-key="style.key"
|
||||
:key="style.key"
|
||||
class="button-default theme-preview"
|
||||
:class="{ toggled: isThemeActive(style.key) }"
|
||||
@click="setTheme(style.key)"
|
||||
>
|
||||
<!-- eslint-disable vue/no-v-text-v-html-on-component -->
|
||||
<component
|
||||
:is="'style'"
|
||||
v-if="style.ready || noIntersectionObserver"
|
||||
v-html="previewTheme(style.key, style.data)"
|
||||
/>
|
||||
<!-- eslint-enable vue/no-v-text-v-html-on-component -->
|
||||
<preview :class="{ placeholder: ready }" :id="'theme-preview-' + style.key"/>
|
||||
<h4 class="theme-name">{{ style.name }}</h4>
|
||||
</button>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="alert neutral theme-notice">
|
||||
{{ $t("settings.style.appearance_tab_note") }}
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<h2>{{ $t('settings.scale_and_layout') }}</h2>
|
||||
<ul class="setting-list">
|
||||
<li>
|
||||
<UnitSetting
|
||||
path="textSize"
|
||||
step="0.1"
|
||||
:units="['px', 'rem']"
|
||||
:reset-default="{ 'px': 14, 'rem': 1 }"
|
||||
timed-apply-mode
|
||||
>
|
||||
{{ $t('settings.text_size') }}
|
||||
</UnitSetting>
|
||||
<div>
|
||||
<small>
|
||||
<i18n-t
|
||||
scope="global"
|
||||
keypath="settings.text_size_tip"
|
||||
tag="span"
|
||||
>
|
||||
<code>px</code>
|
||||
<code>rem</code>
|
||||
</i18n-t>
|
||||
<br/>
|
||||
<i18n-t
|
||||
scope="global"
|
||||
keypath="settings.text_size_tip2"
|
||||
tag="span"
|
||||
>
|
||||
<code>14px</code>
|
||||
</i18n-t>
|
||||
</small>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<h3>{{ $t('settings.style.interface_font_user_override') }}</h3>
|
||||
<ul class="setting-list">
|
||||
<li>
|
||||
<FontControl
|
||||
:model-value="mergedConfig.theme3hacks.fonts.interface"
|
||||
name="ui"
|
||||
:label="$t('settings.style.fonts.components.interface')"
|
||||
:fallback="{ family: 'sans-serif' }"
|
||||
no-inherit="1"
|
||||
@update:modelValue="v => updateFont('interface', v)"
|
||||
/>
|
||||
</li>
|
||||
<li>
|
||||
<FontControl
|
||||
v-if="expertLevel > 0"
|
||||
:model-value="mergedConfig.theme3hacks.fonts.input"
|
||||
name="input"
|
||||
:fallback="{ family: 'inherit' }"
|
||||
:label="$t('settings.style.fonts.components.input')"
|
||||
@update:modelValue="v => updateFont('input', v)"
|
||||
/>
|
||||
</li>
|
||||
<li>
|
||||
<FontControl
|
||||
v-if="expertLevel > 0"
|
||||
:model-value="mergedConfig.theme3hacks.fonts.post"
|
||||
name="post"
|
||||
:fallback="{ family: 'inherit' }"
|
||||
:label="$t('settings.style.fonts.components.post')"
|
||||
@update:modelValue="v => updateFont('post', v)"
|
||||
/>
|
||||
</li>
|
||||
<li>
|
||||
<FontControl
|
||||
v-if="expertLevel > 0"
|
||||
:model-value="mergedConfig.theme3hacks.fonts.monospace"
|
||||
name="postCode"
|
||||
:fallback="{ family: 'monospace' }"
|
||||
:label="$t('settings.style.fonts.components.monospace')"
|
||||
@update:modelValue="v => updateFont('monospace', v)"
|
||||
/>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<UnitSetting
|
||||
path="emojiSize"
|
||||
step="0.1"
|
||||
:units="['px', 'rem']"
|
||||
:reset-default="{ 'px': 32, 'rem': 2.2 }"
|
||||
>
|
||||
{{ $t('settings.emoji_size') }}
|
||||
</UnitSetting>
|
||||
<ul
|
||||
class="setting-list suboptions"
|
||||
>
|
||||
<li>
|
||||
<FloatSetting
|
||||
v-if="user"
|
||||
path="emojiReactionsScale"
|
||||
expert="1"
|
||||
>
|
||||
{{ $t('settings.emoji_reactions_scale') }}
|
||||
</FloatSetting>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<UnitSetting
|
||||
path="navbarSize"
|
||||
step="0.1"
|
||||
:units="['px', 'rem']"
|
||||
:reset-default="{ 'px': 55, 'rem': 3.5 }"
|
||||
>
|
||||
{{ $t('settings.navbar_size') }}
|
||||
</UnitSetting>
|
||||
</li>
|
||||
<h3>{{ $t('settings.columns') }}</h3>
|
||||
<li>
|
||||
<UnitSetting
|
||||
path="panelHeaderSize"
|
||||
step="0.1"
|
||||
:units="['px', 'rem']"
|
||||
:reset-default="{ 'px': 52, 'rem': 3.2 }"
|
||||
timed-apply-mode
|
||||
>
|
||||
{{ $t('settings.panel_header_size') }}
|
||||
</UnitSetting>
|
||||
</li>
|
||||
<li>
|
||||
<BooleanSetting path="sidebarRight">
|
||||
{{ $t('settings.right_sidebar') }}
|
||||
</BooleanSetting>
|
||||
</li>
|
||||
<li>
|
||||
<BooleanSetting path="navbarColumnStretch">
|
||||
{{ $t('settings.navbar_column_stretch') }}
|
||||
</BooleanSetting>
|
||||
</li>
|
||||
<li>
|
||||
<ChoiceSetting
|
||||
v-if="user"
|
||||
id="thirdColumnMode"
|
||||
path="thirdColumnMode"
|
||||
:options="thirdColumnModeOptions"
|
||||
>
|
||||
{{ $t('settings.third_column_mode') }}
|
||||
</ChoiceSetting>
|
||||
</li>
|
||||
<li v-if="expertLevel > 0">
|
||||
{{ $t('settings.column_sizes') }}
|
||||
<div class="column-settings">
|
||||
<UnitSetting
|
||||
v-for="column in columns"
|
||||
:key="column"
|
||||
:path="column + 'ColumnWidth'"
|
||||
:units="horizontalUnits"
|
||||
expert="1"
|
||||
>
|
||||
{{ $t('settings.column_sizes_' + column) }}
|
||||
</UnitSetting>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<BooleanSetting path="disableStickyHeaders">
|
||||
{{ $t('settings.disable_sticky_headers') }}
|
||||
</BooleanSetting>
|
||||
</li>
|
||||
<li>
|
||||
<BooleanSetting path="showScrollbars">
|
||||
{{ $t('settings.show_scrollbars') }}
|
||||
</BooleanSetting>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<h2>{{ $t('settings.visual_tweaks') }}</h2>
|
||||
<ul class="setting-list">
|
||||
<li>
|
||||
<ChoiceSetting
|
||||
id="forcedRoundness"
|
||||
path="forcedRoundness"
|
||||
:options="forcedRoundnessOptions"
|
||||
>
|
||||
{{ $t('settings.style.themes3.hacks.force_interface_roundness') }}
|
||||
</ChoiceSetting>
|
||||
</li>
|
||||
<li>
|
||||
<ChoiceSetting
|
||||
id="underlayOverride"
|
||||
path="theme3hacks.underlay"
|
||||
:options="underlayOverrideModes"
|
||||
>
|
||||
{{ $t('settings.style.themes3.hacks.underlay_overrides') }}
|
||||
</ChoiceSetting>
|
||||
</li>
|
||||
<li v-if="instanceWallpaperUsed">
|
||||
<BooleanSetting path="hideInstanceWallpaper">
|
||||
{{ $t('settings.hide_wallpaper') }}
|
||||
</BooleanSetting>
|
||||
</li>
|
||||
<li>
|
||||
<BooleanSetting
|
||||
path="forceThemeRecompilation"
|
||||
:expert="1"
|
||||
>
|
||||
{{ $t('settings.force_theme_recompilation_debug') }}
|
||||
</BooleanSetting>
|
||||
</li>
|
||||
<li>
|
||||
<BooleanSetting
|
||||
path="themeDebug"
|
||||
:expert="1"
|
||||
>
|
||||
{{ $t('settings.theme_debug') }}
|
||||
</BooleanSetting>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script src="./appearance_tab.js"></script>
|
||||
|
||||
<style lang="scss">
|
||||
.appearance-tab {
|
||||
.theme-notice {
|
||||
padding: 0.5em;
|
||||
margin: 1em;
|
||||
}
|
||||
|
||||
.column-settings {
|
||||
display: flex;
|
||||
justify-content: space-evenly;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.column-settings .size-label {
|
||||
display: block;
|
||||
margin-bottom: 0.5em;
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
.theme-list {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin: -0.5em 0;
|
||||
height: 25em;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
scrollbar-gutter: stable;
|
||||
border-radius: var(--roundness);
|
||||
border: 1px solid var(--border);
|
||||
padding: 0;
|
||||
|
||||
.theme-preview {
|
||||
font-size: 1rem; // fix for firefox
|
||||
width: 19rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin: 0.5em;
|
||||
|
||||
&.placeholder {
|
||||
opacity: 0.2;
|
||||
}
|
||||
|
||||
.preview-container {
|
||||
pointer-events: none;
|
||||
zoom: 0.5;
|
||||
border: none;
|
||||
border-radius: var(--roundness);
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -49,24 +49,6 @@
|
|||
{{ $t('settings.mute_sensitive_posts') }}
|
||||
</BooleanSetting>
|
||||
</li>
|
||||
<li>
|
||||
<BooleanSetting path="hideMutedFederationRestrictions">
|
||||
{{ $t('settings.hide_muted_federation_restrictions') }}
|
||||
</BooleanSetting>
|
||||
<ul
|
||||
class="setting-list suboptions"
|
||||
:class="[{disabled: !streaming}]"
|
||||
>
|
||||
<li
|
||||
v-for="item in muteFederationRestrictionsLevels"
|
||||
:key="'mute_' + item + '_federation_restriction'"
|
||||
>
|
||||
<BooleanSetting :path="'muteFederationRestrictions.' + item">
|
||||
{{ $t('settings.mute_' + item + '_federation_restriction') }}
|
||||
</BooleanSetting>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<BooleanSetting path="hidePostStats">
|
||||
{{ $t('settings.hide_post_stats') }}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import ChoiceSetting from '../helpers/choice_setting.vue'
|
|||
import ScopeSelector from 'src/components/scope_selector/scope_selector.vue'
|
||||
import IntegerSetting from '../helpers/integer_setting.vue'
|
||||
import FloatSetting from '../helpers/float_setting.vue'
|
||||
import UnitSetting, { defaultHorizontalUnits } from '../helpers/unit_setting.vue'
|
||||
import UnitSetting from '../helpers/unit_setting.vue'
|
||||
import InterfaceLanguageSwitcher from 'src/components/interface_language_switcher/interface_language_switcher.vue'
|
||||
|
||||
import SharedComputedObject from '../helpers/shared_computed_object.js'
|
||||
|
|
@ -40,11 +40,6 @@ const GeneralTab = {
|
|||
value: mode,
|
||||
label: this.$t(`settings.mention_link_display_${mode}`)
|
||||
})),
|
||||
thirdColumnModeOptions: ['none', 'notifications', 'postform'].map(mode => ({
|
||||
key: mode,
|
||||
value: mode,
|
||||
label: this.$t(`settings.third_column_mode_${mode}`)
|
||||
})),
|
||||
userPopoverAvatarActionOptions: ['close', 'zoom', 'open'].map(mode => ({
|
||||
key: mode,
|
||||
value: mode,
|
||||
|
|
@ -70,9 +65,6 @@ const GeneralTab = {
|
|||
ProfileSettingIndicator
|
||||
},
|
||||
computed: {
|
||||
horizontalUnits () {
|
||||
return defaultHorizontalUnits
|
||||
},
|
||||
postFormats () {
|
||||
return this.$store.state.instance.postFormats || []
|
||||
},
|
||||
|
|
@ -83,29 +75,6 @@ const GeneralTab = {
|
|||
label: this.$t(`post_status.content_type["${format}"]`)
|
||||
}))
|
||||
},
|
||||
columns () {
|
||||
const mode = this.$store.getters.mergedConfig.thirdColumnMode
|
||||
|
||||
const notif = mode === 'none' ? [] : ['notifs']
|
||||
|
||||
if (this.$store.getters.mergedConfig.sidebarRight || mode === 'postform') {
|
||||
return [...notif, 'content', 'sidebar']
|
||||
} else {
|
||||
return ['sidebar', 'content', ...notif]
|
||||
}
|
||||
},
|
||||
instanceSpecificPanelPresent () { return this.$store.state.instance.showInstanceSpecificPanel },
|
||||
instanceWallpaperUsed () {
|
||||
return this.$store.state.instance.background &&
|
||||
!this.$store.state.users.currentUser.background_image
|
||||
},
|
||||
instanceShoutboxPresent () { return this.$store.state.instance.shoutAvailable },
|
||||
language: {
|
||||
get: function () { return this.$store.getters.mergedConfig.interfaceLanguage },
|
||||
set: function (val) {
|
||||
this.$store.dispatch('setOption', { name: 'interfaceLanguage', value: val })
|
||||
}
|
||||
},
|
||||
...SharedComputedObject()
|
||||
},
|
||||
methods: {
|
||||
|
|
|
|||
|
|
@ -15,11 +15,6 @@
|
|||
{{ $t('settings.hide_isp') }}
|
||||
</BooleanSetting>
|
||||
</li>
|
||||
<li v-if="instanceWallpaperUsed">
|
||||
<BooleanSetting path="hideInstanceWallpaper">
|
||||
{{ $t('settings.hide_wallpaper') }}
|
||||
</BooleanSetting>
|
||||
</li>
|
||||
<li>
|
||||
<BooleanSetting path="stopGifs">
|
||||
{{ $t('settings.stop_gifs') }}
|
||||
|
|
@ -98,53 +93,6 @@
|
|||
{{ $t('settings.hide_shoutbox') }}
|
||||
</BooleanSetting>
|
||||
</li>
|
||||
<li>
|
||||
<h3>{{ $t('settings.columns') }}</h3>
|
||||
</li>
|
||||
<li>
|
||||
<BooleanSetting path="disableStickyHeaders">
|
||||
{{ $t('settings.disable_sticky_headers') }}
|
||||
</BooleanSetting>
|
||||
</li>
|
||||
<li>
|
||||
<BooleanSetting path="showScrollbars">
|
||||
{{ $t('settings.show_scrollbars') }}
|
||||
</BooleanSetting>
|
||||
</li>
|
||||
<li>
|
||||
<BooleanSetting path="sidebarRight">
|
||||
{{ $t('settings.right_sidebar') }}
|
||||
</BooleanSetting>
|
||||
</li>
|
||||
<li>
|
||||
<BooleanSetting path="navbarColumnStretch">
|
||||
{{ $t('settings.navbar_column_stretch') }}
|
||||
</BooleanSetting>
|
||||
</li>
|
||||
<li>
|
||||
<ChoiceSetting
|
||||
v-if="user"
|
||||
id="thirdColumnMode"
|
||||
path="thirdColumnMode"
|
||||
:options="thirdColumnModeOptions"
|
||||
>
|
||||
{{ $t('settings.third_column_mode') }}
|
||||
</ChoiceSetting>
|
||||
</li>
|
||||
<li v-if="expertLevel > 0">
|
||||
{{ $t('settings.column_sizes') }}
|
||||
<div class="column-settings">
|
||||
<UnitSetting
|
||||
v-for="column in columns"
|
||||
:key="column"
|
||||
:path="column + 'ColumnWidth'"
|
||||
:units="horizontalUnits"
|
||||
expert="1"
|
||||
>
|
||||
{{ $t('settings.column_sizes_' + column) }}
|
||||
</UnitSetting>
|
||||
</div>
|
||||
</li>
|
||||
<li class="select-multiple">
|
||||
<span class="label">{{ $t('settings.confirm_dialogs') }}</span>
|
||||
<ul class="option-list">
|
||||
|
|
@ -200,14 +148,6 @@
|
|||
<div class="setting-item">
|
||||
<h2>{{ $t('settings.post_look_feel') }}</h2>
|
||||
<ul class="setting-list">
|
||||
<li>
|
||||
<BooleanSetting
|
||||
path="forceThemeRecompilation"
|
||||
:expert="1"
|
||||
>
|
||||
{{ $t('settings.force_theme_recompilation_debug') }}
|
||||
</BooleanSetting>
|
||||
</li>
|
||||
<li>
|
||||
<ChoiceSetting
|
||||
id="conversationDisplay"
|
||||
|
|
@ -277,15 +217,6 @@
|
|||
{{ $t('settings.no_rich_text_description') }}
|
||||
</BooleanSetting>
|
||||
</li>
|
||||
<li>
|
||||
<FloatSetting
|
||||
v-if="user"
|
||||
path="emojiReactionsScale"
|
||||
expert="1"
|
||||
>
|
||||
{{ $t('settings.emoji_reactions_scale') }}
|
||||
</FloatSetting>
|
||||
</li>
|
||||
<h3>{{ $t('settings.attachments') }}</h3>
|
||||
<li>
|
||||
<BooleanSetting
|
||||
|
|
@ -528,17 +459,3 @@
|
|||
</template>
|
||||
|
||||
<script src="./general_tab.js"></script>
|
||||
|
||||
<style lang="scss">
|
||||
.column-settings {
|
||||
display: flex;
|
||||
justify-content: space-evenly;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.column-settings .size-label {
|
||||
display: block;
|
||||
margin-bottom: 0.5em;
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -99,15 +99,9 @@
|
|||
>
|
||||
|
||||
<div class="actions">
|
||||
<span class="checkbox">
|
||||
<input
|
||||
id="preview_checkbox"
|
||||
checked="very yes"
|
||||
type="checkbox"
|
||||
class="input"
|
||||
>
|
||||
<label for="preview_checkbox">{{ $t('settings.style.preview.checkbox') }}</label>
|
||||
</span>
|
||||
<Checkbox>
|
||||
{{ $t('settings.style.preview.checkbox') }}
|
||||
</Checkbox>
|
||||
<button class="btn button-default">
|
||||
{{ $t('settings.style.preview.button') }}
|
||||
</button>
|
||||
|
|
@ -118,6 +112,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import Checkbox from 'src/components/checkbox/checkbox.vue'
|
||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||
import {
|
||||
faTimes,
|
||||
|
|
@ -133,12 +128,116 @@ library.add(
|
|||
faReply
|
||||
)
|
||||
|
||||
export default {}
|
||||
export default {
|
||||
components: {
|
||||
Checkbox
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.preview-container {
|
||||
position: relative;
|
||||
border-top: 1px dashed;
|
||||
border-bottom: 1px dashed;
|
||||
border-color: var(--border);
|
||||
margin: 1em 0;
|
||||
padding: 1em;
|
||||
background-color: var(--wallpaper);
|
||||
background-image: var(--body-background-image);
|
||||
background-size: cover;
|
||||
background-position: 50% 50%;
|
||||
|
||||
.theme-preview-content {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.dummy {
|
||||
.post {
|
||||
font-family: var(--postFont);
|
||||
display: flex;
|
||||
|
||||
.content {
|
||||
flex: 1;
|
||||
|
||||
h4 {
|
||||
margin-bottom: 0.25em;
|
||||
}
|
||||
|
||||
.icons {
|
||||
margin-top: 0.5em;
|
||||
display: flex;
|
||||
|
||||
i {
|
||||
margin-right: 1em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.after-post {
|
||||
margin-top: 1em;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.avatar,
|
||||
.avatar-alt {
|
||||
background:
|
||||
linear-gradient(
|
||||
135deg,
|
||||
#b8e1fc 0%,
|
||||
#a9d2f3 10%,
|
||||
#90bae4 25%,
|
||||
#90bcea 37%,
|
||||
#90bff0 50%,
|
||||
#6ba8e5 51%,
|
||||
#a2daf5 83%,
|
||||
#bdf3fd 100%
|
||||
);
|
||||
color: black;
|
||||
font-family: sans-serif;
|
||||
text-align: center;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
.avatar-alt {
|
||||
flex: 0 auto;
|
||||
margin-left: 28px;
|
||||
font-size: 12px;
|
||||
min-width: 20px;
|
||||
min-height: 20px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
flex: 0 auto;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
font-size: 14px;
|
||||
line-height: 48px;
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
|
||||
.checkbox {
|
||||
margin-right: 1em;
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.separator {
|
||||
margin: 1em;
|
||||
border-bottom: 1px solid;
|
||||
border-color: var(--border);
|
||||
}
|
||||
|
||||
.btn {
|
||||
min-width: 3em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.underlay-preview {
|
||||
|
|
@ -148,4 +247,4 @@ export default {}
|
|||
left: 10px;
|
||||
right: 10px;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import {
|
||||
rgb2hex,
|
||||
hex2rgb,
|
||||
getContrastRatioLayers
|
||||
getContrastRatioLayers,
|
||||
relativeLuminance
|
||||
} from 'src/services/color_convert/color_convert.js'
|
||||
import {
|
||||
getThemes
|
||||
|
|
@ -23,10 +24,17 @@ import {
|
|||
generateShadows,
|
||||
generateRadii,
|
||||
generateFonts,
|
||||
composePreset,
|
||||
shadows2to3,
|
||||
colors2to3
|
||||
} from 'src/services/theme_data/theme_data.service.js'
|
||||
|
||||
import { convertTheme2To3 } from 'src/services/theme_data/theme2_to_theme3.js'
|
||||
import { init } from 'src/services/theme_data/theme_data_3.service.js'
|
||||
import {
|
||||
getCssRules,
|
||||
getScopedVersion
|
||||
} from 'src/services/theme_data/css_utils.js'
|
||||
|
||||
import ColorInput from 'src/components/color_input/color_input.vue'
|
||||
import RangeInput from 'src/components/range_input/range_input.vue'
|
||||
import OpacityInput from 'src/components/opacity_input/opacity_input.vue'
|
||||
|
|
@ -62,6 +70,7 @@ const colorConvert = (color) => {
|
|||
export default {
|
||||
data () {
|
||||
return {
|
||||
themeV3Preview: [],
|
||||
themeImporter: newImporter({
|
||||
validator: this.importValidator,
|
||||
onImport: this.onImport,
|
||||
|
|
@ -78,10 +87,7 @@ export default {
|
|||
tempImportFile: undefined,
|
||||
engineVersion: 0,
|
||||
|
||||
previewShadows: {},
|
||||
previewColors: {},
|
||||
previewRadii: {},
|
||||
previewFonts: {},
|
||||
previewTheme: {},
|
||||
|
||||
shadowsInvalid: true,
|
||||
colorsInvalid: true,
|
||||
|
|
@ -232,13 +238,6 @@ export default {
|
|||
chatMessage: this.chatMessageRadiusLocal
|
||||
}
|
||||
},
|
||||
preview () {
|
||||
return composePreset(this.previewColors, this.previewRadii, this.previewShadows, this.previewFonts)
|
||||
},
|
||||
previewTheme () {
|
||||
if (!this.preview.theme.colors) return { colors: {}, opacity: {}, radii: {}, shadows: {}, fonts: {} }
|
||||
return this.preview.theme
|
||||
},
|
||||
// This needs optimization maybe
|
||||
previewContrast () {
|
||||
try {
|
||||
|
|
@ -306,14 +305,6 @@ export default {
|
|||
return {}
|
||||
}
|
||||
},
|
||||
previewRules () {
|
||||
if (!this.preview.rules) return ''
|
||||
return [
|
||||
...Object.values(this.preview.rules),
|
||||
'color: var(--text)',
|
||||
'font-family: var(--interfaceFont, sans-serif)'
|
||||
].join(';')
|
||||
},
|
||||
shadowsAvailable () {
|
||||
return Object.keys(DEFAULT_SHADOWS).sort()
|
||||
},
|
||||
|
|
@ -511,17 +502,14 @@ export default {
|
|||
}
|
||||
},
|
||||
setCustomTheme () {
|
||||
this.$store.dispatch('setOption', {
|
||||
name: 'customTheme',
|
||||
value: {
|
||||
this.$store.dispatch('setThemeV2', {
|
||||
customTheme: {
|
||||
ignore: true,
|
||||
themeFileVersion: this.selectedVersion,
|
||||
themeEngineVersion: CURRENT_VERSION,
|
||||
...this.previewTheme
|
||||
}
|
||||
})
|
||||
this.$store.dispatch('setOption', {
|
||||
name: 'customThemeSource',
|
||||
value: {
|
||||
},
|
||||
customThemeSource: {
|
||||
themeFileVersion: this.selectedVersion,
|
||||
themeEngineVersion: CURRENT_VERSION,
|
||||
shadows: this.shadowsLocal,
|
||||
|
|
@ -532,16 +520,24 @@ export default {
|
|||
}
|
||||
})
|
||||
},
|
||||
updatePreviewColorsAndShadows () {
|
||||
this.previewColors = generateColors({
|
||||
updatePreviewColors () {
|
||||
const result = generateColors({
|
||||
opacity: this.currentOpacity,
|
||||
colors: this.currentColors
|
||||
})
|
||||
this.previewShadows = generateShadows(
|
||||
{ shadows: this.shadowsLocal, opacity: this.previewTheme.opacity, themeEngineVersion: this.engineVersion },
|
||||
this.previewColors.theme.colors,
|
||||
this.previewColors.mod
|
||||
)
|
||||
this.previewTheme.colors = result.theme.colors
|
||||
this.previewTheme.opacity = result.theme.opacity
|
||||
},
|
||||
updatePreviewShadows () {
|
||||
this.previewTheme.shadows = generateShadows(
|
||||
{
|
||||
shadows: this.shadowsLocal,
|
||||
opacity: this.previewTheme.opacity,
|
||||
themeEngineVersion: this.engineVersion
|
||||
},
|
||||
this.previewTheme.colors,
|
||||
relativeLuminance(this.previewTheme.colors.bg) < 0.5 ? 1 : -1
|
||||
).theme.shadows
|
||||
},
|
||||
importTheme () { this.themeImporter.importData() },
|
||||
exportTheme () { this.themeExporter.exportData() },
|
||||
|
|
@ -610,7 +606,7 @@ export default {
|
|||
normalizeLocalState (theme, version = 0, source, forceSource = false) {
|
||||
let input
|
||||
if (typeof source !== 'undefined') {
|
||||
if (forceSource || source.themeEngineVersion === CURRENT_VERSION) {
|
||||
if (forceSource || source?.themeEngineVersion === CURRENT_VERSION) {
|
||||
input = source
|
||||
version = source.themeEngineVersion
|
||||
} else {
|
||||
|
|
@ -692,6 +688,8 @@ export default {
|
|||
} else {
|
||||
this.shadowsLocal = shadows
|
||||
}
|
||||
this.updatePreviewColors()
|
||||
this.updatePreviewShadows()
|
||||
this.shadowSelected = this.shadowsAvailable[0]
|
||||
}
|
||||
|
||||
|
|
@ -699,12 +697,25 @@ export default {
|
|||
this.clearFonts()
|
||||
this.fontsLocal = fonts
|
||||
}
|
||||
},
|
||||
updateTheme3Preview () {
|
||||
const theme2 = convertTheme2To3(this.previewTheme)
|
||||
const theme3 = init({
|
||||
inputRuleset: theme2,
|
||||
ultimateBackgroundColor: '#000000',
|
||||
liteMode: true
|
||||
})
|
||||
|
||||
this.themeV3Preview = getScopedVersion(
|
||||
getCssRules(theme3.eager),
|
||||
'#theme-preview'
|
||||
).join('\n')
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
currentRadii () {
|
||||
try {
|
||||
this.previewRadii = generateRadii({ radii: this.currentRadii })
|
||||
this.previewTheme.radii = generateRadii({ radii: this.currentRadii }).theme.radii
|
||||
this.radiiInvalid = false
|
||||
} catch (e) {
|
||||
this.radiiInvalid = true
|
||||
|
|
@ -713,9 +724,8 @@ export default {
|
|||
},
|
||||
shadowsLocal: {
|
||||
handler () {
|
||||
if (Object.getOwnPropertyNames(this.previewColors).length === 1) return
|
||||
try {
|
||||
this.updatePreviewColorsAndShadows()
|
||||
this.updatePreviewShadows()
|
||||
this.shadowsInvalid = false
|
||||
} catch (e) {
|
||||
this.shadowsInvalid = true
|
||||
|
|
@ -727,7 +737,7 @@ export default {
|
|||
fontsLocal: {
|
||||
handler () {
|
||||
try {
|
||||
this.previewFonts = generateFonts({ fonts: this.fontsLocal })
|
||||
this.previewTheme.fonts = generateFonts({ fonts: this.fontsLocal }).theme.fonts
|
||||
this.fontsInvalid = false
|
||||
} catch (e) {
|
||||
this.fontsInvalid = true
|
||||
|
|
@ -738,18 +748,16 @@ export default {
|
|||
},
|
||||
currentColors () {
|
||||
try {
|
||||
this.updatePreviewColorsAndShadows()
|
||||
this.updatePreviewColors()
|
||||
this.colorsInvalid = false
|
||||
this.shadowsInvalid = false
|
||||
} catch (e) {
|
||||
this.colorsInvalid = true
|
||||
this.shadowsInvalid = true
|
||||
console.warn(e)
|
||||
}
|
||||
},
|
||||
currentOpacity () {
|
||||
try {
|
||||
this.updatePreviewColorsAndShadows()
|
||||
this.updatePreviewColors()
|
||||
} catch (e) {
|
||||
console.warn(e)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,9 @@
|
|||
.theme-tab {
|
||||
.deprecation-warning {
|
||||
padding: 0.5em;
|
||||
margin: 2em;
|
||||
}
|
||||
|
||||
padding-bottom: 2em;
|
||||
|
||||
.preset-switcher {
|
||||
|
|
@ -10,6 +15,10 @@
|
|||
margin-right: 0.25em;
|
||||
}
|
||||
|
||||
.btn-group .btn {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.style-control {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
|
|
@ -157,107 +166,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.preview-container {
|
||||
border-top: 1px dashed;
|
||||
border-bottom: 1px dashed;
|
||||
border-color: var(--border);
|
||||
margin: 1em 0;
|
||||
padding: 1em;
|
||||
background-color: var(--wallpaper);
|
||||
background-image: var(--body-background-image);
|
||||
background-size: cover;
|
||||
background-position: 50% 50%;
|
||||
|
||||
.dummy {
|
||||
.post {
|
||||
font-family: var(--postFont);
|
||||
display: flex;
|
||||
|
||||
.content {
|
||||
flex: 1;
|
||||
|
||||
h4 {
|
||||
margin-bottom: 0.25em;
|
||||
}
|
||||
|
||||
.icons {
|
||||
margin-top: 0.5em;
|
||||
display: flex;
|
||||
|
||||
i {
|
||||
margin-right: 1em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.after-post {
|
||||
margin-top: 1em;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.avatar,
|
||||
.avatar-alt {
|
||||
background:
|
||||
linear-gradient(
|
||||
135deg,
|
||||
#b8e1fc 0%,
|
||||
#a9d2f3 10%,
|
||||
#90bae4 25%,
|
||||
#90bcea 37%,
|
||||
#90bff0 50%,
|
||||
#6ba8e5 51%,
|
||||
#a2daf5 83%,
|
||||
#bdf3fd 100%
|
||||
);
|
||||
color: black;
|
||||
font-family: sans-serif;
|
||||
text-align: center;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
.avatar-alt {
|
||||
flex: 0 auto;
|
||||
margin-left: 28px;
|
||||
font-size: 12px;
|
||||
min-width: 20px;
|
||||
min-height: 20px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
flex: 0 auto;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
font-size: 14px;
|
||||
line-height: 48px;
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
|
||||
.checkbox {
|
||||
display: inline-flex;
|
||||
align-items: baseline;
|
||||
margin-right: 1em;
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.separator {
|
||||
margin: 1em;
|
||||
border-bottom: 1px solid;
|
||||
border-color: var(--border);
|
||||
}
|
||||
|
||||
.btn {
|
||||
min-width: 3em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.radius-item {
|
||||
flex-basis: auto;
|
||||
}
|
||||
|
|
@ -310,10 +218,6 @@
|
|||
max-width: 50em;
|
||||
}
|
||||
|
||||
.theme-preview-content {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.theme-warning {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
<template>
|
||||
<div class="theme-tab">
|
||||
<div class="alert warning deprecation-warning">
|
||||
{{ $t("settings.style.themes2_outdated") }}
|
||||
</div>
|
||||
<div class="presets-container">
|
||||
<div class="save-load">
|
||||
<div
|
||||
|
|
@ -120,7 +123,19 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<preview :style="previewRules" />
|
||||
<!-- eslint-disable vue/no-v-text-v-html-on-component -->
|
||||
<component :is="'style'" v-html="themeV3Preview"/>
|
||||
<!-- eslint-enable vue/no-v-text-v-html-on-component -->
|
||||
<preview id="theme-preview"/>
|
||||
|
||||
<div>
|
||||
<button
|
||||
class="btn button-default"
|
||||
@click="updateTheme3Preview"
|
||||
>
|
||||
{{ $t("settings.style.update_preview") }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<keep-alive>
|
||||
<tab-switcher key="style-tweak">
|
||||
|
|
@ -156,7 +171,7 @@
|
|||
<OpacityInput
|
||||
v-model="bgOpacityLocal"
|
||||
name="bgOpacity"
|
||||
:fallback="previewTheme.opacity.bg"
|
||||
:fallback="previewTheme.opacity?.bg"
|
||||
/>
|
||||
<ColorInput
|
||||
v-model="textColorLocal"
|
||||
|
|
@ -167,14 +182,14 @@
|
|||
<ColorInput
|
||||
v-model="accentColorLocal"
|
||||
name="accentColor"
|
||||
:fallback="previewTheme.colors.link"
|
||||
:fallback="previewTheme.colors?.link"
|
||||
:label="$t('settings.accent')"
|
||||
:show-optional-tickbox="typeof linkColorLocal !== 'undefined'"
|
||||
/>
|
||||
<ColorInput
|
||||
v-model="linkColorLocal"
|
||||
name="linkColor"
|
||||
:fallback="previewTheme.colors.accent"
|
||||
:fallback="previewTheme.colors?.accent"
|
||||
:label="$t('settings.links')"
|
||||
:show-optional-tickbox="typeof accentColorLocal !== 'undefined'"
|
||||
/>
|
||||
|
|
@ -190,13 +205,13 @@
|
|||
v-model="fgTextColorLocal"
|
||||
name="fgTextColor"
|
||||
:label="$t('settings.text')"
|
||||
:fallback="previewTheme.colors.fgText"
|
||||
:fallback="previewTheme.colors?.fgText"
|
||||
/>
|
||||
<ColorInput
|
||||
v-model="fgLinkColorLocal"
|
||||
name="fgLinkColor"
|
||||
:label="$t('settings.links')"
|
||||
:fallback="previewTheme.colors.fgLink"
|
||||
:fallback="previewTheme.colors?.fgLink"
|
||||
/>
|
||||
<p>{{ $t('settings.style.common_colors.foreground_hint') }}</p>
|
||||
</div>
|
||||
|
|
@ -256,14 +271,14 @@
|
|||
<ColorInput
|
||||
v-model="postLinkColorLocal"
|
||||
name="postLinkColor"
|
||||
:fallback="previewTheme.colors.accent"
|
||||
:fallback="previewTheme.colors?.accent"
|
||||
:label="$t('settings.links')"
|
||||
/>
|
||||
<ContrastRatio :contrast="previewContrast.postLink" />
|
||||
<ColorInput
|
||||
v-model="postGreentextColorLocal"
|
||||
name="postGreentextColor"
|
||||
:fallback="previewTheme.colors.cGreen"
|
||||
:fallback="previewTheme.colors?.cGreen"
|
||||
:label="$t('settings.greentext')"
|
||||
/>
|
||||
<ContrastRatio :contrast="previewContrast.postGreentext" />
|
||||
|
|
@ -272,13 +287,13 @@
|
|||
v-model="alertErrorColorLocal"
|
||||
name="alertError"
|
||||
:label="$t('settings.style.advanced_colors.alert_error')"
|
||||
:fallback="previewTheme.colors.alertError"
|
||||
:fallback="previewTheme.colors?.alertError"
|
||||
/>
|
||||
<ColorInput
|
||||
v-model="alertErrorTextColorLocal"
|
||||
name="alertErrorText"
|
||||
:label="$t('settings.text')"
|
||||
:fallback="previewTheme.colors.alertErrorText"
|
||||
:fallback="previewTheme.colors?.alertErrorText"
|
||||
/>
|
||||
<ContrastRatio
|
||||
:contrast="previewContrast.alertErrorText"
|
||||
|
|
@ -288,13 +303,13 @@
|
|||
v-model="alertWarningColorLocal"
|
||||
name="alertWarning"
|
||||
:label="$t('settings.style.advanced_colors.alert_warning')"
|
||||
:fallback="previewTheme.colors.alertWarning"
|
||||
:fallback="previewTheme.colors?.alertWarning"
|
||||
/>
|
||||
<ColorInput
|
||||
v-model="alertWarningTextColorLocal"
|
||||
name="alertWarningText"
|
||||
:label="$t('settings.text')"
|
||||
:fallback="previewTheme.colors.alertWarningText"
|
||||
:fallback="previewTheme.colors?.alertWarningText"
|
||||
/>
|
||||
<ContrastRatio
|
||||
:contrast="previewContrast.alertWarningText"
|
||||
|
|
@ -304,13 +319,13 @@
|
|||
v-model="alertNeutralColorLocal"
|
||||
name="alertNeutral"
|
||||
:label="$t('settings.style.advanced_colors.alert_neutral')"
|
||||
:fallback="previewTheme.colors.alertNeutral"
|
||||
:fallback="previewTheme.colors?.alertNeutral"
|
||||
/>
|
||||
<ColorInput
|
||||
v-model="alertNeutralTextColorLocal"
|
||||
name="alertNeutralText"
|
||||
:label="$t('settings.text')"
|
||||
:fallback="previewTheme.colors.alertNeutralText"
|
||||
:fallback="previewTheme.colors?.alertNeutralText"
|
||||
/>
|
||||
<ContrastRatio
|
||||
:contrast="previewContrast.alertNeutralText"
|
||||
|
|
@ -319,7 +334,7 @@
|
|||
<OpacityInput
|
||||
v-model="alertOpacityLocal"
|
||||
name="alertOpacity"
|
||||
:fallback="previewTheme.opacity.alert"
|
||||
:fallback="previewTheme.opacity?.alert"
|
||||
/>
|
||||
</div>
|
||||
<div class="color-item">
|
||||
|
|
@ -328,13 +343,13 @@
|
|||
v-model="badgeNotificationColorLocal"
|
||||
name="badgeNotification"
|
||||
:label="$t('settings.style.advanced_colors.badge_notification')"
|
||||
:fallback="previewTheme.colors.badgeNotification"
|
||||
:fallback="previewTheme.colors?.badgeNotification"
|
||||
/>
|
||||
<ColorInput
|
||||
v-model="badgeNotificationTextColorLocal"
|
||||
name="badgeNotificationText"
|
||||
:label="$t('settings.text')"
|
||||
:fallback="previewTheme.colors.badgeNotificationText"
|
||||
:fallback="previewTheme.colors?.badgeNotificationText"
|
||||
/>
|
||||
<ContrastRatio
|
||||
:contrast="previewContrast.badgeNotificationText"
|
||||
|
|
@ -346,19 +361,19 @@
|
|||
<ColorInput
|
||||
v-model="panelColorLocal"
|
||||
name="panelColor"
|
||||
:fallback="previewTheme.colors.panel"
|
||||
:fallback="previewTheme.colors?.panel"
|
||||
:label="$t('settings.background')"
|
||||
/>
|
||||
<OpacityInput
|
||||
v-model="panelOpacityLocal"
|
||||
name="panelOpacity"
|
||||
:fallback="previewTheme.opacity.panel"
|
||||
:fallback="previewTheme.opacity?.panel"
|
||||
:disabled="panelColorLocal === 'transparent'"
|
||||
/>
|
||||
<ColorInput
|
||||
v-model="panelTextColorLocal"
|
||||
name="panelTextColor"
|
||||
:fallback="previewTheme.colors.panelText"
|
||||
:fallback="previewTheme.colors?.panelText"
|
||||
:label="$t('settings.text')"
|
||||
/>
|
||||
<ContrastRatio
|
||||
|
|
@ -368,7 +383,7 @@
|
|||
<ColorInput
|
||||
v-model="panelLinkColorLocal"
|
||||
name="panelLinkColor"
|
||||
:fallback="previewTheme.colors.panelLink"
|
||||
:fallback="previewTheme.colors?.panelLink"
|
||||
:label="$t('settings.links')"
|
||||
/>
|
||||
<ContrastRatio
|
||||
|
|
@ -381,20 +396,20 @@
|
|||
<ColorInput
|
||||
v-model="topBarColorLocal"
|
||||
name="topBarColor"
|
||||
:fallback="previewTheme.colors.topBar"
|
||||
:fallback="previewTheme.colors?.topBar"
|
||||
:label="$t('settings.background')"
|
||||
/>
|
||||
<ColorInput
|
||||
v-model="topBarTextColorLocal"
|
||||
name="topBarTextColor"
|
||||
:fallback="previewTheme.colors.topBarText"
|
||||
:fallback="previewTheme.colors?.topBarText"
|
||||
:label="$t('settings.text')"
|
||||
/>
|
||||
<ContrastRatio :contrast="previewContrast.topBarText" />
|
||||
<ColorInput
|
||||
v-model="topBarLinkColorLocal"
|
||||
name="topBarLinkColor"
|
||||
:fallback="previewTheme.colors.topBarLink"
|
||||
:fallback="previewTheme.colors?.topBarLink"
|
||||
:label="$t('settings.links')"
|
||||
/>
|
||||
<ContrastRatio :contrast="previewContrast.topBarLink" />
|
||||
|
|
@ -404,19 +419,19 @@
|
|||
<ColorInput
|
||||
v-model="inputColorLocal"
|
||||
name="inputColor"
|
||||
:fallback="previewTheme.colors.input"
|
||||
:fallback="previewTheme.colors?.input"
|
||||
:label="$t('settings.background')"
|
||||
/>
|
||||
<OpacityInput
|
||||
v-model="inputOpacityLocal"
|
||||
name="inputOpacity"
|
||||
:fallback="previewTheme.opacity.input"
|
||||
:fallback="previewTheme.opacity?.input"
|
||||
:disabled="inputColorLocal === 'transparent'"
|
||||
/>
|
||||
<ColorInput
|
||||
v-model="inputTextColorLocal"
|
||||
name="inputTextColor"
|
||||
:fallback="previewTheme.colors.inputText"
|
||||
:fallback="previewTheme.colors?.inputText"
|
||||
:label="$t('settings.text')"
|
||||
/>
|
||||
<ContrastRatio :contrast="previewContrast.inputText" />
|
||||
|
|
@ -426,33 +441,33 @@
|
|||
<ColorInput
|
||||
v-model="btnColorLocal"
|
||||
name="btnColor"
|
||||
:fallback="previewTheme.colors.btn"
|
||||
:fallback="previewTheme.colors?.btn"
|
||||
:label="$t('settings.background')"
|
||||
/>
|
||||
<OpacityInput
|
||||
v-model="btnOpacityLocal"
|
||||
name="btnOpacity"
|
||||
:fallback="previewTheme.opacity.btn"
|
||||
:fallback="previewTheme.opacity?.btn"
|
||||
:disabled="btnColorLocal === 'transparent'"
|
||||
/>
|
||||
<ColorInput
|
||||
v-model="btnTextColorLocal"
|
||||
name="btnTextColor"
|
||||
:fallback="previewTheme.colors.btnText"
|
||||
:fallback="previewTheme.colors?.btnText"
|
||||
:label="$t('settings.text')"
|
||||
/>
|
||||
<ContrastRatio :contrast="previewContrast.btnText" />
|
||||
<ColorInput
|
||||
v-model="btnPanelTextColorLocal"
|
||||
name="btnPanelTextColor"
|
||||
:fallback="previewTheme.colors.btnPanelText"
|
||||
:fallback="previewTheme.colors?.btnPanelText"
|
||||
:label="$t('settings.style.advanced_colors.panel_header')"
|
||||
/>
|
||||
<ContrastRatio :contrast="previewContrast.btnPanelText" />
|
||||
<ColorInput
|
||||
v-model="btnTopBarTextColorLocal"
|
||||
name="btnTopBarTextColor"
|
||||
:fallback="previewTheme.colors.btnTopBarText"
|
||||
:fallback="previewTheme.colors?.btnTopBarText"
|
||||
:label="$t('settings.style.advanced_colors.top_bar')"
|
||||
/>
|
||||
<ContrastRatio :contrast="previewContrast.btnTopBarText" />
|
||||
|
|
@ -460,27 +475,27 @@
|
|||
<ColorInput
|
||||
v-model="btnPressedColorLocal"
|
||||
name="btnPressedColor"
|
||||
:fallback="previewTheme.colors.btnPressed"
|
||||
:fallback="previewTheme.colors?.btnPressed"
|
||||
:label="$t('settings.background')"
|
||||
/>
|
||||
<ColorInput
|
||||
v-model="btnPressedTextColorLocal"
|
||||
name="btnPressedTextColor"
|
||||
:fallback="previewTheme.colors.btnPressedText"
|
||||
:fallback="previewTheme.colors?.btnPressedText"
|
||||
:label="$t('settings.text')"
|
||||
/>
|
||||
<ContrastRatio :contrast="previewContrast.btnPressedText" />
|
||||
<ColorInput
|
||||
v-model="btnPressedPanelTextColorLocal"
|
||||
name="btnPressedPanelTextColor"
|
||||
:fallback="previewTheme.colors.btnPressedPanelText"
|
||||
:fallback="previewTheme.colors?.btnPressedPanelText"
|
||||
:label="$t('settings.style.advanced_colors.panel_header')"
|
||||
/>
|
||||
<ContrastRatio :contrast="previewContrast.btnPressedPanelText" />
|
||||
<ColorInput
|
||||
v-model="btnPressedTopBarTextColorLocal"
|
||||
name="btnPressedTopBarTextColor"
|
||||
:fallback="previewTheme.colors.btnPressedTopBarText"
|
||||
:fallback="previewTheme.colors?.btnPressedTopBarText"
|
||||
:label="$t('settings.style.advanced_colors.top_bar')"
|
||||
/>
|
||||
<ContrastRatio :contrast="previewContrast.btnPressedTopBarText" />
|
||||
|
|
@ -488,52 +503,52 @@
|
|||
<ColorInput
|
||||
v-model="btnDisabledColorLocal"
|
||||
name="btnDisabledColor"
|
||||
:fallback="previewTheme.colors.btnDisabled"
|
||||
:fallback="previewTheme.colors?.btnDisabled"
|
||||
:label="$t('settings.background')"
|
||||
/>
|
||||
<ColorInput
|
||||
v-model="btnDisabledTextColorLocal"
|
||||
name="btnDisabledTextColor"
|
||||
:fallback="previewTheme.colors.btnDisabledText"
|
||||
:fallback="previewTheme.colors?.btnDisabledText"
|
||||
:label="$t('settings.text')"
|
||||
/>
|
||||
<ColorInput
|
||||
v-model="btnDisabledPanelTextColorLocal"
|
||||
name="btnDisabledPanelTextColor"
|
||||
:fallback="previewTheme.colors.btnDisabledPanelText"
|
||||
:fallback="previewTheme.colors?.btnDisabledPanelText"
|
||||
:label="$t('settings.style.advanced_colors.panel_header')"
|
||||
/>
|
||||
<ColorInput
|
||||
v-model="btnDisabledTopBarTextColorLocal"
|
||||
name="btnDisabledTopBarTextColor"
|
||||
:fallback="previewTheme.colors.btnDisabledTopBarText"
|
||||
:fallback="previewTheme.colors?.btnDisabledTopBarText"
|
||||
:label="$t('settings.style.advanced_colors.top_bar')"
|
||||
/>
|
||||
<h5>{{ $t('settings.style.advanced_colors.toggled') }}</h5>
|
||||
<ColorInput
|
||||
v-model="btnToggledColorLocal"
|
||||
name="btnToggledColor"
|
||||
:fallback="previewTheme.colors.btnToggled"
|
||||
:fallback="previewTheme.colors?.btnToggled"
|
||||
:label="$t('settings.background')"
|
||||
/>
|
||||
<ColorInput
|
||||
v-model="btnToggledTextColorLocal"
|
||||
name="btnToggledTextColor"
|
||||
:fallback="previewTheme.colors.btnToggledText"
|
||||
:fallback="previewTheme.colors?.btnToggledText"
|
||||
:label="$t('settings.text')"
|
||||
/>
|
||||
<ContrastRatio :contrast="previewContrast.btnToggledText" />
|
||||
<ColorInput
|
||||
v-model="btnToggledPanelTextColorLocal"
|
||||
name="btnToggledPanelTextColor"
|
||||
:fallback="previewTheme.colors.btnToggledPanelText"
|
||||
:fallback="previewTheme.colors?.btnToggledPanelText"
|
||||
:label="$t('settings.style.advanced_colors.panel_header')"
|
||||
/>
|
||||
<ContrastRatio :contrast="previewContrast.btnToggledPanelText" />
|
||||
<ColorInput
|
||||
v-model="btnToggledTopBarTextColorLocal"
|
||||
name="btnToggledTopBarTextColor"
|
||||
:fallback="previewTheme.colors.btnToggledTopBarText"
|
||||
:fallback="previewTheme.colors?.btnToggledTopBarText"
|
||||
:label="$t('settings.style.advanced_colors.top_bar')"
|
||||
/>
|
||||
<ContrastRatio :contrast="previewContrast.btnToggledTopBarText" />
|
||||
|
|
@ -543,20 +558,20 @@
|
|||
<ColorInput
|
||||
v-model="tabColorLocal"
|
||||
name="tabColor"
|
||||
:fallback="previewTheme.colors.tab"
|
||||
:fallback="previewTheme.colors?.tab"
|
||||
:label="$t('settings.background')"
|
||||
/>
|
||||
<ColorInput
|
||||
v-model="tabTextColorLocal"
|
||||
name="tabTextColor"
|
||||
:fallback="previewTheme.colors.tabText"
|
||||
:fallback="previewTheme.colors?.tabText"
|
||||
:label="$t('settings.text')"
|
||||
/>
|
||||
<ContrastRatio :contrast="previewContrast.tabText" />
|
||||
<ColorInput
|
||||
v-model="tabActiveTextColorLocal"
|
||||
name="tabActiveTextColor"
|
||||
:fallback="previewTheme.colors.tabActiveText"
|
||||
:fallback="previewTheme.colors?.tabActiveText"
|
||||
:label="$t('settings.text')"
|
||||
/>
|
||||
<ContrastRatio :contrast="previewContrast.tabActiveText" />
|
||||
|
|
@ -566,13 +581,13 @@
|
|||
<ColorInput
|
||||
v-model="borderColorLocal"
|
||||
name="borderColor"
|
||||
:fallback="previewTheme.colors.border"
|
||||
:fallback="previewTheme.colors?.border"
|
||||
:label="$t('settings.style.common.color')"
|
||||
/>
|
||||
<OpacityInput
|
||||
v-model="borderOpacityLocal"
|
||||
name="borderOpacity"
|
||||
:fallback="previewTheme.opacity.border"
|
||||
:fallback="previewTheme.opacity?.border"
|
||||
:disabled="borderColorLocal === 'transparent'"
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -581,25 +596,25 @@
|
|||
<ColorInput
|
||||
v-model="faintColorLocal"
|
||||
name="faintColor"
|
||||
:fallback="previewTheme.colors.faint"
|
||||
:fallback="previewTheme.colors?.faint"
|
||||
:label="$t('settings.text')"
|
||||
/>
|
||||
<ColorInput
|
||||
v-model="faintLinkColorLocal"
|
||||
name="faintLinkColor"
|
||||
:fallback="previewTheme.colors.faintLink"
|
||||
:fallback="previewTheme.colors?.faintLink"
|
||||
:label="$t('settings.links')"
|
||||
/>
|
||||
<ColorInput
|
||||
v-model="panelFaintColorLocal"
|
||||
name="panelFaintColor"
|
||||
:fallback="previewTheme.colors.panelFaint"
|
||||
:fallback="previewTheme.colors?.panelFaint"
|
||||
:label="$t('settings.style.advanced_colors.panel_header')"
|
||||
/>
|
||||
<OpacityInput
|
||||
v-model="faintOpacityLocal"
|
||||
name="faintOpacity"
|
||||
:fallback="previewTheme.opacity.faint"
|
||||
:fallback="previewTheme.opacity?.faint"
|
||||
/>
|
||||
</div>
|
||||
<div class="color-item">
|
||||
|
|
@ -608,12 +623,12 @@
|
|||
v-model="underlayColorLocal"
|
||||
name="underlay"
|
||||
:label="$t('settings.style.advanced_colors.underlay')"
|
||||
:fallback="previewTheme.colors.underlay"
|
||||
:fallback="previewTheme.colors?.underlay"
|
||||
/>
|
||||
<OpacityInput
|
||||
v-model="underlayOpacityLocal"
|
||||
name="underlayOpacity"
|
||||
:fallback="previewTheme.opacity.underlay"
|
||||
:fallback="previewTheme.opacity?.underlay"
|
||||
:disabled="underlayOpacityLocal === 'transparent'"
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -623,7 +638,7 @@
|
|||
v-model="wallpaperColorLocal"
|
||||
name="wallpaper"
|
||||
:label="$t('settings.style.advanced_colors.wallpaper')"
|
||||
:fallback="previewTheme.colors.wallpaper"
|
||||
:fallback="previewTheme.colors?.wallpaper"
|
||||
/>
|
||||
</div>
|
||||
<div class="color-item">
|
||||
|
|
@ -632,13 +647,13 @@
|
|||
v-model="pollColorLocal"
|
||||
name="poll"
|
||||
:label="$t('settings.background')"
|
||||
:fallback="previewTheme.colors.poll"
|
||||
:fallback="previewTheme.colors?.poll"
|
||||
/>
|
||||
<ColorInput
|
||||
v-model="pollTextColorLocal"
|
||||
name="pollText"
|
||||
:label="$t('settings.text')"
|
||||
:fallback="previewTheme.colors.pollText"
|
||||
:fallback="previewTheme.colors?.pollText"
|
||||
/>
|
||||
</div>
|
||||
<div class="color-item">
|
||||
|
|
@ -647,7 +662,7 @@
|
|||
v-model="iconColorLocal"
|
||||
name="icon"
|
||||
:label="$t('settings.style.advanced_colors.icons')"
|
||||
:fallback="previewTheme.colors.icon"
|
||||
:fallback="previewTheme.colors?.icon"
|
||||
/>
|
||||
</div>
|
||||
<div class="color-item">
|
||||
|
|
@ -656,20 +671,20 @@
|
|||
v-model="highlightColorLocal"
|
||||
name="highlight"
|
||||
:label="$t('settings.background')"
|
||||
:fallback="previewTheme.colors.highlight"
|
||||
:fallback="previewTheme.colors?.highlight"
|
||||
/>
|
||||
<ColorInput
|
||||
v-model="highlightTextColorLocal"
|
||||
name="highlightText"
|
||||
:label="$t('settings.text')"
|
||||
:fallback="previewTheme.colors.highlightText"
|
||||
:fallback="previewTheme.colors?.highlightText"
|
||||
/>
|
||||
<ContrastRatio :contrast="previewContrast.highlightText" />
|
||||
<ColorInput
|
||||
v-model="highlightLinkColorLocal"
|
||||
name="highlightLink"
|
||||
:label="$t('settings.links')"
|
||||
:fallback="previewTheme.colors.highlightLink"
|
||||
:fallback="previewTheme.colors?.highlightLink"
|
||||
/>
|
||||
<ContrastRatio :contrast="previewContrast.highlightLink" />
|
||||
</div>
|
||||
|
|
@ -679,26 +694,26 @@
|
|||
v-model="popoverColorLocal"
|
||||
name="popover"
|
||||
:label="$t('settings.background')"
|
||||
:fallback="previewTheme.colors.popover"
|
||||
:fallback="previewTheme.colors?.popover"
|
||||
/>
|
||||
<OpacityInput
|
||||
v-model="popoverOpacityLocal"
|
||||
name="popoverOpacity"
|
||||
:fallback="previewTheme.opacity.popover"
|
||||
:fallback="previewTheme.opacity?.popover"
|
||||
:disabled="popoverOpacityLocal === 'transparent'"
|
||||
/>
|
||||
<ColorInput
|
||||
v-model="popoverTextColorLocal"
|
||||
name="popoverText"
|
||||
:label="$t('settings.text')"
|
||||
:fallback="previewTheme.colors.popoverText"
|
||||
:fallback="previewTheme.colors?.popoverText"
|
||||
/>
|
||||
<ContrastRatio :contrast="previewContrast.popoverText" />
|
||||
<ColorInput
|
||||
v-model="popoverLinkColorLocal"
|
||||
name="popoverLink"
|
||||
:label="$t('settings.links')"
|
||||
:fallback="previewTheme.colors.popoverLink"
|
||||
:fallback="previewTheme.colors?.popoverLink"
|
||||
/>
|
||||
<ContrastRatio :contrast="previewContrast.popoverLink" />
|
||||
</div>
|
||||
|
|
@ -708,20 +723,20 @@
|
|||
v-model="selectedPostColorLocal"
|
||||
name="selectedPost"
|
||||
:label="$t('settings.background')"
|
||||
:fallback="previewTheme.colors.selectedPost"
|
||||
:fallback="previewTheme.colors?.selectedPost"
|
||||
/>
|
||||
<ColorInput
|
||||
v-model="selectedPostTextColorLocal"
|
||||
name="selectedPostText"
|
||||
:label="$t('settings.text')"
|
||||
:fallback="previewTheme.colors.selectedPostText"
|
||||
:fallback="previewTheme.colors?.selectedPostText"
|
||||
/>
|
||||
<ContrastRatio :contrast="previewContrast.selectedPostText" />
|
||||
<ColorInput
|
||||
v-model="selectedPostLinkColorLocal"
|
||||
name="selectedPostLink"
|
||||
:label="$t('settings.links')"
|
||||
:fallback="previewTheme.colors.selectedPostLink"
|
||||
:fallback="previewTheme.colors?.selectedPostLink"
|
||||
/>
|
||||
<ContrastRatio :contrast="previewContrast.selectedPostLink" />
|
||||
</div>
|
||||
|
|
@ -731,20 +746,20 @@
|
|||
v-model="selectedMenuColorLocal"
|
||||
name="selectedMenu"
|
||||
:label="$t('settings.background')"
|
||||
:fallback="previewTheme.colors.selectedMenu"
|
||||
:fallback="previewTheme.colors?.selectedMenu"
|
||||
/>
|
||||
<ColorInput
|
||||
v-model="selectedMenuTextColorLocal"
|
||||
name="selectedMenuText"
|
||||
:label="$t('settings.text')"
|
||||
:fallback="previewTheme.colors.selectedMenuText"
|
||||
:fallback="previewTheme.colors?.selectedMenuText"
|
||||
/>
|
||||
<ContrastRatio :contrast="previewContrast.selectedMenuText" />
|
||||
<ColorInput
|
||||
v-model="selectedMenuLinkColorLocal"
|
||||
name="selectedMenuLink"
|
||||
:label="$t('settings.links')"
|
||||
:fallback="previewTheme.colors.selectedMenuLink"
|
||||
:fallback="previewTheme.colors?.selectedMenuLink"
|
||||
/>
|
||||
<ContrastRatio :contrast="previewContrast.selectedMenuLink" />
|
||||
</div>
|
||||
|
|
@ -753,57 +768,57 @@
|
|||
<ColorInput
|
||||
v-model="chatBgColorLocal"
|
||||
name="chatBgColor"
|
||||
:fallback="previewTheme.colors.bg"
|
||||
:fallback="previewTheme.colors?.bg"
|
||||
:label="$t('settings.background')"
|
||||
/>
|
||||
<h5>{{ $t('settings.style.advanced_colors.chat.incoming') }}</h5>
|
||||
<ColorInput
|
||||
v-model="chatMessageIncomingBgColorLocal"
|
||||
name="chatMessageIncomingBgColor"
|
||||
:fallback="previewTheme.colors.bg"
|
||||
:fallback="previewTheme.colors?.bg"
|
||||
:label="$t('settings.background')"
|
||||
/>
|
||||
<ColorInput
|
||||
v-model="chatMessageIncomingTextColorLocal"
|
||||
name="chatMessageIncomingTextColor"
|
||||
:fallback="previewTheme.colors.text"
|
||||
:fallback="previewTheme.colors?.text"
|
||||
:label="$t('settings.text')"
|
||||
/>
|
||||
<ColorInput
|
||||
v-model="chatMessageIncomingLinkColorLocal"
|
||||
name="chatMessageIncomingLinkColor"
|
||||
:fallback="previewTheme.colors.link"
|
||||
:fallback="previewTheme.colors?.link"
|
||||
:label="$t('settings.links')"
|
||||
/>
|
||||
<ColorInput
|
||||
v-model="chatMessageIncomingBorderColorLocal"
|
||||
name="chatMessageIncomingBorderLinkColor"
|
||||
:fallback="previewTheme.colors.fg"
|
||||
:fallback="previewTheme.colors?.fg"
|
||||
:label="$t('settings.style.advanced_colors.chat.border')"
|
||||
/>
|
||||
<h5>{{ $t('settings.style.advanced_colors.chat.outgoing') }}</h5>
|
||||
<ColorInput
|
||||
v-model="chatMessageOutgoingBgColorLocal"
|
||||
name="chatMessageOutgoingBgColor"
|
||||
:fallback="previewTheme.colors.bg"
|
||||
:fallback="previewTheme.colors?.bg"
|
||||
:label="$t('settings.background')"
|
||||
/>
|
||||
<ColorInput
|
||||
v-model="chatMessageOutgoingTextColorLocal"
|
||||
name="chatMessageOutgoingTextColor"
|
||||
:fallback="previewTheme.colors.text"
|
||||
:fallback="previewTheme.colors?.text"
|
||||
:label="$t('settings.text')"
|
||||
/>
|
||||
<ColorInput
|
||||
v-model="chatMessageOutgoingLinkColorLocal"
|
||||
name="chatMessageOutgoingLinkColor"
|
||||
:fallback="previewTheme.colors.link"
|
||||
:fallback="previewTheme.colors?.link"
|
||||
:label="$t('settings.links')"
|
||||
/>
|
||||
<ColorInput
|
||||
v-model="chatMessageOutgoingBorderColorLocal"
|
||||
name="chatMessageOutgoingBorderLinkColor"
|
||||
:fallback="previewTheme.colors.bg"
|
||||
:fallback="previewTheme.colors?.bg"
|
||||
:label="$t('settings.style.advanced_colors.chat.border')"
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -826,7 +841,7 @@
|
|||
v-model="btnRadiusLocal"
|
||||
name="btnRadius"
|
||||
:label="$t('settings.btnRadius')"
|
||||
:fallback="previewTheme.radii.btn"
|
||||
:fallback="previewTheme.radii?.btn"
|
||||
max="16"
|
||||
hard-min="0"
|
||||
/>
|
||||
|
|
@ -834,7 +849,7 @@
|
|||
v-model="inputRadiusLocal"
|
||||
name="inputRadius"
|
||||
:label="$t('settings.inputRadius')"
|
||||
:fallback="previewTheme.radii.input"
|
||||
:fallback="previewTheme.radii?.input"
|
||||
max="9"
|
||||
hard-min="0"
|
||||
/>
|
||||
|
|
@ -842,7 +857,7 @@
|
|||
v-model="checkboxRadiusLocal"
|
||||
name="checkboxRadius"
|
||||
:label="$t('settings.checkboxRadius')"
|
||||
:fallback="previewTheme.radii.checkbox"
|
||||
:fallback="previewTheme.radii?.checkbox"
|
||||
max="16"
|
||||
hard-min="0"
|
||||
/>
|
||||
|
|
@ -850,7 +865,7 @@
|
|||
v-model="panelRadiusLocal"
|
||||
name="panelRadius"
|
||||
:label="$t('settings.panelRadius')"
|
||||
:fallback="previewTheme.radii.panel"
|
||||
:fallback="previewTheme.radii?.panel"
|
||||
max="50"
|
||||
hard-min="0"
|
||||
/>
|
||||
|
|
@ -858,7 +873,7 @@
|
|||
v-model="avatarRadiusLocal"
|
||||
name="avatarRadius"
|
||||
:label="$t('settings.avatarRadius')"
|
||||
:fallback="previewTheme.radii.avatar"
|
||||
:fallback="previewTheme.radii?.avatar"
|
||||
max="28"
|
||||
hard-min="0"
|
||||
/>
|
||||
|
|
@ -866,7 +881,7 @@
|
|||
v-model="avatarAltRadiusLocal"
|
||||
name="avatarAltRadius"
|
||||
:label="$t('settings.avatarAltRadius')"
|
||||
:fallback="previewTheme.radii.avatarAlt"
|
||||
:fallback="previewTheme.radii?.avatarAlt"
|
||||
max="28"
|
||||
hard-min="0"
|
||||
/>
|
||||
|
|
@ -874,7 +889,7 @@
|
|||
v-model="attachmentRadiusLocal"
|
||||
name="attachmentRadius"
|
||||
:label="$t('settings.attachmentRadius')"
|
||||
:fallback="previewTheme.radii.attachment"
|
||||
:fallback="previewTheme.radii?.attachment"
|
||||
max="50"
|
||||
hard-min="0"
|
||||
/>
|
||||
|
|
@ -882,7 +897,7 @@
|
|||
v-model="tooltipRadiusLocal"
|
||||
name="tooltipRadius"
|
||||
:label="$t('settings.tooltipRadius')"
|
||||
:fallback="previewTheme.radii.tooltip"
|
||||
:fallback="previewTheme.radii?.tooltip"
|
||||
max="50"
|
||||
hard-min="0"
|
||||
/>
|
||||
|
|
@ -890,7 +905,7 @@
|
|||
v-model="chatMessageRadiusLocal"
|
||||
name="chatMessageRadius"
|
||||
:label="$t('settings.chatMessageRadius')"
|
||||
:fallback="previewTheme.radii.chatMessage || 2"
|
||||
:fallback="previewTheme.radii?.chatMessage || 2"
|
||||
max="50"
|
||||
hard-min="0"
|
||||
/>
|
||||
|
|
@ -996,26 +1011,26 @@
|
|||
v-model="fontsLocal.interface"
|
||||
name="ui"
|
||||
:label="$t('settings.style.fonts.components.interface')"
|
||||
:fallback="previewTheme.fonts.interface"
|
||||
:fallback="previewTheme.fonts?.interface"
|
||||
no-inherit="1"
|
||||
/>
|
||||
<FontControl
|
||||
v-model="fontsLocal.input"
|
||||
name="input"
|
||||
:label="$t('settings.style.fonts.components.input')"
|
||||
:fallback="previewTheme.fonts.input"
|
||||
:fallback="previewTheme.fonts?.input"
|
||||
/>
|
||||
<FontControl
|
||||
v-model="fontsLocal.post"
|
||||
name="post"
|
||||
:label="$t('settings.style.fonts.components.post')"
|
||||
:fallback="previewTheme.fonts.post"
|
||||
:fallback="previewTheme.fonts?.post"
|
||||
/>
|
||||
<FontControl
|
||||
v-model="fontsLocal.postCode"
|
||||
name="postCode"
|
||||
:label="$t('settings.style.fonts.components.postCode')"
|
||||
:fallback="previewTheme.fonts.postCode"
|
||||
:fallback="previewTheme.fonts?.postCode"
|
||||
/>
|
||||
</div>
|
||||
</tab-switcher>
|
||||
|
|
|
|||
|
|
@ -17,6 +17,15 @@ export default {
|
|||
'Attachment',
|
||||
'PollGraph'
|
||||
],
|
||||
validInnerComponentsLite: [
|
||||
'Text',
|
||||
'Link',
|
||||
'Icon',
|
||||
'Border',
|
||||
'ButtonUnstyled',
|
||||
'RichContent',
|
||||
'Avatar'
|
||||
],
|
||||
defaultRules: [
|
||||
{
|
||||
directives: {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue