moved stuff from settings, cleaned up naming for tabs, added close and peek
This commit is contained in:
parent
2e35289c33
commit
bcebec478e
42 changed files with 801 additions and 1053 deletions
48
src/App.scss
48
src/App.scss
|
@ -860,54 +860,6 @@ nav {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DELETE
|
|
||||||
.setting-item {
|
|
||||||
border-bottom: 2px solid var(--fg, $fallback--fg);
|
|
||||||
margin: 1em 1em 1.4em;
|
|
||||||
padding-bottom: 1.4em;
|
|
||||||
|
|
||||||
> div {
|
|
||||||
margin-bottom: .5em;
|
|
||||||
&:last-child {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
border-bottom: none;
|
|
||||||
padding-bottom: 0;
|
|
||||||
margin-bottom: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
select {
|
|
||||||
min-width: 10em;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
textarea {
|
|
||||||
width: 100%;
|
|
||||||
max-width: 100%;
|
|
||||||
height: 100px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.unavailable,
|
|
||||||
.unavailable i {
|
|
||||||
color: var(--cRed, $fallback--cRed);
|
|
||||||
color: $fallback--cRed;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn {
|
|
||||||
min-height: 28px;
|
|
||||||
min-width: 10em;
|
|
||||||
padding: 0 2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.number-input {
|
|
||||||
max-width: 6em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// DELETE
|
|
||||||
|
|
||||||
.select-multiple {
|
.select-multiple {
|
||||||
display: flex;
|
display: flex;
|
||||||
.option-list {
|
.option-list {
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
v-show="isOpen"
|
v-show="isOpen"
|
||||||
v-body-scroll-lock="isOpen"
|
v-body-scroll-lock="isOpen"
|
||||||
class="modal-view"
|
class="modal-view"
|
||||||
|
:class="{ 'modal-background': !noBackground }"
|
||||||
@click.self="$emit('backdropClicked')"
|
@click.self="$emit('backdropClicked')"
|
||||||
>
|
>
|
||||||
<slot />
|
<slot />
|
||||||
|
@ -15,6 +16,10 @@ export default {
|
||||||
isOpen: {
|
isOpen: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: true
|
||||||
|
},
|
||||||
|
noBackground: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,10 +37,19 @@ export default {
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
pointer-events: none;
|
||||||
animation-duration: 0.2s;
|
animation-duration: 0.2s;
|
||||||
background-color: rgba(0, 0, 0, 0.5);
|
|
||||||
animation-name: modal-background-fadein;
|
animation-name: modal-background-fadein;
|
||||||
|
|
||||||
|
> * {
|
||||||
|
pointer-events: initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.modal-background {
|
||||||
|
pointer-events: initial;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
body:not(.scroll-locked) & {
|
body:not(.scroll-locked) & {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,128 +0,0 @@
|
||||||
/* eslint-env browser */
|
|
||||||
import { filter, trim } from 'lodash'
|
|
||||||
|
|
||||||
import TabSwitcher from '../tab_switcher/tab_switcher.js'
|
|
||||||
import StyleSwitcher from '../style_switcher/style_switcher.vue'
|
|
||||||
import InterfaceLanguageSwitcher from '../interface_language_switcher/interface_language_switcher.vue'
|
|
||||||
import { extractCommit } from '../../services/version/version.service'
|
|
||||||
import { instanceDefaultProperties, defaultState as configDefaultState } from '../../modules/config.js'
|
|
||||||
import Checkbox from '../checkbox/checkbox.vue'
|
|
||||||
|
|
||||||
const pleromaFeCommitUrl = 'https://git.pleroma.social/pleroma/pleroma-fe/commit/'
|
|
||||||
const pleromaBeCommitUrl = 'https://git.pleroma.social/pleroma/pleroma/commit/'
|
|
||||||
|
|
||||||
const multiChoiceProperties = [
|
|
||||||
'postContentType',
|
|
||||||
'subjectLineBehavior'
|
|
||||||
]
|
|
||||||
|
|
||||||
const settings = {
|
|
||||||
data () {
|
|
||||||
const instance = this.$store.state.instance
|
|
||||||
|
|
||||||
return {
|
|
||||||
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'),
|
|
||||||
|
|
||||||
backendVersion: instance.backendVersion,
|
|
||||||
frontendVersion: instance.frontendVersion
|
|
||||||
}
|
|
||||||
},
|
|
||||||
components: {
|
|
||||||
TabSwitcher,
|
|
||||||
StyleSwitcher,
|
|
||||||
InterfaceLanguageSwitcher,
|
|
||||||
Checkbox
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
user () {
|
|
||||||
return this.$store.state.users.currentUser
|
|
||||||
},
|
|
||||||
currentSaveStateNotice () {
|
|
||||||
return this.$store.state.interface.settings.currentSaveStateNotice
|
|
||||||
},
|
|
||||||
postFormats () {
|
|
||||||
return this.$store.state.instance.postFormats || []
|
|
||||||
},
|
|
||||||
instanceSpecificPanelPresent () { return this.$store.state.instance.showInstanceSpecificPanel },
|
|
||||||
frontendVersionLink () {
|
|
||||||
return pleromaFeCommitUrl + this.frontendVersion
|
|
||||||
},
|
|
||||||
backendVersionLink () {
|
|
||||||
return pleromaBeCommitUrl + extractCommit(this.backendVersion)
|
|
||||||
},
|
|
||||||
// Getting localized values for instance-default properties
|
|
||||||
...instanceDefaultProperties
|
|
||||||
.filter(key => multiChoiceProperties.includes(key))
|
|
||||||
.map(key => [
|
|
||||||
key + 'DefaultValue',
|
|
||||||
function () {
|
|
||||||
return this.$store.getters.instanceDefaultConfig[key]
|
|
||||||
}
|
|
||||||
])
|
|
||||||
.reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}),
|
|
||||||
...instanceDefaultProperties
|
|
||||||
.filter(key => !multiChoiceProperties.includes(key))
|
|
||||||
.map(key => [
|
|
||||||
key + 'LocalizedValue',
|
|
||||||
function () {
|
|
||||||
return this.$t('settings.values.' + this.$store.getters.instanceDefaultConfig[key])
|
|
||||||
}
|
|
||||||
])
|
|
||||||
.reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}),
|
|
||||||
// Generating computed values for vuex properties
|
|
||||||
...Object.keys(configDefaultState)
|
|
||||||
.map(key => [key, {
|
|
||||||
get () { return this.$store.getters.mergedConfig[key] },
|
|
||||||
set (value) {
|
|
||||||
this.$store.dispatch('setOption', { name: key, value })
|
|
||||||
}
|
|
||||||
}])
|
|
||||||
.reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}),
|
|
||||||
// Special cases (need to transform values or perform actions first)
|
|
||||||
muteWordsString: {
|
|
||||||
get () { return this.$store.getters.mergedConfig.muteWords.join('\n') },
|
|
||||||
set (value) {
|
|
||||||
this.$store.dispatch('setOption', {
|
|
||||||
name: 'muteWords',
|
|
||||||
value: filter(value.split('\n'), (word) => trim(word).length > 0)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
useStreamingApi: {
|
|
||||||
get () { return this.$store.getters.mergedConfig.useStreamingApi },
|
|
||||||
set (value) {
|
|
||||||
const promise = value
|
|
||||||
? this.$store.dispatch('enableMastoSockets')
|
|
||||||
: this.$store.dispatch('disableMastoSockets')
|
|
||||||
|
|
||||||
promise.then(() => {
|
|
||||||
this.$store.dispatch('setOption', { name: 'useStreamingApi', value })
|
|
||||||
}).catch((e) => {
|
|
||||||
console.error('Failed starting MastoAPI Streaming socket', e)
|
|
||||||
this.$store.dispatch('disableMastoSockets')
|
|
||||||
this.$store.dispatch('setOption', { name: 'useStreamingApi', value: false })
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// Updating nested properties
|
|
||||||
watch: {
|
|
||||||
notificationVisibility: {
|
|
||||||
handler (value) {
|
|
||||||
this.$store.dispatch('setOption', {
|
|
||||||
name: 'notificationVisibility',
|
|
||||||
value: this.$store.getters.mergedConfig.notificationVisibility
|
|
||||||
})
|
|
||||||
},
|
|
||||||
deep: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default settings
|
|
|
@ -1,424 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="settings panel panel-default">
|
|
||||||
<div class="panel-heading">
|
|
||||||
<div class="title">
|
|
||||||
{{ $t('settings.settings') }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<transition name="fade">
|
|
||||||
<template v-if="currentSaveStateNotice">
|
|
||||||
<div
|
|
||||||
v-if="currentSaveStateNotice.error"
|
|
||||||
class="alert error"
|
|
||||||
@click.prevent
|
|
||||||
>
|
|
||||||
{{ $t('settings.saving_err') }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
v-if="!currentSaveStateNotice.error"
|
|
||||||
class="alert transparent"
|
|
||||||
@click.prevent
|
|
||||||
>
|
|
||||||
{{ $t('settings.saving_ok') }}
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</transition>
|
|
||||||
</div>
|
|
||||||
<div class="panel-body">
|
|
||||||
<keep-alive>
|
|
||||||
<tab-switcher>
|
|
||||||
<div :label="$t('settings.general')">
|
|
||||||
<div class="setting-item">
|
|
||||||
<h2>{{ $t('settings.interface') }}</h2>
|
|
||||||
<ul class="setting-list">
|
|
||||||
<li>
|
|
||||||
<interface-language-switcher />
|
|
||||||
</li>
|
|
||||||
<li v-if="instanceSpecificPanelPresent">
|
|
||||||
<Checkbox v-model="hideISP">
|
|
||||||
{{ $t('settings.hide_isp') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="setting-item">
|
|
||||||
<h2>{{ $t('nav.timeline') }}</h2>
|
|
||||||
<ul class="setting-list">
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="hideMutedPosts">
|
|
||||||
{{ $t('settings.hide_muted_posts') }} {{ $t('settings.instance_default', { value: hideMutedPostsLocalizedValue }) }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="collapseMessageWithSubject">
|
|
||||||
{{ $t('settings.collapse_subject') }} {{ $t('settings.instance_default', { value: collapseMessageWithSubjectLocalizedValue }) }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="streaming">
|
|
||||||
{{ $t('settings.streaming') }}
|
|
||||||
</Checkbox>
|
|
||||||
<ul
|
|
||||||
class="setting-list suboptions"
|
|
||||||
:class="[{disabled: !streaming}]"
|
|
||||||
>
|
|
||||||
<li>
|
|
||||||
<Checkbox
|
|
||||||
v-model="pauseOnUnfocused"
|
|
||||||
:disabled="!streaming"
|
|
||||||
>
|
|
||||||
{{ $t('settings.pause_on_unfocused') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="useStreamingApi">
|
|
||||||
{{ $t('settings.useStreamingApi') }}
|
|
||||||
<br>
|
|
||||||
<small>
|
|
||||||
{{ $t('settings.useStreamingApiWarning') }}
|
|
||||||
</small>
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="autoLoad">
|
|
||||||
{{ $t('settings.autoload') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="hoverPreview">
|
|
||||||
{{ $t('settings.reply_link_preview') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="emojiReactionsOnTimeline">
|
|
||||||
{{ $t('settings.emoji_reactions_on_timeline') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="setting-item">
|
|
||||||
<h2>{{ $t('settings.composing') }}</h2>
|
|
||||||
<ul class="setting-list">
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="scopeCopy">
|
|
||||||
{{ $t('settings.scope_copy') }} {{ $t('settings.instance_default', { value: scopeCopyLocalizedValue }) }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="alwaysShowSubjectInput">
|
|
||||||
{{ $t('settings.subject_input_always_show') }} {{ $t('settings.instance_default', { value: alwaysShowSubjectInputLocalizedValue }) }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<div>
|
|
||||||
{{ $t('settings.subject_line_behavior') }}
|
|
||||||
<label
|
|
||||||
for="subjectLineBehavior"
|
|
||||||
class="select"
|
|
||||||
>
|
|
||||||
<select
|
|
||||||
id="subjectLineBehavior"
|
|
||||||
v-model="subjectLineBehavior"
|
|
||||||
>
|
|
||||||
<option value="email">
|
|
||||||
{{ $t('settings.subject_line_email') }}
|
|
||||||
{{ subjectLineBehaviorDefaultValue == 'email' ? $t('settings.instance_default_simple') : '' }}
|
|
||||||
</option>
|
|
||||||
<option value="masto">
|
|
||||||
{{ $t('settings.subject_line_mastodon') }}
|
|
||||||
{{ subjectLineBehaviorDefaultValue == 'mastodon' ? $t('settings.instance_default_simple') : '' }}
|
|
||||||
</option>
|
|
||||||
<option value="noop">
|
|
||||||
{{ $t('settings.subject_line_noop') }}
|
|
||||||
{{ subjectLineBehaviorDefaultValue == 'noop' ? $t('settings.instance_default_simple') : '' }}
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
<i class="icon-down-open" />
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
<li v-if="postFormats.length > 0">
|
|
||||||
<div>
|
|
||||||
{{ $t('settings.post_status_content_type') }}
|
|
||||||
<label
|
|
||||||
for="postContentType"
|
|
||||||
class="select"
|
|
||||||
>
|
|
||||||
<select
|
|
||||||
id="postContentType"
|
|
||||||
v-model="postContentType"
|
|
||||||
>
|
|
||||||
<option
|
|
||||||
v-for="postFormat in postFormats"
|
|
||||||
:key="postFormat"
|
|
||||||
:value="postFormat"
|
|
||||||
>
|
|
||||||
{{ $t(`post_status.content_type["${postFormat}"]`) }}
|
|
||||||
{{ postContentTypeDefaultValue === postFormat ? $t('settings.instance_default_simple') : '' }}
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
<i class="icon-down-open" />
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="minimalScopesMode">
|
|
||||||
{{ $t('settings.minimal_scopes_mode') }} {{ $t('settings.instance_default', { value: minimalScopesModeLocalizedValue }) }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="autohideFloatingPostButton">
|
|
||||||
{{ $t('settings.autohide_floating_post_button') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="padEmoji">
|
|
||||||
{{ $t('settings.pad_emoji') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="setting-item">
|
|
||||||
<h2>{{ $t('settings.attachments') }}</h2>
|
|
||||||
<ul class="setting-list">
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="hideAttachments">
|
|
||||||
{{ $t('settings.hide_attachments_in_tl') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="hideAttachmentsInConv">
|
|
||||||
{{ $t('settings.hide_attachments_in_convo') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<label for="maxThumbnails">
|
|
||||||
{{ $t('settings.max_thumbnails') }}
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
id="maxThumbnails"
|
|
||||||
v-model.number="maxThumbnails"
|
|
||||||
class="number-input"
|
|
||||||
type="number"
|
|
||||||
min="0"
|
|
||||||
step="1"
|
|
||||||
>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="hideNsfw">
|
|
||||||
{{ $t('settings.nsfw_clickthrough') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<ul class="setting-list suboptions">
|
|
||||||
<li>
|
|
||||||
<Checkbox
|
|
||||||
v-model="preloadImage"
|
|
||||||
:disabled="!hideNsfw"
|
|
||||||
>
|
|
||||||
{{ $t('settings.preload_images') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox
|
|
||||||
v-model="useOneClickNsfw"
|
|
||||||
:disabled="!hideNsfw"
|
|
||||||
>
|
|
||||||
{{ $t('settings.use_one_click_nsfw') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="stopGifs">
|
|
||||||
{{ $t('settings.stop_gifs') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="loopVideo">
|
|
||||||
{{ $t('settings.loop_video') }}
|
|
||||||
</Checkbox>
|
|
||||||
<ul
|
|
||||||
class="setting-list suboptions"
|
|
||||||
:class="[{disabled: !streaming}]"
|
|
||||||
>
|
|
||||||
<li>
|
|
||||||
<Checkbox
|
|
||||||
v-model="loopVideoSilentOnly"
|
|
||||||
:disabled="!loopVideo || !loopSilentAvailable"
|
|
||||||
>
|
|
||||||
{{ $t('settings.loop_video_silent_only') }}
|
|
||||||
</Checkbox>
|
|
||||||
<div
|
|
||||||
v-if="!loopSilentAvailable"
|
|
||||||
class="unavailable"
|
|
||||||
>
|
|
||||||
<i class="icon-globe" />! {{ $t('settings.limited_availability') }}
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="playVideosInModal">
|
|
||||||
{{ $t('settings.play_videos_in_modal') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="useContainFit">
|
|
||||||
{{ $t('settings.use_contain_fit') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="setting-item">
|
|
||||||
<h2>{{ $t('settings.notifications') }}</h2>
|
|
||||||
<ul class="setting-list">
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="webPushNotifications">
|
|
||||||
{{ $t('settings.enable_web_push_notifications') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="setting-item">
|
|
||||||
<h2>{{ $t('settings.fun') }}</h2>
|
|
||||||
<ul class="setting-list">
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="greentext">
|
|
||||||
{{ $t('settings.greentext') }} {{ $t('settings.instance_default', { value: greentextLocalizedValue }) }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div :label="$t('settings.theme')">
|
|
||||||
<div class="setting-item">
|
|
||||||
<style-switcher />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div :label="$t('settings.filtering')">
|
|
||||||
<div class="setting-item">
|
|
||||||
<div class="select-multiple">
|
|
||||||
<span class="label">{{ $t('settings.notification_visibility') }}</span>
|
|
||||||
<ul class="option-list">
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="notificationVisibility.likes">
|
|
||||||
{{ $t('settings.notification_visibility_likes') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="notificationVisibility.repeats">
|
|
||||||
{{ $t('settings.notification_visibility_repeats') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="notificationVisibility.follows">
|
|
||||||
{{ $t('settings.notification_visibility_follows') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="notificationVisibility.mentions">
|
|
||||||
{{ $t('settings.notification_visibility_mentions') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="notificationVisibility.moves">
|
|
||||||
{{ $t('settings.notification_visibility_moves') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Checkbox v-model="notificationVisibility.emojiReactions">
|
|
||||||
{{ $t('settings.notification_visibility_emoji_reactions') }}
|
|
||||||
</Checkbox>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
{{ $t('settings.replies_in_timeline') }}
|
|
||||||
<label
|
|
||||||
for="replyVisibility"
|
|
||||||
class="select"
|
|
||||||
>
|
|
||||||
<select
|
|
||||||
id="replyVisibility"
|
|
||||||
v-model="replyVisibility"
|
|
||||||
>
|
|
||||||
<option
|
|
||||||
value="all"
|
|
||||||
selected
|
|
||||||
>{{ $t('settings.reply_visibility_all') }}</option>
|
|
||||||
<option value="following">{{ $t('settings.reply_visibility_following') }}</option>
|
|
||||||
<option value="self">{{ $t('settings.reply_visibility_self') }}</option>
|
|
||||||
</select>
|
|
||||||
<i class="icon-down-open" />
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<Checkbox v-model="hidePostStats">
|
|
||||||
{{ $t('settings.hide_post_stats') }} {{ $t('settings.instance_default', { value: hidePostStatsLocalizedValue }) }}
|
|
||||||
</Checkbox>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<Checkbox v-model="hideUserStats">
|
|
||||||
{{ $t('settings.hide_user_stats') }} {{ $t('settings.instance_default', { value: hideUserStatsLocalizedValue }) }}
|
|
||||||
</Checkbox>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="setting-item">
|
|
||||||
<div>
|
|
||||||
<p>{{ $t('settings.filtering_explanation') }}</p>
|
|
||||||
<textarea
|
|
||||||
id="muteWords"
|
|
||||||
v-model="muteWordsString"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<Checkbox v-model="hideFilteredStatuses">
|
|
||||||
{{ $t('settings.hide_filtered_statuses') }} {{ $t('settings.instance_default', { value: hideFilteredStatusesLocalizedValue }) }}
|
|
||||||
</Checkbox>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<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="backendVersionLink"
|
|
||||||
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>
|
|
||||||
</tab-switcher>
|
|
||||||
</keep-alive>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script src="./settings.js">
|
|
||||||
</script>
|
|
|
@ -1,21 +1,30 @@
|
||||||
import Modal from '../modal/modal.vue'
|
import Modal from 'src/components/modal/modal.vue'
|
||||||
import TabSwitcher from '../tab_switcher/tab_switcher.js'
|
import TabSwitcher from 'src/components/tab_switcher/tab_switcher.js'
|
||||||
|
|
||||||
import Profile from './tabs/profile.vue'
|
import DataImportExportTab from './tabs/data_import_export_tab.vue'
|
||||||
import Security from './tabs/security.vue'
|
import MutesAndBlocksTab from './tabs/mutes_and_blocks_tab.vue'
|
||||||
import Notifications from './tabs/notifications.vue'
|
import NotificationsTab from './tabs/notifications_tab.vue'
|
||||||
import DataImportExport from './tabs/data_import_export.vue'
|
import FilteringTab from './tabs/filtering_tab.vue'
|
||||||
import MutesAndBlocks from './tabs/mutes_and_blocks.vue'
|
import SecurityTab from './tabs/security_tab/security_tab.vue'
|
||||||
|
import ProfileTab from './tabs/profile_tab.vue'
|
||||||
|
import GeneralTab from './tabs/general_tab.vue'
|
||||||
|
import VersionTab from './tabs/version_tab.vue'
|
||||||
|
import ThemeTab from './tabs/theme_tab/theme_tab.vue'
|
||||||
|
|
||||||
const SettingsModal = {
|
const SettingsModal = {
|
||||||
components: {
|
components: {
|
||||||
Modal,
|
Modal,
|
||||||
TabSwitcher,
|
TabSwitcher,
|
||||||
Profile,
|
|
||||||
Security,
|
DataImportExportTab,
|
||||||
Notifications,
|
MutesAndBlocksTab,
|
||||||
DataImportExport,
|
NotificationsTab,
|
||||||
MutesAndBlocks
|
FilteringTab,
|
||||||
|
SecurityTab,
|
||||||
|
ProfileTab,
|
||||||
|
GeneralTab,
|
||||||
|
VersionTab,
|
||||||
|
ThemeTab
|
||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
|
@ -28,11 +37,20 @@ const SettingsModal = {
|
||||||
},
|
},
|
||||||
modalActivated () {
|
modalActivated () {
|
||||||
return this.$store.state.interface.settingsModalState !== 'hidden'
|
return this.$store.state.interface.settingsModalState !== 'hidden'
|
||||||
|
},
|
||||||
|
modalPeeked () {
|
||||||
|
return this.$store.state.interface.settingsModalState === 'minimized'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
closeModal () {
|
||||||
|
this.$store.dispatch('closeSettingsModal')
|
||||||
|
},
|
||||||
|
peekModal () {
|
||||||
|
this.$store.dispatch('togglePeekSettingsModal')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,29 @@
|
||||||
@import '../../_variables.scss';
|
@import 'src/_variables.scss';
|
||||||
.settings-modal {
|
.settings-modal {
|
||||||
|
|
||||||
.settings_tab-switcher {
|
.settings_tab-switcher {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
&.peek {
|
||||||
.settings-modal-panel {
|
.settings-modal-panel {
|
||||||
|
transform: translateY(calc(100% - 50px));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-modal-panel {
|
||||||
|
transition: transform;
|
||||||
|
transition-timing-function: ease-in-out;
|
||||||
|
transition-duration: 300ms;
|
||||||
width: 1000px;
|
width: 1000px;
|
||||||
max-width: 90vw;
|
max-width: 90vw;
|
||||||
height: 90vh;
|
height: 90vh;
|
||||||
|
@media all and (max-width: 800px) {
|
||||||
|
max-width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.panel-body {
|
.panel-body {
|
||||||
|
height: 100%;
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
}
|
}
|
||||||
.setting-item {
|
.setting-item {
|
||||||
|
@ -16,6 +31,12 @@
|
||||||
margin: 1em 1em 1.4em;
|
margin: 1em 1em 1.4em;
|
||||||
padding-bottom: 1.4em;
|
padding-bottom: 1.4em;
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
min-height: 28px;
|
||||||
|
min-width: 10em;
|
||||||
|
padding: 0 2em;
|
||||||
|
}
|
||||||
|
|
||||||
> div {
|
> div {
|
||||||
margin-bottom: .5em;
|
margin-bottom: .5em;
|
||||||
&:last-child {
|
&:last-child {
|
||||||
|
@ -33,7 +54,6 @@
|
||||||
min-width: 10em;
|
min-width: 10em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
textarea {
|
textarea {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
|
@ -46,12 +66,6 @@
|
||||||
color: $fallback--cRed;
|
color: $fallback--cRed;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn {
|
|
||||||
min-height: 28px;
|
|
||||||
min-width: 10em;
|
|
||||||
padding: 0 2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.number-input {
|
.number-input {
|
||||||
max-width: 6em;
|
max-width: 6em;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,20 @@
|
||||||
v-if="isLoggedIn && !resettingForm"
|
v-if="isLoggedIn && !resettingForm"
|
||||||
:is-open="modalActivated"
|
:is-open="modalActivated"
|
||||||
class="settings-modal"
|
class="settings-modal"
|
||||||
|
:class="{ peek: modalPeeked }"
|
||||||
|
:no-background="modalPeeked"
|
||||||
>
|
>
|
||||||
<div class="settings-modal-panel panel">
|
<div class="settings-modal-panel panel">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
|
<span class="title">
|
||||||
{{ $t('settings.settings') }}
|
{{ $t('settings.settings') }}
|
||||||
|
</span>
|
||||||
|
<button class="btn" @click="peekModal">
|
||||||
|
{{ $t('general.peek') }}
|
||||||
|
</button>
|
||||||
|
<button class="btn" @click="closeModal">
|
||||||
|
{{ $t('general.close') }}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<tab-switcher
|
<tab-switcher
|
||||||
|
@ -15,11 +25,15 @@
|
||||||
:scrollableTabs="true"
|
:scrollableTabs="true"
|
||||||
ref="tabSwitcher"
|
ref="tabSwitcher"
|
||||||
>
|
>
|
||||||
<div :label="$t('settings.profile_tab')"><Profile /></div>
|
<div :label="$t('settings.general')"><GeneralTab /></div>
|
||||||
<div :label="$t('settings.security_tab')"><Security /></div>
|
<div :label="$t('settings.profile_tab')"><ProfileTab /></div>
|
||||||
<div :label="$t('settings.notifications')"><Notifications /></div>
|
<div :label="$t('settings.security_tab')"><SecurityTab /></div>
|
||||||
<div :label="$t('settings.data_import_export_tab')"><DataImportExport /></div>
|
<div :label="$t('settings.filtering')"><FilteringTab /></div>
|
||||||
<div :label="$t('settings.mutes_and_blocks')"><MutesAndBlocks /></div>
|
<div :label="$t('settings.theme')"><ThemeTab /></div>
|
||||||
|
<div :label="$t('settings.notifications')"><NotificationsTab /></div>
|
||||||
|
<div :label="$t('settings.data_import_export_tab')"><DataImportExportTab /></div>
|
||||||
|
<div :label="$t('settings.mutes_and_blocks')"><MutesAndBlocksTab /></div>
|
||||||
|
<div :label="$t('settings.version.title')"><VersionTab /></div>
|
||||||
</tab-switcher>
|
</tab-switcher>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import Importer from '../../importer/importer.vue'
|
import Importer from 'src/components/importer/importer.vue'
|
||||||
import Exporter from '../../exporter/exporter.vue'
|
import Exporter from 'src/components/exporter/exporter.vue'
|
||||||
import Checkbox from '../../checkbox/checkbox.vue'
|
import Checkbox from 'src/components/checkbox/checkbox.vue'
|
||||||
|
|
||||||
const DataImportExport = {
|
const DataImportExportTab = {
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
activeTab: 'profile',
|
activeTab: 'profile',
|
||||||
|
@ -62,4 +62,4 @@ const DataImportExport = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default DataImportExport
|
export default DataImportExportTab
|
|
@ -39,5 +39,5 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="./data_import_export.js"></script>
|
<script src="./data_import_export_tab.js"></script>
|
||||||
<!-- <style lang="scss" src="./profile.scss"></style> -->
|
<!-- <style lang="scss" src="./profile.scss"></style> -->
|
26
src/components/settings_modal/tabs/filtering_tab.js
Normal file
26
src/components/settings_modal/tabs/filtering_tab.js
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
import Checkbox from 'src/components/checkbox/checkbox.vue'
|
||||||
|
|
||||||
|
import SharedComputedObject from './helpers/shared_computed_object.js'
|
||||||
|
|
||||||
|
const FilteringTab = {
|
||||||
|
components: {
|
||||||
|
Checkbox
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...SharedComputedObject()
|
||||||
|
},
|
||||||
|
// Updating nested properties
|
||||||
|
watch: {
|
||||||
|
notificationVisibility: {
|
||||||
|
handler (value) {
|
||||||
|
this.$store.dispatch('setOption', {
|
||||||
|
name: 'notificationVisibility',
|
||||||
|
value: this.$store.getters.mergedConfig.notificationVisibility
|
||||||
|
})
|
||||||
|
},
|
||||||
|
deep: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default FilteringTab
|
86
src/components/settings_modal/tabs/filtering_tab.vue
Normal file
86
src/components/settings_modal/tabs/filtering_tab.vue
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
<template>
|
||||||
|
<div :label="$t('settings.filtering')">
|
||||||
|
<div class="setting-item">
|
||||||
|
<div class="select-multiple">
|
||||||
|
<span class="label">{{ $t('settings.notification_visibility') }}</span>
|
||||||
|
<ul class="option-list">
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="notificationVisibility.likes">
|
||||||
|
{{ $t('settings.notification_visibility_likes') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="notificationVisibility.repeats">
|
||||||
|
{{ $t('settings.notification_visibility_repeats') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="notificationVisibility.follows">
|
||||||
|
{{ $t('settings.notification_visibility_follows') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="notificationVisibility.mentions">
|
||||||
|
{{ $t('settings.notification_visibility_mentions') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="notificationVisibility.moves">
|
||||||
|
{{ $t('settings.notification_visibility_moves') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="notificationVisibility.emojiReactions">
|
||||||
|
{{ $t('settings.notification_visibility_emoji_reactions') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{{ $t('settings.replies_in_timeline') }}
|
||||||
|
<label
|
||||||
|
for="replyVisibility"
|
||||||
|
class="select"
|
||||||
|
>
|
||||||
|
<select
|
||||||
|
id="replyVisibility"
|
||||||
|
v-model="replyVisibility"
|
||||||
|
>
|
||||||
|
<option
|
||||||
|
value="all"
|
||||||
|
selected
|
||||||
|
>{{ $t('settings.reply_visibility_all') }}</option>
|
||||||
|
<option value="following">{{ $t('settings.reply_visibility_following') }}</option>
|
||||||
|
<option value="self">{{ $t('settings.reply_visibility_self') }}</option>
|
||||||
|
</select>
|
||||||
|
<i class="icon-down-open" />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Checkbox v-model="hidePostStats">
|
||||||
|
{{ $t('settings.hide_post_stats') }} {{ $t('settings.instance_default', { value: hidePostStatsLocalizedValue }) }}
|
||||||
|
</Checkbox>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Checkbox v-model="hideUserStats">
|
||||||
|
{{ $t('settings.hide_user_stats') }} {{ $t('settings.instance_default', { value: hideUserStatsLocalizedValue }) }}
|
||||||
|
</Checkbox>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="setting-item">
|
||||||
|
<div>
|
||||||
|
<p>{{ $t('settings.filtering_explanation') }}</p>
|
||||||
|
<textarea
|
||||||
|
id="muteWords"
|
||||||
|
v-model="muteWordsString"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Checkbox v-model="hideFilteredStatuses">
|
||||||
|
{{ $t('settings.hide_filtered_statuses') }} {{ $t('settings.instance_default', { value: hideFilteredStatusesLocalizedValue }) }}
|
||||||
|
</Checkbox>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script src="./filtering_tab.js"></script>
|
32
src/components/settings_modal/tabs/general_tab.js
Normal file
32
src/components/settings_modal/tabs/general_tab.js
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
import Checkbox from 'src/components/checkbox/checkbox.vue'
|
||||||
|
import InterfaceLanguageSwitcher from 'src/components/interface_language_switcher/interface_language_switcher.vue'
|
||||||
|
|
||||||
|
import SharedComputedObject from './helpers/shared_computed_object.js'
|
||||||
|
|
||||||
|
const GeneralTab = {
|
||||||
|
data () {
|
||||||
|
const instance = this.$store.state.instance
|
||||||
|
return {
|
||||||
|
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: {
|
||||||
|
Checkbox,
|
||||||
|
InterfaceLanguageSwitcher
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
postFormats () {
|
||||||
|
return this.$store.state.instance.postFormats || []
|
||||||
|
},
|
||||||
|
instanceSpecificPanelPresent () { return this.$store.state.instance.showInstanceSpecificPanel },
|
||||||
|
...SharedComputedObject()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default GeneralTab
|
272
src/components/settings_modal/tabs/general_tab.vue
Normal file
272
src/components/settings_modal/tabs/general_tab.vue
Normal file
|
@ -0,0 +1,272 @@
|
||||||
|
<template>
|
||||||
|
<div :label="$t('settings.general')">
|
||||||
|
<div class="setting-item">
|
||||||
|
<h2>{{ $t('settings.interface') }}</h2>
|
||||||
|
<ul class="setting-list">
|
||||||
|
<li>
|
||||||
|
<interface-language-switcher />
|
||||||
|
</li>
|
||||||
|
<li v-if="instanceSpecificPanelPresent">
|
||||||
|
<Checkbox v-model="hideISP">
|
||||||
|
{{ $t('settings.hide_isp') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="setting-item">
|
||||||
|
<h2>{{ $t('nav.timeline') }}</h2>
|
||||||
|
<ul class="setting-list">
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="hideMutedPosts">
|
||||||
|
{{ $t('settings.hide_muted_posts') }} {{ $t('settings.instance_default', { value: hideMutedPostsLocalizedValue }) }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="collapseMessageWithSubject">
|
||||||
|
{{ $t('settings.collapse_subject') }} {{ $t('settings.instance_default', { value: collapseMessageWithSubjectLocalizedValue }) }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="streaming">
|
||||||
|
{{ $t('settings.streaming') }}
|
||||||
|
</Checkbox>
|
||||||
|
<ul
|
||||||
|
class="setting-list suboptions"
|
||||||
|
:class="[{disabled: !streaming}]"
|
||||||
|
>
|
||||||
|
<li>
|
||||||
|
<Checkbox
|
||||||
|
v-model="pauseOnUnfocused"
|
||||||
|
:disabled="!streaming"
|
||||||
|
>
|
||||||
|
{{ $t('settings.pause_on_unfocused') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="useStreamingApi">
|
||||||
|
{{ $t('settings.useStreamingApi') }}
|
||||||
|
<br>
|
||||||
|
<small>
|
||||||
|
{{ $t('settings.useStreamingApiWarning') }}
|
||||||
|
</small>
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="autoLoad">
|
||||||
|
{{ $t('settings.autoload') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="hoverPreview">
|
||||||
|
{{ $t('settings.reply_link_preview') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="emojiReactionsOnTimeline">
|
||||||
|
{{ $t('settings.emoji_reactions_on_timeline') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="setting-item">
|
||||||
|
<h2>{{ $t('settings.composing') }}</h2>
|
||||||
|
<ul class="setting-list">
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="scopeCopy">
|
||||||
|
{{ $t('settings.scope_copy') }} {{ $t('settings.instance_default', { value: scopeCopyLocalizedValue }) }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="alwaysShowSubjectInput">
|
||||||
|
{{ $t('settings.subject_input_always_show') }} {{ $t('settings.instance_default', { value: alwaysShowSubjectInputLocalizedValue }) }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<div>
|
||||||
|
{{ $t('settings.subject_line_behavior') }}
|
||||||
|
<label
|
||||||
|
for="subjectLineBehavior"
|
||||||
|
class="select"
|
||||||
|
>
|
||||||
|
<select
|
||||||
|
id="subjectLineBehavior"
|
||||||
|
v-model="subjectLineBehavior"
|
||||||
|
>
|
||||||
|
<option value="email">
|
||||||
|
{{ $t('settings.subject_line_email') }}
|
||||||
|
{{ subjectLineBehaviorDefaultValue == 'email' ? $t('settings.instance_default_simple') : '' }}
|
||||||
|
</option>
|
||||||
|
<option value="masto">
|
||||||
|
{{ $t('settings.subject_line_mastodon') }}
|
||||||
|
{{ subjectLineBehaviorDefaultValue == 'mastodon' ? $t('settings.instance_default_simple') : '' }}
|
||||||
|
</option>
|
||||||
|
<option value="noop">
|
||||||
|
{{ $t('settings.subject_line_noop') }}
|
||||||
|
{{ subjectLineBehaviorDefaultValue == 'noop' ? $t('settings.instance_default_simple') : '' }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
<i class="icon-down-open" />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li v-if="postFormats.length > 0">
|
||||||
|
<div>
|
||||||
|
{{ $t('settings.post_status_content_type') }}
|
||||||
|
<label
|
||||||
|
for="postContentType"
|
||||||
|
class="select"
|
||||||
|
>
|
||||||
|
<select
|
||||||
|
id="postContentType"
|
||||||
|
v-model="postContentType"
|
||||||
|
>
|
||||||
|
<option
|
||||||
|
v-for="postFormat in postFormats"
|
||||||
|
:key="postFormat"
|
||||||
|
:value="postFormat"
|
||||||
|
>
|
||||||
|
{{ $t(`post_status.content_type["${postFormat}"]`) }}
|
||||||
|
{{ postContentTypeDefaultValue === postFormat ? $t('settings.instance_default_simple') : '' }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
<i class="icon-down-open" />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="minimalScopesMode">
|
||||||
|
{{ $t('settings.minimal_scopes_mode') }} {{ $t('settings.instance_default', { value: minimalScopesModeLocalizedValue }) }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="autohideFloatingPostButton">
|
||||||
|
{{ $t('settings.autohide_floating_post_button') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="padEmoji">
|
||||||
|
{{ $t('settings.pad_emoji') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="setting-item">
|
||||||
|
<h2>{{ $t('settings.attachments') }}</h2>
|
||||||
|
<ul class="setting-list">
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="hideAttachments">
|
||||||
|
{{ $t('settings.hide_attachments_in_tl') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="hideAttachmentsInConv">
|
||||||
|
{{ $t('settings.hide_attachments_in_convo') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<label for="maxThumbnails">
|
||||||
|
{{ $t('settings.max_thumbnails') }}
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="maxThumbnails"
|
||||||
|
v-model.number="maxThumbnails"
|
||||||
|
class="number-input"
|
||||||
|
type="number"
|
||||||
|
min="0"
|
||||||
|
step="1"
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="hideNsfw">
|
||||||
|
{{ $t('settings.nsfw_clickthrough') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
<ul class="setting-list suboptions">
|
||||||
|
<li>
|
||||||
|
<Checkbox
|
||||||
|
v-model="preloadImage"
|
||||||
|
:disabled="!hideNsfw"
|
||||||
|
>
|
||||||
|
{{ $t('settings.preload_images') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox
|
||||||
|
v-model="useOneClickNsfw"
|
||||||
|
:disabled="!hideNsfw"
|
||||||
|
>
|
||||||
|
{{ $t('settings.use_one_click_nsfw') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="stopGifs">
|
||||||
|
{{ $t('settings.stop_gifs') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="loopVideo">
|
||||||
|
{{ $t('settings.loop_video') }}
|
||||||
|
</Checkbox>
|
||||||
|
<ul
|
||||||
|
class="setting-list suboptions"
|
||||||
|
:class="[{disabled: !streaming}]"
|
||||||
|
>
|
||||||
|
<li>
|
||||||
|
<Checkbox
|
||||||
|
v-model="loopVideoSilentOnly"
|
||||||
|
:disabled="!loopVideo || !loopSilentAvailable"
|
||||||
|
>
|
||||||
|
{{ $t('settings.loop_video_silent_only') }}
|
||||||
|
</Checkbox>
|
||||||
|
<div
|
||||||
|
v-if="!loopSilentAvailable"
|
||||||
|
class="unavailable"
|
||||||
|
>
|
||||||
|
<i class="icon-globe" />! {{ $t('settings.limited_availability') }}
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="playVideosInModal">
|
||||||
|
{{ $t('settings.play_videos_in_modal') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="useContainFit">
|
||||||
|
{{ $t('settings.use_contain_fit') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="setting-item">
|
||||||
|
<h2>{{ $t('settings.notifications') }}</h2>
|
||||||
|
<ul class="setting-list">
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="webPushNotifications">
|
||||||
|
{{ $t('settings.enable_web_push_notifications') }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="setting-item">
|
||||||
|
<h2>{{ $t('settings.fun') }}</h2>
|
||||||
|
<ul class="setting-list">
|
||||||
|
<li>
|
||||||
|
<Checkbox v-model="greentext">
|
||||||
|
{{ $t('settings.greentext') }} {{ $t('settings.instance_default', { value: greentextLocalizedValue }) }}
|
||||||
|
</Checkbox>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script src="./general_tab.js"></script>
|
|
@ -0,0 +1,69 @@
|
||||||
|
import { filter, trim } from 'lodash'
|
||||||
|
import { instanceDefaultProperties, defaultState as configDefaultState } from 'src/modules/config.js'
|
||||||
|
|
||||||
|
const multiChoiceProperties = [
|
||||||
|
'postContentType',
|
||||||
|
'subjectLineBehavior'
|
||||||
|
]
|
||||||
|
|
||||||
|
const SharedComputedObject = () => ({
|
||||||
|
user () {
|
||||||
|
return this.$store.state.users.currentUser
|
||||||
|
},
|
||||||
|
// Getting localized values for instance-default properties
|
||||||
|
...instanceDefaultProperties
|
||||||
|
.filter(key => multiChoiceProperties.includes(key))
|
||||||
|
.map(key => [
|
||||||
|
key + 'DefaultValue',
|
||||||
|
function () {
|
||||||
|
return this.$store.getters.instanceDefaultConfig[key]
|
||||||
|
}
|
||||||
|
])
|
||||||
|
.reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}),
|
||||||
|
...instanceDefaultProperties
|
||||||
|
.filter(key => !multiChoiceProperties.includes(key))
|
||||||
|
.map(key => [
|
||||||
|
key + 'LocalizedValue',
|
||||||
|
function () {
|
||||||
|
return this.$t('settings.values.' + this.$store.getters.instanceDefaultConfig[key])
|
||||||
|
}
|
||||||
|
])
|
||||||
|
.reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}),
|
||||||
|
// Generating computed values for vuex properties
|
||||||
|
...Object.keys(configDefaultState)
|
||||||
|
.map(key => [key, {
|
||||||
|
get () { return this.$store.getters.mergedConfig[key] },
|
||||||
|
set (value) {
|
||||||
|
this.$store.dispatch('setOption', { name: key, value })
|
||||||
|
}
|
||||||
|
}])
|
||||||
|
.reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}),
|
||||||
|
// Special cases (need to transform values or perform actions first)
|
||||||
|
muteWordsString: {
|
||||||
|
get () { return this.$store.getters.mergedConfig.muteWords.join('\n') },
|
||||||
|
set (value) {
|
||||||
|
this.$store.dispatch('setOption', {
|
||||||
|
name: 'muteWords',
|
||||||
|
value: filter(value.split('\n'), (word) => trim(word).length > 0)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
useStreamingApi: {
|
||||||
|
get () { return this.$store.getters.mergedConfig.useStreamingApi },
|
||||||
|
set (value) {
|
||||||
|
const promise = value
|
||||||
|
? this.$store.dispatch('enableMastoSockets')
|
||||||
|
: this.$store.dispatch('disableMastoSockets')
|
||||||
|
|
||||||
|
promise.then(() => {
|
||||||
|
this.$store.dispatch('setOption', { name: 'useStreamingApi', value })
|
||||||
|
}).catch((e) => {
|
||||||
|
console.error('Failed starting MastoAPI Streaming socket', e)
|
||||||
|
this.$store.dispatch('disableMastoSockets')
|
||||||
|
this.$store.dispatch('setOption', { name: 'useStreamingApi', value: false })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
export default SharedComputedObject
|
|
@ -1,15 +1,15 @@
|
||||||
import get from 'lodash/get'
|
import get from 'lodash/get'
|
||||||
import map from 'lodash/map'
|
import map from 'lodash/map'
|
||||||
import reject from 'lodash/reject'
|
import reject from 'lodash/reject'
|
||||||
import Autosuggest from '../../autosuggest/autosuggest.vue'
|
import Autosuggest from 'src/components/autosuggest/autosuggest.vue'
|
||||||
import TabSwitcher from '../../tab_switcher/tab_switcher.js'
|
import TabSwitcher from 'src/components/tab_switcher/tab_switcher.js'
|
||||||
import BlockCard from '../../block_card/block_card.vue'
|
import BlockCard from 'src/components/block_card/block_card.vue'
|
||||||
import MuteCard from '../../mute_card/mute_card.vue'
|
import MuteCard from 'src/components/mute_card/mute_card.vue'
|
||||||
import DomainMuteCard from '../../domain_mute_card/domain_mute_card.vue'
|
import DomainMuteCard from 'src/components/domain_mute_card/domain_mute_card.vue'
|
||||||
import SelectableList from '../../selectable_list/selectable_list.vue'
|
import SelectableList from 'src/components/selectable_list/selectable_list.vue'
|
||||||
import ProgressButton from '../../progress_button/progress_button.vue'
|
import ProgressButton from 'src/components/progress_button/progress_button.vue'
|
||||||
import withSubscription from '../../../hocs/with_subscription/with_subscription'
|
import withSubscription from 'src/components/../hocs/with_subscription/with_subscription'
|
||||||
import Checkbox from '../../checkbox/checkbox.vue'
|
import Checkbox from 'src/components/checkbox/checkbox.vue'
|
||||||
|
|
||||||
const BlockList = withSubscription({
|
const BlockList = withSubscription({
|
||||||
fetch: (props, $store) => $store.dispatch('fetchBlocks'),
|
fetch: (props, $store) => $store.dispatch('fetchBlocks'),
|
|
@ -15,7 +15,7 @@
|
||||||
</div>
|
</div>
|
||||||
<BlockList
|
<BlockList
|
||||||
:refresh="true"
|
:refresh="true"
|
||||||
:get-key="identity"
|
:get-key="i => i"
|
||||||
>
|
>
|
||||||
<template
|
<template
|
||||||
slot="header"
|
slot="header"
|
||||||
|
@ -73,7 +73,7 @@
|
||||||
</div>
|
</div>
|
||||||
<MuteList
|
<MuteList
|
||||||
:refresh="true"
|
:refresh="true"
|
||||||
:get-key="identity"
|
:get-key="i => i"
|
||||||
>
|
>
|
||||||
<template
|
<template
|
||||||
slot="header"
|
slot="header"
|
||||||
|
@ -134,7 +134,7 @@
|
||||||
</div>
|
</div>
|
||||||
<DomainMuteList
|
<DomainMuteList
|
||||||
:refresh="true"
|
:refresh="true"
|
||||||
:get-key="identity"
|
:get-key="i => i"
|
||||||
>
|
>
|
||||||
<template
|
<template
|
||||||
slot="header"
|
slot="header"
|
||||||
|
@ -169,5 +169,5 @@
|
||||||
</tab-switcher>
|
</tab-switcher>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="./mutes_and_blocks.js"></script>
|
<script src="./mutes_and_blocks_tab.js"></script>
|
||||||
<!-- <style lang="scss" src="./profile.scss"></style> -->
|
<!-- <style lang="scss" src="./profile.scss"></style> -->
|
|
@ -1,6 +1,6 @@
|
||||||
import Checkbox from '../../checkbox/checkbox.vue'
|
import Checkbox from 'src/components/checkbox/checkbox.vue'
|
||||||
|
|
||||||
const Notifications = {
|
const NotificationsTab = {
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
activeTab: 'profile',
|
activeTab: 'profile',
|
||||||
|
@ -24,4 +24,4 @@ const Notifications = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Notifications
|
export default NotificationsTab
|
|
@ -38,5 +38,5 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="./notifications.js"></script>
|
<script src="./notifications_tab.js"></script>
|
||||||
<!-- <style lang="scss" src="./profile.scss"></style> -->
|
<!-- <style lang="scss" src="./profile.scss"></style> -->
|
|
@ -1,12 +1,12 @@
|
||||||
import unescape from 'lodash/unescape'
|
import unescape from 'lodash/unescape'
|
||||||
import ImageCropper from '../../image_cropper/image_cropper.vue'
|
import ImageCropper from 'src/components/image_cropper/image_cropper.vue'
|
||||||
import ScopeSelector from '../../scope_selector/scope_selector.vue'
|
import ScopeSelector from 'src/components/scope_selector/scope_selector.vue'
|
||||||
import fileSizeFormatService from '../../../services/file_size_format/file_size_format.js'
|
import fileSizeFormatService from 'src/components/../services/file_size_format/file_size_format.js'
|
||||||
import ProgressButton from '../../progress_button/progress_button.vue'
|
import ProgressButton from 'src/components/progress_button/progress_button.vue'
|
||||||
import EmojiInput from '../../emoji_input/emoji_input.vue'
|
import EmojiInput from 'src/components/emoji_input/emoji_input.vue'
|
||||||
import suggestor from '../../emoji_input/suggestor.js'
|
import suggestor from 'src/components/emoji_input/suggestor.js'
|
||||||
import Autosuggest from '../../autosuggest/autosuggest.vue'
|
import Autosuggest from 'src/components/autosuggest/autosuggest.vue'
|
||||||
import Checkbox from '../../checkbox/checkbox.vue'
|
import Checkbox from 'src/components/checkbox/checkbox.vue'
|
||||||
|
|
||||||
const ProfileTab = {
|
const ProfileTab = {
|
||||||
data () {
|
data () {
|
|
@ -209,5 +209,5 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="./profile.js"></script>
|
<script src="./profile_tab.js"></script>
|
||||||
<style lang="scss" src="./profile.scss"></style>
|
<style lang="scss" src="./profile_tab.scss"></style>
|
|
@ -137,11 +137,7 @@
|
||||||
|
|
||||||
<script src="./mfa.js"></script>
|
<script src="./mfa.js"></script>
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@import '../../_variables.scss';
|
@import '../../../../_variables.scss';
|
||||||
.warning {
|
|
||||||
color: $fallback--cOrange;
|
|
||||||
color: var(--cOrange, $fallback--cOrange);
|
|
||||||
}
|
|
||||||
.mfa-settings {
|
.mfa-settings {
|
||||||
.mfa-heading, .method-item {
|
.mfa-heading, .method-item {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
@ -151,6 +147,11 @@
|
||||||
align-items: baseline;
|
align-items: baseline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.warning {
|
||||||
|
color: $fallback--cOrange;
|
||||||
|
color: var(--cOrange, $fallback--cOrange);
|
||||||
|
}
|
||||||
|
|
||||||
.setup-otp {
|
.setup-otp {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div class="mfa-backup-codes">
|
||||||
<h4 v-if="displayTitle">
|
<h4 v-if="displayTitle">
|
||||||
{{ $t('settings.mfa.recovery_codes') }}
|
{{ $t('settings.mfa.recovery_codes') }}
|
||||||
</h4>
|
</h4>
|
||||||
|
@ -21,13 +21,15 @@
|
||||||
</template>
|
</template>
|
||||||
<script src="./mfa_backup_codes.js"></script>
|
<script src="./mfa_backup_codes.js"></script>
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@import '../../_variables.scss';
|
@import '../../../../_variables.scss';
|
||||||
|
|
||||||
.warning {
|
.mfa-backup-codes {
|
||||||
|
.warning {
|
||||||
color: $fallback--cOrange;
|
color: $fallback--cOrange;
|
||||||
color: var(--cOrange, $fallback--cOrange);
|
color: var(--cOrange, $fallback--cOrange);
|
||||||
}
|
}
|
||||||
.backup-codes {
|
.backup-codes {
|
||||||
font-family: var(--postCodeFont, monospace);
|
font-family: var(--postCodeFont, monospace);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
|
@ -1,8 +1,8 @@
|
||||||
import ProgressButton from '../../progress_button/progress_button.vue'
|
import ProgressButton from 'src/components/progress_button/progress_button.vue'
|
||||||
import Checkbox from '../../checkbox/checkbox.vue'
|
import Checkbox from 'src/components/checkbox/checkbox.vue'
|
||||||
import Mfa from '../../user_settings/mfa.vue'
|
import Mfa from './mfa.vue'
|
||||||
|
|
||||||
const Security = {
|
const SecurityTab = {
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
newEmail: '',
|
newEmail: '',
|
||||||
|
@ -103,4 +103,4 @@ const Security = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Security
|
export default SecurityTab
|
|
@ -139,5 +139,5 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="./security.js"></script>
|
<script src="./security_tab.js"></script>
|
||||||
<!-- <style lang="scss" src="./profile.scss"></style> -->
|
<!-- <style lang="scss" src="./profile.scss"></style> -->
|
|
@ -3,7 +3,7 @@ import {
|
||||||
rgb2hex,
|
rgb2hex,
|
||||||
hex2rgb,
|
hex2rgb,
|
||||||
getContrastRatioLayers
|
getContrastRatioLayers
|
||||||
} from '../../services/color_convert/color_convert.js'
|
} from 'src/services/color_convert/color_convert.js'
|
||||||
import {
|
import {
|
||||||
DEFAULT_SHADOWS,
|
DEFAULT_SHADOWS,
|
||||||
generateColors,
|
generateColors,
|
||||||
|
@ -14,26 +14,27 @@ import {
|
||||||
getThemes,
|
getThemes,
|
||||||
shadows2to3,
|
shadows2to3,
|
||||||
colors2to3
|
colors2to3
|
||||||
} from '../../services/style_setter/style_setter.js'
|
} from 'src/services/style_setter/style_setter.js'
|
||||||
import {
|
import {
|
||||||
SLOT_INHERITANCE
|
SLOT_INHERITANCE
|
||||||
} from '../../services/theme_data/pleromafe.js'
|
} from 'src/services/theme_data/pleromafe.js'
|
||||||
import {
|
import {
|
||||||
CURRENT_VERSION,
|
CURRENT_VERSION,
|
||||||
OPACITIES,
|
OPACITIES,
|
||||||
getLayers,
|
getLayers,
|
||||||
getOpacitySlot
|
getOpacitySlot
|
||||||
} from '../../services/theme_data/theme_data.service.js'
|
} from 'src/services/theme_data/theme_data.service.js'
|
||||||
import ColorInput from '../color_input/color_input.vue'
|
import ColorInput from 'src/components/color_input/color_input.vue'
|
||||||
import RangeInput from '../range_input/range_input.vue'
|
import RangeInput from 'src/components/range_input/range_input.vue'
|
||||||
import OpacityInput from '../opacity_input/opacity_input.vue'
|
import OpacityInput from 'src/components/opacity_input/opacity_input.vue'
|
||||||
import ShadowControl from '../shadow_control/shadow_control.vue'
|
import ShadowControl from 'src/components/shadow_control/shadow_control.vue'
|
||||||
import FontControl from '../font_control/font_control.vue'
|
import FontControl from 'src/components/font_control/font_control.vue'
|
||||||
import ContrastRatio from '../contrast_ratio/contrast_ratio.vue'
|
import ContrastRatio from 'src/components/contrast_ratio/contrast_ratio.vue'
|
||||||
import TabSwitcher from '../tab_switcher/tab_switcher.js'
|
import TabSwitcher from 'src/components/tab_switcher/tab_switcher.js'
|
||||||
|
import ExportImport from 'src/components/export_import/export_import.vue'
|
||||||
|
import Checkbox from 'src/components/checkbox/checkbox.vue'
|
||||||
|
|
||||||
import Preview from './preview.vue'
|
import Preview from './preview.vue'
|
||||||
import ExportImport from '../export_import/export_import.vue'
|
|
||||||
import Checkbox from '../checkbox/checkbox.vue'
|
|
||||||
|
|
||||||
// List of color values used in v1
|
// List of color values used in v1
|
||||||
const v1OnlyNames = [
|
const v1OnlyNames = [
|
|
@ -1,5 +1,5 @@
|
||||||
@import '../../_variables.scss';
|
@import 'src/_variables.scss';
|
||||||
.style-switcher {
|
.theme-tab {
|
||||||
.theme-warning {
|
.theme-warning {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: baseline;
|
align-items: baseline;
|
||||||
|
@ -54,10 +54,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab-switcher {
|
|
||||||
margin: 0 -1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.reset-container {
|
.reset-container {
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
@ -161,7 +157,7 @@
|
||||||
border-bottom: 1px dashed;
|
border-bottom: 1px dashed;
|
||||||
border-color: $fallback--border;
|
border-color: $fallback--border;
|
||||||
border-color: var(--border, $fallback--border);
|
border-color: var(--border, $fallback--border);
|
||||||
margin: 1em -1em 0;
|
margin: 1em 0;
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
background: var(--body-background-image);
|
background: var(--body-background-image);
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
|
@ -328,6 +324,14 @@
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.apply-container {
|
||||||
|
.btn {
|
||||||
|
min-height: 28px;
|
||||||
|
min-width: 10em;
|
||||||
|
padding: 0 2em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.btn {
|
.btn {
|
||||||
margin-left: .25em;
|
margin-left: .25em;
|
||||||
margin-right: .25em;
|
margin-right: .25em;
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="style-switcher">
|
<div class="theme-tab">
|
||||||
<div class="presets-container">
|
<div class="presets-container">
|
||||||
<div class="save-load">
|
<div class="save-load">
|
||||||
<div
|
<div
|
||||||
|
@ -951,6 +951,6 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="./style_switcher.js"></script>
|
<script src="./theme_tab.js"></script>
|
||||||
|
|
||||||
<style src="./style_switcher.scss" lang="scss"></style>
|
<style src="./theme_tab.scss" lang="scss"></style>
|
24
src/components/settings_modal/tabs/version_tab.js
Normal file
24
src/components/settings_modal/tabs/version_tab.js
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
import { extractCommit } from 'src/services/version/version.service'
|
||||||
|
|
||||||
|
const pleromaFeCommitUrl = 'https://git.pleroma.social/pleroma/pleroma-fe/commit/'
|
||||||
|
const pleromaBeCommitUrl = 'https://git.pleroma.social/pleroma/pleroma/commit/'
|
||||||
|
|
||||||
|
const VersionTab = {
|
||||||
|
data () {
|
||||||
|
const instance = this.$store.state.instance
|
||||||
|
return {
|
||||||
|
backendVersion: instance.backendVersion,
|
||||||
|
frontendVersion: instance.frontendVersion
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
frontendVersionLink () {
|
||||||
|
return pleromaFeCommitUrl + this.frontendVersion
|
||||||
|
},
|
||||||
|
backendVersionLink () {
|
||||||
|
return pleromaBeCommitUrl + extractCommit(this.backendVersion)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default VersionTab
|
31
src/components/settings_modal/tabs/version_tab.vue
Normal file
31
src/components/settings_modal/tabs/version_tab.vue
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
<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="backendVersionLink"
|
||||||
|
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">
|
|
@ -46,8 +46,14 @@
|
||||||
|
|
||||||
&.side-tabs {
|
&.side-tabs {
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
@media all and (max-width: 800px) {
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
> .contents {
|
> .contents {
|
||||||
flex: 0 1 80%;
|
flex: 0 1 80%;
|
||||||
|
@media all and (max-width: 800px) {
|
||||||
|
min-width: 96vw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
> .tabs {
|
> .tabs {
|
||||||
flex: 1 0 auto;
|
flex: 1 0 auto;
|
||||||
|
|
|
@ -50,15 +50,6 @@
|
||||||
>
|
>
|
||||||
{{ user.name }}
|
{{ user.name }}
|
||||||
</div>
|
</div>
|
||||||
<router-link
|
|
||||||
v-if="!isOtherUser"
|
|
||||||
:to="{ name: 'user-settings' }"
|
|
||||||
>
|
|
||||||
<i
|
|
||||||
class="button-icon icon-wrench usersettings"
|
|
||||||
:title="$t('tool_tip.user_settings')"
|
|
||||||
/>
|
|
||||||
</router-link>
|
|
||||||
<a
|
<a
|
||||||
v-if="isOtherUser && !user.is_local"
|
v-if="isOtherUser && !user.is_local"
|
||||||
:href="user.statusnet_profile_url"
|
:href="user.statusnet_profile_url"
|
||||||
|
@ -117,7 +108,7 @@
|
||||||
type="color"
|
type="color"
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
for="style-switcher"
|
for="theme_tab"
|
||||||
class="userHighlightSel select"
|
class="userHighlightSel select"
|
||||||
>
|
>
|
||||||
<select
|
<select
|
||||||
|
|
|
@ -1,140 +0,0 @@
|
||||||
import get from 'lodash/get'
|
|
||||||
import map from 'lodash/map'
|
|
||||||
import reject from 'lodash/reject'
|
|
||||||
import Autosuggest from '../autosuggest/autosuggest.vue'
|
|
||||||
import TabSwitcher from '../tab_switcher/tab_switcher.js'
|
|
||||||
import BlockCard from '../block_card/block_card.vue'
|
|
||||||
import MuteCard from '../mute_card/mute_card.vue'
|
|
||||||
import DomainMuteCard from '../domain_mute_card/domain_mute_card.vue'
|
|
||||||
import SelectableList from '../selectable_list/selectable_list.vue'
|
|
||||||
import ProgressButton from '../progress_button/progress_button.vue'
|
|
||||||
import Importer from '../importer/importer.vue'
|
|
||||||
import Exporter from '../exporter/exporter.vue'
|
|
||||||
import withSubscription from '../../hocs/with_subscription/with_subscription'
|
|
||||||
import Checkbox from '../checkbox/checkbox.vue'
|
|
||||||
|
|
||||||
const BlockList = withSubscription({
|
|
||||||
fetch: (props, $store) => $store.dispatch('fetchBlocks'),
|
|
||||||
select: (props, $store) => get($store.state.users.currentUser, 'blockIds', []),
|
|
||||||
childPropName: 'items'
|
|
||||||
})(SelectableList)
|
|
||||||
|
|
||||||
const MuteList = withSubscription({
|
|
||||||
fetch: (props, $store) => $store.dispatch('fetchMutes'),
|
|
||||||
select: (props, $store) => get($store.state.users.currentUser, 'muteIds', []),
|
|
||||||
childPropName: 'items'
|
|
||||||
})(SelectableList)
|
|
||||||
|
|
||||||
const DomainMuteList = withSubscription({
|
|
||||||
fetch: (props, $store) => $store.dispatch('fetchDomainMutes'),
|
|
||||||
select: (props, $store) => get($store.state.users.currentUser, 'domainMutes', []),
|
|
||||||
childPropName: 'items'
|
|
||||||
})(SelectableList)
|
|
||||||
|
|
||||||
const UserSettings = {
|
|
||||||
data () {
|
|
||||||
return {
|
|
||||||
activeTab: 'profile',
|
|
||||||
newDomainToMute: ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created () {
|
|
||||||
this.$store.dispatch('fetchTokens')
|
|
||||||
},
|
|
||||||
components: {
|
|
||||||
TabSwitcher,
|
|
||||||
BlockList,
|
|
||||||
MuteList,
|
|
||||||
DomainMuteList,
|
|
||||||
BlockCard,
|
|
||||||
MuteCard,
|
|
||||||
DomainMuteCard,
|
|
||||||
ProgressButton,
|
|
||||||
Autosuggest,
|
|
||||||
Checkbox
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
user () {
|
|
||||||
return this.$store.state.users.currentUser
|
|
||||||
},
|
|
||||||
pleromaBackend () {
|
|
||||||
return this.$store.state.instance.pleromaBackend
|
|
||||||
},
|
|
||||||
currentSaveStateNotice () {
|
|
||||||
return this.$store.state.interface.settings.currentSaveStateNotice
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
importFollows (file) {
|
|
||||||
return this.$store.state.api.backendInteractor.importFollows({ file })
|
|
||||||
.then((status) => {
|
|
||||||
if (!status) {
|
|
||||||
throw new Error('failed')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
importBlocks (file) {
|
|
||||||
return this.$store.state.api.backendInteractor.importBlocks({ file })
|
|
||||||
.then((status) => {
|
|
||||||
if (!status) {
|
|
||||||
throw new Error('failed')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
generateExportableUsersContent (users) {
|
|
||||||
// Get addresses
|
|
||||||
return users.map((user) => {
|
|
||||||
// check is it's a local user
|
|
||||||
if (user && user.is_local) {
|
|
||||||
// append the instance address
|
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
return user.screen_name + '@' + location.hostname
|
|
||||||
}
|
|
||||||
return user.screen_name
|
|
||||||
}).join('\n')
|
|
||||||
},
|
|
||||||
activateTab (tabName) {
|
|
||||||
this.activeTab = tabName
|
|
||||||
},
|
|
||||||
filterUnblockedUsers (userIds) {
|
|
||||||
return reject(userIds, (userId) => {
|
|
||||||
const user = this.$store.getters.findUser(userId)
|
|
||||||
return !user || user.statusnet_blocking || user.id === this.$store.state.users.currentUser.id
|
|
||||||
})
|
|
||||||
},
|
|
||||||
filterUnMutedUsers (userIds) {
|
|
||||||
return reject(userIds, (userId) => {
|
|
||||||
const user = this.$store.getters.findUser(userId)
|
|
||||||
return !user || user.muted || user.id === this.$store.state.users.currentUser.id
|
|
||||||
})
|
|
||||||
},
|
|
||||||
queryUserIds (query) {
|
|
||||||
return this.$store.dispatch('searchUsers', query)
|
|
||||||
.then((users) => map(users, 'id'))
|
|
||||||
},
|
|
||||||
blockUsers (ids) {
|
|
||||||
return this.$store.dispatch('blockUsers', ids)
|
|
||||||
},
|
|
||||||
unblockUsers (ids) {
|
|
||||||
return this.$store.dispatch('unblockUsers', ids)
|
|
||||||
},
|
|
||||||
muteUsers (ids) {
|
|
||||||
return this.$store.dispatch('muteUsers', ids)
|
|
||||||
},
|
|
||||||
unmuteUsers (ids) {
|
|
||||||
return this.$store.dispatch('unmuteUsers', ids)
|
|
||||||
},
|
|
||||||
unmuteDomains (domains) {
|
|
||||||
return this.$store.dispatch('unmuteDomains', domains)
|
|
||||||
},
|
|
||||||
muteDomain () {
|
|
||||||
return this.$store.dispatch('muteDomain', this.newDomainToMute)
|
|
||||||
.then(() => { this.newDomainToMute = '' })
|
|
||||||
},
|
|
||||||
identity (value) {
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default UserSettings
|
|
|
@ -1,119 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="settings panel panel-default">
|
|
||||||
<div class="panel-heading">
|
|
||||||
<div class="title">
|
|
||||||
{{ $t('settings.user_settings') }}
|
|
||||||
</div>
|
|
||||||
<transition name="fade">
|
|
||||||
<template v-if="currentSaveStateNotice">
|
|
||||||
<div
|
|
||||||
v-if="currentSaveStateNotice.error"
|
|
||||||
class="alert error"
|
|
||||||
@click.prevent
|
|
||||||
>
|
|
||||||
{{ $t('settings.saving_err') }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
v-if="!currentSaveStateNotice.error"
|
|
||||||
class="alert transparent"
|
|
||||||
@click.prevent
|
|
||||||
>
|
|
||||||
{{ $t('settings.saving_ok') }}
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</transition>
|
|
||||||
</div>
|
|
||||||
<div class="panel-body profile-edit">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script src="./user_settings.js">
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
@import '../../_variables.scss';
|
|
||||||
|
|
||||||
.profile-edit {
|
|
||||||
.bio {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.visibility-tray {
|
|
||||||
padding-top: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type=file] {
|
|
||||||
padding: 5px;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.banner {
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.uploading {
|
|
||||||
font-size: 1.5em;
|
|
||||||
margin: 0.25em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.name-changer {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg {
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.current-avatar {
|
|
||||||
display: block;
|
|
||||||
width: 150px;
|
|
||||||
height: 150px;
|
|
||||||
border-radius: $fallback--avatarRadius;
|
|
||||||
border-radius: var(--avatarRadius, $fallback--avatarRadius);
|
|
||||||
}
|
|
||||||
|
|
||||||
.oauth-tokens {
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
th {
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.actions {
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&-usersearch-wrapper {
|
|
||||||
padding: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
&-bulk-actions {
|
|
||||||
text-align: right;
|
|
||||||
padding: 0 1em;
|
|
||||||
min-height: 28px;
|
|
||||||
|
|
||||||
button {
|
|
||||||
width: 10em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&-domain-mute-form {
|
|
||||||
padding: 1em;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
button {
|
|
||||||
align-self: flex-end;
|
|
||||||
margin-top: 1em;
|
|
||||||
width: 10em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.setting-subitem {
|
|
||||||
margin-left: 1.75em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -68,7 +68,9 @@
|
||||||
"disable": "Disable",
|
"disable": "Disable",
|
||||||
"enable": "Enable",
|
"enable": "Enable",
|
||||||
"confirm": "Confirm",
|
"confirm": "Confirm",
|
||||||
"verify": "Verify"
|
"verify": "Verify",
|
||||||
|
"close": "Close",
|
||||||
|
"peek": "Peek"
|
||||||
},
|
},
|
||||||
"image_cropper": {
|
"image_cropper": {
|
||||||
"crop_picture": "Crop picture",
|
"crop_picture": "Crop picture",
|
||||||
|
|
Loading…
Reference in a new issue