Merge branch 'settings-shuffle' into 'develop'
Settings shuffle See merge request pleroma/pleroma-fe!2186
This commit is contained in:
commit
0252d39c75
59 changed files with 2614 additions and 1528 deletions
3
changelog.d/settings-shuffle.change
Normal file
3
changelog.d/settings-shuffle.change
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
rearranged and split settings to make more sense and be less of a wall of text
|
||||||
|
on mobile settings now take up full width and presented in navigation style
|
||||||
|
improved styles for settings
|
||||||
|
|
@ -1,18 +1,27 @@
|
||||||
.color-input {
|
.color-input {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
max-width: 10em;
|
||||||
|
|
||||||
|
&.-compact {
|
||||||
|
max-width: none;
|
||||||
|
}
|
||||||
|
|
||||||
.label {
|
.label {
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
|
grid-area: label;
|
||||||
}
|
}
|
||||||
|
|
||||||
.opt {
|
.opt {
|
||||||
|
grid-area: checkbox;
|
||||||
margin-right: 0.5em;
|
margin-right: 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-field.input {
|
&-field.input {
|
||||||
display: inline-flex;
|
flex: 1 1 10em;
|
||||||
flex: 0 0 0;
|
max-width: 10em;
|
||||||
max-width: 9em;
|
grid-area: input;
|
||||||
|
display: flex;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
|
|
||||||
input {
|
input {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="color-input style-control"
|
class="color-input style-control"
|
||||||
:class="{ disabled: !present || disabled }"
|
:class="{ disabled: !present || disabled, '-compact': compact }"
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
:for="name"
|
:for="name"
|
||||||
|
|
@ -127,6 +127,10 @@ export default {
|
||||||
required: false,
|
required: false,
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
|
},
|
||||||
|
compact: {
|
||||||
|
required: false,
|
||||||
|
type: Boolean
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
emits: ['update:modelValue'],
|
emits: ['update:modelValue'],
|
||||||
|
|
|
||||||
|
|
@ -104,6 +104,7 @@
|
||||||
v-model="colorOverride"
|
v-model="colorOverride"
|
||||||
class="input-color-input"
|
class="input-color-input"
|
||||||
fallback="#606060"
|
fallback="#606060"
|
||||||
|
:compact="true"
|
||||||
:label="$t('settings.style.shadows.color_override')"
|
:label="$t('settings.style.shadows.color_override')"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,9 @@
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.exporter {
|
.exporter {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
&-processing {
|
&-processing {
|
||||||
margin: 0.25em;
|
margin: 0.25em;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="font-control">
|
<div class="font-control">
|
||||||
<label
|
|
||||||
:id="name + '-label'"
|
|
||||||
:for="manualEntry ? name : name + '-font-switcher'"
|
|
||||||
class="label"
|
|
||||||
>
|
|
||||||
{{ $t('settings.style.themes3.font.label', { label }) }}
|
|
||||||
</label>
|
|
||||||
{{ ' ' }}
|
|
||||||
<Checkbox
|
<Checkbox
|
||||||
v-if="typeof fallback !== 'undefined'"
|
v-if="typeof fallback !== 'undefined'"
|
||||||
:id="name + '-o'"
|
:id="name + '-o'"
|
||||||
|
|
@ -15,8 +7,15 @@
|
||||||
:model-value="present"
|
:model-value="present"
|
||||||
@change="$emit('update:modelValue', typeof modelValue === 'undefined' ? fallback : undefined)"
|
@change="$emit('update:modelValue', typeof modelValue === 'undefined' ? fallback : undefined)"
|
||||||
>
|
>
|
||||||
{{ $t('settings.style.themes3.define') }}
|
<i18n-t
|
||||||
|
scope="global"
|
||||||
|
keypath="settings.style.fonts.override"
|
||||||
|
tag="span"
|
||||||
|
>
|
||||||
|
{{ label }}
|
||||||
|
</i18n-t>
|
||||||
</Checkbox>
|
</Checkbox>
|
||||||
|
{{ ' ' }}
|
||||||
<div
|
<div
|
||||||
v-if="modelValue?.family"
|
v-if="modelValue?.family"
|
||||||
class="font-input"
|
class="font-input"
|
||||||
|
|
@ -143,10 +142,6 @@
|
||||||
margin-left: 2em;
|
margin-left: 2em;
|
||||||
margin-top: 0.5em;
|
margin-top: 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.font-checkbox {
|
|
||||||
margin-left: 1em;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.invalid-tooltip {
|
.invalid-tooltip {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="importer">
|
<div class="importer btn-group">
|
||||||
<form>
|
<form>
|
||||||
<input
|
<input
|
||||||
ref="input"
|
ref="input"
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
class="btn button-default"
|
class="btn button-default"
|
||||||
@click="submit"
|
@click="submit"
|
||||||
>
|
>
|
||||||
{{ submitButtonLabel || $t('importer.submit') }}
|
{{ submitButtonLabel || $t('importer.import') }}
|
||||||
</button>
|
</button>
|
||||||
<div v-if="success">
|
<div v-if="success">
|
||||||
<button
|
<button
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
class="label"
|
class="label"
|
||||||
:class="{ faint: !present || disabled }"
|
:class="{ faint: !present || disabled }"
|
||||||
>
|
>
|
||||||
{{ label }}
|
{{ label || $t('settings.style.themes3.editor.opacity') }}
|
||||||
</label>
|
</label>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
v-if="typeof fallback !== 'undefined'"
|
v-if="typeof fallback !== 'undefined'"
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="PaletteEditor"
|
class="PaletteEditor"
|
||||||
:class="{ '-compact': compact, '-apply': apply }"
|
:class="{ '-compact': compact, '-apply': apply, '-mobile': mobile }"
|
||||||
>
|
>
|
||||||
|
<div class="palette">
|
||||||
<ColorInput
|
<ColorInput
|
||||||
v-for="key in paletteKeys"
|
v-for="key in paletteKeys"
|
||||||
:key="key"
|
:key="key"
|
||||||
|
|
@ -12,6 +13,8 @@
|
||||||
:label="$t('settings.style.themes3.palette.' + key)"
|
:label="$t('settings.style.themes3.palette.' + key)"
|
||||||
@update:model-value="value => updatePalette(key, value)"
|
@update:model-value="value => updatePalette(key, value)"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="buttons">
|
||||||
<button
|
<button
|
||||||
class="btn button-default palette-import-button"
|
class="btn button-default palette-import-button"
|
||||||
@click="importPalette"
|
@click="importPalette"
|
||||||
|
|
@ -26,6 +29,8 @@
|
||||||
<FAIcon icon="file-export" />
|
<FAIcon icon="file-export" />
|
||||||
{{ $t('settings.style.themes3.palette.export') }}
|
{{ $t('settings.style.themes3.palette.export') }}
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="buttons">
|
||||||
<button
|
<button
|
||||||
v-if="apply"
|
v-if="apply"
|
||||||
class="btn button-default palette-apply-button"
|
class="btn button-default palette-apply-button"
|
||||||
|
|
@ -36,9 +41,12 @@
|
||||||
{{ $t('settings.style.themes3.palette.apply') }}
|
{{ $t('settings.style.themes3.palette.apply') }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import { computed } from 'vue'
|
||||||
|
|
||||||
import ColorInput from 'src/components/color_input/color_input.vue'
|
import ColorInput from 'src/components/color_input/color_input.vue'
|
||||||
import {
|
import {
|
||||||
newImporter,
|
newImporter,
|
||||||
|
|
@ -51,6 +59,8 @@ import {
|
||||||
faFileExport
|
faFileExport
|
||||||
} from '@fortawesome/free-solid-svg-icons'
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
|
|
||||||
|
import { useInterfaceStore } from 'src/stores/interface'
|
||||||
|
|
||||||
library.add(
|
library.add(
|
||||||
faFileImport,
|
faFileImport,
|
||||||
faFileExport
|
faFileExport
|
||||||
|
|
@ -104,6 +114,10 @@ const applyPalette = () => {
|
||||||
emit('applyPalette', getExportedObject())
|
emit('applyPalette', getExportedObject())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const mobile = computed(() => {
|
||||||
|
return useInterfaceStore().layoutType === 'mobile'
|
||||||
|
})
|
||||||
|
|
||||||
const fallback = (key) => {
|
const fallback = (key) => {
|
||||||
if (key === 'accent') {
|
if (key === 'accent') {
|
||||||
return props.modelValue.link
|
return props.modelValue.link
|
||||||
|
|
@ -129,13 +143,28 @@ const updatePalette = (paletteKey, value) => {
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.PaletteEditor {
|
.PaletteEditor {
|
||||||
display: grid;
|
|
||||||
justify-content: space-around;
|
justify-content: space-around;
|
||||||
grid-template-columns: repeat(4, 1fr);
|
grid-template-columns: repeat(4, 1fr);
|
||||||
grid-template-rows: repeat(5, 1fr) auto;
|
grid-template-rows: repeat(5, 1fr) auto;
|
||||||
grid-gap: 0.5em;
|
grid-gap: 0.5em;
|
||||||
align-items: baseline;
|
align-items: baseline;
|
||||||
|
|
||||||
|
.buttons {
|
||||||
|
margin-top: 0.5em;
|
||||||
|
display: grid;
|
||||||
|
gap: 0.5em
|
||||||
|
}
|
||||||
|
|
||||||
|
.palette {
|
||||||
|
display: grid;
|
||||||
|
grid-template-rows: 1fr;
|
||||||
|
grid-auto-flow: row;
|
||||||
|
grid-auto-rows: auto;
|
||||||
|
grid-template-columns: repeat(auto-fill, 10em);
|
||||||
|
grid-gap: 0.5em;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
.palette-import-button {
|
.palette-import-button {
|
||||||
grid-column: 1 / span 2;
|
grid-column: 1 / span 2;
|
||||||
}
|
}
|
||||||
|
|
@ -171,24 +200,22 @@ const updatePalette = (paletteKey, value) => {
|
||||||
grid-column: 1 / span 2;
|
grid-column: 1 / span 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.-mobile & {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
grid-template-rows: repeat(10, 1fr) auto;
|
|
||||||
|
|
||||||
.palette-import-button {
|
|
||||||
grid-column: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.palette-export-button {
|
|
||||||
grid-column: 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.-mobile {
|
||||||
&.-apply {
|
&.-apply {
|
||||||
.palette-apply-button {
|
.palette-apply-button {
|
||||||
grid-column: 1;
|
grid-column: 1 / span 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.color-input {
|
||||||
|
display: grid;
|
||||||
|
gap: 0.5em;
|
||||||
|
|
||||||
|
label {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -299,8 +299,8 @@ const Popover = {
|
||||||
if (this.trigger === 'click') {
|
if (this.trigger === 'click') {
|
||||||
document.removeEventListener('click', this.onClickOutside)
|
document.removeEventListener('click', this.onClickOutside)
|
||||||
}
|
}
|
||||||
this.scrollable.removeEventListener('scroll', this.onScroll)
|
this.scrollable?.removeEventListener('scroll', this.onScroll)
|
||||||
this.scrollable.removeEventListener('resize', this.onResize)
|
this.scrollable?.removeEventListener('resize', this.onResize)
|
||||||
},
|
},
|
||||||
resizePopover () {
|
resizePopover () {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
|
|
||||||
|
|
@ -104,8 +104,8 @@
|
||||||
.visibility-tray {
|
.visibility-tray {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding-top: 0.5em;
|
|
||||||
align-items: baseline;
|
align-items: baseline;
|
||||||
|
margin-left: -0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.visibility-notice {
|
.visibility-notice {
|
||||||
|
|
|
||||||
|
|
@ -14,13 +14,33 @@ library.add(
|
||||||
)
|
)
|
||||||
|
|
||||||
const ScopeSelector = {
|
const ScopeSelector = {
|
||||||
props: [
|
props: {
|
||||||
'showAll',
|
showAll: {
|
||||||
'userDefault',
|
required: true,
|
||||||
'originalScope',
|
type: Boolean
|
||||||
'initialScope',
|
},
|
||||||
'onScopeChange'
|
userDefault: {
|
||||||
],
|
required: true,
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
originalScope: {
|
||||||
|
required: false,
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
initialScope: {
|
||||||
|
required: false,
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
onScopeChange: {
|
||||||
|
required: true,
|
||||||
|
type: Function
|
||||||
|
},
|
||||||
|
unstyled: {
|
||||||
|
required: false,
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
}
|
||||||
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
currentScope: this.initialScope
|
currentScope: this.initialScope
|
||||||
|
|
@ -43,11 +63,12 @@ const ScopeSelector = {
|
||||||
return this.shouldShow('direct')
|
return this.shouldShow('direct')
|
||||||
},
|
},
|
||||||
css () {
|
css () {
|
||||||
|
const style = this.unstyled ? 'button-unstyled' : 'button-default'
|
||||||
return {
|
return {
|
||||||
public: { toggled: this.currentScope === 'public' },
|
public: [style, { toggled: this.currentScope === 'public' }],
|
||||||
unlisted: { toggled: this.currentScope === 'unlisted' },
|
unlisted: [style, { toggled: this.currentScope === 'unlisted' }],
|
||||||
private: { toggled: this.currentScope === 'private' },
|
private: [style, { toggled: this.currentScope === 'private' }],
|
||||||
direct: { toggled: this.currentScope === 'direct' }
|
direct: [style, { toggled: this.currentScope === 'direct' }]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
v-if="!showNothing"
|
v-if="!showNothing"
|
||||||
class="ScopeSelector"
|
class="ScopeSelector btn-group"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
v-if="showDirect"
|
v-if="showDirect"
|
||||||
class="button-unstyled scope"
|
class="scope"
|
||||||
:class="css.direct"
|
:class="css.direct"
|
||||||
:title="$t('post_status.scope.direct')"
|
:title="$t('post_status.scope.direct')"
|
||||||
type="button"
|
type="button"
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
{{ ' ' }}
|
{{ ' ' }}
|
||||||
<button
|
<button
|
||||||
v-if="showPrivate"
|
v-if="showPrivate"
|
||||||
class="button-unstyled scope"
|
class="scope"
|
||||||
:class="css.private"
|
:class="css.private"
|
||||||
:title="$t('post_status.scope.private')"
|
:title="$t('post_status.scope.private')"
|
||||||
type="button"
|
type="button"
|
||||||
|
|
@ -33,7 +33,7 @@
|
||||||
{{ ' ' }}
|
{{ ' ' }}
|
||||||
<button
|
<button
|
||||||
v-if="showUnlisted"
|
v-if="showUnlisted"
|
||||||
class="button-unstyled scope"
|
class="scope"
|
||||||
:class="css.unlisted"
|
:class="css.unlisted"
|
||||||
:title="$t('post_status.scope.unlisted')"
|
:title="$t('post_status.scope.unlisted')"
|
||||||
type="button"
|
type="button"
|
||||||
|
|
@ -47,7 +47,7 @@
|
||||||
{{ ' ' }}
|
{{ ' ' }}
|
||||||
<button
|
<button
|
||||||
v-if="showPublic"
|
v-if="showPublic"
|
||||||
class="button-unstyled scope"
|
class="scope"
|
||||||
:class="css.public"
|
:class="css.public"
|
||||||
:title="$t('post_status.scope.public')"
|
:title="$t('post_status.scope.public')"
|
||||||
type="button"
|
type="button"
|
||||||
|
|
@ -65,12 +65,14 @@
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.ScopeSelector {
|
.ScopeSelector {
|
||||||
|
display: inline-block;
|
||||||
|
|
||||||
.scope {
|
.scope {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
cursor: pointer;
|
|
||||||
min-width: 1.3em;
|
min-width: 1.3em;
|
||||||
min-height: 1.3em;
|
min-height: 1.3em;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
padding: 0.5em 0.25em
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
213
src/components/settings_modal/helpers/vertical_tab_switcher.jsx
Normal file
213
src/components/settings_modal/helpers/vertical_tab_switcher.jsx
Normal file
|
|
@ -0,0 +1,213 @@
|
||||||
|
// eslint-disable-next-line no-unused
|
||||||
|
import { h, Fragment } from 'vue'
|
||||||
|
import { mapState } from 'pinia'
|
||||||
|
import { throttle } from 'lodash'
|
||||||
|
import { mapState as mapPiniaState } from 'pinia'
|
||||||
|
import { FontAwesomeIcon as FAIcon } from '@fortawesome/vue-fontawesome'
|
||||||
|
|
||||||
|
import './vertical_tab_switcher.scss'
|
||||||
|
import { useInterfaceStore } from 'src/stores/interface'
|
||||||
|
|
||||||
|
const findFirstUsable = (slots) => slots.findIndex(_ => _.props)
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'VerticalTabSwitcher',
|
||||||
|
props: {
|
||||||
|
renderOnlyFocused: {
|
||||||
|
required: false,
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
onSwitch: {
|
||||||
|
required: false,
|
||||||
|
type: Function,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
activeTab: {
|
||||||
|
required: false,
|
||||||
|
type: String,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
bodyScrollLock: {
|
||||||
|
required: false,
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
parentCollapsed: {
|
||||||
|
required: false,
|
||||||
|
type: Boolean,
|
||||||
|
default: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
active: findFirstUsable(this.slots()),
|
||||||
|
resizeHandler: null,
|
||||||
|
navSide: 'tabs',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
activeIndex () {
|
||||||
|
// In case of controlled component
|
||||||
|
if (this.activeTab) {
|
||||||
|
return this.slots().findIndex(slot => slot && slot.props && this.activeTab === slot.props.key)
|
||||||
|
} else {
|
||||||
|
return this.active
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isActive () {
|
||||||
|
return tabName => {
|
||||||
|
const isWanted = slot => slot.props && slot.props['data-tab-name'] === tabName
|
||||||
|
return this.$slots.default().findIndex(isWanted) === this.activeIndex
|
||||||
|
}
|
||||||
|
},
|
||||||
|
...mapPiniaState(useInterfaceStore, {
|
||||||
|
mobileLayout: store => store.layoutType === 'mobile'
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
beforeUpdate () {
|
||||||
|
const currentSlot = this.slots()[this.active]
|
||||||
|
if (!currentSlot.props) {
|
||||||
|
this.active = findFirstUsable(this.slots())
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
clickTab (index) {
|
||||||
|
return (e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
this.setTab(index)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setTab (index) {
|
||||||
|
if (typeof this.onSwitch === 'function') {
|
||||||
|
this.onSwitch.call(null, this.slots()[index].key)
|
||||||
|
}
|
||||||
|
this.active = index
|
||||||
|
this.changeNavSide('content')
|
||||||
|
},
|
||||||
|
changeNavSide (side) {
|
||||||
|
if (this.navSide !== side) {
|
||||||
|
this.navSide = side
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// DO NOT put it to computed, it doesn't work (caching?)
|
||||||
|
slots () {
|
||||||
|
if (this.$slots.default()[0].type === Fragment) {
|
||||||
|
return this.$slots.default()[0].children
|
||||||
|
}
|
||||||
|
return this.$slots.default()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
render () {
|
||||||
|
const tabs = this.slots()
|
||||||
|
.map((slot, index) => {
|
||||||
|
const props = slot.props
|
||||||
|
if (!props) return
|
||||||
|
const classesTab = ['vertical-tab', 'menu-item']
|
||||||
|
if (this.activeIndex === index && useInterfaceStore().layoutType !== 'mobile') {
|
||||||
|
classesTab.push('-active')
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
disabled={props.disabled}
|
||||||
|
onClick={this.clickTab(index)}
|
||||||
|
class={classesTab.join(' ')}
|
||||||
|
type="button"
|
||||||
|
role="tab"
|
||||||
|
title={props.label}
|
||||||
|
>
|
||||||
|
{!props.icon ? '' : (<FAIcon class="tab-icon" size="1x" fixed-width icon={props.icon}/>)}
|
||||||
|
<span class="text">
|
||||||
|
{props.label}
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
const contents = this.slots().map((slot, index) => {
|
||||||
|
const props = slot.props
|
||||||
|
if (!props) return
|
||||||
|
const active = this.activeIndex === index
|
||||||
|
|
||||||
|
let delayRender = slot.props['delay-render']
|
||||||
|
if (delayRender && active) {
|
||||||
|
slot.props['delay-render'] = false
|
||||||
|
delayRender = false
|
||||||
|
}
|
||||||
|
const renderSlot = (!delayRender && (!this.renderOnlyFocused || active))
|
||||||
|
? slot
|
||||||
|
: ''
|
||||||
|
|
||||||
|
const headerClasses = ['tab-content-label']
|
||||||
|
const header = (
|
||||||
|
<h2 class={headerClasses}>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => this.changeNavSide('tabs')}
|
||||||
|
title={this.$t('nav.back')}
|
||||||
|
class="button-unstyled"
|
||||||
|
>
|
||||||
|
<FAIcon
|
||||||
|
size="lg"
|
||||||
|
class="back-button-icon"
|
||||||
|
icon="chevron-left"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
{props.label}
|
||||||
|
</h2>
|
||||||
|
)
|
||||||
|
|
||||||
|
const wrapperClasses = ['tab-content-wrapper', active ? '-active' : '-hidden' ]
|
||||||
|
const contentClasses = ['tab-content']
|
||||||
|
if (props['full-width']) {
|
||||||
|
contentClasses.push('-full-width')
|
||||||
|
}
|
||||||
|
if (props['full-height']) {
|
||||||
|
contentClasses.push('-full-height')
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div class={wrapperClasses} >
|
||||||
|
<div class="tab-mobile-header">
|
||||||
|
{header}
|
||||||
|
</div>
|
||||||
|
<div class="tab-slot-wrapper">
|
||||||
|
<div class={contentClasses} >
|
||||||
|
{renderSlot}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
const rootClasses = ['vertical-tab-switcher']
|
||||||
|
if (useInterfaceStore().layoutType === 'mobile') {
|
||||||
|
rootClasses.push('-mobile')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.navSide === 'tabs') {
|
||||||
|
rootClasses.push('-nav-tabs')
|
||||||
|
} else {
|
||||||
|
rootClasses.push('-nav-contents')
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div ref="root" class={ rootClasses.join(' ') }>
|
||||||
|
<div
|
||||||
|
class="tabs"
|
||||||
|
role="tablist"
|
||||||
|
ref="nav"
|
||||||
|
>
|
||||||
|
{tabs}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
role="tabpanel"
|
||||||
|
class={'contents' + (this.scrollableTabs ? ' scrollable-tabs' : '')}
|
||||||
|
v-body-scroll-lock={this.bodyScrollLock}
|
||||||
|
ref="contents"
|
||||||
|
>
|
||||||
|
{contents}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
181
src/components/settings_modal/helpers/vertical_tab_switcher.scss
Normal file
181
src/components/settings_modal/helpers/vertical_tab_switcher.scss
Normal file
|
|
@ -0,0 +1,181 @@
|
||||||
|
.vertical-tab-switcher {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
container-type: inline-size;
|
||||||
|
|
||||||
|
> .tabs {
|
||||||
|
flex: 0 0 15em;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden auto;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
width: 15em;
|
||||||
|
min-width: 15em;
|
||||||
|
border-right: 1px solid;
|
||||||
|
border-right-color: var(--border);
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
> .menu-item {
|
||||||
|
padding: 0.5em 1em;
|
||||||
|
|
||||||
|
.tab-icon {
|
||||||
|
vertical-align: middle;
|
||||||
|
margin-right: 0.75em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> .contents {
|
||||||
|
flex: 1 0 35em;
|
||||||
|
|
||||||
|
.tab-content {
|
||||||
|
align-self: center;
|
||||||
|
|
||||||
|
&:not(.-full-width) {
|
||||||
|
max-width: 40em;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.-full-width {
|
||||||
|
align-self: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.-full-height {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-content-label {
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin: 0;
|
||||||
|
border-bottom: 1px solid var(--border);
|
||||||
|
display: none;
|
||||||
|
|
||||||
|
button {
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 0.5em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-slot-wrapper {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
height: 100%;
|
||||||
|
overflow-y: auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-content-wrapper {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
|
||||||
|
&.-hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.-mobile {
|
||||||
|
> .contents {
|
||||||
|
.tab-content-label {
|
||||||
|
display: block
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.-nav-contents {
|
||||||
|
> .contents {
|
||||||
|
display: block;
|
||||||
|
flex-grow: 1;
|
||||||
|
flex-shrink: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .tabs {
|
||||||
|
display: none;
|
||||||
|
flex-grow: 0;
|
||||||
|
flex-shrink: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.-nav-tabs {
|
||||||
|
> .tabs {
|
||||||
|
display: block;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .contents {
|
||||||
|
display: none;
|
||||||
|
flex-grow: 0;
|
||||||
|
flex-shrink: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@supports (container-type: inline-size) {
|
||||||
|
&,
|
||||||
|
&.-mobile {
|
||||||
|
&.-nav-contents,
|
||||||
|
&.-nav-tabs {
|
||||||
|
/* I THINK it's a false positive and eslint doesn't understand the @-rule */
|
||||||
|
/* stylelint-disable no-descending-specificity */
|
||||||
|
> .contents {
|
||||||
|
display: block;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .tabs {
|
||||||
|
display: block;
|
||||||
|
flex-grow: 0;
|
||||||
|
}
|
||||||
|
/* stylelint-enable no-descending-specificity */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@container (width < 50em) {
|
||||||
|
> .contents {
|
||||||
|
.tab-content-label {
|
||||||
|
display: block
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.-mobile {
|
||||||
|
> .contents {
|
||||||
|
.tab-content-label {
|
||||||
|
display: block
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&,
|
||||||
|
&.-mobile {
|
||||||
|
&.-nav-contents {
|
||||||
|
> .contents {
|
||||||
|
display: block;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .tabs {
|
||||||
|
display: none;
|
||||||
|
flex-grow: 0;
|
||||||
|
flex-shrink: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.-nav-tabs {
|
||||||
|
/* stylelint-disable no-descending-specificity */
|
||||||
|
> .tabs {
|
||||||
|
display: block;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .contents {
|
||||||
|
display: none;
|
||||||
|
flex-grow: 0;
|
||||||
|
flex-shrink: 1;
|
||||||
|
}
|
||||||
|
/* stylelint-enable no-descending-specificity */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,21 +1,48 @@
|
||||||
.settings-modal {
|
.settings-modal {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
h4 {
|
h2 {
|
||||||
|
font-size: 1.3rem;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-top: 1em;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-top: 1em;
|
||||||
margin-bottom: 0.5em;
|
margin-bottom: 0.5em;
|
||||||
|
border-bottom: 1px solid var(--border);
|
||||||
|
padding-bottom: 0.25em;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding-left: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
margin-top: 1em;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
h5 {
|
||||||
|
font-size: 1rem;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.setting-list,
|
.setting-list,
|
||||||
.option-list {
|
.option-list {
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
padding-left: 2em;
|
padding-left: 2em;
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
.btn:not(.dropdown-button) {
|
.btn:not(.dropdown-button) {
|
||||||
padding: 0 2em;
|
padding: 0 2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
li {
|
li {
|
||||||
margin-bottom: 0.5em;
|
margin: 1em 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.suboptions {
|
.suboptions {
|
||||||
|
|
@ -23,9 +50,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&.two-column {
|
&.two-column {
|
||||||
column-count: 2;
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
|
||||||
> li {
|
> li {
|
||||||
|
margin: 0;
|
||||||
break-inside: avoid;
|
break-inside: avoid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -42,7 +71,7 @@
|
||||||
transition: transform;
|
transition: transform;
|
||||||
transition-timing-function: ease-in-out;
|
transition-timing-function: ease-in-out;
|
||||||
transition-duration: 300ms;
|
transition-duration: 300ms;
|
||||||
width: 1000px;
|
width: 70em;
|
||||||
max-width: 90vw;
|
max-width: 90vw;
|
||||||
height: 90vh;
|
height: 90vh;
|
||||||
|
|
||||||
|
|
@ -77,18 +106,30 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&.-mobile {
|
&.-mobile {
|
||||||
.setting-list,
|
.tabs {
|
||||||
|
.menu-item {
|
||||||
|
font-size: 1.2em;
|
||||||
|
padding-top: 0.75em;
|
||||||
|
padding-bottom: 0.75em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-list:not(.suboptions),
|
||||||
.option-list {
|
.option-list {
|
||||||
padding-left: 0.25em;
|
padding-left: 0.25em;
|
||||||
|
|
||||||
|
|
||||||
|
/* stylelint-disable no-descending-specificity */
|
||||||
|
// it makes no sense
|
||||||
> li {
|
> li {
|
||||||
margin: 1em 0;
|
margin: 1em 0;
|
||||||
line-height: 1.5em;
|
line-height: 1.5em;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
/* stylelint-enable no-descending-specificity */
|
||||||
|
|
||||||
&.two-column {
|
&.two-column {
|
||||||
column-count: 1;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import TabSwitcher from 'src/components/tab_switcher/tab_switcher.jsx'
|
import VerticalTabSwitcher from './helpers/vertical_tab_switcher.jsx'
|
||||||
|
|
||||||
import InstanceTab from './admin_tabs/instance_tab.vue'
|
import InstanceTab from './admin_tabs/instance_tab.vue'
|
||||||
import LimitsTab from './admin_tabs/limits_tab.vue'
|
import LimitsTab from './admin_tabs/limits_tab.vue'
|
||||||
|
|
@ -31,7 +31,7 @@ library.add(
|
||||||
|
|
||||||
const SettingsModalAdminContent = {
|
const SettingsModalAdminContent = {
|
||||||
components: {
|
components: {
|
||||||
TabSwitcher,
|
VerticalTabSwitcher,
|
||||||
|
|
||||||
InstanceTab,
|
InstanceTab,
|
||||||
LimitsTab,
|
LimitsTab,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<tab-switcher
|
<vertical-tab-switcher
|
||||||
v-if="adminDescriptionsLoaded && (noDb || adminDbLoaded)"
|
v-if="adminDescriptionsLoaded && (noDb || adminDbLoaded)"
|
||||||
ref="tabSwitcher"
|
ref="tabSwitcher"
|
||||||
class="settings_tab-switcher"
|
class="settings_tab-switcher"
|
||||||
|
|
@ -71,7 +71,7 @@
|
||||||
>
|
>
|
||||||
<EmojiTab />
|
<EmojiTab />
|
||||||
</div>
|
</div>
|
||||||
</tab-switcher>
|
</vertical-tab-switcher>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="./settings_modal_admin_content.js"></script>
|
<script src="./settings_modal_admin_content.js"></script>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import TabSwitcher from 'src/components/tab_switcher/tab_switcher.jsx'
|
import VerticalTabSwitcher from './helpers/vertical_tab_switcher.jsx'
|
||||||
|
|
||||||
import DataImportExportTab from './tabs/data_import_export_tab.vue'
|
import DataImportExportTab from './tabs/data_import_export_tab.vue'
|
||||||
import MutesAndBlocksTab from './tabs/mutes_and_blocks_tab.vue'
|
import MutesAndBlocksTab from './tabs/mutes_and_blocks_tab.vue'
|
||||||
|
|
@ -7,42 +7,54 @@ import FilteringTab from './tabs/filtering_tab.vue'
|
||||||
import SecurityTab from './tabs/security_tab/security_tab.vue'
|
import SecurityTab from './tabs/security_tab/security_tab.vue'
|
||||||
import ProfileTab from './tabs/profile_tab.vue'
|
import ProfileTab from './tabs/profile_tab.vue'
|
||||||
import GeneralTab from './tabs/general_tab.vue'
|
import GeneralTab from './tabs/general_tab.vue'
|
||||||
|
import PostsTab from './tabs/posts_tab.vue'
|
||||||
|
import ComposingTab from './tabs/composing_tab.vue'
|
||||||
|
import ClutterTab from './tabs/clutter_tab.vue'
|
||||||
|
import LayoutTab from './tabs/layout_tab.vue'
|
||||||
import AppearanceTab from './tabs/appearance_tab.vue'
|
import AppearanceTab from './tabs/appearance_tab.vue'
|
||||||
import VersionTab from './tabs/version_tab.vue'
|
import DeveloperTab from './tabs/developer_tab.vue'
|
||||||
import ThemeTab from './tabs/theme_tab/theme_tab.vue'
|
import OldThemeTab from './tabs/old_theme_tab/old_theme_tab.vue'
|
||||||
import StyleTab from './tabs/style_tab/style_tab.vue'
|
import StyleTab from './tabs/style_tab/style_tab.vue'
|
||||||
|
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
import {
|
import {
|
||||||
faWrench,
|
faWrench,
|
||||||
faUser,
|
faUser,
|
||||||
|
faMessage,
|
||||||
faFilter,
|
faFilter,
|
||||||
faPaintBrush,
|
faPaintBrush,
|
||||||
faPalette,
|
faPalette,
|
||||||
faBell,
|
faBell,
|
||||||
faDownload,
|
faDownload,
|
||||||
faEyeSlash,
|
faEyeSlash,
|
||||||
faInfo,
|
faWindowRestore,
|
||||||
faWindowRestore
|
faCode,
|
||||||
|
faBroom,
|
||||||
|
faLock,
|
||||||
|
faColumns
|
||||||
} from '@fortawesome/free-solid-svg-icons'
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
import { useInterfaceStore } from 'src/stores/interface'
|
import { useInterfaceStore } from 'src/stores/interface'
|
||||||
|
|
||||||
library.add(
|
library.add(
|
||||||
faWrench,
|
faWrench,
|
||||||
faUser,
|
faUser,
|
||||||
faFilter,
|
faMessage,
|
||||||
faPaintBrush,
|
faWindowRestore,
|
||||||
faPalette,
|
faColumns,
|
||||||
faBell,
|
faBell,
|
||||||
faDownload,
|
faFilter,
|
||||||
faEyeSlash,
|
faEyeSlash,
|
||||||
faInfo,
|
faBroom,
|
||||||
faWindowRestore
|
faLock,
|
||||||
|
faDownload,
|
||||||
|
faPalette,
|
||||||
|
faPaintBrush,
|
||||||
|
faCode
|
||||||
)
|
)
|
||||||
|
|
||||||
const SettingsModalContent = {
|
const SettingsModalContent = {
|
||||||
components: {
|
components: {
|
||||||
TabSwitcher,
|
VerticalTabSwitcher,
|
||||||
|
|
||||||
DataImportExportTab,
|
DataImportExportTab,
|
||||||
MutesAndBlocksTab,
|
MutesAndBlocksTab,
|
||||||
|
|
@ -51,10 +63,14 @@ const SettingsModalContent = {
|
||||||
SecurityTab,
|
SecurityTab,
|
||||||
ProfileTab,
|
ProfileTab,
|
||||||
GeneralTab,
|
GeneralTab,
|
||||||
|
PostsTab,
|
||||||
|
ComposingTab,
|
||||||
|
ClutterTab,
|
||||||
|
LayoutTab,
|
||||||
AppearanceTab,
|
AppearanceTab,
|
||||||
StyleTab,
|
StyleTab,
|
||||||
VersionTab,
|
DeveloperTab,
|
||||||
ThemeTab
|
OldThemeTab
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
isLoggedIn () {
|
isLoggedIn () {
|
||||||
|
|
@ -68,9 +84,12 @@ const SettingsModalContent = {
|
||||||
},
|
},
|
||||||
expertLevel () {
|
expertLevel () {
|
||||||
return this.$store.state.config.expertLevel
|
return this.$store.state.config.expertLevel
|
||||||
|
}
|
||||||
},
|
},
|
||||||
isMobileLayout () {
|
data () {
|
||||||
return useInterfaceStore().layoutType === 'mobile'
|
return {
|
||||||
|
navCollapsed: false,
|
||||||
|
navHideHeader: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,11 @@
|
||||||
.settings_tab-switcher {
|
.settings_tab-switcher {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
h1 {
|
[full-height="true"] {
|
||||||
margin-bottom: 0.5em;
|
height: 100%
|
||||||
margin-top: 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
h4 {
|
|
||||||
margin-bottom: 0;
|
|
||||||
margin-top: 0.25em;
|
|
||||||
}
|
|
||||||
|
|
||||||
h5 {
|
|
||||||
margin-bottom: 0;
|
|
||||||
margin-top: 0.25em;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.setting-item {
|
.setting-item {
|
||||||
border-bottom: 2px solid var(--border);
|
|
||||||
margin: 1em 1em 1.4em;
|
margin: 1em 1em 1.4em;
|
||||||
padding-bottom: 1.4em;
|
padding-bottom: 1.4em;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
<template>
|
<template>
|
||||||
<tab-switcher
|
<vertical-tab-switcher
|
||||||
ref="tabSwitcher"
|
ref="tabSwitcher"
|
||||||
class="settings_tab-switcher"
|
class="settings_tab-switcher"
|
||||||
:side-tab-bar="true"
|
|
||||||
:scrollable-tabs="true"
|
:scrollable-tabs="true"
|
||||||
|
:child-collapsed="childCollapsed"
|
||||||
:body-scroll-lock="bodyLock"
|
:body-scroll-lock="bodyLock"
|
||||||
|
:hide-header="navHideHeader"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
:label="$t('settings.general')"
|
:label="$t('settings.general')"
|
||||||
|
|
@ -14,6 +15,32 @@
|
||||||
<GeneralTab />
|
<GeneralTab />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
v-if="isLoggedIn"
|
||||||
|
:label="$t('settings.profile_tab')"
|
||||||
|
icon="user"
|
||||||
|
data-tab-name="profile"
|
||||||
|
:full-width="true"
|
||||||
|
>
|
||||||
|
<ProfileTab />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
:label="$t('settings.composing')"
|
||||||
|
icon="pen-alt"
|
||||||
|
data-tab-name="composing"
|
||||||
|
:delay-render="true"
|
||||||
|
>
|
||||||
|
<ComposingTab />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
:label="$t('settings.posts')"
|
||||||
|
icon="message"
|
||||||
|
data-tab-name="posts"
|
||||||
|
:delay-render="true"
|
||||||
|
>
|
||||||
|
<PostsTab />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
:full-width="true"
|
||||||
:label="$t('settings.appearance')"
|
:label="$t('settings.appearance')"
|
||||||
icon="window-restore"
|
icon="window-restore"
|
||||||
data-tab-name="appearance"
|
data-tab-name="appearance"
|
||||||
|
|
@ -22,39 +49,48 @@
|
||||||
<AppearanceTab />
|
<AppearanceTab />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="expertLevel > 0"
|
:full-width="true"
|
||||||
:label="$t('settings.style.themes3.editor.title')"
|
:label="$t('settings.layout')"
|
||||||
icon="palette"
|
icon="table-columns"
|
||||||
data-tab-name="style"
|
data-tab-name="layout"
|
||||||
:delay-render="true"
|
:delay-render="true"
|
||||||
>
|
>
|
||||||
<StyleTab />
|
<LayoutTab />
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-if="expertLevel > 0"
|
|
||||||
:label="$t('settings.theme_old')"
|
|
||||||
icon="paint-brush"
|
|
||||||
data-tab-name="theme"
|
|
||||||
:delay-render="true"
|
|
||||||
>
|
|
||||||
<ThemeTab />
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-if="isLoggedIn"
|
|
||||||
:label="$t('settings.profile_tab')"
|
|
||||||
icon="user"
|
|
||||||
data-tab-name="profile"
|
|
||||||
>
|
|
||||||
<ProfileTab />
|
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="isLoggedIn"
|
v-if="isLoggedIn"
|
||||||
|
:full-width="true"
|
||||||
:label="$t('settings.notifications')"
|
:label="$t('settings.notifications')"
|
||||||
icon="bell"
|
icon="bell"
|
||||||
data-tab-name="notifications"
|
data-tab-name="notifications"
|
||||||
>
|
>
|
||||||
<NotificationsTab />
|
<NotificationsTab />
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
:label="$t('settings.filtering')"
|
||||||
|
:full-width="true"
|
||||||
|
icon="filter"
|
||||||
|
data-tab-name="filtering"
|
||||||
|
>
|
||||||
|
<FilteringTab />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="isLoggedIn"
|
||||||
|
:label="$t('settings.mutes_and_blocks')"
|
||||||
|
icon="eye-slash"
|
||||||
|
data-tab-name="mutesAndBlocks"
|
||||||
|
:full-width="true"
|
||||||
|
:full-height="true"
|
||||||
|
>
|
||||||
|
<MutesAndBlocksTab />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
:label="$t('settings.clutter')"
|
||||||
|
icon="broom"
|
||||||
|
data-tab-name="clutter"
|
||||||
|
>
|
||||||
|
<ClutterTab />
|
||||||
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="isLoggedIn"
|
v-if="isLoggedIn"
|
||||||
:label="$t('settings.security_tab')"
|
:label="$t('settings.security_tab')"
|
||||||
|
|
@ -63,22 +99,6 @@
|
||||||
>
|
>
|
||||||
<SecurityTab />
|
<SecurityTab />
|
||||||
</div>
|
</div>
|
||||||
<div
|
|
||||||
:label="$t('settings.filtering')"
|
|
||||||
icon="filter"
|
|
||||||
data-tab-name="filtering"
|
|
||||||
>
|
|
||||||
<FilteringTab />
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-if="isLoggedIn"
|
|
||||||
:label="$t('settings.mutes_and_blocks')"
|
|
||||||
:fullHeight="true"
|
|
||||||
icon="eye-slash"
|
|
||||||
data-tab-name="mutesAndBlocks"
|
|
||||||
>
|
|
||||||
<MutesAndBlocksTab />
|
|
||||||
</div>
|
|
||||||
<div
|
<div
|
||||||
v-if="isLoggedIn"
|
v-if="isLoggedIn"
|
||||||
:label="$t('settings.data_import_export_tab')"
|
:label="$t('settings.data_import_export_tab')"
|
||||||
|
|
@ -88,13 +108,34 @@
|
||||||
<DataImportExportTab />
|
<DataImportExportTab />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
:label="$t('settings.version.title')"
|
v-if="expertLevel > 0"
|
||||||
icon="info"
|
:label="$t('settings.style.themes3.editor.title')"
|
||||||
data-tab-name="version"
|
icon="palette"
|
||||||
|
data-tab-name="style"
|
||||||
|
:delay-render="true"
|
||||||
|
:full-width="true"
|
||||||
>
|
>
|
||||||
<VersionTab />
|
<StyleTab />
|
||||||
</div>
|
</div>
|
||||||
</tab-switcher>
|
<div
|
||||||
|
v-if="expertLevel > 0"
|
||||||
|
:label="$t('settings.theme_old')"
|
||||||
|
icon="paint-brush"
|
||||||
|
data-tab-name="theme"
|
||||||
|
:delay-render="true"
|
||||||
|
:full-width="true"
|
||||||
|
>
|
||||||
|
<OldThemeTab />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="expertLevel > 0"
|
||||||
|
:label="$t('settings.developer')"
|
||||||
|
icon="code"
|
||||||
|
data-tab-name="developer"
|
||||||
|
>
|
||||||
|
<DeveloperTab />
|
||||||
|
</div>
|
||||||
|
</vertical-tab-switcher>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="./settings_modal_user_content.js"></script>
|
<script src="./settings_modal_user_content.js"></script>
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,8 @@ import ChoiceSetting from '../helpers/choice_setting.vue'
|
||||||
import IntegerSetting from '../helpers/integer_setting.vue'
|
import IntegerSetting from '../helpers/integer_setting.vue'
|
||||||
import FloatSetting from '../helpers/float_setting.vue'
|
import FloatSetting from '../helpers/float_setting.vue'
|
||||||
import UnitSetting from '../helpers/unit_setting.vue'
|
import UnitSetting from '../helpers/unit_setting.vue'
|
||||||
import { defaultHorizontalUnits } from '../helpers/unit_setting.js'
|
|
||||||
import PaletteEditor from 'src/components/palette_editor/palette_editor.vue'
|
import PaletteEditor from 'src/components/palette_editor/palette_editor.vue'
|
||||||
import Preview from './theme_tab/theme_preview.vue'
|
import Preview from './old_theme_tab/theme_preview.vue'
|
||||||
import FontControl from 'src/components/font_control/font_control.vue'
|
|
||||||
|
|
||||||
import { newImporter } from 'src/services/export_import/export_import.js'
|
import { newImporter } from 'src/services/export_import/export_import.js'
|
||||||
import { convertTheme2To3 } from 'src/services/theme_data/theme2_to_theme3.js'
|
import { convertTheme2To3 } from 'src/services/theme_data/theme2_to_theme3.js'
|
||||||
|
|
@ -24,15 +22,6 @@ import ProfileSettingIndicator from '../helpers/profile_setting_indicator.vue'
|
||||||
import { mapActions } from 'pinia'
|
import { mapActions } from 'pinia'
|
||||||
import { useInterfaceStore, normalizeThemeData } from 'src/stores/interface'
|
import { useInterfaceStore, normalizeThemeData } from 'src/stores/interface'
|
||||||
|
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
|
||||||
import {
|
|
||||||
faGlobe
|
|
||||||
} from '@fortawesome/free-solid-svg-icons'
|
|
||||||
|
|
||||||
library.add(
|
|
||||||
faGlobe
|
|
||||||
)
|
|
||||||
|
|
||||||
const AppearanceTab = {
|
const AppearanceTab = {
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
|
|
@ -59,11 +48,6 @@ const AppearanceTab = {
|
||||||
],
|
],
|
||||||
userPalette: {},
|
userPalette: {},
|
||||||
intersectionObserver: null,
|
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) => ({
|
forcedRoundnessOptions: ['disabled', 'sharp', 'nonsharp', 'round'].map((mode, i) => ({
|
||||||
key: mode,
|
key: mode,
|
||||||
value: i - 1,
|
value: i - 1,
|
||||||
|
|
@ -86,7 +70,6 @@ const AppearanceTab = {
|
||||||
FloatSetting,
|
FloatSetting,
|
||||||
UnitSetting,
|
UnitSetting,
|
||||||
ProfileSettingIndicator,
|
ProfileSettingIndicator,
|
||||||
FontControl,
|
|
||||||
Preview,
|
Preview,
|
||||||
PaletteEditor
|
PaletteEditor
|
||||||
},
|
},
|
||||||
|
|
@ -253,33 +236,14 @@ const AppearanceTab = {
|
||||||
noIntersectionObserver () {
|
noIntersectionObserver () {
|
||||||
return !window.IntersectionObserver
|
return !window.IntersectionObserver
|
||||||
},
|
},
|
||||||
horizontalUnits () {
|
instanceWallpaper () {
|
||||||
return defaultHorizontalUnits
|
console.log(this.$store.state.instance.background)
|
||||||
},
|
this.$store.state.instance.background
|
||||||
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]
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
instanceWallpaperUsed () {
|
instanceWallpaperUsed () {
|
||||||
return this.$store.state.instance.background &&
|
return this.$store.state.instance.background &&
|
||||||
!this.$store.state.users.currentUser.background_image
|
!this.$store.state.users.currentUser.background_image
|
||||||
},
|
},
|
||||||
language: {
|
|
||||||
get: function () { return this.$store.getters.mergedConfig.interfaceLanguage },
|
|
||||||
set: function (val) {
|
|
||||||
this.$store.dispatch('setOption', { name: 'interfaceLanguage', value: val })
|
|
||||||
}
|
|
||||||
},
|
|
||||||
customThemeVersion () {
|
customThemeVersion () {
|
||||||
const { themeVersion } = useInterfaceStore()
|
const { themeVersion } = useInterfaceStore()
|
||||||
return themeVersion
|
return themeVersion
|
||||||
|
|
@ -295,18 +259,6 @@ const AppearanceTab = {
|
||||||
...SharedComputedObject()
|
...SharedComputedObject()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
updateFont (key, value) {
|
|
||||||
this.$store.dispatch('setOption', {
|
|
||||||
name: 'theme3hacks',
|
|
||||||
value: {
|
|
||||||
...this.mergedConfig.theme3hacks,
|
|
||||||
fonts: {
|
|
||||||
...this.mergedConfig.theme3hacks.fonts,
|
|
||||||
[key]: value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
importFile () {
|
importFile () {
|
||||||
this.fileImporter.importData()
|
this.fileImporter.importData()
|
||||||
},
|
},
|
||||||
|
|
@ -463,6 +415,9 @@ const AppearanceTab = {
|
||||||
this.submitBackground('')
|
this.submitBackground('')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
resetUploadedBackground () {
|
||||||
|
this.backgroundPreview = null
|
||||||
|
},
|
||||||
submitBackground (background) {
|
submitBackground (background) {
|
||||||
if (!this.backgroundPreview && background !== '') { return }
|
if (!this.backgroundPreview && background !== '') { return }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,16 @@
|
||||||
.appearance-tab {
|
.appearance-tab {
|
||||||
|
h3 {
|
||||||
|
border: none
|
||||||
|
}
|
||||||
|
|
||||||
.palette,
|
.palette,
|
||||||
.theme-notice {
|
.theme-notice {
|
||||||
padding: 0.5em;
|
padding: 0.5em;
|
||||||
margin: 1em;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.setting-item {
|
.theme-name {
|
||||||
padding-bottom: 0;
|
font-weight: 900;
|
||||||
|
padding-bottom: 0.5em;
|
||||||
&.heading {
|
|
||||||
display: grid;
|
|
||||||
align-items: baseline;
|
|
||||||
grid-template-columns: 1fr auto auto auto;
|
|
||||||
grid-gap: 0.5em;
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
flex: 1 0 auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
h4 {
|
|
||||||
margin: 0.5em 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="file"] {
|
input[type="file"] {
|
||||||
|
|
@ -29,7 +18,31 @@
|
||||||
height: auto;
|
height: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.banner-background {
|
||||||
|
display: flex;
|
||||||
|
gap: 1em;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner-background-input {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.5em;
|
||||||
|
|
||||||
|
.custom-bg-control {
|
||||||
|
display: grid;
|
||||||
|
gap: 0.5em;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.banner-background-preview {
|
.banner-background-preview {
|
||||||
|
display: flex;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
width: 300px;
|
width: 300px;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
@ -37,32 +50,85 @@
|
||||||
img {
|
img {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.fun-monitor {
|
||||||
|
position: relative;
|
||||||
|
pointer-events: none;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
* {
|
||||||
|
line-height: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.reset-button {
|
&-display-bezel,
|
||||||
|
&-display-screen {
|
||||||
|
aspect-ratio: 16 / 9;
|
||||||
|
width: 16em;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wallpaper {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0.2em;
|
inset: 0;
|
||||||
right: 0.2em;
|
background-color: var(--wallpaper);
|
||||||
border-radius: var(--roundness);
|
}
|
||||||
|
|
||||||
|
&-display-uploading {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
z-index: 1;
|
||||||
|
display: flex;
|
||||||
|
place-items: center;
|
||||||
|
place-content: center;
|
||||||
background-color: rgb(0 0 0 / 60%);
|
background-color: rgb(0 0 0 / 60%);
|
||||||
opacity: 0.7;
|
font-size: 4em;
|
||||||
width: 1.5em;
|
|
||||||
height: 1.5em;
|
|
||||||
text-align: center;
|
|
||||||
line-height: 1.5em;
|
|
||||||
font-size: 1.5em;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
svg {
|
&-display-screen {
|
||||||
color: white;
|
padding: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&-overlay {
|
||||||
|
background: transparent;
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-image {
|
||||||
|
aspect-ratio: 16 / 9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&-display-bezel {
|
||||||
|
padding: 1em;
|
||||||
|
margin: 0;
|
||||||
|
order: 1;
|
||||||
|
z-index: 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-neck {
|
||||||
|
width: 5em;
|
||||||
|
height: 3em;
|
||||||
|
margin-top: -1em;
|
||||||
|
margin-bottom: -0.5em;
|
||||||
|
order: 2
|
||||||
|
}
|
||||||
|
|
||||||
|
&-stand {
|
||||||
|
width: 8em;
|
||||||
|
height: 1em;
|
||||||
|
order: 3;
|
||||||
|
z-index: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.palettes-container {
|
.palettes-container {
|
||||||
height: 15em;
|
height: 15em;
|
||||||
|
|
@ -70,7 +136,8 @@
|
||||||
scrollbar-gutter: stable;
|
scrollbar-gutter: stable;
|
||||||
border-radius: var(--roundness);
|
border-radius: var(--roundness);
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
margin: -0.5em;
|
margin-bottom: 0.5em;
|
||||||
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.palettes {
|
.palettes {
|
||||||
|
|
@ -80,9 +147,9 @@
|
||||||
padding: 0.5em;
|
padding: 0.5em;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
h4 {
|
h5 {
|
||||||
margin: 0;
|
|
||||||
grid-column: 1 / span 2;
|
grid-column: 1 / span 2;
|
||||||
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -160,7 +227,7 @@
|
||||||
|
|
||||||
.theme-preview {
|
.theme-preview {
|
||||||
font-size: 1rem; // fix for firefox
|
font-size: 1rem; // fix for firefox
|
||||||
width: 19rem;
|
width: 14rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,15 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="appearance-tab"
|
class="appearance-tab"
|
||||||
:label="$t('settings.general')"
|
:label="$t('settings.interface')"
|
||||||
|
icon="table-columns"
|
||||||
>
|
>
|
||||||
<div class="setting-item">
|
<div
|
||||||
<h2>{{ $t('settings.theme') }}</h2>
|
class="setting-item"
|
||||||
|
:label="$t('settings.theme')"
|
||||||
|
icon="paintbrush"
|
||||||
|
>
|
||||||
|
<h3>{{ $t('settings.style.style_section') }}</h3>
|
||||||
<ul
|
<ul
|
||||||
ref="themeList"
|
ref="themeList"
|
||||||
class="theme-list"
|
class="theme-list"
|
||||||
|
|
@ -17,10 +22,10 @@
|
||||||
@click="resetTheming"
|
@click="resetTheming"
|
||||||
>
|
>
|
||||||
<preview id="theme-preview-stock" />
|
<preview id="theme-preview-stock" />
|
||||||
<h4 class="theme-name">
|
<span class="theme-name">
|
||||||
{{ $t('settings.style.stock_theme_used') }}
|
{{ $t('settings.style.stock_theme_used') }}
|
||||||
<span class="alert neutral version">v3</span>
|
<span class="alert neutral version">v3</span>
|
||||||
</h4>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
v-if="isCustomThemeUsed"
|
v-if="isCustomThemeUsed"
|
||||||
|
|
@ -28,10 +33,10 @@
|
||||||
class="button-default theme-preview toggled"
|
class="button-default theme-preview toggled"
|
||||||
>
|
>
|
||||||
<preview />
|
<preview />
|
||||||
<h4 class="theme-name">
|
<span class="theme-name">
|
||||||
{{ $t('settings.style.custom_theme_used') }}
|
{{ $t('settings.style.custom_theme_used') }}
|
||||||
<span class="alert neutral version">v2</span>
|
<span class="alert neutral version">v2</span>
|
||||||
</h4>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
v-if="isCustomStyleUsed"
|
v-if="isCustomStyleUsed"
|
||||||
|
|
@ -39,10 +44,10 @@
|
||||||
class="button-default theme-preview toggled"
|
class="button-default theme-preview toggled"
|
||||||
>
|
>
|
||||||
<preview />
|
<preview />
|
||||||
<h4 class="theme-name">
|
<span class="theme-name">
|
||||||
{{ $t('settings.style.custom_style_used') }}
|
{{ $t('settings.style.custom_style_used') }}
|
||||||
<span class="alert neutral version">v3</span>
|
<span class="alert neutral version">v3</span>
|
||||||
</h4>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
v-for="style in availableStyles"
|
v-for="style in availableStyles"
|
||||||
|
|
@ -54,10 +59,10 @@
|
||||||
@click="style.version === 'v2' ? setTheme(style.key) : setStyle(style.key)"
|
@click="style.version === 'v2' ? setTheme(style.key) : setStyle(style.key)"
|
||||||
>
|
>
|
||||||
<preview :id="'theme-preview-' + style.key" />
|
<preview :id="'theme-preview-' + style.key" />
|
||||||
<h4 class="theme-name">
|
<span class="theme-name">
|
||||||
{{ style.name }}
|
{{ style.name }}
|
||||||
<span class="alert neutral version">{{ style.version }}</span>
|
<span class="alert neutral version">{{ style.version }}</span>
|
||||||
</h4>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="import-file-container">
|
<div class="import-file-container">
|
||||||
|
|
@ -70,16 +75,14 @@
|
||||||
<FAIcon icon="folder-open" />
|
<FAIcon icon="folder-open" />
|
||||||
{{ $t('settings.style.themes3.editor.load_style') }}
|
{{ $t('settings.style.themes3.editor.load_style') }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
<h4>{{ $t('settings.style.themes3.palette.label') }}</h4>
|
||||||
<div class="setting-item">
|
|
||||||
<h2>{{ $t('settings.style.themes3.palette.label') }}</h2>
|
|
||||||
<div
|
<div
|
||||||
v-if="customThemeVersion === 'v3'"
|
v-if="customThemeVersion === 'v3'"
|
||||||
class="palettes-container"
|
class="palettes-container"
|
||||||
>
|
>
|
||||||
<h4 v-if="stylePalettes?.length > 0">
|
<h5 v-if="stylePalettes?.length > 0">
|
||||||
{{ $t('settings.style.themes3.palette.style') }}
|
{{ $t('settings.style.themes3.palette.style') }}
|
||||||
</h4>
|
</h5>
|
||||||
<div class="palettes">
|
<div class="palettes">
|
||||||
<button
|
<button
|
||||||
v-for="p in stylePalettes || []"
|
v-for="p in stylePalettes || []"
|
||||||
|
|
@ -103,7 +106,7 @@
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
<h4>{{ $t('settings.style.themes3.palette.bundled') }}</h4>
|
<h5>{{ $t('settings.style.themes3.palette.bundled') }}</h5>
|
||||||
<button
|
<button
|
||||||
v-for="p in bundledPalettes"
|
v-for="p in bundledPalettes"
|
||||||
:key="p.name"
|
:key="p.name"
|
||||||
|
|
@ -130,9 +133,9 @@
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<template v-if="customThemeVersion === 'v3'">
|
<template v-if="customThemeVersion === 'v3'">
|
||||||
<h4 v-if="expertLevel > 0">
|
<h5 v-if="expertLevel > 0">
|
||||||
{{ $t('settings.style.themes3.palette.user') }}
|
{{ $t('settings.style.themes3.palette.user') }}
|
||||||
</h4>
|
</h5>
|
||||||
<PaletteEditor
|
<PaletteEditor
|
||||||
v-if="expertLevel > 0"
|
v-if="expertLevel > 0"
|
||||||
v-model="userPalette"
|
v-model="userPalette"
|
||||||
|
|
@ -150,236 +153,73 @@
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<h3>{{ $t('settings.background') }}</h3>
|
||||||
<div class="setting-item">
|
<div class="banner-background">
|
||||||
<h2>{{ $t('settings.background') }}</h2>
|
|
||||||
<div class="banner-background-preview">
|
<div class="banner-background-preview">
|
||||||
<img :src="user.background_image">
|
<div class="fun-monitor">
|
||||||
<button
|
<div class="fun-monitor-stand button-default" />
|
||||||
v-if="!isDefaultBackground"
|
<div class="fun-monitor-neck button-default" />
|
||||||
class="button-unstyled reset-button"
|
<div class="fun-monitor-display-bezel button-default">
|
||||||
:title="$t('settings.reset_profile_background')"
|
<div class="fun-monitor-display-screen input">
|
||||||
@click="resetBackground"
|
<img
|
||||||
|
v-if="backgroundPreview || user.background_image || instanceWallpaper"
|
||||||
|
class="fun-monitor-display-screen-image"
|
||||||
|
:src="backgroundPreview || user.background_image || instanceWallpaper"
|
||||||
|
/>
|
||||||
|
<div v-else class="wallpaper" />
|
||||||
|
<div class="fun-monitor-display-screen-overlay input" />
|
||||||
|
<div
|
||||||
|
v-if="backgroundUploading"
|
||||||
|
class="fun-monitor-display-uploading"
|
||||||
>
|
>
|
||||||
<FAIcon
|
<FAIcon
|
||||||
icon="times"
|
class="fun-monitor-display-screen-uploading"
|
||||||
type="button"
|
spin
|
||||||
|
icon="circle-notch"
|
||||||
/>
|
/>
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
<p>{{ $t('settings.set_new_background') }}</p>
|
</div>
|
||||||
<img
|
</div>
|
||||||
v-if="backgroundPreview"
|
</div>
|
||||||
class="banner-background-preview"
|
</div>
|
||||||
:src="backgroundPreview"
|
<div class="banner-background-input">
|
||||||
>
|
<h4>{{ $t('settings.set_new_background') }}</h4>
|
||||||
<div>
|
|
||||||
<input
|
<input
|
||||||
type="file"
|
type="file"
|
||||||
class="input"
|
class="input"
|
||||||
@change="uploadFile('background', $event)"
|
@change="uploadFile('background', $event)"
|
||||||
>
|
>
|
||||||
</div>
|
<div class="custom-bg-control">
|
||||||
<FAIcon
|
|
||||||
v-if="backgroundUploading"
|
|
||||||
class="uploading"
|
|
||||||
spin
|
|
||||||
icon="circle-notch"
|
|
||||||
/>
|
|
||||||
<button
|
<button
|
||||||
v-else-if="backgroundPreview"
|
:disabled="!backgroundPreview"
|
||||||
class="btn button-default"
|
class="btn button-default"
|
||||||
@click="submitBackground(background)"
|
@click="submitBackground(background)"
|
||||||
>
|
>
|
||||||
{{ $t('settings.save') }}
|
{{ $t('settings.save') }}
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
:disabled="!backgroundPreview"
|
||||||
|
class="btn button-default"
|
||||||
|
@click="resetUploadedBackground"
|
||||||
|
>
|
||||||
|
{{ $t('settings.reset') }}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-item">
|
<button
|
||||||
<h2>{{ $t('settings.scale_and_layout') }}</h2>
|
v-if="!isDefaultBackground"
|
||||||
|
class="btn button-default reset-button"
|
||||||
|
:title="$t('settings.reset_profile_background')"
|
||||||
|
@click="resetBackground"
|
||||||
|
>
|
||||||
|
{{ $t('settings.reset_profile_background') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h3>{{ $t('settings.visual_tweaks') }}</h3>
|
||||||
<div class="alert neutral theme-notice">
|
<div class="alert neutral theme-notice">
|
||||||
{{ $t("settings.style.appearance_tab_note") }}
|
{{ $t("settings.style.visual_tweaks_section_note") }}
|
||||||
</div>
|
</div>
|
||||||
<ul class="setting-list">
|
<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>
|
|
||||||
<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.style.interface_font_user_override') }}</h3>
|
|
||||||
<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:model-value="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:model-value="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:model-value="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:model-value="v => updateFont('monospace', v)"
|
|
||||||
/>
|
|
||||||
</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>
|
|
||||||
<li>
|
|
||||||
<UnitSetting
|
|
||||||
path="themeEditorMinWidth"
|
|
||||||
:units="['px', 'rem']"
|
|
||||||
expert="1"
|
|
||||||
>
|
|
||||||
{{ $t('settings.theme_editor_min_width') }}
|
|
||||||
</UnitSetting>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="setting-item">
|
|
||||||
<h2>{{ $t('settings.visual_tweaks') }}</h2>
|
|
||||||
<ul class="setting-list">
|
|
||||||
<li>
|
|
||||||
<BooleanSetting path="modalMobileCenter">
|
|
||||||
{{ $t('settings.mobile_center_dialog') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
<li>
|
<li>
|
||||||
<ChoiceSetting
|
<ChoiceSetting
|
||||||
id="forcedRoundness"
|
id="forcedRoundness"
|
||||||
|
|
@ -403,22 +243,6 @@
|
||||||
{{ $t('settings.hide_wallpaper') }}
|
{{ $t('settings.hide_wallpaper') }}
|
||||||
</BooleanSetting>
|
</BooleanSetting>
|
||||||
</li>
|
</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>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
194
src/components/settings_modal/tabs/clutter_tab.js
Normal file
194
src/components/settings_modal/tabs/clutter_tab.js
Normal file
|
|
@ -0,0 +1,194 @@
|
||||||
|
import { mapState, mapActions } from 'pinia'
|
||||||
|
import { mapState as mapVuexState } from 'vuex'
|
||||||
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
|
import { useServerSideStorageStore } from 'src/stores/serverSideStorage'
|
||||||
|
|
||||||
|
import BooleanSetting from '../helpers/boolean_setting.vue'
|
||||||
|
import ChoiceSetting from '../helpers/choice_setting.vue'
|
||||||
|
import UnitSetting from '../helpers/unit_setting.vue'
|
||||||
|
import IntegerSetting from '../helpers/integer_setting.vue'
|
||||||
|
import HelpIndicator from '../helpers/help_indicator.vue'
|
||||||
|
import Checkbox from 'src/components/checkbox/checkbox.vue'
|
||||||
|
import Select from 'src/components/select/select.vue'
|
||||||
|
|
||||||
|
import SharedComputedObject from '../helpers/shared_computed_object.js'
|
||||||
|
|
||||||
|
|
||||||
|
const ClutterTab = {
|
||||||
|
components: {
|
||||||
|
BooleanSetting,
|
||||||
|
ChoiceSetting,
|
||||||
|
UnitSetting,
|
||||||
|
IntegerSetting,
|
||||||
|
Checkbox,
|
||||||
|
Select,
|
||||||
|
HelpIndicator
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
instanceSpecificPanelPresent () { return this.$store.state.instance.showInstanceSpecificPanel },
|
||||||
|
...SharedComputedObject(),
|
||||||
|
...mapState(
|
||||||
|
useServerSideStorageStore,
|
||||||
|
{
|
||||||
|
muteFilters: store => Object.entries(store.prefsStorage.simple.muteFilters),
|
||||||
|
muteFiltersObject: store => store.prefsStorage.simple.muteFilters
|
||||||
|
}
|
||||||
|
),
|
||||||
|
...mapVuexState({
|
||||||
|
blockExpirationSupported: state => state.instance.blockExpiration
|
||||||
|
}),
|
||||||
|
onMuteDefaultActionLv1: {
|
||||||
|
get () {
|
||||||
|
const value = this.$store.state.config.onMuteDefaultAction
|
||||||
|
if (value === 'ask' || value === 'forever') {
|
||||||
|
return value
|
||||||
|
} else {
|
||||||
|
return 'temporarily'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
set (value) {
|
||||||
|
let realValue = value
|
||||||
|
if (value !== 'ask' && value !== 'forever') {
|
||||||
|
realValue = '14d'
|
||||||
|
}
|
||||||
|
this.$store.dispatch('setOption', { name: 'onMuteDefaultAction', value: realValue })
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onBlockDefaultActionLv1: {
|
||||||
|
get () {
|
||||||
|
const value = this.$store.state.config.onBlockDefaultAction
|
||||||
|
if (value === 'ask' || value === 'forever') {
|
||||||
|
return value
|
||||||
|
} else {
|
||||||
|
return 'temporarily'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
set (value) {
|
||||||
|
let realValue = value
|
||||||
|
if (value !== 'ask' && value !== 'forever') {
|
||||||
|
realValue = '14d'
|
||||||
|
}
|
||||||
|
this.$store.dispatch('setOption', { name: 'onBlockDefaultAction', value: realValue })
|
||||||
|
}
|
||||||
|
},
|
||||||
|
muteFiltersDraft () {
|
||||||
|
return Object.entries(this.muteFiltersDraftObject)
|
||||||
|
},
|
||||||
|
muteFiltersExpired () {
|
||||||
|
const now = Date.now()
|
||||||
|
return Object
|
||||||
|
.entries(this.muteFiltersDraftObject)
|
||||||
|
.filter(([, { expires }]) => expires != null && expires <= now)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapActions(useServerSideStorageStore, ['setPreference', 'unsetPreference', 'pushServerSideStorage']),
|
||||||
|
getDatetimeLocal (timestamp) {
|
||||||
|
const date = new Date(timestamp)
|
||||||
|
const fmt = new Intl.NumberFormat("en-US", {minimumIntegerDigits: 2})
|
||||||
|
const datetime = [
|
||||||
|
date.getFullYear(),
|
||||||
|
'-',
|
||||||
|
fmt.format(date.getMonth() + 1),
|
||||||
|
'-',
|
||||||
|
fmt.format(date.getDate()),
|
||||||
|
'T',
|
||||||
|
fmt.format(date.getHours()),
|
||||||
|
':',
|
||||||
|
fmt.format(date.getMinutes())
|
||||||
|
].join('')
|
||||||
|
return datetime
|
||||||
|
},
|
||||||
|
checkRegexValid (id) {
|
||||||
|
const filter = this.muteFiltersObject[id]
|
||||||
|
if (filter.type !== 'regexp') return true
|
||||||
|
if (filter.type !== 'user_regexp') return true
|
||||||
|
const { value } = filter
|
||||||
|
let valid = true
|
||||||
|
try {
|
||||||
|
new RegExp(value)
|
||||||
|
} catch {
|
||||||
|
valid = false
|
||||||
|
console.error('Invalid RegExp: ' + value)
|
||||||
|
}
|
||||||
|
return valid
|
||||||
|
},
|
||||||
|
createFilter (filter = {
|
||||||
|
type: 'word',
|
||||||
|
value: '',
|
||||||
|
name: 'New Filter',
|
||||||
|
enabled: true,
|
||||||
|
expires: null,
|
||||||
|
hide: false,
|
||||||
|
}) {
|
||||||
|
const newId = uuidv4()
|
||||||
|
|
||||||
|
filter.order = this.muteFilters.length + 2
|
||||||
|
this.muteFiltersDraftObject[newId] = filter
|
||||||
|
this.setPreference({ path: 'simple.muteFilters.' + newId , value: filter })
|
||||||
|
this.pushServerSideStorage()
|
||||||
|
},
|
||||||
|
exportFilter(id) {
|
||||||
|
this.exportedFilter = { ...this.muteFiltersDraftObject[id] }
|
||||||
|
delete this.exportedFilter.order
|
||||||
|
this.filterExporter.exportData()
|
||||||
|
},
|
||||||
|
importFilter() {
|
||||||
|
this.filterImporter.importData()
|
||||||
|
},
|
||||||
|
copyFilter (id) {
|
||||||
|
const filter = { ...this.muteFiltersDraftObject[id] }
|
||||||
|
const newId = uuidv4()
|
||||||
|
|
||||||
|
this.muteFiltersDraftObject[newId] = filter
|
||||||
|
this.setPreference({ path: 'simple.muteFilters.' + newId , value: filter })
|
||||||
|
this.pushServerSideStorage()
|
||||||
|
},
|
||||||
|
deleteFilter (id) {
|
||||||
|
delete this.muteFiltersDraftObject[id]
|
||||||
|
this.unsetPreference({ path: 'simple.muteFilters.' + id , value: null })
|
||||||
|
this.pushServerSideStorage()
|
||||||
|
},
|
||||||
|
purgeExpiredFilters () {
|
||||||
|
this.muteFiltersExpired.forEach(([id]) => {
|
||||||
|
console.log(id)
|
||||||
|
delete this.muteFiltersDraftObject[id]
|
||||||
|
this.unsetPreference({ path: 'simple.muteFilters.' + id , value: null })
|
||||||
|
})
|
||||||
|
this.pushServerSideStorage()
|
||||||
|
},
|
||||||
|
updateFilter(id, field, value) {
|
||||||
|
const filter = { ...this.muteFiltersDraftObject[id] }
|
||||||
|
if (field === 'expires-never') {
|
||||||
|
if (!value) {
|
||||||
|
const offset = 1000 * 60 * 60 * 24 * 14 // 2 weeks
|
||||||
|
const date = Date.now() + offset
|
||||||
|
filter.expires = date
|
||||||
|
} else {
|
||||||
|
filter.expires = null
|
||||||
|
}
|
||||||
|
} else if (field === 'expires') {
|
||||||
|
const parsed = Date.parse(value)
|
||||||
|
filter.expires = parsed.valueOf()
|
||||||
|
} else {
|
||||||
|
filter[field] = value
|
||||||
|
}
|
||||||
|
this.muteFiltersDraftObject[id] = filter
|
||||||
|
this.muteFiltersDraftDirty[id] = true
|
||||||
|
},
|
||||||
|
saveFilter(id) {
|
||||||
|
this.setPreference({ path: 'simple.muteFilters.' + id , value: this.muteFiltersDraftObject[id] })
|
||||||
|
this.pushServerSideStorage()
|
||||||
|
this.muteFiltersDraftDirty[id] = false
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Updating nested properties
|
||||||
|
watch: {
|
||||||
|
replyVisibility () {
|
||||||
|
this.$store.dispatch('queueFlushAll')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ClutterTab
|
||||||
88
src/components/settings_modal/tabs/clutter_tab.vue
Normal file
88
src/components/settings_modal/tabs/clutter_tab.vue
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
<template>
|
||||||
|
<div class="clutter-tab">
|
||||||
|
<div class="setting-item">
|
||||||
|
<h3>{{ $t('settings.interface') }}</h3>
|
||||||
|
<ul class="setting-list">
|
||||||
|
<li>
|
||||||
|
<BooleanSetting path="alwaysShowSubjectInput">
|
||||||
|
{{ $t('settings.subject_input_always_show') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting path="minimalScopesMode">
|
||||||
|
{{ $t('settings.minimal_scopes_mode') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting path="hidePostStats">
|
||||||
|
{{ $t('settings.hide_post_stats') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting
|
||||||
|
path="hideUserStats"
|
||||||
|
>
|
||||||
|
{{ $t('settings.hide_user_stats') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting path="hideBotIndication">
|
||||||
|
{{ $t('settings.hide_actor_type_indication') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting path="hideScrobbles">
|
||||||
|
{{ $t('settings.hide_scrobbles') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
<ul class="setting-list suboptions">
|
||||||
|
<li>
|
||||||
|
<UnitSetting
|
||||||
|
key="hideScrobblesAfter"
|
||||||
|
path="hideScrobblesAfter"
|
||||||
|
:units="['m', 'h', 'd']"
|
||||||
|
unit-set="time"
|
||||||
|
>
|
||||||
|
{{ $t('settings.hide_scrobbles_after') }}
|
||||||
|
</UnitSetting>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<h3>{{ $t('settings.attachments') }}</h3>
|
||||||
|
<ul class="setting-list">
|
||||||
|
<li>
|
||||||
|
<IntegerSetting
|
||||||
|
path="maxThumbnails"
|
||||||
|
:min="0"
|
||||||
|
>
|
||||||
|
{{ $t('settings.max_thumbnails') }}
|
||||||
|
</IntegerSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting path="hideAttachments">
|
||||||
|
{{ $t('settings.hide_attachments_in_tl') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting path="hideAttachmentsInConv">
|
||||||
|
{{ $t('settings.hide_attachments_in_convo') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting path="userCardHidePersonalMarks">
|
||||||
|
{{ $t('settings.user_card_hide_personal_marks') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<li v-if="instanceShoutboxPresent">
|
||||||
|
<BooleanSetting
|
||||||
|
path="hideShoutbox"
|
||||||
|
>
|
||||||
|
{{ $t('settings.hide_shoutbox') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script src="./clutter_tab.js"></script>
|
||||||
178
src/components/settings_modal/tabs/composing_tab.js
Normal file
178
src/components/settings_modal/tabs/composing_tab.js
Normal file
|
|
@ -0,0 +1,178 @@
|
||||||
|
import { mapState } from 'vuex'
|
||||||
|
|
||||||
|
import BooleanSetting from '../helpers/boolean_setting.vue'
|
||||||
|
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 from '../helpers/unit_setting.vue'
|
||||||
|
import InterfaceLanguageSwitcher from 'src/components/interface_language_switcher/interface_language_switcher.vue'
|
||||||
|
import Select from 'src/components/select/select.vue'
|
||||||
|
import ProfileSettingIndicator from '../helpers/profile_setting_indicator.vue'
|
||||||
|
import FontControl from 'src/components/font_control/font_control.vue'
|
||||||
|
|
||||||
|
import SharedComputedObject from '../helpers/shared_computed_object.js'
|
||||||
|
|
||||||
|
import localeService from 'src/services/locale/locale.service.js'
|
||||||
|
import { clearCache, cacheKey, emojiCacheKey } from 'src/services/sw/sw.js'
|
||||||
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
|
import {
|
||||||
|
faGlobe,
|
||||||
|
faMessage,
|
||||||
|
faPenAlt,
|
||||||
|
faDatabase,
|
||||||
|
faSliders
|
||||||
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
|
|
||||||
|
library.add(
|
||||||
|
faGlobe,
|
||||||
|
faMessage,
|
||||||
|
faPenAlt,
|
||||||
|
faDatabase,
|
||||||
|
faSliders
|
||||||
|
)
|
||||||
|
|
||||||
|
const ComposingTab = {
|
||||||
|
props: {
|
||||||
|
parentCollapsed: {
|
||||||
|
required: true,
|
||||||
|
type: Boolean
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
subjectLineOptions: ['email', 'noop', 'masto'].map(mode => ({
|
||||||
|
key: mode,
|
||||||
|
value: mode,
|
||||||
|
label: this.$t(`settings.subject_line_${mode === 'masto' ? 'mastodon' : mode}`)
|
||||||
|
})),
|
||||||
|
conversationDisplayOptions: ['tree', 'linear'].map(mode => ({
|
||||||
|
key: mode,
|
||||||
|
value: mode,
|
||||||
|
label: this.$t(`settings.conversation_display_${mode}`)
|
||||||
|
})),
|
||||||
|
absoluteTime12hOptions: ['24h', '12h'].map(mode => ({
|
||||||
|
key: mode,
|
||||||
|
value: mode,
|
||||||
|
label: this.$t(`settings.absolute_time_format_12h_${mode}`)
|
||||||
|
})),
|
||||||
|
conversationOtherRepliesButtonOptions: ['below', 'inside'].map(mode => ({
|
||||||
|
key: mode,
|
||||||
|
value: mode,
|
||||||
|
label: this.$t(`settings.conversation_other_replies_button_${mode}`)
|
||||||
|
})),
|
||||||
|
mentionLinkDisplayOptions: ['short', 'full_for_remote', 'full'].map(mode => ({
|
||||||
|
key: mode,
|
||||||
|
value: mode,
|
||||||
|
label: this.$t(`settings.mention_link_display_${mode}`)
|
||||||
|
})),
|
||||||
|
userPopoverAvatarActionOptions: ['close', 'zoom', 'open'].map(mode => ({
|
||||||
|
key: mode,
|
||||||
|
value: mode,
|
||||||
|
label: this.$t(`settings.user_popover_avatar_action_${mode}`)
|
||||||
|
})),
|
||||||
|
unsavedPostActionOptions: ['save', 'discard', 'confirm'].map(mode => ({
|
||||||
|
key: mode,
|
||||||
|
value: mode,
|
||||||
|
label: this.$t(`settings.unsaved_post_action_${mode}`)
|
||||||
|
})),
|
||||||
|
loopSilentAvailable:
|
||||||
|
// Firefox
|
||||||
|
Object.getOwnPropertyDescriptor(HTMLVideoElement.prototype, 'mozHasAudio') ||
|
||||||
|
// Chrome-likes
|
||||||
|
Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'webkitAudioDecodedByteCount') ||
|
||||||
|
// Future spec, still not supported in Nightly 63 as of 08/2018
|
||||||
|
Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'audioTracks'),
|
||||||
|
emailLanguage: this.$store.state.users.currentUser.language || ['']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
BooleanSetting,
|
||||||
|
ChoiceSetting,
|
||||||
|
IntegerSetting,
|
||||||
|
FloatSetting,
|
||||||
|
UnitSetting,
|
||||||
|
InterfaceLanguageSwitcher,
|
||||||
|
ProfileSettingIndicator,
|
||||||
|
ScopeSelector,
|
||||||
|
Select,
|
||||||
|
FontControl
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
postFormats () {
|
||||||
|
return this.$store.state.instance.postFormats || []
|
||||||
|
},
|
||||||
|
postContentOptions () {
|
||||||
|
return this.postFormats.map(format => ({
|
||||||
|
key: format,
|
||||||
|
value: format,
|
||||||
|
label: this.$t(`post_status.content_type["${format}"]`)
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
language: {
|
||||||
|
get: function () { return this.$store.getters.mergedConfig.interfaceLanguage },
|
||||||
|
set: function (val) {
|
||||||
|
this.$store.dispatch('setOption', { name: 'interfaceLanguage', value: val })
|
||||||
|
}
|
||||||
|
},
|
||||||
|
...SharedComputedObject(),
|
||||||
|
...mapState({
|
||||||
|
blockExpirationSupported: state => state.instance.blockExpiration,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
changeDefaultScope (value) {
|
||||||
|
this.$store.dispatch('setProfileOption', { name: 'defaultScope', value })
|
||||||
|
},
|
||||||
|
clearCache (key) {
|
||||||
|
clearCache(key)
|
||||||
|
.then(() => {
|
||||||
|
this.$store.dispatch('settingsSaved', { success: true })
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
this.$store.dispatch('settingsSaved', { error })
|
||||||
|
})
|
||||||
|
},
|
||||||
|
tooSmall () {
|
||||||
|
this.$emit('tooSmall')
|
||||||
|
},
|
||||||
|
tooBig () {
|
||||||
|
this.$emit('tooBig')
|
||||||
|
},
|
||||||
|
getNavMode () {
|
||||||
|
return this.$refs.tabSwitcher.getNavMode()
|
||||||
|
},
|
||||||
|
clearAssetCache () {
|
||||||
|
this.clearCache(cacheKey)
|
||||||
|
},
|
||||||
|
clearEmojiCache () {
|
||||||
|
this.clearCache(emojiCacheKey)
|
||||||
|
},
|
||||||
|
updateProfile () {
|
||||||
|
const params = {
|
||||||
|
language: localeService.internalToBackendLocaleMulti(this.emailLanguage)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$store.state.api.backendInteractor
|
||||||
|
.updateProfile({ params })
|
||||||
|
.then((user) => {
|
||||||
|
this.$store.commit('addNewUsers', [user])
|
||||||
|
this.$store.commit('setCurrentUser', user)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
updateFont (key, value) {
|
||||||
|
this.$store.dispatch('setOption', {
|
||||||
|
name: 'theme3hacks',
|
||||||
|
value: {
|
||||||
|
...this.mergedConfig.theme3hacks,
|
||||||
|
fonts: {
|
||||||
|
...this.mergedConfig.theme3hacks.fonts,
|
||||||
|
[key]: value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ComposingTab
|
||||||
115
src/components/settings_modal/tabs/composing_tab.vue
Normal file
115
src/components/settings_modal/tabs/composing_tab.vue
Normal file
|
|
@ -0,0 +1,115 @@
|
||||||
|
<template>
|
||||||
|
<div :label="$t('settings.posts')">
|
||||||
|
<div class="setting-item">
|
||||||
|
<h3>{{ $t('settings.general') }}</h3>
|
||||||
|
<ul class="setting-list">
|
||||||
|
<li>
|
||||||
|
<label for="default-vis">
|
||||||
|
{{ $t('settings.default_vis') }}
|
||||||
|
{{ ' ' }}
|
||||||
|
<ScopeSelector
|
||||||
|
class="scope-selector"
|
||||||
|
:show-all="true"
|
||||||
|
:user-default="$store.state.profileConfig.defaultScope"
|
||||||
|
:initial-scope="$store.state.profileConfig.defaultScope"
|
||||||
|
:on-scope-change="changeDefaultScope"
|
||||||
|
:unstyled="false"
|
||||||
|
uns
|
||||||
|
/>
|
||||||
|
<ProfileSettingIndicator :is-profile="true" />
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<!-- <BooleanSetting source="profile" path="defaultNSFW"> -->
|
||||||
|
<BooleanSetting path="sensitiveByDefault">
|
||||||
|
{{ $t('settings.sensitive_by_default') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<li v-if="postFormats.length > 0">
|
||||||
|
<ChoiceSetting
|
||||||
|
id="postContentType"
|
||||||
|
path="postContentType"
|
||||||
|
:options="postContentOptions"
|
||||||
|
>
|
||||||
|
{{ $t('settings.default_post_status_content_type') }}
|
||||||
|
</ChoiceSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting path="padEmoji">
|
||||||
|
{{ $t('settings.pad_emoji') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting
|
||||||
|
path="autocompleteSelect"
|
||||||
|
expert="1"
|
||||||
|
>
|
||||||
|
{{ $t('settings.autocomplete_select_first') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting
|
||||||
|
path="autoSaveDraft"
|
||||||
|
>
|
||||||
|
{{ $t('settings.auto_save_draft') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<li v-if="!mergedConfig.autoSaveDraft">
|
||||||
|
<ChoiceSetting
|
||||||
|
id="unsavedPostAction"
|
||||||
|
path="unsavedPostAction"
|
||||||
|
:options="unsavedPostActionOptions"
|
||||||
|
expert="1"
|
||||||
|
>
|
||||||
|
{{ $t('settings.unsaved_post_action') }}
|
||||||
|
</ChoiceSetting>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<h3>{{ $t('settings.replies') }}</h3>
|
||||||
|
<ul class="setting-list">
|
||||||
|
<li>
|
||||||
|
<BooleanSetting
|
||||||
|
path="scopeCopy"
|
||||||
|
>
|
||||||
|
{{ $t('settings.scope_copy') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<ChoiceSetting
|
||||||
|
id="subjectLineBehavior"
|
||||||
|
path="subjectLineBehavior"
|
||||||
|
:options="subjectLineOptions"
|
||||||
|
>
|
||||||
|
{{ $t('settings.subject_line_behavior') }}
|
||||||
|
</ChoiceSetting>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<h3 v-if="expertLevel > 0">
|
||||||
|
{{ $t('settings.attachments') }}
|
||||||
|
</h3>
|
||||||
|
<ul class="setting-list">
|
||||||
|
<li>
|
||||||
|
<BooleanSetting
|
||||||
|
path="imageCompression"
|
||||||
|
expert="1"
|
||||||
|
>
|
||||||
|
{{ $t('settings.image_compression') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
<ul class="setting-list suboptions">
|
||||||
|
<li>
|
||||||
|
<BooleanSetting
|
||||||
|
path="alwaysUseJpeg"
|
||||||
|
expert="1"
|
||||||
|
parent-path="imageCompression"
|
||||||
|
>
|
||||||
|
{{ $t('settings.always_use_jpeg') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script src="./composing_tab.js"></script>
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
.data-import-export-tab {
|
||||||
|
.importer-exporter {
|
||||||
|
display: inline-flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
td, th {
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
padding: 0 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
padding: 0.5em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,62 +1,77 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
|
class="data-import-export-tab"
|
||||||
:label="$t('settings.data_import_export_tab')"
|
:label="$t('settings.data_import_export_tab')"
|
||||||
>
|
>
|
||||||
<div class="setting-item">
|
<div class="setting-item">
|
||||||
<h2>{{ $t('settings.follow_import') }}</h2>
|
<h3>{{ $t('settings.import_export.title') }}</h3>
|
||||||
|
<ul class="setting-list">
|
||||||
|
<li>
|
||||||
|
<h4>{{ $t('settings.import_export.follows') }}</h4>
|
||||||
<p>{{ $t('settings.import_followers_from_a_csv_file') }}</p>
|
<p>{{ $t('settings.import_followers_from_a_csv_file') }}</p>
|
||||||
|
<div class="importer-exporter">
|
||||||
<Importer
|
<Importer
|
||||||
:submit-handler="importFollows"
|
:submit-handler="importFollows"
|
||||||
:success-message="$t('settings.follows_imported')"
|
:success-message="$t('settings.follows_imported')"
|
||||||
:error-message="$t('settings.follow_import_error')"
|
:error-message="$t('settings.follow_import_error')"
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
<div class="setting-item">
|
|
||||||
<h2>{{ $t('settings.follow_export') }}</h2>
|
|
||||||
<Exporter
|
<Exporter
|
||||||
:get-content="getFollowsContent"
|
:get-content="getFollowsContent"
|
||||||
filename="friends.csv"
|
filename="friends.csv"
|
||||||
:export-button-label="$t('settings.follow_export_button')"
|
:export-button-label="$t('settings.follow_export_button')"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-item">
|
</li>
|
||||||
<h2>{{ $t('settings.block_import') }}</h2>
|
<li>
|
||||||
<p>{{ $t('settings.import_blocks_from_a_csv_file') }}</p>
|
<h4>{{ $t('settings.import_export.mutes') }}</h4>
|
||||||
<Importer
|
|
||||||
:submit-handler="importBlocks"
|
|
||||||
:success-message="$t('settings.blocks_imported')"
|
|
||||||
:error-message="$t('settings.block_import_error')"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="setting-item">
|
|
||||||
<h2>{{ $t('settings.block_export') }}</h2>
|
|
||||||
<Exporter
|
|
||||||
:get-content="getBlocksContent"
|
|
||||||
filename="blocks.csv"
|
|
||||||
:export-button-label="$t('settings.block_export_button')"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="setting-item">
|
|
||||||
<h2>{{ $t('settings.mute_import') }}</h2>
|
|
||||||
<p>{{ $t('settings.import_mutes_from_a_csv_file') }}</p>
|
<p>{{ $t('settings.import_mutes_from_a_csv_file') }}</p>
|
||||||
|
<div class="importer-exporter">
|
||||||
<Importer
|
<Importer
|
||||||
:submit-handler="importMutes"
|
:submit-handler="importMutes"
|
||||||
:success-message="$t('settings.mutes_imported')"
|
:success-message="$t('settings.mutes_imported')"
|
||||||
:error-message="$t('settings.mute_import_error')"
|
:error-message="$t('settings.mute_import_error')"
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
<div class="setting-item">
|
|
||||||
<h2>{{ $t('settings.mute_export') }}</h2>
|
|
||||||
<Exporter
|
<Exporter
|
||||||
:get-content="getMutesContent"
|
:get-content="getMutesContent"
|
||||||
filename="mutes.csv"
|
filename="friends.csv"
|
||||||
:export-button-label="$t('settings.mute_export_button')"
|
:export-button-label="$t('settings.mute_export_button')"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-item">
|
</li>
|
||||||
<h2>{{ $t('settings.account_backup') }}</h2>
|
<li>
|
||||||
|
<h4>{{ $t('settings.import_export.blocks') }}</h4>
|
||||||
|
<p>{{ $t('settings.import_blocks_from_a_csv_file') }}</p>
|
||||||
|
<div class="importer-exporter">
|
||||||
|
<Importer
|
||||||
|
:submit-handler="importBlocks"
|
||||||
|
:success-message="$t('settings.blocks_imported')"
|
||||||
|
:error-message="$t('settings.block_import_error')"
|
||||||
|
/>
|
||||||
|
<Exporter
|
||||||
|
:get-content="getBlocksContent"
|
||||||
|
filename="friends.csv"
|
||||||
|
:export-button-label="$t('settings.block_export_button')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<h3>{{ $t('settings.account_backup') }}</h3>
|
||||||
|
<div class="setting-list">
|
||||||
<p>{{ $t('settings.account_backup_description') }}</p>
|
<p>{{ $t('settings.account_backup_description') }}</p>
|
||||||
<table>
|
<button
|
||||||
|
class="btn button-default"
|
||||||
|
@click="addBackup"
|
||||||
|
>
|
||||||
|
{{ $t('settings.add_backup') }}
|
||||||
|
</button>
|
||||||
|
<p v-if="addedBackup">
|
||||||
|
{{ $t('settings.added_backup') }}
|
||||||
|
</p>
|
||||||
|
<template v-if="addBackupError !== false">
|
||||||
|
<p>{{ $t('settings.add_backup_error', { error: addBackupError }) }}</p>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
<table class="setting-list">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>{{ $t('settings.account_backup_table_head') }}</th>
|
<th>{{ $t('settings.account_backup_table_head') }}</th>
|
||||||
|
|
@ -111,21 +126,9 @@
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<button
|
|
||||||
class="btn button-default"
|
|
||||||
@click="addBackup"
|
|
||||||
>
|
|
||||||
{{ $t('settings.add_backup') }}
|
|
||||||
</button>
|
|
||||||
<p v-if="addedBackup">
|
|
||||||
{{ $t('settings.added_backup') }}
|
|
||||||
</p>
|
|
||||||
<template v-if="addBackupError !== false">
|
|
||||||
<p>{{ $t('settings.add_backup_error', { error: addBackupError }) }}</p>
|
|
||||||
</template>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="./data_import_export_tab.js"></script>
|
<script src="./data_import_export_tab.js"></script>
|
||||||
<!-- <style lang="scss" src="./profile.scss"></style> -->
|
<style lang="scss" src="./data_import_export_tab.scss"></style>
|
||||||
|
|
|
||||||
46
src/components/settings_modal/tabs/developer_tab.js
Normal file
46
src/components/settings_modal/tabs/developer_tab.js
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
import BooleanSetting from '../helpers/boolean_setting.vue'
|
||||||
|
|
||||||
|
import SharedComputedObject from '../helpers/shared_computed_object.js'
|
||||||
|
|
||||||
|
import { clearCache, cacheKey, emojiCacheKey } from 'src/services/sw/sw.js'
|
||||||
|
|
||||||
|
const pleromaFeCommitUrl = 'https://git.pleroma.social/pleroma/pleroma-fe/commit/'
|
||||||
|
|
||||||
|
const VersionTab = {
|
||||||
|
data () {
|
||||||
|
const instance = this.$store.state.instance
|
||||||
|
return {
|
||||||
|
backendVersion: instance.backendVersion,
|
||||||
|
backendRepository: instance.backendRepository,
|
||||||
|
frontendVersion: instance.frontendVersion
|
||||||
|
}
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
BooleanSetting
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
frontendVersionLink () {
|
||||||
|
return pleromaFeCommitUrl + this.frontendVersion
|
||||||
|
},
|
||||||
|
...SharedComputedObject(),
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
clearAssetCache () {
|
||||||
|
this.clearCache(cacheKey)
|
||||||
|
},
|
||||||
|
clearEmojiCache () {
|
||||||
|
this.clearCache(emojiCacheKey)
|
||||||
|
},
|
||||||
|
clearCache (key) {
|
||||||
|
clearCache(key)
|
||||||
|
.then(() => {
|
||||||
|
this.$store.dispatch('settingsSaved', { success: true })
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
this.$store.dispatch('settingsSaved', { error })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default VersionTab
|
||||||
10
src/components/settings_modal/tabs/developer_tab.scss
Normal file
10
src/components/settings_modal/tabs/developer_tab.scss
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
.developer-tab {
|
||||||
|
dt {
|
||||||
|
font-weight: 900;
|
||||||
|
}
|
||||||
|
|
||||||
|
dd {
|
||||||
|
margin-top: 0.5em;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
}
|
||||||
72
src/components/settings_modal/tabs/developer_tab.vue
Normal file
72
src/components/settings_modal/tabs/developer_tab.vue
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
:label="$t('settings.developer')"
|
||||||
|
class="developer-tab"
|
||||||
|
>
|
||||||
|
<div class="setting-item">
|
||||||
|
<h3>{{ $t('settings.version.title') }}</h3>
|
||||||
|
<dl class="setting-list">
|
||||||
|
<dt>{{ $t('settings.version.backend_version') }}</dt>
|
||||||
|
<dd>
|
||||||
|
<a
|
||||||
|
:href="backendRepository"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
{{ backendVersion }}
|
||||||
|
</a>
|
||||||
|
</dd>
|
||||||
|
<dt>{{ $t('settings.version.frontend_version') }}</dt>
|
||||||
|
<dd>
|
||||||
|
<a
|
||||||
|
:href="frontendVersionLink"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
{{ frontendVersion }}
|
||||||
|
</a>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
<h3>{{ $t('settings.debug') }}</h3>
|
||||||
|
<ul class="setting-list">
|
||||||
|
<li>
|
||||||
|
<BooleanSetting path="virtualScrolling">
|
||||||
|
{{ $t('settings.virtual_scrolling') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button
|
||||||
|
class="btn button-default"
|
||||||
|
@click="clearAssetCache"
|
||||||
|
>
|
||||||
|
{{ $t('settings.clear_asset_cache') }}
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button
|
||||||
|
class="btn button-default"
|
||||||
|
@click="clearEmojiCache"
|
||||||
|
>
|
||||||
|
{{ $t('settings.clear_emoji_cache') }}
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting
|
||||||
|
path="themeDebug"
|
||||||
|
:expert="1"
|
||||||
|
>
|
||||||
|
{{ $t('settings.theme_debug') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting
|
||||||
|
path="forceThemeRecompilation"
|
||||||
|
:expert="1"
|
||||||
|
>
|
||||||
|
{{ $t('settings.force_theme_recompilation_debug') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script src="./developer_tab.js" />
|
||||||
|
<style lang="scss" src="./developer_tab.scss"></style>
|
||||||
|
|
@ -91,6 +91,7 @@ const FilteringTab = {
|
||||||
HelpIndicator
|
HelpIndicator
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
instanceSpecificPanelPresent () { return this.$store.state.instance.showInstanceSpecificPanel },
|
||||||
...SharedComputedObject(),
|
...SharedComputedObject(),
|
||||||
...mapState(
|
...mapState(
|
||||||
useServerSideStorageStore,
|
useServerSideStorageStore,
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div class="filtering-tab">
|
||||||
:label="$t('settings.filtering')"
|
|
||||||
class="filtering-tab"
|
|
||||||
>
|
|
||||||
<div class="setting-item">
|
<div class="setting-item">
|
||||||
<h2>{{ $t('settings.filter.clutter') }}</h2>
|
<h3>{{ $t('settings.filter.mute_filter') }}</h3>
|
||||||
<ul class="setting-list">
|
<ul class="setting-list">
|
||||||
<li>
|
<li>
|
||||||
<ChoiceSetting
|
<ChoiceSetting
|
||||||
|
|
@ -16,70 +13,6 @@
|
||||||
{{ $t('settings.replies_in_timeline') }}
|
{{ $t('settings.replies_in_timeline') }}
|
||||||
</ChoiceSetting>
|
</ChoiceSetting>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
|
||||||
<BooleanSetting
|
|
||||||
expert="1"
|
|
||||||
path="hidePostStats"
|
|
||||||
>
|
|
||||||
{{ $t('settings.hide_post_stats') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<BooleanSetting
|
|
||||||
expert="1"
|
|
||||||
path="hideUserStats"
|
|
||||||
>
|
|
||||||
{{ $t('settings.hide_user_stats') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<BooleanSetting path="hideBotIndication">
|
|
||||||
{{ $t('settings.hide_actor_type_indication') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<BooleanSetting path="hideScrobbles">
|
|
||||||
{{ $t('settings.hide_scrobbles') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
<ul class="setting-list suboptions">
|
|
||||||
<li>
|
|
||||||
<UnitSetting
|
|
||||||
key="hideScrobblesAfter"
|
|
||||||
path="hideScrobblesAfter"
|
|
||||||
:units="['m', 'h', 'd']"
|
|
||||||
unit-set="time"
|
|
||||||
expert="1"
|
|
||||||
>
|
|
||||||
{{ $t('settings.hide_scrobbles_after') }}
|
|
||||||
</UnitSetting>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<h3>{{ $t('settings.attachments') }}</h3>
|
|
||||||
<li>
|
|
||||||
<IntegerSetting
|
|
||||||
path="maxThumbnails"
|
|
||||||
expert="1"
|
|
||||||
:min="0"
|
|
||||||
>
|
|
||||||
{{ $t('settings.max_thumbnails') }}
|
|
||||||
</IntegerSetting>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<BooleanSetting path="hideAttachments">
|
|
||||||
{{ $t('settings.hide_attachments_in_tl') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<BooleanSetting path="hideAttachmentsInConv">
|
|
||||||
{{ $t('settings.hide_attachments_in_convo') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="setting-item">
|
|
||||||
<h2>{{ $t('settings.filter.mute_filter') }}</h2>
|
|
||||||
<ul class="setting-list">
|
|
||||||
<li>
|
<li>
|
||||||
{{ $t('user_card.default_mute_expiration') }}
|
{{ $t('user_card.default_mute_expiration') }}
|
||||||
<Select
|
<Select
|
||||||
|
|
|
||||||
|
|
@ -2,129 +2,55 @@ import { mapState } from 'vuex'
|
||||||
|
|
||||||
import BooleanSetting from '../helpers/boolean_setting.vue'
|
import BooleanSetting from '../helpers/boolean_setting.vue'
|
||||||
import ChoiceSetting from '../helpers/choice_setting.vue'
|
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 from '../helpers/unit_setting.vue'
|
import UnitSetting from '../helpers/unit_setting.vue'
|
||||||
|
import FloatSetting from '../helpers/float_setting.vue'
|
||||||
import InterfaceLanguageSwitcher from 'src/components/interface_language_switcher/interface_language_switcher.vue'
|
import InterfaceLanguageSwitcher from 'src/components/interface_language_switcher/interface_language_switcher.vue'
|
||||||
import Select from 'src/components/select/select.vue'
|
|
||||||
import ProfileSettingIndicator from '../helpers/profile_setting_indicator.vue'
|
import ProfileSettingIndicator from '../helpers/profile_setting_indicator.vue'
|
||||||
|
import FontControl from 'src/components/font_control/font_control.vue'
|
||||||
|
|
||||||
import SharedComputedObject from '../helpers/shared_computed_object.js'
|
import SharedComputedObject from '../helpers/shared_computed_object.js'
|
||||||
|
|
||||||
import localeService from 'src/services/locale/locale.service.js'
|
import localeService from 'src/services/locale/locale.service.js'
|
||||||
import { clearCache, cacheKey, emojiCacheKey } from 'src/services/sw/sw.js'
|
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
|
||||||
import {
|
|
||||||
faGlobe
|
|
||||||
} from '@fortawesome/free-solid-svg-icons'
|
|
||||||
|
|
||||||
library.add(
|
|
||||||
faGlobe
|
|
||||||
)
|
|
||||||
|
|
||||||
const GeneralTab = {
|
const GeneralTab = {
|
||||||
|
props: {
|
||||||
|
parentCollapsed: {
|
||||||
|
required: true,
|
||||||
|
type: Boolean
|
||||||
|
}
|
||||||
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
subjectLineOptions: ['email', 'noop', 'masto'].map(mode => ({
|
|
||||||
key: mode,
|
|
||||||
value: mode,
|
|
||||||
label: this.$t(`settings.subject_line_${mode === 'masto' ? 'mastodon' : mode}`)
|
|
||||||
})),
|
|
||||||
conversationDisplayOptions: ['tree', 'linear'].map(mode => ({
|
|
||||||
key: mode,
|
|
||||||
value: mode,
|
|
||||||
label: this.$t(`settings.conversation_display_${mode}`)
|
|
||||||
})),
|
|
||||||
absoluteTime12hOptions: ['24h', '12h'].map(mode => ({
|
absoluteTime12hOptions: ['24h', '12h'].map(mode => ({
|
||||||
key: mode,
|
key: mode,
|
||||||
value: mode,
|
value: mode,
|
||||||
label: this.$t(`settings.absolute_time_format_12h_${mode}`)
|
label: this.$t(`settings.absolute_time_format_12h_${mode}`)
|
||||||
})),
|
})),
|
||||||
conversationOtherRepliesButtonOptions: ['below', 'inside'].map(mode => ({
|
|
||||||
key: mode,
|
|
||||||
value: mode,
|
|
||||||
label: this.$t(`settings.conversation_other_replies_button_${mode}`)
|
|
||||||
})),
|
|
||||||
mentionLinkDisplayOptions: ['short', 'full_for_remote', 'full'].map(mode => ({
|
|
||||||
key: mode,
|
|
||||||
value: mode,
|
|
||||||
label: this.$t(`settings.mention_link_display_${mode}`)
|
|
||||||
})),
|
|
||||||
userPopoverAvatarActionOptions: ['close', 'zoom', 'open'].map(mode => ({
|
|
||||||
key: mode,
|
|
||||||
value: mode,
|
|
||||||
label: this.$t(`settings.user_popover_avatar_action_${mode}`)
|
|
||||||
})),
|
|
||||||
unsavedPostActionOptions: ['save', 'discard', 'confirm'].map(mode => ({
|
|
||||||
key: mode,
|
|
||||||
value: mode,
|
|
||||||
label: this.$t(`settings.unsaved_post_action_${mode}`)
|
|
||||||
})),
|
|
||||||
loopSilentAvailable:
|
|
||||||
// Firefox
|
|
||||||
Object.getOwnPropertyDescriptor(HTMLVideoElement.prototype, 'mozHasAudio') ||
|
|
||||||
// Chrome-likes
|
|
||||||
Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'webkitAudioDecodedByteCount') ||
|
|
||||||
// Future spec, still not supported in Nightly 63 as of 08/2018
|
|
||||||
Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'audioTracks'),
|
|
||||||
emailLanguage: this.$store.state.users.currentUser.language || ['']
|
emailLanguage: this.$store.state.users.currentUser.language || ['']
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
BooleanSetting,
|
BooleanSetting,
|
||||||
ChoiceSetting,
|
ChoiceSetting,
|
||||||
IntegerSetting,
|
|
||||||
FloatSetting,
|
|
||||||
UnitSetting,
|
UnitSetting,
|
||||||
|
FloatSetting,
|
||||||
|
FontControl,
|
||||||
InterfaceLanguageSwitcher,
|
InterfaceLanguageSwitcher,
|
||||||
ProfileSettingIndicator,
|
ProfileSettingIndicator
|
||||||
ScopeSelector,
|
|
||||||
Select
|
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
postFormats () {
|
|
||||||
return this.$store.state.instance.postFormats || []
|
|
||||||
},
|
|
||||||
postContentOptions () {
|
|
||||||
return this.postFormats.map(format => ({
|
|
||||||
key: format,
|
|
||||||
value: format,
|
|
||||||
label: this.$t(`post_status.content_type["${format}"]`)
|
|
||||||
}))
|
|
||||||
},
|
|
||||||
language: {
|
language: {
|
||||||
get: function () { return this.$store.getters.mergedConfig.interfaceLanguage },
|
get: function () { return this.$store.getters.mergedConfig.interfaceLanguage },
|
||||||
set: function (val) {
|
set: function (val) {
|
||||||
this.$store.dispatch('setOption', { name: 'interfaceLanguage', value: val })
|
this.$store.dispatch('setOption', { name: 'interfaceLanguage', value: val })
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
instanceShoutboxPresent () { return this.$store.state.instance.shoutAvailable },
|
|
||||||
instanceSpecificPanelPresent () { return this.$store.state.instance.showInstanceSpecificPanel },
|
|
||||||
...SharedComputedObject(),
|
...SharedComputedObject(),
|
||||||
...mapState({
|
...mapState({
|
||||||
blockExpirationSupported: state => state.instance.blockExpiration,
|
blockExpirationSupported: state => state.instance.blockExpiration,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
changeDefaultScope (value) {
|
|
||||||
this.$store.dispatch('setProfileOption', { name: 'defaultScope', value })
|
|
||||||
},
|
|
||||||
clearCache (key) {
|
|
||||||
clearCache(key)
|
|
||||||
.then(() => {
|
|
||||||
this.$store.dispatch('settingsSaved', { success: true })
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
this.$store.dispatch('settingsSaved', { error })
|
|
||||||
})
|
|
||||||
},
|
|
||||||
clearAssetCache () {
|
|
||||||
this.clearCache(cacheKey)
|
|
||||||
},
|
|
||||||
clearEmojiCache () {
|
|
||||||
this.clearCache(emojiCacheKey)
|
|
||||||
},
|
|
||||||
updateProfile () {
|
updateProfile () {
|
||||||
const params = {
|
const params = {
|
||||||
language: localeService.internalToBackendLocaleMulti(this.emailLanguage)
|
language: localeService.internalToBackendLocaleMulti(this.emailLanguage)
|
||||||
|
|
@ -137,6 +63,18 @@ const GeneralTab = {
|
||||||
this.$store.commit('setCurrentUser', user)
|
this.$store.commit('setCurrentUser', user)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
updateFont (key, value) {
|
||||||
|
this.$store.dispatch('setOption', {
|
||||||
|
name: 'theme3hacks',
|
||||||
|
value: {
|
||||||
|
...this.mergedConfig.theme3hacks,
|
||||||
|
fonts: {
|
||||||
|
...this.mergedConfig.theme3hacks.fonts,
|
||||||
|
[key]: value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div :label="$t('settings.general')">
|
<div>
|
||||||
<div class="setting-item">
|
<div class="setting-item">
|
||||||
<h2>{{ $t('settings.interface') }}</h2>
|
<h3>{{ $t('settings.format_and_language') }}</h3>
|
||||||
<ul class="setting-list">
|
<ul class="setting-list">
|
||||||
<li>
|
<li>
|
||||||
<interface-language-switcher
|
<interface-language-switcher
|
||||||
|
|
@ -20,16 +20,98 @@
|
||||||
{{ $t('settings.email_language') }}
|
{{ $t('settings.email_language') }}
|
||||||
</interface-language-switcher>
|
</interface-language-switcher>
|
||||||
</li>
|
</li>
|
||||||
<li v-if="instanceSpecificPanelPresent">
|
<li>
|
||||||
<BooleanSetting path="hideISP">
|
<BooleanSetting path="useAbsoluteTimeFormat">
|
||||||
{{ $t('settings.hide_isp') }}
|
{{ $t('settings.absolute_time_format') }}
|
||||||
</BooleanSetting>
|
</BooleanSetting>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<BooleanSetting path="stopGifs">
|
<ChoiceSetting
|
||||||
{{ $t('settings.stop_gifs') }}
|
id="absoluteTime12h"
|
||||||
</BooleanSetting>
|
path="absoluteTime12h"
|
||||||
|
:options="absoluteTime12hOptions"
|
||||||
|
>
|
||||||
|
{{ $t('settings.absolute_time_format_12h') }}
|
||||||
|
</ChoiceSetting>
|
||||||
</li>
|
</li>
|
||||||
|
</ul>
|
||||||
|
<h3>{{ $t('settings.scale_and_font') }}</h3>
|
||||||
|
<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>
|
||||||
|
<FontControl
|
||||||
|
:model-value="mergedConfig.theme3hacks.fonts.interface"
|
||||||
|
name="ui"
|
||||||
|
:label="$t('settings.style.fonts.components_inline.interface')"
|
||||||
|
:fallback="{ family: 'sans-serif' }"
|
||||||
|
no-inherit="1"
|
||||||
|
@update:model-value="v => updateFont('interface', v)"
|
||||||
|
/>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<FontControl
|
||||||
|
:model-value="mergedConfig.theme3hacks.fonts.input"
|
||||||
|
name="input"
|
||||||
|
:fallback="{ family: 'inherit' }"
|
||||||
|
:label="$t('settings.style.fonts.components_inline.input')"
|
||||||
|
@update:model-value="v => updateFont('input', v)"
|
||||||
|
/>
|
||||||
|
</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"
|
||||||
|
>
|
||||||
|
{{ $t('settings.emoji_reactions_scale') }}
|
||||||
|
</FloatSetting>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<h3>{{ $t('settings.timelines') }}</h3>
|
||||||
|
<ul class="setting-list">
|
||||||
<li>
|
<li>
|
||||||
<BooleanSetting path="streaming">
|
<BooleanSetting path="streaming">
|
||||||
{{ $t('settings.streaming') }}
|
{{ $t('settings.streaming') }}
|
||||||
|
|
@ -53,72 +135,14 @@
|
||||||
{{ $t('settings.useStreamingApi') }}
|
{{ $t('settings.useStreamingApi') }}
|
||||||
</BooleanSetting>
|
</BooleanSetting>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
</ul>
|
||||||
<BooleanSetting
|
<h3 v-if="expertLevel > 0">
|
||||||
path="virtualScrolling"
|
{{ $t('settings.confirmations') }}
|
||||||
expert="1"
|
</h3>
|
||||||
|
<ul
|
||||||
|
v-if="expertLevel > 0"
|
||||||
|
class="setting-list"
|
||||||
>
|
>
|
||||||
{{ $t('settings.virtual_scrolling') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<ChoiceSetting
|
|
||||||
id="userPopoverAvatarAction"
|
|
||||||
path="userPopoverAvatarAction"
|
|
||||||
:options="userPopoverAvatarActionOptions"
|
|
||||||
expert="1"
|
|
||||||
>
|
|
||||||
{{ $t('settings.user_popover_avatar_action') }}
|
|
||||||
</ChoiceSetting>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<BooleanSetting
|
|
||||||
path="userPopoverOverlay"
|
|
||||||
expert="1"
|
|
||||||
>
|
|
||||||
{{ $t('settings.user_popover_avatar_overlay') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<BooleanSetting
|
|
||||||
path="userCardLeftJustify"
|
|
||||||
expert="1"
|
|
||||||
>
|
|
||||||
{{ $t('settings.user_card_left_justify') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<BooleanSetting
|
|
||||||
path="userCardHidePersonalMarks"
|
|
||||||
expert="1"
|
|
||||||
>
|
|
||||||
{{ $t('settings.user_card_hide_personal_marks') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<BooleanSetting
|
|
||||||
path="alwaysShowNewPostButton"
|
|
||||||
expert="1"
|
|
||||||
>
|
|
||||||
{{ $t('settings.always_show_post_button') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<BooleanSetting
|
|
||||||
path="autohideFloatingPostButton"
|
|
||||||
expert="1"
|
|
||||||
>
|
|
||||||
{{ $t('settings.autohide_floating_post_button') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
<li v-if="instanceShoutboxPresent">
|
|
||||||
<BooleanSetting
|
|
||||||
path="hideShoutbox"
|
|
||||||
expert="1"
|
|
||||||
>
|
|
||||||
{{ $t('settings.hide_shoutbox') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
<li class="select-multiple">
|
<li class="select-multiple">
|
||||||
<span class="label">{{ $t('settings.confirm_dialogs') }}</span>
|
<span class="label">{{ $t('settings.confirm_dialogs') }}</span>
|
||||||
<ul class="option-list">
|
<ul class="option-list">
|
||||||
|
|
@ -179,383 +203,6 @@
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-item">
|
|
||||||
<h2>{{ $t('settings.post_look_feel') }}</h2>
|
|
||||||
<ul class="setting-list">
|
|
||||||
<li>
|
|
||||||
<ChoiceSetting
|
|
||||||
id="conversationDisplay"
|
|
||||||
path="conversationDisplay"
|
|
||||||
:options="conversationDisplayOptions"
|
|
||||||
>
|
|
||||||
{{ $t('settings.conversation_display') }}
|
|
||||||
</ChoiceSetting>
|
|
||||||
</li>
|
|
||||||
<ul
|
|
||||||
v-if="mergedConfig.conversationDisplay !== 'linear'"
|
|
||||||
class="setting-list suboptions"
|
|
||||||
>
|
|
||||||
<li>
|
|
||||||
<BooleanSetting path="conversationTreeAdvanced">
|
|
||||||
{{ $t('settings.tree_advanced') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<BooleanSetting
|
|
||||||
path="conversationTreeFadeAncestors"
|
|
||||||
:expert="1"
|
|
||||||
>
|
|
||||||
{{ $t('settings.tree_fade_ancestors') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<IntegerSetting
|
|
||||||
path="maxDepthInThread"
|
|
||||||
:min="3"
|
|
||||||
:expert="1"
|
|
||||||
>
|
|
||||||
{{ $t('settings.max_depth_in_thread') }}
|
|
||||||
</IntegerSetting>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<ChoiceSetting
|
|
||||||
id="conversationOtherRepliesButton"
|
|
||||||
path="conversationOtherRepliesButton"
|
|
||||||
:options="conversationOtherRepliesButtonOptions"
|
|
||||||
:expert="1"
|
|
||||||
>
|
|
||||||
{{ $t('settings.conversation_other_replies_button') }}
|
|
||||||
</ChoiceSetting>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<li>
|
|
||||||
<BooleanSetting path="collapseMessageWithSubject">
|
|
||||||
{{ $t('settings.collapse_subject') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<BooleanSetting
|
|
||||||
path="emojiReactionsOnTimeline"
|
|
||||||
expert="1"
|
|
||||||
>
|
|
||||||
{{ $t('settings.emoji_reactions_on_timeline') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<BooleanSetting
|
|
||||||
v-if="user"
|
|
||||||
source="profile"
|
|
||||||
path="stripRichContent"
|
|
||||||
expert="1"
|
|
||||||
>
|
|
||||||
{{ $t('settings.no_rich_text_description') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<BooleanSetting
|
|
||||||
path="useAbsoluteTimeFormat"
|
|
||||||
expert="1"
|
|
||||||
>
|
|
||||||
{{ $t('settings.absolute_time_format') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
<ul
|
|
||||||
v-if="mergedConfig.useAbsoluteTimeFormat"
|
|
||||||
class="setting-list suboptions"
|
|
||||||
>
|
|
||||||
<li>
|
|
||||||
<UnitSetting
|
|
||||||
path="absoluteTimeFormatMinAge"
|
|
||||||
unit-set="time"
|
|
||||||
:units="['s', 'm', 'h', 'd']"
|
|
||||||
:min="0"
|
|
||||||
>
|
|
||||||
{{ $t('settings.absolute_time_format_min_age') }}
|
|
||||||
</UnitSetting>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<ChoiceSetting
|
|
||||||
id="absoluteTime12h"
|
|
||||||
path="absoluteTime12h"
|
|
||||||
:options="absoluteTime12hOptions"
|
|
||||||
:expert="1"
|
|
||||||
>
|
|
||||||
{{ $t('settings.absolute_time_format_12h') }}
|
|
||||||
</ChoiceSetting>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<h3>{{ $t('settings.attachments') }}</h3>
|
|
||||||
<li>
|
|
||||||
<BooleanSetting
|
|
||||||
path="imageCompression"
|
|
||||||
expert="1"
|
|
||||||
>
|
|
||||||
{{ $t('settings.image_compression') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
<ul class="setting-list suboptions">
|
|
||||||
<li>
|
|
||||||
<BooleanSetting
|
|
||||||
path="alwaysUseJpeg"
|
|
||||||
expert="1"
|
|
||||||
parent-path="imageCompression"
|
|
||||||
>
|
|
||||||
{{ $t('settings.always_use_jpeg') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<li>
|
|
||||||
<BooleanSetting
|
|
||||||
path="useContainFit"
|
|
||||||
expert="1"
|
|
||||||
>
|
|
||||||
{{ $t('settings.use_contain_fit') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<BooleanSetting path="hideNsfw">
|
|
||||||
{{ $t('settings.nsfw_clickthrough') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
<ul class="setting-list suboptions">
|
|
||||||
<li>
|
|
||||||
<BooleanSetting
|
|
||||||
path="preloadImage"
|
|
||||||
expert="1"
|
|
||||||
parent-path="hideNsfw"
|
|
||||||
>
|
|
||||||
{{ $t('settings.preload_images') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<BooleanSetting
|
|
||||||
path="useOneClickNsfw"
|
|
||||||
expert="1"
|
|
||||||
parent-path="hideNsfw"
|
|
||||||
>
|
|
||||||
{{ $t('settings.use_one_click_nsfw') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<li>
|
|
||||||
<BooleanSetting
|
|
||||||
path="loopVideo"
|
|
||||||
expert="1"
|
|
||||||
>
|
|
||||||
{{ $t('settings.loop_video') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
<ul class="setting-list suboptions">
|
|
||||||
<li>
|
|
||||||
<BooleanSetting
|
|
||||||
path="loopVideoSilentOnly"
|
|
||||||
expert="1"
|
|
||||||
parent-path="loopVideo"
|
|
||||||
:disabled="!loopSilentAvailable"
|
|
||||||
>
|
|
||||||
{{ $t('settings.loop_video_silent_only') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
<div
|
|
||||||
v-if="!loopSilentAvailable"
|
|
||||||
class="unavailable"
|
|
||||||
>
|
|
||||||
<FAIcon icon="globe" />! {{ $t('settings.limited_availability') }}
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<BooleanSetting
|
|
||||||
path="playVideosInModal"
|
|
||||||
expert="1"
|
|
||||||
>
|
|
||||||
{{ $t('settings.play_videos_in_modal') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
<h3>{{ $t('settings.mention_links') }}</h3>
|
|
||||||
<li>
|
|
||||||
<ChoiceSetting
|
|
||||||
id="mentionLinkDisplay"
|
|
||||||
path="mentionLinkDisplay"
|
|
||||||
:options="mentionLinkDisplayOptions"
|
|
||||||
>
|
|
||||||
{{ $t('settings.mention_link_display') }}
|
|
||||||
</ChoiceSetting>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<BooleanSetting
|
|
||||||
path="mentionLinkShowTooltip"
|
|
||||||
expert="1"
|
|
||||||
>
|
|
||||||
{{ $t('settings.mention_link_use_tooltip') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<BooleanSetting path="mentionLinkShowAvatar">
|
|
||||||
{{ $t('settings.mention_link_show_avatar') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<BooleanSetting
|
|
||||||
path="mentionLinkFadeDomain"
|
|
||||||
expert="1"
|
|
||||||
>
|
|
||||||
{{ $t('settings.mention_link_fade_domain') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
<li v-if="user">
|
|
||||||
<BooleanSetting
|
|
||||||
path="mentionLinkBoldenYou"
|
|
||||||
expert="1"
|
|
||||||
>
|
|
||||||
{{ $t('settings.mention_link_bolden_you') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
<h3 v-if="expertLevel > 0">
|
|
||||||
{{ $t('settings.fun') }}
|
|
||||||
</h3>
|
|
||||||
<li>
|
|
||||||
<BooleanSetting
|
|
||||||
path="greentext"
|
|
||||||
expert="1"
|
|
||||||
>
|
|
||||||
{{ $t('settings.greentext') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
<li v-if="user">
|
|
||||||
<BooleanSetting
|
|
||||||
path="mentionLinkShowYous"
|
|
||||||
expert="1"
|
|
||||||
>
|
|
||||||
{{ $t('settings.show_yous') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
v-if="user"
|
|
||||||
class="setting-item"
|
|
||||||
>
|
|
||||||
<h2>{{ $t('settings.composing') }}</h2>
|
|
||||||
<ul class="setting-list">
|
|
||||||
<li>
|
|
||||||
<label for="default-vis">
|
|
||||||
{{ $t('settings.default_vis') }} <ProfileSettingIndicator :is-profile="true" />
|
|
||||||
<ScopeSelector
|
|
||||||
class="scope-selector"
|
|
||||||
:show-all="true"
|
|
||||||
:user-default="$store.state.profileConfig.defaultScope"
|
|
||||||
:initial-scope="$store.state.profileConfig.defaultScope"
|
|
||||||
:on-scope-change="changeDefaultScope"
|
|
||||||
/>
|
|
||||||
</label>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<!-- <BooleanSetting source="profile" path="defaultNSFW"> -->
|
|
||||||
<BooleanSetting path="sensitiveByDefault">
|
|
||||||
{{ $t('settings.sensitive_by_default') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<BooleanSetting
|
|
||||||
path="scopeCopy"
|
|
||||||
expert="1"
|
|
||||||
>
|
|
||||||
{{ $t('settings.scope_copy') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<BooleanSetting
|
|
||||||
path="alwaysShowSubjectInput"
|
|
||||||
expert="1"
|
|
||||||
>
|
|
||||||
{{ $t('settings.subject_input_always_show') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<ChoiceSetting
|
|
||||||
id="subjectLineBehavior"
|
|
||||||
path="subjectLineBehavior"
|
|
||||||
:options="subjectLineOptions"
|
|
||||||
expert="1"
|
|
||||||
>
|
|
||||||
{{ $t('settings.subject_line_behavior') }}
|
|
||||||
</ChoiceSetting>
|
|
||||||
</li>
|
|
||||||
<li v-if="postFormats.length > 0">
|
|
||||||
<ChoiceSetting
|
|
||||||
id="postContentType"
|
|
||||||
path="postContentType"
|
|
||||||
:options="postContentOptions"
|
|
||||||
>
|
|
||||||
{{ $t('settings.post_status_content_type') }}
|
|
||||||
</ChoiceSetting>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<BooleanSetting
|
|
||||||
path="minimalScopesMode"
|
|
||||||
expert="1"
|
|
||||||
>
|
|
||||||
{{ $t('settings.minimal_scopes_mode') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<BooleanSetting
|
|
||||||
path="padEmoji"
|
|
||||||
expert="1"
|
|
||||||
>
|
|
||||||
{{ $t('settings.pad_emoji') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<BooleanSetting
|
|
||||||
path="autocompleteSelect"
|
|
||||||
expert="1"
|
|
||||||
>
|
|
||||||
{{ $t('settings.autocomplete_select_first') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<BooleanSetting
|
|
||||||
path="autoSaveDraft"
|
|
||||||
>
|
|
||||||
{{ $t('settings.auto_save_draft') }}
|
|
||||||
</BooleanSetting>
|
|
||||||
</li>
|
|
||||||
<li v-if="!mergedConfig.autoSaveDraft">
|
|
||||||
<ChoiceSetting
|
|
||||||
id="unsavedPostAction"
|
|
||||||
path="unsavedPostAction"
|
|
||||||
:options="unsavedPostActionOptions"
|
|
||||||
>
|
|
||||||
{{ $t('settings.unsaved_post_action') }}
|
|
||||||
</ChoiceSetting>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="setting-item"
|
|
||||||
>
|
|
||||||
<h2>{{ $t('settings.cache') }}</h2>
|
|
||||||
<ul class="setting-list">
|
|
||||||
<li>
|
|
||||||
<button
|
|
||||||
class="btn button-default"
|
|
||||||
@click="clearAssetCache"
|
|
||||||
>
|
|
||||||
{{ $t('settings.clear_asset_cache') }}
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<button
|
|
||||||
class="btn button-default"
|
|
||||||
@click="clearEmojiCache"
|
|
||||||
>
|
|
||||||
{{ $t('settings.clear_emoji_cache') }}
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
||||||
50
src/components/settings_modal/tabs/layout_tab.js
Normal file
50
src/components/settings_modal/tabs/layout_tab.js
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
import BooleanSetting from '../helpers/boolean_setting.vue'
|
||||||
|
import ChoiceSetting from '../helpers/choice_setting.vue'
|
||||||
|
import UnitSetting from '../helpers/unit_setting.vue'
|
||||||
|
import ProfileSettingIndicator from '../helpers/profile_setting_indicator.vue'
|
||||||
|
|
||||||
|
import SharedComputedObject from '../helpers/shared_computed_object.js'
|
||||||
|
|
||||||
|
const GeneralTab = {
|
||||||
|
props: {
|
||||||
|
parentCollapsed: {
|
||||||
|
required: true,
|
||||||
|
type: Boolean
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
thirdColumnModeOptions: ['none', 'notifications', 'postform'].map(mode => ({
|
||||||
|
key: mode,
|
||||||
|
value: mode,
|
||||||
|
label: this.$t(`settings.third_column_mode_${mode}`)
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
BooleanSetting,
|
||||||
|
ChoiceSetting,
|
||||||
|
UnitSetting,
|
||||||
|
ProfileSettingIndicator
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
postFormats () {
|
||||||
|
return this.$store.state.instance.postFormats || []
|
||||||
|
},
|
||||||
|
instanceShoutboxPresent () { return this.$store.state.instance.shoutAvailable },
|
||||||
|
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]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
...SharedComputedObject(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default GeneralTab
|
||||||
127
src/components/settings_modal/tabs/layout_tab.vue
Normal file
127
src/components/settings_modal/tabs/layout_tab.vue
Normal file
|
|
@ -0,0 +1,127 @@
|
||||||
|
<template>
|
||||||
|
<div :label="$t('settings.layout')">
|
||||||
|
<div class="setting-item">
|
||||||
|
<h3>{{ $t('settings.general') }}</h3>
|
||||||
|
<ul class="setting-list">
|
||||||
|
<li>
|
||||||
|
<BooleanSetting path="modalMobileCenter">
|
||||||
|
{{ $t('settings.mobile_center_dialog') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting
|
||||||
|
path="alwaysShowNewPostButton"
|
||||||
|
expert="1"
|
||||||
|
>
|
||||||
|
{{ $t('settings.always_show_post_button') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting
|
||||||
|
path="autohideFloatingPostButton"
|
||||||
|
expert="1"
|
||||||
|
>
|
||||||
|
{{ $t('settings.autohide_floating_post_button') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting
|
||||||
|
path="userPopoverOverlay"
|
||||||
|
expert="1"
|
||||||
|
>
|
||||||
|
{{ $t('settings.user_popover_avatar_overlay') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting path="userCardLeftJustify">
|
||||||
|
{{ $t('settings.user_card_left_justify') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<UnitSetting
|
||||||
|
path="themeEditorMinWidth"
|
||||||
|
:units="['px', 'rem']"
|
||||||
|
expert="1"
|
||||||
|
>
|
||||||
|
{{ $t('settings.theme_editor_min_width') }}
|
||||||
|
</UnitSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<UnitSetting
|
||||||
|
path="navbarSize"
|
||||||
|
:step="0.1"
|
||||||
|
:units="['px', 'rem']"
|
||||||
|
:reset-default="{ 'px': 55, 'rem': 3.5 }"
|
||||||
|
>
|
||||||
|
{{ $t('settings.navbar_size') }}
|
||||||
|
</UnitSetting>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<h3>{{ $t('settings.columns') }}</h3>
|
||||||
|
<ul class="setting-list">
|
||||||
|
<li>
|
||||||
|
<BooleanSetting path="disableStickyHeaders">
|
||||||
|
{{ $t('settings.disable_sticky_headers') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting path="showScrollbars">
|
||||||
|
{{ $t('settings.show_scrollbars') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<li v-if="instanceSpecificPanelPresent">
|
||||||
|
<BooleanSetting path="hideISP">
|
||||||
|
{{ $t('settings.hide_isp') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<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">
|
||||||
|
<h4> {{ $t('settings.column_sizes') }} </h4>
|
||||||
|
<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>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script src="./layout_tab.js"></script>
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div :label="$t('settings.notifications')">
|
<div :label="$t('settings.notifications')">
|
||||||
<div class="setting-item">
|
<div class="setting-item">
|
||||||
<h2>{{ $t('settings.notification_setting_annoyance') }}</h2>
|
<h3>{{ $t('settings.notification_setting_annoyance') }}</h3>
|
||||||
<ul class="setting-list">
|
<ul class="setting-list">
|
||||||
<li>
|
<li>
|
||||||
<BooleanSetting path="closingDrawerMarksAsSeen">
|
<BooleanSetting path="closingDrawerMarksAsSeen">
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-item">
|
<div class="setting-item">
|
||||||
<h2>{{ $t('settings.notification_setting_filters') }}</h2>
|
<h3>{{ $t('settings.notification_setting_filters') }}</h3>
|
||||||
<ul class="setting-list">
|
<ul class="setting-list">
|
||||||
<li>
|
<li>
|
||||||
<BooleanSetting
|
<BooleanSetting
|
||||||
|
|
@ -40,13 +40,13 @@
|
||||||
</BooleanSetting>
|
</BooleanSetting>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<h3> {{ $t('settings.notification_visibility') }}</h3>
|
<h4> {{ $t('settings.notification_visibility') }}</h4>
|
||||||
<p v-if="expertLevel > 0">
|
<p v-if="expertLevel > 0">
|
||||||
{{ $t('settings.notification_setting_filters_chrome_push') }}
|
{{ $t('settings.notification_setting_filters_chrome_push') }}
|
||||||
</p>
|
</p>
|
||||||
<ul class="setting-list two-column">
|
<ul class="setting-list two-column">
|
||||||
<li>
|
<li>
|
||||||
<h4> {{ $t('settings.notification_visibility_mentions') }}</h4>
|
<h5> {{ $t('settings.notification_visibility_mentions') }}</h5>
|
||||||
<ul class="setting-list">
|
<ul class="setting-list">
|
||||||
<li>
|
<li>
|
||||||
<BooleanSetting path="notificationVisibility.mentions">
|
<BooleanSetting path="notificationVisibility.mentions">
|
||||||
|
|
@ -61,7 +61,7 @@
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<h4> {{ $t('settings.notification_visibility_statuses') }}</h4>
|
<h5> {{ $t('settings.notification_visibility_statuses') }}</h5>
|
||||||
<ul class="setting-list">
|
<ul class="setting-list">
|
||||||
<li>
|
<li>
|
||||||
<BooleanSetting path="notificationVisibility.statuses">
|
<BooleanSetting path="notificationVisibility.statuses">
|
||||||
|
|
@ -76,7 +76,7 @@
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<h4> {{ $t('settings.notification_visibility_likes') }}</h4>
|
<h5> {{ $t('settings.notification_visibility_likes') }}</h5>
|
||||||
<ul class="setting-list">
|
<ul class="setting-list">
|
||||||
<li>
|
<li>
|
||||||
<BooleanSetting path="notificationVisibility.likes">
|
<BooleanSetting path="notificationVisibility.likes">
|
||||||
|
|
@ -91,7 +91,7 @@
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<h4> {{ $t('settings.notification_visibility_repeats') }}</h4>
|
<h5> {{ $t('settings.notification_visibility_repeats') }}</h5>
|
||||||
<ul class="setting-list">
|
<ul class="setting-list">
|
||||||
<li>
|
<li>
|
||||||
<BooleanSetting path="notificationVisibility.repeats">
|
<BooleanSetting path="notificationVisibility.repeats">
|
||||||
|
|
@ -106,7 +106,7 @@
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<h4> {{ $t('settings.notification_visibility_emoji_reactions') }}</h4>
|
<h5> {{ $t('settings.notification_visibility_emoji_reactions') }}</h5>
|
||||||
<ul class="setting-list">
|
<ul class="setting-list">
|
||||||
<li>
|
<li>
|
||||||
<BooleanSetting path="notificationVisibility.emojiReactions">
|
<BooleanSetting path="notificationVisibility.emojiReactions">
|
||||||
|
|
@ -121,7 +121,7 @@
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<h4> {{ $t('settings.notification_visibility_follows') }}</h4>
|
<h5> {{ $t('settings.notification_visibility_follows') }}</h5>
|
||||||
<ul class="setting-list">
|
<ul class="setting-list">
|
||||||
<li>
|
<li>
|
||||||
<BooleanSetting path="notificationVisibility.follows">
|
<BooleanSetting path="notificationVisibility.follows">
|
||||||
|
|
@ -136,7 +136,7 @@
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<h4> {{ $t('settings.notification_visibility_follow_requests') }}</h4>
|
<h5> {{ $t('settings.notification_visibility_follow_requests') }}</h5>
|
||||||
<ul class="setting-list">
|
<ul class="setting-list">
|
||||||
<li>
|
<li>
|
||||||
<BooleanSetting path="notificationVisibility.followRequest">
|
<BooleanSetting path="notificationVisibility.followRequest">
|
||||||
|
|
@ -151,7 +151,7 @@
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<h4> {{ $t('settings.notification_visibility_moves') }}</h4>
|
<h5> {{ $t('settings.notification_visibility_moves') }}</h5>
|
||||||
<ul class="setting-list">
|
<ul class="setting-list">
|
||||||
<li>
|
<li>
|
||||||
<BooleanSetting path="notificationVisibility.moves">
|
<BooleanSetting path="notificationVisibility.moves">
|
||||||
|
|
@ -166,7 +166,7 @@
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<h4> {{ $t('settings.notification_visibility_polls') }}</h4>
|
<h5> {{ $t('settings.notification_visibility_polls') }}</h5>
|
||||||
<ul class="setting-list">
|
<ul class="setting-list">
|
||||||
<li>
|
<li>
|
||||||
<BooleanSetting path="notificationVisibility.polls">
|
<BooleanSetting path="notificationVisibility.polls">
|
||||||
|
|
@ -181,7 +181,7 @@
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li v-if="canReceiveReports">
|
<li v-if="canReceiveReports">
|
||||||
<h4> {{ $t('settings.notification_visibility_reports') }}</h4>
|
<h5> {{ $t('settings.notification_visibility_reports') }}</h5>
|
||||||
<ul class="setting-list">
|
<ul class="setting-list">
|
||||||
<li>
|
<li>
|
||||||
<BooleanSetting path="notificationVisibility.reports">
|
<BooleanSetting path="notificationVisibility.reports">
|
||||||
|
|
@ -201,8 +201,6 @@
|
||||||
<BooleanSetting path="showExtraNotifications">
|
<BooleanSetting path="showExtraNotifications">
|
||||||
{{ $t('settings.notification_show_extra') }}
|
{{ $t('settings.notification_show_extra') }}
|
||||||
</BooleanSetting>
|
</BooleanSetting>
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<ul class="setting-list suboptions">
|
<ul class="setting-list suboptions">
|
||||||
<li>
|
<li>
|
||||||
<BooleanSetting
|
<BooleanSetting
|
||||||
|
|
@ -245,7 +243,7 @@
|
||||||
v-if="expertLevel > 0"
|
v-if="expertLevel > 0"
|
||||||
class="setting-item"
|
class="setting-item"
|
||||||
>
|
>
|
||||||
<h2>{{ $t('settings.notification_setting_privacy') }}</h2>
|
<h3>{{ $t('settings.notification_setting_privacy') }}</h3>
|
||||||
<ul class="setting-list">
|
<ul class="setting-list">
|
||||||
<li>
|
<li>
|
||||||
<BooleanSetting
|
<BooleanSetting
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
.theme-tab {
|
.old-theme-tab {
|
||||||
min-width: var(--themeEditorMinWidth, fit-content);
|
min-width: var(--themeEditorMinWidth, fit-content);
|
||||||
|
|
||||||
.deprecation-warning {
|
.deprecation-warning {
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="theme-tab">
|
<div class="old-theme-tab">
|
||||||
<div class="alert warning deprecation-warning">
|
<div class="alert warning deprecation-warning">
|
||||||
{{ $t("settings.style.themes2_outdated") }}
|
{{ $t("settings.style.themes2_outdated") }}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -1020,6 +1020,6 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="./theme_tab.js"></script>
|
<script src="./old_theme_tab.js"></script>
|
||||||
|
|
||||||
<style src="./theme_tab.scss" lang="scss"></style>
|
<style src="./old_theme_tab.scss" lang="scss"></style>
|
||||||
78
src/components/settings_modal/tabs/posts_tab.js
Normal file
78
src/components/settings_modal/tabs/posts_tab.js
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
import BooleanSetting from '../helpers/boolean_setting.vue'
|
||||||
|
import ChoiceSetting from '../helpers/choice_setting.vue'
|
||||||
|
import IntegerSetting from '../helpers/integer_setting.vue'
|
||||||
|
import ProfileSettingIndicator from '../helpers/profile_setting_indicator.vue'
|
||||||
|
import FontControl from 'src/components/font_control/font_control.vue'
|
||||||
|
|
||||||
|
import SharedComputedObject from '../helpers/shared_computed_object.js'
|
||||||
|
|
||||||
|
const GeneralTab = {
|
||||||
|
props: {
|
||||||
|
parentCollapsed: {
|
||||||
|
required: true,
|
||||||
|
type: Boolean
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
conversationDisplayOptions: ['tree', 'linear'].map(mode => ({
|
||||||
|
key: mode,
|
||||||
|
value: mode,
|
||||||
|
label: this.$t(`settings.conversation_display_${mode}`)
|
||||||
|
})),
|
||||||
|
conversationOtherRepliesButtonOptions: ['below', 'inside'].map(mode => ({
|
||||||
|
key: mode,
|
||||||
|
value: mode,
|
||||||
|
label: this.$t(`settings.conversation_other_replies_button_${mode}`)
|
||||||
|
})),
|
||||||
|
mentionLinkDisplayOptions: ['short', 'full_for_remote', 'full'].map(mode => ({
|
||||||
|
key: mode,
|
||||||
|
value: mode,
|
||||||
|
label: this.$t(`settings.mention_link_display_${mode}`)
|
||||||
|
})),
|
||||||
|
userPopoverAvatarActionOptions: ['close', 'zoom', 'open'].map(mode => ({
|
||||||
|
key: mode,
|
||||||
|
value: mode,
|
||||||
|
label: this.$t(`settings.user_popover_avatar_action_${mode}`)
|
||||||
|
})),
|
||||||
|
unsavedPostActionOptions: ['save', 'discard', 'confirm'].map(mode => ({
|
||||||
|
key: mode,
|
||||||
|
value: mode,
|
||||||
|
label: this.$t(`settings.unsaved_post_action_${mode}`)
|
||||||
|
})),
|
||||||
|
loopSilentAvailable:
|
||||||
|
// Firefox
|
||||||
|
Object.getOwnPropertyDescriptor(HTMLVideoElement.prototype, 'mozHasAudio') ||
|
||||||
|
// Chrome-likes
|
||||||
|
Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'webkitAudioDecodedByteCount') ||
|
||||||
|
// Future spec, still not supported in Nightly 63 as of 08/2018
|
||||||
|
Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'audioTracks')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
BooleanSetting,
|
||||||
|
ChoiceSetting,
|
||||||
|
IntegerSetting,
|
||||||
|
FontControl,
|
||||||
|
ProfileSettingIndicator
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...SharedComputedObject(),
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
updateFont (key, value) {
|
||||||
|
this.$store.dispatch('setOption', {
|
||||||
|
name: 'theme3hacks',
|
||||||
|
value: {
|
||||||
|
...this.mergedConfig.theme3hacks,
|
||||||
|
fonts: {
|
||||||
|
...this.mergedConfig.theme3hacks.fonts,
|
||||||
|
[key]: value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default GeneralTab
|
||||||
5
src/components/settings_modal/tabs/posts_tab.scss
Normal file
5
src/components/settings_modal/tabs/posts_tab.scss
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
.posts-tab {
|
||||||
|
.greentext {
|
||||||
|
color: var(--funtextGreentext);
|
||||||
|
}
|
||||||
|
}
|
||||||
257
src/components/settings_modal/tabs/posts_tab.vue
Normal file
257
src/components/settings_modal/tabs/posts_tab.vue
Normal file
|
|
@ -0,0 +1,257 @@
|
||||||
|
<template>
|
||||||
|
<div class="posts-tab">
|
||||||
|
<div class="setting-item">
|
||||||
|
<h3>{{ $t('settings.posts_appearance') }}</h3>
|
||||||
|
<ul class="setting-list">
|
||||||
|
<li>
|
||||||
|
<BooleanSetting path="collapseMessageWithSubject">
|
||||||
|
{{ $t('settings.collapse_subject') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<ChoiceSetting
|
||||||
|
id="conversationDisplay"
|
||||||
|
path="conversationDisplay"
|
||||||
|
:options="conversationDisplayOptions"
|
||||||
|
>
|
||||||
|
{{ $t('settings.conversation_display') }}
|
||||||
|
</ChoiceSetting>
|
||||||
|
<ul
|
||||||
|
v-if="mergedConfig.conversationDisplay !== 'linear'"
|
||||||
|
class="setting-list suboptions"
|
||||||
|
>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting path="conversationTreeAdvanced">
|
||||||
|
{{ $t('settings.tree_advanced') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting
|
||||||
|
path="conversationTreeFadeAncestors"
|
||||||
|
:expert="1"
|
||||||
|
>
|
||||||
|
{{ $t('settings.tree_fade_ancestors') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<IntegerSetting
|
||||||
|
path="maxDepthInThread"
|
||||||
|
:min="3"
|
||||||
|
:expert="1"
|
||||||
|
>
|
||||||
|
{{ $t('settings.max_depth_in_thread') }}
|
||||||
|
</IntegerSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<ChoiceSetting
|
||||||
|
id="conversationOtherRepliesButton"
|
||||||
|
path="conversationOtherRepliesButton"
|
||||||
|
:options="conversationOtherRepliesButtonOptions"
|
||||||
|
:expert="1"
|
||||||
|
>
|
||||||
|
{{ $t('settings.conversation_other_replies_button') }}
|
||||||
|
</ChoiceSetting>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<FontControl
|
||||||
|
:model-value="mergedConfig.theme3hacks.fonts.post"
|
||||||
|
name="post"
|
||||||
|
:fallback="{ family: 'inherit' }"
|
||||||
|
:label="$t('settings.style.fonts.components.post')"
|
||||||
|
@update:model-value="v => updateFont('post', v)"
|
||||||
|
/>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<FontControl
|
||||||
|
:model-value="mergedConfig.theme3hacks.fonts.monospace"
|
||||||
|
name="postCode"
|
||||||
|
:fallback="{ family: 'monospace' }"
|
||||||
|
:label="$t('settings.style.fonts.components.monospace')"
|
||||||
|
@update:model-value="v => updateFont('monospace', v)"
|
||||||
|
/>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting path="greentext">
|
||||||
|
<i18n-t
|
||||||
|
keypath="settings.plaintext_quotes"
|
||||||
|
tag="span"
|
||||||
|
>
|
||||||
|
<span class="greentext">
|
||||||
|
{{ $t('settings.greentext_quotes') }}
|
||||||
|
</span>
|
||||||
|
</i18n-t>
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting
|
||||||
|
path="emojiReactionsOnTimeline"
|
||||||
|
expert="1"
|
||||||
|
>
|
||||||
|
{{ $t('settings.emoji_reactions_on_timeline') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<h3>{{ $t('settings.mention_links') }}</h3>
|
||||||
|
<ul class="setting-list">
|
||||||
|
<li>
|
||||||
|
<ChoiceSetting
|
||||||
|
id="mentionLinkDisplay"
|
||||||
|
path="mentionLinkDisplay"
|
||||||
|
:options="mentionLinkDisplayOptions"
|
||||||
|
>
|
||||||
|
{{ $t('settings.mention_link_display') }}
|
||||||
|
</ChoiceSetting>
|
||||||
|
<ul class="setting-list suboptions">
|
||||||
|
<li>
|
||||||
|
<BooleanSetting
|
||||||
|
v-if="mergedConfig.mentionLinkDisplay !== 'short'"
|
||||||
|
path="mentionLinkFadeDomain"
|
||||||
|
>
|
||||||
|
{{ $t('settings.mention_link_fade_domain') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting
|
||||||
|
path="mentionLinkShowTooltip"
|
||||||
|
expert="1"
|
||||||
|
>
|
||||||
|
{{ $t('settings.mention_link_use_tooltip') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting path="mentionLinkShowAvatar">
|
||||||
|
{{ $t('settings.mention_link_show_avatar') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<li v-if="user">
|
||||||
|
<BooleanSetting
|
||||||
|
path="mentionLinkBoldenYou"
|
||||||
|
expert="1"
|
||||||
|
>
|
||||||
|
{{ $t('settings.mention_link_bolden_you') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting
|
||||||
|
v-if="user"
|
||||||
|
source="profile"
|
||||||
|
path="stripRichContent"
|
||||||
|
expert="1"
|
||||||
|
>
|
||||||
|
{{ $t('settings.no_rich_text_description') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
<ul
|
||||||
|
v-if="mergedConfig.useAbsoluteTimeFormat"
|
||||||
|
class="setting-list suboptions"
|
||||||
|
>
|
||||||
|
<li>
|
||||||
|
<UnitSetting
|
||||||
|
path="absoluteTimeFormatMinAge"
|
||||||
|
unit-set="time"
|
||||||
|
:units="['s', 'm', 'h', 'd']"
|
||||||
|
:min="0"
|
||||||
|
>
|
||||||
|
{{ $t('settings.absolute_time_format_min_age') }}
|
||||||
|
</UnitSetting>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<h3>{{ $t('settings.attachments') }}</h3>
|
||||||
|
<ul class="setting-list">
|
||||||
|
<li>
|
||||||
|
<BooleanSetting path="stopGifs">
|
||||||
|
{{ $t('settings.stop_gifs') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting path="hideNsfw">
|
||||||
|
{{ $t('settings.nsfw_clickthrough') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
<ul class="setting-list suboptions">
|
||||||
|
<li>
|
||||||
|
<BooleanSetting
|
||||||
|
path="preloadImage"
|
||||||
|
expert="1"
|
||||||
|
parent-path="hideNsfw"
|
||||||
|
>
|
||||||
|
{{ $t('settings.preload_images') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting
|
||||||
|
path="useOneClickNsfw"
|
||||||
|
expert="1"
|
||||||
|
parent-path="hideNsfw"
|
||||||
|
>
|
||||||
|
{{ $t('settings.use_one_click_nsfw') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting
|
||||||
|
path="loopVideo"
|
||||||
|
expert="1"
|
||||||
|
>
|
||||||
|
{{ $t('settings.loop_video') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
<ul class="setting-list suboptions">
|
||||||
|
<li>
|
||||||
|
<BooleanSetting
|
||||||
|
path="loopVideoSilentOnly"
|
||||||
|
expert="1"
|
||||||
|
parent-path="loopVideo"
|
||||||
|
:disabled="!loopSilentAvailable"
|
||||||
|
>
|
||||||
|
{{ $t('settings.loop_video_silent_only') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
<div
|
||||||
|
v-if="!loopSilentAvailable"
|
||||||
|
class="unavailable"
|
||||||
|
>
|
||||||
|
<FAIcon icon="globe" />! {{ $t('settings.limited_availability') }}
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting
|
||||||
|
path="playVideosInModal"
|
||||||
|
expert="1"
|
||||||
|
>
|
||||||
|
{{ $t('settings.play_videos_in_modal') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting
|
||||||
|
path="useContainFit"
|
||||||
|
expert="1"
|
||||||
|
>
|
||||||
|
{{ $t('settings.use_contain_fit') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<h3 v-if="expertLevel > 0">
|
||||||
|
{{ $t('settings.fun') }}
|
||||||
|
</h3>
|
||||||
|
<ul
|
||||||
|
v-if="expertLevel > 0"
|
||||||
|
class="setting-list"
|
||||||
|
>
|
||||||
|
<li v-if="user">
|
||||||
|
<BooleanSetting path="mentionLinkShowYous">
|
||||||
|
{{ $t('settings.show_yous') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script src="./posts_tab.js"></script>
|
||||||
|
<style src="./posts_tab.scss"></style>
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="profile-tab">
|
<div class="profile-tab">
|
||||||
<div class="setting-item profile-edit">
|
<div class="setting-item profile-edit">
|
||||||
<h2>{{ $t('settings.account_profile_edit') }}</h2>
|
|
||||||
<UserCard
|
<UserCard
|
||||||
:user-id="user.id"
|
:user-id="user.id"
|
||||||
:editable="true"
|
:editable="true"
|
||||||
|
|
@ -9,7 +8,7 @@
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-item">
|
<div class="setting-item">
|
||||||
<h2>{{ $t('settings.account_privacy') }}</h2>
|
<h3>{{ $t('settings.account_privacy') }}</h3>
|
||||||
<ul class="setting-list">
|
<ul class="setting-list">
|
||||||
<li>
|
<li>
|
||||||
<Checkbox v-model="locked">
|
<Checkbox v-model="locked">
|
||||||
|
|
|
||||||
|
|
@ -1,31 +1,35 @@
|
||||||
<template>
|
<template>
|
||||||
<div :label="$t('settings.security_tab')">
|
<div :label="$t('settings.security_tab')">
|
||||||
<div class="setting-item">
|
<div class="setting-item">
|
||||||
<h2>{{ $t('settings.change_email') }}</h2>
|
<h3>{{ $t('settings.change_email') }}</h3>
|
||||||
<div>
|
<ul class="setting-list">
|
||||||
<p>{{ $t('settings.new_email') }}</p>
|
<li>
|
||||||
|
<h4>{{ $t('settings.new_email') }}</h4>
|
||||||
<input
|
<input
|
||||||
v-model="newEmail"
|
v-model="newEmail"
|
||||||
type="email"
|
type="email"
|
||||||
autocomplete="email"
|
autocomplete="email"
|
||||||
class="input"
|
class="input"
|
||||||
>
|
>
|
||||||
</div>
|
</li>
|
||||||
<div>
|
<li>
|
||||||
<p>{{ $t('settings.current_password') }}</p>
|
<h4>{{ $t('settings.current_password') }}</h4>
|
||||||
<input
|
<input
|
||||||
v-model="changeEmailPassword"
|
v-model="changeEmailPassword"
|
||||||
type="password"
|
type="password"
|
||||||
autocomplete="current-password"
|
autocomplete="current-password"
|
||||||
class="input"
|
class="input"
|
||||||
>
|
>
|
||||||
</div>
|
</li>
|
||||||
|
<li>
|
||||||
<button
|
<button
|
||||||
class="btn button-default"
|
class="btn button-default"
|
||||||
@click="changeEmail"
|
@click="changeEmail"
|
||||||
>
|
>
|
||||||
{{ $t('settings.save') }}
|
{{ $t('settings.save') }}
|
||||||
</button>
|
</button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
<p v-if="changedEmail">
|
<p v-if="changedEmail">
|
||||||
{{ $t('settings.changed_email') }}
|
{{ $t('settings.changed_email') }}
|
||||||
</p>
|
</p>
|
||||||
|
|
@ -33,40 +37,46 @@
|
||||||
<p>{{ $t('settings.change_email_error') }}</p>
|
<p>{{ $t('settings.change_email_error') }}</p>
|
||||||
<p>{{ changeEmailError }}</p>
|
<p>{{ changeEmailError }}</p>
|
||||||
</template>
|
</template>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="setting-item">
|
<div class="setting-item">
|
||||||
<h2>{{ $t('settings.change_password') }}</h2>
|
<h3>{{ $t('settings.change_password') }}</h3>
|
||||||
<div>
|
<ul class="setting-list">
|
||||||
<p>{{ $t('settings.current_password') }}</p>
|
<li>
|
||||||
|
<h4>{{ $t('settings.current_password') }}</h4>
|
||||||
<input
|
<input
|
||||||
v-model="changePasswordInputs[0]"
|
v-model="changePasswordInputs[0]"
|
||||||
type="password"
|
type="password"
|
||||||
class="input"
|
class="input"
|
||||||
>
|
>
|
||||||
</div>
|
</li>
|
||||||
<div>
|
<li>
|
||||||
<p>{{ $t('settings.new_password') }}</p>
|
<h4>{{ $t('settings.new_password') }}</h4>
|
||||||
<input
|
<input
|
||||||
v-model="changePasswordInputs[1]"
|
v-model="changePasswordInputs[1]"
|
||||||
type="password"
|
type="password"
|
||||||
class="input"
|
class="input"
|
||||||
>
|
>
|
||||||
</div>
|
</li>
|
||||||
<div>
|
<li>
|
||||||
<p>{{ $t('settings.confirm_new_password') }}</p>
|
<h4>{{ $t('settings.confirm_new_password') }}</h4>
|
||||||
<input
|
<input
|
||||||
v-model="changePasswordInputs[2]"
|
v-model="changePasswordInputs[2]"
|
||||||
type="password"
|
type="password"
|
||||||
class="input"
|
class="input"
|
||||||
>
|
>
|
||||||
</div>
|
</li>
|
||||||
|
<li>
|
||||||
<button
|
<button
|
||||||
class="btn button-default"
|
class="btn button-default"
|
||||||
@click="changePassword"
|
@click="changePassword"
|
||||||
>
|
>
|
||||||
{{ $t('settings.save') }}
|
{{ $t('settings.save') }}
|
||||||
</button>
|
</button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
<p v-if="changedPassword">
|
<p v-if="changedPassword">
|
||||||
{{ $t('settings.changed_password') }}
|
{{ $t('settings.changed_password') }}
|
||||||
</p>
|
</p>
|
||||||
|
|
@ -76,41 +86,12 @@
|
||||||
<p v-if="changePasswordError">
|
<p v-if="changePasswordError">
|
||||||
{{ changePasswordError }}
|
{{ changePasswordError }}
|
||||||
</p>
|
</p>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="setting-item">
|
<div class="setting-item">
|
||||||
<h2>{{ $t('settings.oauth_tokens') }}</h2>
|
<h3>{{ $t('settings.account_alias') }}</h3>
|
||||||
<table class="oauth-tokens">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>{{ $t('settings.app_name') }}</th>
|
|
||||||
<th>{{ $t('settings.valid_until') }}</th>
|
|
||||||
<th />
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr
|
|
||||||
v-for="oauthToken in oauthTokens"
|
|
||||||
:key="oauthToken.id"
|
|
||||||
>
|
|
||||||
<td>{{ oauthToken.appName }}</td>
|
|
||||||
<td>{{ oauthToken.validUntil }}</td>
|
|
||||||
<td class="actions">
|
|
||||||
<button
|
|
||||||
class="btn button-default"
|
|
||||||
@click="revokeToken(oauthToken.id)"
|
|
||||||
>
|
|
||||||
{{ $t('settings.revoke_token') }}
|
|
||||||
</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<mfa />
|
|
||||||
|
|
||||||
<div class="setting-item">
|
|
||||||
<h2>{{ $t('settings.account_alias') }}</h2>
|
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
@ -178,8 +159,40 @@
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="setting-item">
|
<div class="setting-item">
|
||||||
<h2>{{ $t('settings.move_account') }}</h2>
|
<h3>{{ $t('settings.oauth_tokens') }}</h3>
|
||||||
|
<table class="oauth-tokens">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{{ $t('settings.app_name') }}</th>
|
||||||
|
<th>{{ $t('settings.valid_until') }}</th>
|
||||||
|
<th />
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr
|
||||||
|
v-for="oauthToken in oauthTokens"
|
||||||
|
:key="oauthToken.id"
|
||||||
|
>
|
||||||
|
<td>{{ oauthToken.appName }}</td>
|
||||||
|
<td>{{ oauthToken.validUntil }}</td>
|
||||||
|
<td class="actions">
|
||||||
|
<button
|
||||||
|
class="btn button-default"
|
||||||
|
@click="revokeToken(oauthToken.id)"
|
||||||
|
>
|
||||||
|
{{ $t('settings.revoke_token') }}
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<mfa />
|
||||||
|
|
||||||
|
<div class="setting-item">
|
||||||
|
<h3>{{ $t('settings.move_account') }}</h3>
|
||||||
<p>{{ $t('settings.move_account_notes') }}</p>
|
<p>{{ $t('settings.move_account_notes') }}</p>
|
||||||
<div>
|
<div>
|
||||||
<i18n-t
|
<i18n-t
|
||||||
|
|
@ -222,7 +235,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="setting-item">
|
<div class="setting-item">
|
||||||
<h2>{{ $t('settings.delete_account') }}</h2>
|
<h3>{{ $t('settings.delete_account') }}</h3>
|
||||||
<p v-if="!deletingAccount">
|
<p v-if="!deletingAccount">
|
||||||
{{ $t('settings.delete_account_description') }}
|
{{ $t('settings.delete_account_description') }}
|
||||||
</p>
|
</p>
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ import RoundnessInput from 'src/components/roundness_input/roundness_input.vue'
|
||||||
import TabSwitcher from 'src/components/tab_switcher/tab_switcher.jsx'
|
import TabSwitcher from 'src/components/tab_switcher/tab_switcher.jsx'
|
||||||
import Tooltip from 'src/components/tooltip/tooltip.vue'
|
import Tooltip from 'src/components/tooltip/tooltip.vue'
|
||||||
import ContrastRatio from 'src/components/contrast_ratio/contrast_ratio.vue'
|
import ContrastRatio from 'src/components/contrast_ratio/contrast_ratio.vue'
|
||||||
import Preview from '../theme_tab/theme_preview.vue'
|
import Preview from '../old_theme_tab/theme_preview.vue'
|
||||||
|
|
||||||
import VirtualDirectivesTab from './virtual_directives_tab.vue'
|
import VirtualDirectivesTab from './virtual_directives_tab.vue'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,13 @@
|
||||||
min-width: var(--themeEditorMinWidth, fit-content);
|
min-width: var(--themeEditorMinWidth, fit-content);
|
||||||
|
|
||||||
.style-control {
|
.style-control {
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
align-items: baseline;
|
align-items: baseline;
|
||||||
margin-bottom: 0.5em;
|
margin-bottom: 0.5em;
|
||||||
|
|
||||||
.label {
|
.label {
|
||||||
|
display: inline-block;
|
||||||
margin-right: 0.5em;
|
margin-right: 0.5em;
|
||||||
flex: 1 1 0;
|
flex: 1 1 auto;
|
||||||
line-height: 2;
|
line-height: 2;
|
||||||
min-height: 2em;
|
min-height: 2em;
|
||||||
}
|
}
|
||||||
|
|
@ -18,10 +17,6 @@
|
||||||
margin-left: 1em;
|
margin-left: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.color-input {
|
|
||||||
flex: 0 0 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
input,
|
input,
|
||||||
select {
|
select {
|
||||||
min-width: 3em;
|
min-width: 3em;
|
||||||
|
|
@ -50,21 +45,24 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.setting-item.heading {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.meta-preview {
|
.meta-preview {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template:
|
grid-template:
|
||||||
"meta meta preview preview"
|
"meta preview";
|
||||||
"meta meta preview preview"
|
grid-gap: 1em;
|
||||||
"meta meta preview preview"
|
grid-template-columns: min-content 6fr;
|
||||||
"meta meta preview preview";
|
|
||||||
grid-gap: 0.5em;
|
.theme-preview-container {
|
||||||
grid-template-columns: min-content min-content 6fr max-content;
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
ul.setting-list {
|
ul.setting-list {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
display: grid;
|
|
||||||
grid-template-rows: subgrid;
|
|
||||||
grid-area: meta;
|
grid-area: meta;
|
||||||
|
|
||||||
> li {
|
> li {
|
||||||
|
|
@ -114,6 +112,7 @@
|
||||||
|
|
||||||
.list-edit-area {
|
.list-edit-area {
|
||||||
grid-area: editor;
|
grid-area: editor;
|
||||||
|
align-items: baseline;
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-select {
|
.list-select {
|
||||||
|
|
@ -134,21 +133,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.palette-editor {
|
|
||||||
width: min-content;
|
|
||||||
|
|
||||||
.list-edit-area {
|
|
||||||
display: grid;
|
|
||||||
align-self: baseline;
|
|
||||||
grid-template-rows: subgrid;
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
}
|
|
||||||
|
|
||||||
.palette-editor-single {
|
|
||||||
grid-row: 2 / span 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.variables-editor {
|
.variables-editor {
|
||||||
.variable-selector {
|
.variable-selector {
|
||||||
display: grid;
|
display: grid;
|
||||||
|
|
@ -249,6 +233,46 @@
|
||||||
justify-items: center;
|
justify-items: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.-mobile & {
|
||||||
|
.meta-preview {
|
||||||
|
grid-template:
|
||||||
|
"meta"
|
||||||
|
"preview"
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-editor {
|
||||||
|
display: grid;
|
||||||
|
grid-template-areas:
|
||||||
|
"label"
|
||||||
|
"selector"
|
||||||
|
"movement"
|
||||||
|
"editor"
|
||||||
|
"editor"
|
||||||
|
"editor"
|
||||||
|
"editor";
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
grid-template-rows: auto 1fr auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.component-editor {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
grid-template-rows: auto;
|
||||||
|
grid-template-areas:
|
||||||
|
"component"
|
||||||
|
"variant"
|
||||||
|
"state"
|
||||||
|
"preview"
|
||||||
|
"settings";
|
||||||
|
}
|
||||||
|
|
||||||
|
.variable-selector {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
grid-template-rows: auto;
|
||||||
|
grid-auto-flow: row;
|
||||||
|
grid-gap: 0.5em;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.extra-content {
|
.extra-content {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="StyleTab">
|
<div class="StyleTab">
|
||||||
<div class="setting-item heading">
|
<div class="setting-item heading">
|
||||||
<h2> {{ $t('settings.style.themes3.editor.title') }} </h2>
|
|
||||||
<div class="meta-preview">
|
<div class="meta-preview">
|
||||||
<Preview id="edited-style-preview" />
|
<Preview id="edited-style-preview" />
|
||||||
<teleport
|
<teleport
|
||||||
|
|
@ -85,6 +84,7 @@
|
||||||
key="component"
|
key="component"
|
||||||
class="setting-item component-editor"
|
class="setting-item component-editor"
|
||||||
:label="$t('settings.style.themes3.editor.component_tab')"
|
:label="$t('settings.style.themes3.editor.component_tab')"
|
||||||
|
:full-width="true"
|
||||||
>
|
>
|
||||||
<div class="component-selector">
|
<div class="component-selector">
|
||||||
<label for="component-selector">
|
<label for="component-selector">
|
||||||
|
|
@ -332,6 +332,7 @@
|
||||||
key="palette"
|
key="palette"
|
||||||
:label="$t('settings.style.themes3.editor.palette_tab')"
|
:label="$t('settings.style.themes3.editor.palette_tab')"
|
||||||
class="setting-item list-editor palette-editor"
|
class="setting-item list-editor palette-editor"
|
||||||
|
:full-width="true"
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
class="list-select-label"
|
class="list-select-label"
|
||||||
|
|
@ -379,6 +380,7 @@
|
||||||
key="variables"
|
key="variables"
|
||||||
:label="$t('settings.style.themes3.editor.variables_tab')"
|
:label="$t('settings.style.themes3.editor.variables_tab')"
|
||||||
:model-value="virtualDirectives"
|
:model-value="virtualDirectives"
|
||||||
|
:full-width="true"
|
||||||
@update:model-value="updateVirtualDirectives"
|
@update:model-value="updateVirtualDirectives"
|
||||||
/>
|
/>
|
||||||
</tab-switcher>
|
</tab-switcher>
|
||||||
|
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
const pleromaFeCommitUrl = 'https://git.pleroma.social/pleroma/pleroma-fe/commit/'
|
|
||||||
|
|
||||||
const VersionTab = {
|
|
||||||
data () {
|
|
||||||
const instance = this.$store.state.instance
|
|
||||||
return {
|
|
||||||
backendVersion: instance.backendVersion,
|
|
||||||
backendRepository: instance.backendRepository,
|
|
||||||
frontendVersion: instance.frontendVersion
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
frontendVersionLink () {
|
|
||||||
return pleromaFeCommitUrl + this.frontendVersion
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default VersionTab
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
<template>
|
|
||||||
<div :label="$t('settings.version.title')">
|
|
||||||
<div class="setting-item">
|
|
||||||
<ul class="setting-list">
|
|
||||||
<li>
|
|
||||||
<p>{{ $t('settings.version.backend_version') }}</p>
|
|
||||||
<ul class="option-list">
|
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
:href="backendRepository"
|
|
||||||
target="_blank"
|
|
||||||
>{{ backendVersion }}</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>{{ $t('settings.version.frontend_version') }}</p>
|
|
||||||
<ul class="option-list">
|
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
:href="frontendVersionLink"
|
|
||||||
target="_blank"
|
|
||||||
>{{ frontendVersion }}</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script src="./version_tab.js" />
|
|
||||||
|
|
@ -6,6 +6,10 @@
|
||||||
grid-gap: 0.5em;
|
grid-gap: 0.5em;
|
||||||
justify-content: stretch;
|
justify-content: stretch;
|
||||||
|
|
||||||
|
.style-control {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
&.-compact {
|
&.-compact {
|
||||||
grid-template-columns: 10em 1fr;
|
grid-template-columns: 10em 1fr;
|
||||||
grid-template-rows: auto auto;
|
grid-template-rows: auto auto;
|
||||||
|
|
@ -110,7 +114,6 @@
|
||||||
|
|
||||||
.shadow-preview {
|
.shadow-preview {
|
||||||
grid-area: preview;
|
grid-area: preview;
|
||||||
min-width: 25em;
|
|
||||||
margin-left: 0.125em;
|
margin-left: 0.125em;
|
||||||
place-self: start center;
|
place-self: start center;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -168,6 +168,7 @@
|
||||||
:disabled="disabled || !present"
|
:disabled="disabled || !present"
|
||||||
:label="$t('settings.style.common.color')"
|
:label="$t('settings.style.common.color')"
|
||||||
:fallback="getColorFallback"
|
:fallback="getColorFallback"
|
||||||
|
:compact="true"
|
||||||
:show-optional-checkbox="false"
|
:show-optional-checkbox="false"
|
||||||
name="shadow"
|
name="shadow"
|
||||||
@update:model-value="e => updateProperty('color', e)"
|
@update:model-value="e => updateProperty('color', e)"
|
||||||
|
|
|
||||||
|
|
@ -31,11 +31,6 @@ export default {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
},
|
},
|
||||||
sideTabBar: {
|
|
||||||
required: false,
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
bodyScrollLock: {
|
bodyScrollLock: {
|
||||||
required: false,
|
required: false,
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
|
|
@ -143,8 +138,11 @@ export default {
|
||||||
if (!props) return
|
if (!props) return
|
||||||
const active = this.activeIndex === index
|
const active = this.activeIndex === index
|
||||||
const classes = [ active ? 'active' : 'hidden' ]
|
const classes = [ active ? 'active' : 'hidden' ]
|
||||||
if (props.fullHeight) {
|
if (props.fullHeight || props['full-height']) {
|
||||||
classes.push('full-height')
|
classes.push('-full-height')
|
||||||
|
}
|
||||||
|
if (props.fullWidth || props['full-width']) {
|
||||||
|
classes.push('-full-width')
|
||||||
}
|
}
|
||||||
let delayRender = slot.props['delay-render']
|
let delayRender = slot.props['delay-render']
|
||||||
if (delayRender && active) {
|
if (delayRender && active) {
|
||||||
|
|
@ -157,29 +155,28 @@ export default {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class={classes}>
|
<div class={classes}>
|
||||||
{
|
|
||||||
this.sideTabBar
|
|
||||||
? <h1 class="mobile-label">{props.label}</h1>
|
|
||||||
: ''
|
|
||||||
}
|
|
||||||
{renderSlot}
|
{renderSlot}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class={'tab-switcher ' + (this.sideTabBar ? 'side-tabs' : 'top-tabs')}>
|
<div
|
||||||
|
class="tab-switcher top-tabs"
|
||||||
|
ref="root"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
class="tabs"
|
class="tabs"
|
||||||
role="tablist"
|
role="tablist"
|
||||||
|
ref="nav"
|
||||||
>
|
>
|
||||||
{tabs}
|
{tabs}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
ref="contents"
|
|
||||||
role="tabpanel"
|
role="tabpanel"
|
||||||
class={'contents' + (this.scrollableTabs ? ' scrollable-tabs' : '')}
|
class={'contents' + (this.scrollableTabs ? ' scrollable-tabs' : '')}
|
||||||
v-body-scroll-lock={this.bodyScrollLock}
|
v-body-scroll-lock={this.bodyScrollLock}
|
||||||
|
ref="content"
|
||||||
>
|
>
|
||||||
{contents}
|
{contents}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -52,104 +52,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.side-tabs {
|
|
||||||
flex-direction: row;
|
|
||||||
|
|
||||||
@media all and (width <= 800px) {
|
|
||||||
overflow-x: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .contents {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .tabs {
|
|
||||||
flex: 0 0 auto;
|
|
||||||
overflow: hidden auto;
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
&::after,
|
|
||||||
&::before {
|
|
||||||
flex-shrink: 0;
|
|
||||||
flex-basis: 0.5em;
|
|
||||||
content: "";
|
|
||||||
border-right: 1px solid;
|
|
||||||
border-right-color: var(--border);
|
|
||||||
}
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
flex-grow: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
flex-grow: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-wrapper {
|
|
||||||
min-width: 10em;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
@media all and (width <= 800px) {
|
|
||||||
min-width: 4em;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:not(.active)::after {
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
border-right: 1px solid;
|
|
||||||
border-right-color: var(--border);
|
|
||||||
}
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
flex: 0 0 6px;
|
|
||||||
content: "";
|
|
||||||
border-right: 1px solid;
|
|
||||||
border-right-color: var(--border);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:last-child .tab {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab {
|
|
||||||
flex: 1;
|
|
||||||
box-sizing: content-box;
|
|
||||||
max-width: 9em;
|
|
||||||
min-width: 1px;
|
|
||||||
border-top-right-radius: 0;
|
|
||||||
border-bottom-right-radius: 0;
|
|
||||||
padding-left: 1em;
|
|
||||||
padding-right: calc(1em + 200px);
|
|
||||||
margin-right: -200px;
|
|
||||||
margin-left: 1em;
|
|
||||||
|
|
||||||
&:not(.active) {
|
|
||||||
margin-top: 0;
|
|
||||||
margin-left: 1.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media all and (width <= 800px) {
|
|
||||||
padding-left: 0.25em;
|
|
||||||
padding-right: calc(0.25em + 200px);
|
|
||||||
margin-right: calc(0.25em - 200px);
|
|
||||||
margin-left: 0.25em;
|
|
||||||
|
|
||||||
&:not(.active) {
|
|
||||||
margin-top: 0;
|
|
||||||
margin-left: 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.contents {
|
.contents {
|
||||||
flex: 1 0 auto;
|
flex: 1 0 auto;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
|
|
@ -158,7 +60,7 @@
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.full-height:not(.hidden) {
|
.-full-height:not(.hidden) {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
@ -168,6 +70,15 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.-full-width:not(.hidden) {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
> *:not(.mobile-label) {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&.scrollable-tabs {
|
&.scrollable-tabs {
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -132,6 +132,7 @@
|
||||||
},
|
},
|
||||||
"importer": {
|
"importer": {
|
||||||
"submit": "Submit",
|
"submit": "Submit",
|
||||||
|
"import": "Import",
|
||||||
"success": "Imported successfully.",
|
"success": "Imported successfully.",
|
||||||
"error": "An error occured while importing this file."
|
"error": "An error occured while importing this file."
|
||||||
},
|
},
|
||||||
|
|
@ -403,7 +404,10 @@
|
||||||
"setting_server_side": "This setting is tied to your profile and affects all sessions and clients",
|
"setting_server_side": "This setting is tied to your profile and affects all sessions and clients",
|
||||||
"enter_current_password_to_confirm": "Enter your current password to confirm your identity",
|
"enter_current_password_to_confirm": "Enter your current password to confirm your identity",
|
||||||
"post_look_feel": "Posts Look & Feel",
|
"post_look_feel": "Posts Look & Feel",
|
||||||
"mention_links": "Mention links",
|
"posts": "Posts",
|
||||||
|
"developer": "Developer",
|
||||||
|
"debug": "Debug",
|
||||||
|
"mention_links": "Mention Links",
|
||||||
"appearance": "Appearance",
|
"appearance": "Appearance",
|
||||||
"confirm_new_setting": "Confirm new setting?",
|
"confirm_new_setting": "Confirm new setting?",
|
||||||
"confirm_new_question": "Does this look ok? Setting will be reverted in 10 seconds.",
|
"confirm_new_question": "Does this look ok? Setting will be reverted in 10 seconds.",
|
||||||
|
|
@ -416,9 +420,14 @@
|
||||||
"navbar_size": "Top bar size",
|
"navbar_size": "Top bar size",
|
||||||
"panel_header_size": "Panel header size",
|
"panel_header_size": "Panel header size",
|
||||||
"visual_tweaks": "Minor visual tweaks",
|
"visual_tweaks": "Minor visual tweaks",
|
||||||
"theme_debug": "Show what background theme engine assumes when dealing with transparancy (DEBUG)",
|
"theme_debug": "Show what background theme engine assumes when dealing with transparancy",
|
||||||
"scale_and_layout": "Interface scale and layout",
|
"scale_and_layout": "Interface scale and layout",
|
||||||
|
"timelines": "Timelines",
|
||||||
|
"format_and_language": "Format and Language",
|
||||||
|
"confirmations": "Confirmations",
|
||||||
|
"layout": "Layout",
|
||||||
"enabled": "Enabled",
|
"enabled": "Enabled",
|
||||||
|
"clutter": "Clutter",
|
||||||
"filter": {
|
"filter": {
|
||||||
"clutter": "Remove clutter",
|
"clutter": "Remove clutter",
|
||||||
"mute_filter": "Mute Filters",
|
"mute_filter": "Mute Filters",
|
||||||
|
|
@ -533,6 +542,7 @@
|
||||||
"chatMessageRadius": "Chat message",
|
"chatMessageRadius": "Chat message",
|
||||||
"collapse_subject": "Collapse posts with subjects",
|
"collapse_subject": "Collapse posts with subjects",
|
||||||
"composing": "Composing",
|
"composing": "Composing",
|
||||||
|
"replies": "Replying",
|
||||||
"confirm_new_password": "Confirm new password",
|
"confirm_new_password": "Confirm new password",
|
||||||
"current_password": "Current password",
|
"current_password": "Current password",
|
||||||
"confirm_dialogs": "Ask for confirmation when",
|
"confirm_dialogs": "Ask for confirmation when",
|
||||||
|
|
@ -594,6 +604,12 @@
|
||||||
"follow_export_button": "Export your follows to a csv file",
|
"follow_export_button": "Export your follows to a csv file",
|
||||||
"follow_import": "Follow import",
|
"follow_import": "Follow import",
|
||||||
"follow_import_error": "Error importing followers",
|
"follow_import_error": "Error importing followers",
|
||||||
|
"import_export": {
|
||||||
|
"title": "Import / Export",
|
||||||
|
"follows": "List of users you follow",
|
||||||
|
"blocks": "List of users you block",
|
||||||
|
"mutes": "List of users you mute"
|
||||||
|
},
|
||||||
"follows_imported": "Follows imported! Processing them will take a while.",
|
"follows_imported": "Follows imported! Processing them will take a while.",
|
||||||
"accent": "Accent",
|
"accent": "Accent",
|
||||||
"foreground": "Foreground",
|
"foreground": "Foreground",
|
||||||
|
|
@ -745,7 +761,7 @@
|
||||||
"subject_line_email": "Like email: \"re: subject\"",
|
"subject_line_email": "Like email: \"re: subject\"",
|
||||||
"subject_line_mastodon": "Like mastodon: copy as is",
|
"subject_line_mastodon": "Like mastodon: copy as is",
|
||||||
"subject_line_noop": "Do not copy",
|
"subject_line_noop": "Do not copy",
|
||||||
"force_theme_recompilation_debug": "Disable theme cahe, force recompile on each boot (DEBUG)",
|
"force_theme_recompilation_debug": "Disable theme cahe, force recompile on each boot",
|
||||||
"conversation_display": "Conversation display style",
|
"conversation_display": "Conversation display style",
|
||||||
"conversation_display_tree": "Tree-style",
|
"conversation_display_tree": "Tree-style",
|
||||||
"conversation_display_tree_quick": "Tree view",
|
"conversation_display_tree_quick": "Tree view",
|
||||||
|
|
@ -760,6 +776,8 @@
|
||||||
"column_sizes_sidebar": "Sidebar",
|
"column_sizes_sidebar": "Sidebar",
|
||||||
"column_sizes_content": "Content",
|
"column_sizes_content": "Content",
|
||||||
"column_sizes_notifs": "Notifications",
|
"column_sizes_notifs": "Notifications",
|
||||||
|
"layout": "Layout",
|
||||||
|
"scale_and_font": "Scale and Font",
|
||||||
"theme_editor_min_width": "Minimum width of theme editor (0 for \"fit-content\")",
|
"theme_editor_min_width": "Minimum width of theme editor (0 for \"fit-content\")",
|
||||||
"tree_advanced": "Allow more flexible navigation in tree view",
|
"tree_advanced": "Allow more flexible navigation in tree view",
|
||||||
"tree_fade_ancestors": "Display ancestors of the current status in faint text",
|
"tree_fade_ancestors": "Display ancestors of the current status in faint text",
|
||||||
|
|
@ -770,6 +788,7 @@
|
||||||
"conversation_other_replies_button_inside": "Inside statuses",
|
"conversation_other_replies_button_inside": "Inside statuses",
|
||||||
"max_depth_in_thread": "Maximum number of levels in thread to display by default",
|
"max_depth_in_thread": "Maximum number of levels in thread to display by default",
|
||||||
"post_status_content_type": "Post status content type",
|
"post_status_content_type": "Post status content type",
|
||||||
|
"default_post_status_content_type": "Default post status content type",
|
||||||
"sensitive_by_default": "Mark posts as sensitive by default",
|
"sensitive_by_default": "Mark posts as sensitive by default",
|
||||||
"stop_gifs": "Pause animated images until you hover on them",
|
"stop_gifs": "Pause animated images until you hover on them",
|
||||||
"streaming": "Automatically show new posts when scrolled to the top",
|
"streaming": "Automatically show new posts when scrolled to the top",
|
||||||
|
|
@ -811,8 +830,11 @@
|
||||||
"user_popover_avatar_overlay": "Show user popover over user avatar",
|
"user_popover_avatar_overlay": "Show user popover over user avatar",
|
||||||
"user_card_left_justify": "Justify user bio to the left",
|
"user_card_left_justify": "Justify user bio to the left",
|
||||||
"user_card_hide_personal_marks": "Hide personal marks (highlight/note) in user profiles",
|
"user_card_hide_personal_marks": "Hide personal marks (highlight/note) in user profiles",
|
||||||
|
"posts_appearance": "Posts Appearance",
|
||||||
"fun": "Fun",
|
"fun": "Fun",
|
||||||
"greentext": "Meme arrows",
|
"greentext": "Meme arrows",
|
||||||
|
"plaintext_quotes": "Highlight plaintext {0}",
|
||||||
|
"greentext_quotes": ">quotes",
|
||||||
"show_yous": "Show (You)s",
|
"show_yous": "Show (You)s",
|
||||||
"notifications": "Notifications",
|
"notifications": "Notifications",
|
||||||
"notification_setting_annoyance": "Annoyance",
|
"notification_setting_annoyance": "Annoyance",
|
||||||
|
|
@ -832,11 +854,13 @@
|
||||||
"enable_web_push_always_show_tip": "Some browsers (Chromium, Chrome) require that push messages always result in a notification, otherwise generic 'Website was updated in background' is shown, enable this to prevent this notification from showing, as Chrome seem to hide push notifications if tab is in focus. Can result in showing duplicate notifications on other browsers.",
|
"enable_web_push_always_show_tip": "Some browsers (Chromium, Chrome) require that push messages always result in a notification, otherwise generic 'Website was updated in background' is shown, enable this to prevent this notification from showing, as Chrome seem to hide push notifications if tab is in focus. Can result in showing duplicate notifications on other browsers.",
|
||||||
"more_settings": "More settings",
|
"more_settings": "More settings",
|
||||||
"style": {
|
"style": {
|
||||||
|
"style_section": "Style",
|
||||||
"custom_theme_used": "(Custom theme)",
|
"custom_theme_used": "(Custom theme)",
|
||||||
"custom_style_used": "(Custom style)",
|
"custom_style_used": "(Custom style)",
|
||||||
"stock_theme_used": "(Stock theme)",
|
"stock_theme_used": "(Stock theme)",
|
||||||
"themes2_outdated": "Editor for Themes V2 is being phased out and will eventually be replaced with a new one that takes advantage of new Themes V3 engine. It should still work but experience might be degraded and inconsistent.",
|
"themes2_outdated": "Editor for Themes V2 is being phased out and will eventually be replaced with a new one that takes advantage of new Themes V3 engine. It should still work but experience might be degraded and inconsistent.",
|
||||||
"appearance_tab_note": "Changes on this tab do not affect the theme used, so exported theme will be different from what seen in the UI",
|
"appearance_tab_note": "Changes on this tab do not affect the theme used, so exported theme will be different from what seen in the UI",
|
||||||
|
"visual_tweaks_section_note": "Changes in this section do not affect the theme used, exported theme will be different from what seen in the UI",
|
||||||
"update_preview": "Update preview",
|
"update_preview": "Update preview",
|
||||||
"themes3": {
|
"themes3": {
|
||||||
"define": "Override",
|
"define": "Override",
|
||||||
|
|
@ -1075,6 +1099,13 @@
|
||||||
"post": "Post text",
|
"post": "Post text",
|
||||||
"monospace": "Monospaced text"
|
"monospace": "Monospaced text"
|
||||||
},
|
},
|
||||||
|
"components_inline": {
|
||||||
|
"interface": "interface",
|
||||||
|
"input": "input fields",
|
||||||
|
"post": "post text",
|
||||||
|
"monospace": "monospaced text"
|
||||||
|
},
|
||||||
|
"override": "Override {0} font",
|
||||||
"family": "Font name",
|
"family": "Font name",
|
||||||
"size": "Size (in px)",
|
"size": "Size (in px)",
|
||||||
"weight": "Weight (boldness)",
|
"weight": "Weight (boldness)",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue