Merge branch 'expert-settings-and-serverside' into shigusegubu

* expert-settings-and-serverside:
  lint
  pre-emptively wipe serverside settings on logout
  fix errors in choicesetting
  fix typos in profile page
  hidden away more settings when logged out
  fix settings behaving erratically and not updating properly
  fix stripping rich content not working
  revert changes related to streaming/firehose setting, reword it so it's not confused with websocket streaming
  fix firefox rendering (??????????)
  revert to using local setting for default nsfw since backend is broken
  better phrasing
  new defaults
  expert settings toggle + server-side settings
This commit is contained in:
Henry Jameson 2022-02-28 18:26:37 +02:00
commit e6cf9efe69
24 changed files with 565 additions and 290 deletions

View file

@ -81,56 +81,56 @@
<button <button
v-if="type === 'flash' && flashLoaded" v-if="type === 'flash' && flashLoaded"
class="button-unstyled attachment-button" class="button-unstyled attachment-button"
@click.prevent="stopFlash"
:title="$t('status.attachment_stop_flash')" :title="$t('status.attachment_stop_flash')"
@click.prevent="stopFlash"
> >
<FAIcon icon="stop" /> <FAIcon icon="stop" />
</button> </button>
<button <button
v-if="attachment.description && size !== 'small' && !edit && type !== 'unknown'" v-if="attachment.description && size !== 'small' && !edit && type !== 'unknown'"
class="button-unstyled attachment-button" class="button-unstyled attachment-button"
@click.prevent="toggleDescription"
:title="$t('status.show_attachment_description')" :title="$t('status.show_attachment_description')"
@click.prevent="toggleDescription"
> >
<FAIcon icon="align-right" /> <FAIcon icon="align-right" />
</button> </button>
<button <button
v-if="!useModal && type !== 'unknown'" v-if="!useModal && type !== 'unknown'"
class="button-unstyled attachment-button" class="button-unstyled attachment-button"
@click.prevent="openModalForce"
:title="$t('status.show_attachment_in_modal')" :title="$t('status.show_attachment_in_modal')"
@click.prevent="openModalForce"
> >
<FAIcon icon="search-plus" /> <FAIcon icon="search-plus" />
</button> </button>
<button <button
v-if="nsfw && hideNsfwLocal" v-if="nsfw && hideNsfwLocal"
class="button-unstyled attachment-button" class="button-unstyled attachment-button"
@click.prevent="toggleHidden"
:title="$t('status.hide_attachment')" :title="$t('status.hide_attachment')"
@click.prevent="toggleHidden"
> >
<FAIcon icon="times" /> <FAIcon icon="times" />
</button> </button>
<button <button
v-if="shiftUp" v-if="shiftUp"
class="button-unstyled attachment-button" class="button-unstyled attachment-button"
@click.prevent="onShiftUp"
:title="$t('status.move_up')" :title="$t('status.move_up')"
@click.prevent="onShiftUp"
> >
<FAIcon icon="chevron-left" /> <FAIcon icon="chevron-left" />
</button> </button>
<button <button
v-if="shiftDn" v-if="shiftDn"
class="button-unstyled attachment-button" class="button-unstyled attachment-button"
@click.prevent="onShiftDn"
:title="$t('status.move_down')" :title="$t('status.move_down')"
@click.prevent="onShiftDn"
> >
<FAIcon icon="chevron-right" /> <FAIcon icon="chevron-right" />
</button> </button>
<button <button
v-if="remove" v-if="remove"
class="button-unstyled attachment-button" class="button-unstyled attachment-button"
@click.prevent="onRemove"
:title="$t('status.remove_attachment')" :title="$t('status.remove_attachment')"
@click.prevent="onRemove"
> >
<FAIcon icon="trash-alt" /> <FAIcon icon="trash-alt" />
</button> </button>
@ -160,7 +160,10 @@
:href="attachment.url" :href="attachment.url"
target="_blank" target="_blank"
> >
<FAIcon size="5x" :icon="placeholderIconClass" /> <FAIcon
size="5x"
:icon="placeholderIconClass"
/>
<p> <p>
{{ localDescription }} {{ localDescription }}
</p> </p>

View file

@ -26,8 +26,8 @@
:size="size" :size="size"
:editable="editable" :editable="editable"
:remove="removeAttachment" :remove="removeAttachment"
:shiftUp="!(attachmentIndex === 0 && rowIndex === 0) && shiftUpAttachment" :shift-up="!(attachmentIndex === 0 && rowIndex === 0) && shiftUpAttachment"
:shiftDn="!(attachmentIndex === row.items.length - 1 && rowIndex === rows.length - 1) && shiftDnAttachment" :shift-dn="!(attachmentIndex === row.items.length - 1 && rowIndex === rows.length - 1) && shiftDnAttachment"
:edit="editAttachment" :edit="editAttachment"
:description="descriptions && descriptions[attachment.id]" :description="descriptions && descriptions[attachment.id]"
:hide-description="size === 'small' || tooManyAttachments && hidingLong" :hide-description="size === 'small' || tooManyAttachments && hidingLong"

View file

@ -117,6 +117,7 @@ const PostStatusForm = {
? this.copyMessageScope ? this.copyMessageScope
: this.$store.state.users.currentUser.default_scope : this.$store.state.users.currentUser.default_scope
// const { defaultNSFW: sensitiveByDefault } = this.$store.state.serverSideConfig
const { postContentType: contentType, sensitiveByDefault } = this.$store.getters.mergedConfig const { postContentType: contentType, sensitiveByDefault } = this.$store.getters.mergedConfig
return { return {

View file

@ -1,14 +1,17 @@
import { get, set } from 'lodash' import { get, set } from 'lodash'
import Checkbox from 'src/components/checkbox/checkbox.vue' import Checkbox from 'src/components/checkbox/checkbox.vue'
import ModifiedIndicator from './modified_indicator.vue' import ModifiedIndicator from './modified_indicator.vue'
import ServerSideIndicator from './server_side_indicator.vue'
export default { export default {
components: { components: {
Checkbox, Checkbox,
ModifiedIndicator ModifiedIndicator,
ServerSideIndicator
}, },
props: [ props: [
'path', 'path',
'disabled' 'disabled',
'expert'
], ],
computed: { computed: {
pathDefault () { pathDefault () {
@ -26,8 +29,14 @@ export default {
defaultState () { defaultState () {
return get(this.$parent, this.pathDefault) return get(this.$parent, this.pathDefault)
}, },
isServerSide () {
return this.path.startsWith('serverSide_')
},
isChanged () { isChanged () {
return this.state !== this.defaultState return !this.path.startsWith('serverSide_') && this.state !== this.defaultState
},
matchesExpertLevel () {
return (this.expert || 0) <= this.$parent.expertLevel
} }
}, },
methods: { methods: {

View file

@ -1,5 +1,6 @@
<template> <template>
<label <label
v-if="matchesExpertLevel"
class="BooleanSetting" class="BooleanSetting"
> >
<Checkbox <Checkbox
@ -13,8 +14,7 @@
> >
<slot /> <slot />
</span> </span>
<ModifiedIndicator :changed="isChanged" /> <ModifiedIndicator :changed="isChanged" /><ServerSideIndicator :server-side="isServerSide" /> </Checkbox>
</Checkbox>
</label> </label>
</template> </template>

View file

@ -1,15 +1,18 @@
import { get, set } from 'lodash' import { get, set } from 'lodash'
import Select from 'src/components/select/select.vue' import Select from 'src/components/select/select.vue'
import ModifiedIndicator from './modified_indicator.vue' import ModifiedIndicator from './modified_indicator.vue'
import ServerSideIndicator from './server_side_indicator.vue'
export default { export default {
components: { components: {
Select, Select,
ModifiedIndicator ModifiedIndicator,
ServerSideIndicator
}, },
props: [ props: [
'path', 'path',
'disabled', 'disabled',
'options' 'options',
'expert'
], ],
computed: { computed: {
pathDefault () { pathDefault () {
@ -27,8 +30,14 @@ export default {
defaultState () { defaultState () {
return get(this.$parent, this.pathDefault) return get(this.$parent, this.pathDefault)
}, },
isServerSide () {
return this.path.startsWith('serverSide_')
},
isChanged () { isChanged () {
return this.state !== this.defaultState return !this.path.startsWith('serverSide_') && this.state !== this.defaultState
},
matchesExpertLevel () {
return (this.expert || 0) <= this.$parent.expertLevel
} }
}, },
methods: { methods: {

View file

@ -1,5 +1,6 @@
<template> <template>
<label <label
v-if="matchesExpertLevel"
class="ChoiceSetting" class="ChoiceSetting"
> >
<slot /> <slot />
@ -18,6 +19,7 @@
</option> </option>
</Select> </Select>
<ModifiedIndicator :changed="isChanged" /> <ModifiedIndicator :changed="isChanged" />
<ServerSideIndicator :server-side="isServerSide" />
</label> </label>
</template> </template>

View file

@ -0,0 +1,51 @@
<template>
<span
v-if="serverSide"
class="ServerSideIndicator"
>
<Popover
trigger="hover"
>
<template v-slot:trigger>
&nbsp;
<FAIcon
icon="server"
:aria-label="$t('settings.setting_server_side')"
/>
</template>
<template v-slot:content>
<div class="serverside-tooltip">
{{ $t('settings.setting_server_side') }}
</div>
</template>
</Popover>
</span>
</template>
<script>
import Popover from 'src/components/popover/popover.vue'
import { library } from '@fortawesome/fontawesome-svg-core'
import { faServer } from '@fortawesome/free-solid-svg-icons'
library.add(
faServer
)
export default {
components: { Popover },
props: ['serverSide']
}
</script>
<style lang="scss">
.ServerSideIndicator {
display: inline-block;
position: relative;
.serverside-tooltip {
margin: 0.5em 1em;
min-width: 10em;
text-align: center;
}
}
</style>

View file

@ -1,4 +1,5 @@
import { defaultState as configDefaultState } from 'src/modules/config.js' import { defaultState as configDefaultState } from 'src/modules/config.js'
import { defaultState as serverSideConfigDefaultState } from 'src/modules/serverSideConfig.js'
const SharedComputedObject = () => ({ const SharedComputedObject = () => ({
user () { user () {
@ -22,6 +23,14 @@ const SharedComputedObject = () => ({
} }
}]) }])
.reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}), .reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}),
...Object.keys(serverSideConfigDefaultState)
.map(key => ['serverSide_' + key, {
get () { return this.$store.state.serverSideConfig[key] },
set (value) {
this.$store.dispatch('setServerSideOption', { name: key, value })
}
}])
.reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}),
// Special cases (need to transform values or perform actions first) // Special cases (need to transform values or perform actions first)
useStreamingApi: { useStreamingApi: {
get () { return this.$store.getters.mergedConfig.useStreamingApi }, get () { return this.$store.getters.mergedConfig.useStreamingApi },

View file

@ -3,6 +3,7 @@ import PanelLoading from 'src/components/panel_loading/panel_loading.vue'
import AsyncComponentError from 'src/components/async_component_error/async_component_error.vue' import AsyncComponentError from 'src/components/async_component_error/async_component_error.vue'
import getResettableAsyncComponent from 'src/services/resettable_async_component.js' import getResettableAsyncComponent from 'src/services/resettable_async_component.js'
import Popover from '../popover/popover.vue' import Popover from '../popover/popover.vue'
import Checkbox from 'src/components/checkbox/checkbox.vue'
import { library } from '@fortawesome/fontawesome-svg-core' import { library } from '@fortawesome/fontawesome-svg-core'
import { cloneDeep } from 'lodash' import { cloneDeep } from 'lodash'
import { import {
@ -51,6 +52,7 @@ const SettingsModal = {
components: { components: {
Modal, Modal,
Popover, Popover,
Checkbox,
SettingsModalContent: getResettableAsyncComponent( SettingsModalContent: getResettableAsyncComponent(
() => import('./settings_modal_content.vue'), () => import('./settings_modal_content.vue'),
{ {
@ -159,6 +161,15 @@ const SettingsModal = {
}, },
modalPeeked () { modalPeeked () {
return this.$store.state.interface.settingsModalState === 'minimized' return this.$store.state.interface.settingsModalState === 'minimized'
},
expertLevel: {
get () {
return this.$store.state.config.expertLevel > 0
},
set (value) {
console.log(value)
this.$store.dispatch('setOption', { name: 'expertLevel', value: value ? 1 : 0 })
}
} }
} }
} }

View file

@ -48,4 +48,11 @@
} }
} }
} }
.settings-footer {
display: flex;
>* {
margin-right: 0.5em;
}
}
} }

View file

@ -53,7 +53,7 @@
<div class="panel-body"> <div class="panel-body">
<SettingsModalContent v-if="modalOpenedOnce" /> <SettingsModalContent v-if="modalOpenedOnce" />
</div> </div>
<div class="panel-footer"> <div class="panel-footer settings-footer">
<Popover <Popover
class="export" class="export"
trigger="click" trigger="click"
@ -108,6 +108,10 @@
</div> </div>
</template> </template>
</Popover> </Popover>
<Checkbox v-model="expertLevel">
{{ $t("settings.expert_mode") }}
</Checkbox>
</div> </div>
</div> </div>
</Modal> </Modal>

View file

@ -21,6 +21,7 @@
</li> </li>
<li> <li>
<BooleanSetting <BooleanSetting
v-if="user"
:disabled="hideFilteredStatuses" :disabled="hideFilteredStatuses"
path="hideMutedThreads" path="hideMutedThreads"
> >
@ -29,6 +30,7 @@
</li> </li>
<li> <li>
<BooleanSetting <BooleanSetting
v-if="user"
:disabled="hideFilteredStatuses" :disabled="hideFilteredStatuses"
path="hideMutedPosts" path="hideMutedPosts"
> >
@ -38,11 +40,15 @@
</ul> </ul>
</li> </li>
<li> <li>
<BooleanSetting path="hidePostStats"> <BooleanSetting
path="hidePostStats"
expert="1"
>
{{ $t('settings.hide_post_stats') }} {{ $t('settings.hide_post_stats') }}
</BooleanSetting> </BooleanSetting>
</li> </li>
<ChoiceSetting <ChoiceSetting
v-if="user"
id="replyVisibility" id="replyVisibility"
path="replyVisibility" path="replyVisibility"
:options="replyVisibilityOptions" :options="replyVisibilityOptions"
@ -59,7 +65,7 @@
<div>{{ $t('settings.filtering_explanation') }}</div> <div>{{ $t('settings.filtering_explanation') }}</div>
</li> </li>
<h3>{{ $t('settings.attachments') }}</h3> <h3>{{ $t('settings.attachments') }}</h3>
<li> <li v-if="expertLevel > 0">
<label for="maxThumbnails"> <label for="maxThumbnails">
{{ $t('settings.max_thumbnails') }} {{ $t('settings.max_thumbnails') }}
</label> </label>
@ -84,7 +90,10 @@
</li> </li>
</ul> </ul>
</div> </div>
<div class="setting-item"> <div
v-if="expertLevel > 0"
class="setting-item"
>
<h2>{{ $t('settings.user_profiles') }}</h2> <h2>{{ $t('settings.user_profiles') }}</h2>
<ul class="setting-list"> <ul class="setting-list">
<li> <li>
@ -94,46 +103,6 @@
</li> </li>
</ul> </ul>
</div> </div>
<div class="setting-item">
<h2>{{ $t('settings.notifications') }}</h2>
<ul class="setting-list">
<li class="select-multiple">
<span class="label">{{ $t('settings.notification_visibility') }}</span>
<ul class="option-list">
<li>
<BooleanSetting path="notificationVisibility.likes">
{{ $t('settings.notification_visibility_likes') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting path="notificationVisibility.repeats">
{{ $t('settings.notification_visibility_repeats') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting path="notificationVisibility.follows">
{{ $t('settings.notification_visibility_follows') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting path="notificationVisibility.mentions">
{{ $t('settings.notification_visibility_mentions') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting path="notificationVisibility.moves">
{{ $t('settings.notification_visibility_moves') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting path="notificationVisibility.emojiReactions">
{{ $t('settings.notification_visibility_emoji_reactions') }}
</BooleanSetting>
</li>
</ul>
</li>
</ul>
</div>
</div> </div>
</template> </template>
<script src="./filtering_tab.js"></script> <script src="./filtering_tab.js"></script>

View file

@ -1,8 +1,10 @@
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 InterfaceLanguageSwitcher from 'src/components/interface_language_switcher/interface_language_switcher.vue' import InterfaceLanguageSwitcher from 'src/components/interface_language_switcher/interface_language_switcher.vue'
import SharedComputedObject from '../helpers/shared_computed_object.js' import SharedComputedObject from '../helpers/shared_computed_object.js'
import ServerSideIndicator from '../helpers/server_side_indicator.vue'
import { library } from '@fortawesome/fontawesome-svg-core' import { library } from '@fortawesome/fontawesome-svg-core'
import { import {
faGlobe faGlobe
@ -47,7 +49,9 @@ const GeneralTab = {
components: { components: {
BooleanSetting, BooleanSetting,
ChoiceSetting, ChoiceSetting,
InterfaceLanguageSwitcher InterfaceLanguageSwitcher,
ScopeSelector,
ServerSideIndicator
}, },
computed: { computed: {
postFormats () { postFormats () {
@ -67,6 +71,11 @@ const GeneralTab = {
}, },
instanceShoutboxPresent () { return this.$store.state.instance.shoutAvailable }, instanceShoutboxPresent () { return this.$store.state.instance.shoutAvailable },
...SharedComputedObject() ...SharedComputedObject()
},
methods: {
changeDefaultScope (value) {
this.$store.dispatch('setServerSideOption', { name: 'defaultScope', value })
}
} }
} }

View file

@ -45,7 +45,10 @@
</ul> </ul>
</li> </li>
<li> <li>
<BooleanSetting path="useStreamingApi"> <BooleanSetting
path="useStreamingApi"
expert="1"
>
{{ $t('settings.useStreamingApi') }} {{ $t('settings.useStreamingApi') }}
<br> <br>
<small> <small>
@ -54,22 +57,34 @@
</BooleanSetting> </BooleanSetting>
</li> </li>
<li> <li>
<BooleanSetting path="virtualScrolling"> <BooleanSetting
path="virtualScrolling"
expert="1"
>
{{ $t('settings.virtual_scrolling') }} {{ $t('settings.virtual_scrolling') }}
</BooleanSetting> </BooleanSetting>
</li> </li>
<li> <li>
<BooleanSetting path="alwaysShowNewPostButton"> <BooleanSetting
path="alwaysShowNewPostButton"
expert="1"
>
{{ $t('settings.always_show_post_button') }} {{ $t('settings.always_show_post_button') }}
</BooleanSetting> </BooleanSetting>
</li> </li>
<li> <li>
<BooleanSetting path="autohideFloatingPostButton"> <BooleanSetting
path="autohideFloatingPostButton"
expert="1"
>
{{ $t('settings.autohide_floating_post_button') }} {{ $t('settings.autohide_floating_post_button') }}
</BooleanSetting> </BooleanSetting>
</li> </li>
<li v-if="instanceShoutboxPresent"> <li v-if="instanceShoutboxPresent">
<BooleanSetting path="hideShoutbox"> <BooleanSetting
path="hideShoutbox"
expert="1"
>
{{ $t('settings.hide_shoutbox') }} {{ $t('settings.hide_shoutbox') }}
</BooleanSetting> </BooleanSetting>
</li> </li>
@ -84,13 +99,28 @@
</BooleanSetting> </BooleanSetting>
</li> </li>
<li> <li>
<BooleanSetting path="emojiReactionsOnTimeline"> <BooleanSetting
path="emojiReactionsOnTimeline"
expert="1"
>
{{ $t('settings.emoji_reactions_on_timeline') }} {{ $t('settings.emoji_reactions_on_timeline') }}
</BooleanSetting> </BooleanSetting>
</li> </li>
<li>
<BooleanSetting
v-if="user"
path="serverSide_stripRichContent"
expert="1"
>
{{ $t('settings.no_rich_text_description') }}
</BooleanSetting>
</li>
<h3>{{ $t('settings.attachments') }}</h3> <h3>{{ $t('settings.attachments') }}</h3>
<li> <li>
<BooleanSetting path="useContainFit"> <BooleanSetting
path="useContainFit"
expert="1"
>
{{ $t('settings.use_contain_fit') }} {{ $t('settings.use_contain_fit') }}
</BooleanSetting> </BooleanSetting>
</li> </li>
@ -103,6 +133,7 @@
<li> <li>
<BooleanSetting <BooleanSetting
path="preloadImage" path="preloadImage"
expert="1"
:disabled="!hideNsfw" :disabled="!hideNsfw"
> >
{{ $t('settings.preload_images') }} {{ $t('settings.preload_images') }}
@ -111,6 +142,7 @@
<li> <li>
<BooleanSetting <BooleanSetting
path="useOneClickNsfw" path="useOneClickNsfw"
expert="1"
:disabled="!hideNsfw" :disabled="!hideNsfw"
> >
{{ $t('settings.use_one_click_nsfw') }} {{ $t('settings.use_one_click_nsfw') }}
@ -118,7 +150,10 @@
</li> </li>
</ul> </ul>
<li> <li>
<BooleanSetting path="loopVideo"> <BooleanSetting
path="loopVideo"
expert="1"
>
{{ $t('settings.loop_video') }} {{ $t('settings.loop_video') }}
</BooleanSetting> </BooleanSetting>
<ul <ul
@ -128,6 +163,7 @@
<li> <li>
<BooleanSetting <BooleanSetting
path="loopVideoSilentOnly" path="loopVideoSilentOnly"
expert="1"
:disabled="!loopVideo || !loopSilentAvailable" :disabled="!loopVideo || !loopSilentAvailable"
> >
{{ $t('settings.loop_video_silent_only') }} {{ $t('settings.loop_video_silent_only') }}
@ -142,57 +178,14 @@
</ul> </ul>
</li> </li>
<li> <li>
<BooleanSetting path="playVideosInModal"> <BooleanSetting
path="playVideosInModal"
expert="1"
>
{{ $t('settings.play_videos_in_modal') }} {{ $t('settings.play_videos_in_modal') }}
</BooleanSetting> </BooleanSetting>
</li> </li>
<h3>{{ $t('settings.fun') }}</h3> <h3>{{ $t('settings.mention_links') }}</h3>
<li>
<BooleanSetting path="greentext">
{{ $t('settings.greentext') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting path="mentionLinkShowYous">
{{ $t('settings.show_yous') }}
</BooleanSetting>
</li>
<li>
<ChoiceSetting
id="conversationDisplay"
path="conversationDisplay"
:options="conversationDisplayOptions"
>
{{ $t('settings.conversation_display') }}
</ChoiceSetting>
</li>
<ul
v-if="conversationDisplay !== 'linear'"
class="setting-list suboptions"
>
<li>
<label for="maxDepthInThread">
{{ $t('settings.max_depth_in_thread') }}
</label>
<input
id="maxDepthInThread"
path.number="maxDepthInThread"
class="number-input"
type="number"
min="3"
step="1"
>
</li>
<li>
<ChoiceSetting
id="conversationOtherRepliesButton"
path="conversationOtherRepliesButton"
:options="conversationOtherRepliesButtonOptions"
>
{{ $t('settings.conversation_other_replies_button') }}
</ChoiceSetting>
</li>
</ul>
<li> <li>
<ChoiceSetting <ChoiceSetting
id="mentionLinkDisplay" id="mentionLinkDisplay"
@ -205,47 +198,103 @@
<ul <ul
class="setting-list suboptions" class="setting-list suboptions"
> >
<li <li v-if="mentionLinkDisplay === 'short'">
v-if="mentionLinkDisplay === 'short'" <BooleanSetting
> path="mentionLinkShowTooltip"
<BooleanSetting path="mentionLinkShowTooltip"> expert="1"
>
{{ $t('settings.mention_link_show_tooltip') }} {{ $t('settings.mention_link_show_tooltip') }}
</BooleanSetting> </BooleanSetting>
</li> </li>
<li>
<BooleanSetting path="useAtIcon">
{{ $t('settings.use_at_icon') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting path="mentionLinkShowAvatar">
{{ $t('settings.mention_link_show_avatar') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting path="mentionLinkFadeDomain">
{{ $t('settings.mention_link_fade_domain') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting path="mentionLinkBoldenYou">
{{ $t('settings.mention_link_bolden_you') }}
</BooleanSetting>
</li>
</ul> </ul>
<li>
<BooleanSetting
path="useAtIcon"
expert="1"
>
{{ $t('settings.use_at_icon') }}
</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> </ul>
</div> </div>
<div class="setting-item"> <div
v-if="user"
class="setting-item"
>
<h2>{{ $t('settings.composing') }}</h2> <h2>{{ $t('settings.composing') }}</h2>
<ul class="setting-list"> <ul class="setting-list">
<li> <li>
<BooleanSetting path="scopeCopy"> <label for="default-vis">
{{ $t('settings.default_vis') }} <ServerSideIndicator :server-side="true" />
<ScopeSelector
class="scope-selector"
:show-all="true"
:user-default="serverSide_defaultScope"
:initial-scope="serverSide_defaultScope"
:on-scope-change="changeDefaultScope"
/>
</label>
</li>
<li>
<!-- <BooleanSetting path="serverSide_defaultNSFW"> -->
<BooleanSetting path="sensitiveByDefault">
{{ $t('settings.sensitive_by_default') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting
path="scopeCopy"
expert="1"
>
{{ $t('settings.scope_copy') }} {{ $t('settings.scope_copy') }}
</BooleanSetting> </BooleanSetting>
</li> </li>
<li> <li>
<BooleanSetting path="alwaysShowSubjectInput"> <BooleanSetting
path="alwaysShowSubjectInput"
expert="1"
>
{{ $t('settings.subject_input_always_show') }} {{ $t('settings.subject_input_always_show') }}
</BooleanSetting> </BooleanSetting>
</li> </li>
@ -254,6 +303,7 @@
id="subjectLineBehavior" id="subjectLineBehavior"
path="subjectLineBehavior" path="subjectLineBehavior"
:options="subjectLineOptions" :options="subjectLineOptions"
expert="1"
> >
{{ $t('settings.subject_line_behavior') }} {{ $t('settings.subject_line_behavior') }}
</ChoiceSetting> </ChoiceSetting>
@ -268,43 +318,39 @@
</ChoiceSetting> </ChoiceSetting>
</li> </li>
<li> <li>
<BooleanSetting path="minimalScopesMode"> <BooleanSetting
path="minimalScopesMode"
expert="1"
>
{{ $t('settings.minimal_scopes_mode') }} {{ $t('settings.minimal_scopes_mode') }}
</BooleanSetting> </BooleanSetting>
</li> </li>
<li> <li>
<BooleanSetting path="sensitiveByDefault"> <BooleanSetting
{{ $t('settings.sensitive_by_default') }} path="alwaysShowNewPostButton"
</BooleanSetting> expert="1"
</li> >
<li>
<BooleanSetting path="alwaysShowNewPostButton">
{{ $t('settings.always_show_post_button') }} {{ $t('settings.always_show_post_button') }}
</BooleanSetting> </BooleanSetting>
</li> </li>
<li> <li>
<BooleanSetting path="autohideFloatingPostButton"> <BooleanSetting
path="autohideFloatingPostButton"
expert="1"
>
{{ $t('settings.autohide_floating_post_button') }} {{ $t('settings.autohide_floating_post_button') }}
</BooleanSetting> </BooleanSetting>
</li> </li>
<li> <li>
<BooleanSetting path="padEmoji"> <BooleanSetting
path="padEmoji"
expert="1"
>
{{ $t('settings.pad_emoji') }} {{ $t('settings.pad_emoji') }}
</BooleanSetting> </BooleanSetting>
</li> </li>
</ul> </ul>
</div> </div>
<div class="setting-item">
<h2>{{ $t('settings.notifications') }}</h2>
<ul class="setting-list">
<li>
<BooleanSetting path="webPushNotifications">
{{ $t('settings.enable_web_push_notifications') }}
</BooleanSetting>
</li>
</ul>
</div>
</div> </div>
</template> </template>

View file

@ -1,4 +1,5 @@
import Checkbox from 'src/components/checkbox/checkbox.vue' import BooleanSetting from '../helpers/boolean_setting.vue'
import SharedComputedObject from '../helpers/shared_computed_object.js'
const NotificationsTab = { const NotificationsTab = {
data () { data () {
@ -9,12 +10,13 @@ const NotificationsTab = {
} }
}, },
components: { components: {
Checkbox BooleanSetting
}, },
computed: { computed: {
user () { user () {
return this.$store.state.users.currentUser return this.$store.state.users.currentUser
} },
...SharedComputedObject()
}, },
methods: { methods: {
updateNotificationSettings () { updateNotificationSettings () {

View file

@ -2,30 +2,77 @@
<div :label="$t('settings.notifications')"> <div :label="$t('settings.notifications')">
<div class="setting-item"> <div class="setting-item">
<h2>{{ $t('settings.notification_setting_filters') }}</h2> <h2>{{ $t('settings.notification_setting_filters') }}</h2>
<p> <ul class="setting-list">
<Checkbox v-model="notificationSettings.block_from_strangers"> <li>
{{ $t('settings.notification_setting_block_from_strangers') }} <BooleanSetting path="serverSide_blockNotificationsFromStrangers">
</Checkbox> {{ $t('settings.notification_setting_block_from_strangers') }}
</p> </BooleanSetting>
</li>
<li class="select-multiple">
<span class="label">{{ $t('settings.notification_visibility') }}</span>
<ul class="option-list">
<li>
<BooleanSetting path="notificationVisibility.likes">
{{ $t('settings.notification_visibility_likes') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting path="notificationVisibility.repeats">
{{ $t('settings.notification_visibility_repeats') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting path="notificationVisibility.follows">
{{ $t('settings.notification_visibility_follows') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting path="notificationVisibility.mentions">
{{ $t('settings.notification_visibility_mentions') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting path="notificationVisibility.moves">
{{ $t('settings.notification_visibility_moves') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting path="notificationVisibility.emojiReactions">
{{ $t('settings.notification_visibility_emoji_reactions') }}
</BooleanSetting>
</li>
</ul>
</li>
</ul>
</div> </div>
<div class="setting-item"> <div
v-if="expertLevel > 0"
class="setting-item"
>
<h2>{{ $t('settings.notification_setting_privacy') }}</h2> <h2>{{ $t('settings.notification_setting_privacy') }}</h2>
<p> <ul class="setting-list">
<Checkbox v-model="notificationSettings.hide_notification_contents"> <li>
{{ $t('settings.notification_setting_hide_notification_contents') }} <BooleanSetting
</Checkbox> path="webPushNotifications"
</p> expert="1"
>
{{ $t('settings.enable_web_push_notifications') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting
path="serverSide_webPushHideContents"
expert="1"
>
{{ $t('settings.notification_setting_hide_notification_contents') }}
</BooleanSetting>
</li>
</ul>
</div> </div>
<div class="setting-item"> <div class="setting-item">
<p>{{ $t('settings.notification_mutes') }}</p> <p>{{ $t('settings.notification_mutes') }}</p>
<p>{{ $t('settings.notification_blocks') }}</p> <p>{{ $t('settings.notification_blocks') }}</p>
<button
class="btn button-default"
@click="updateNotificationSettings"
>
{{ $t('settings.save') }}
</button>
</div> </div>
</div> </div>
</template> </template>

View file

@ -8,6 +8,9 @@ import EmojiInput from 'src/components/emoji_input/emoji_input.vue'
import suggestor from 'src/components/emoji_input/suggestor.js' import suggestor from 'src/components/emoji_input/suggestor.js'
import Autosuggest from 'src/components/autosuggest/autosuggest.vue' import Autosuggest from 'src/components/autosuggest/autosuggest.vue'
import Checkbox from 'src/components/checkbox/checkbox.vue' import Checkbox from 'src/components/checkbox/checkbox.vue'
import BooleanSetting from '../helpers/boolean_setting.vue'
import SharedComputedObject from '../helpers/shared_computed_object.js'
import { library } from '@fortawesome/fontawesome-svg-core' import { library } from '@fortawesome/fontawesome-svg-core'
import { import {
faTimes, faTimes,
@ -27,18 +30,10 @@ const ProfileTab = {
newName: this.$store.state.users.currentUser.name_unescaped, newName: this.$store.state.users.currentUser.name_unescaped,
newBio: unescape(this.$store.state.users.currentUser.description), newBio: unescape(this.$store.state.users.currentUser.description),
newLocked: this.$store.state.users.currentUser.locked, newLocked: this.$store.state.users.currentUser.locked,
newNoRichText: this.$store.state.users.currentUser.no_rich_text,
newDefaultScope: this.$store.state.users.currentUser.default_scope,
newFields: this.$store.state.users.currentUser.fields.map(field => ({ name: field.name, value: field.value })), newFields: this.$store.state.users.currentUser.fields.map(field => ({ name: field.name, value: field.value })),
hideFollows: this.$store.state.users.currentUser.hide_follows,
hideFollowers: this.$store.state.users.currentUser.hide_followers,
hideFollowsCount: this.$store.state.users.currentUser.hide_follows_count,
hideFollowersCount: this.$store.state.users.currentUser.hide_followers_count,
showRole: this.$store.state.users.currentUser.show_role, showRole: this.$store.state.users.currentUser.show_role,
role: this.$store.state.users.currentUser.role, role: this.$store.state.users.currentUser.role,
discoverable: this.$store.state.users.currentUser.discoverable,
bot: this.$store.state.users.currentUser.bot, bot: this.$store.state.users.currentUser.bot,
allowFollowingMove: this.$store.state.users.currentUser.allow_following_move,
pickAvatarBtnVisible: true, pickAvatarBtnVisible: true,
bannerUploading: false, bannerUploading: false,
backgroundUploading: false, backgroundUploading: false,
@ -54,12 +49,14 @@ const ProfileTab = {
EmojiInput, EmojiInput,
Autosuggest, Autosuggest,
ProgressButton, ProgressButton,
Checkbox Checkbox,
BooleanSetting
}, },
computed: { computed: {
user () { user () {
return this.$store.state.users.currentUser return this.$store.state.users.currentUser
}, },
...SharedComputedObject(),
emojiUserSuggestor () { emojiUserSuggestor () {
return suggestor({ return suggestor({
emoji: [ emoji: [
@ -123,15 +120,7 @@ const ProfileTab = {
/* eslint-disable camelcase */ /* eslint-disable camelcase */
display_name: this.newName, display_name: this.newName,
fields_attributes: this.newFields.filter(el => el != null), fields_attributes: this.newFields.filter(el => el != null),
default_scope: this.newDefaultScope,
no_rich_text: this.newNoRichText,
hide_follows: this.hideFollows,
hide_followers: this.hideFollowers,
discoverable: this.discoverable,
bot: this.bot, bot: this.bot,
allow_following_move: this.allowFollowingMove,
hide_follows_count: this.hideFollowsCount,
hide_followers_count: this.hideFollowersCount,
show_role: this.showRole show_role: this.showRole
/* eslint-enable camelcase */ /* eslint-enable camelcase */
} }).then((user) => { } }).then((user) => {

View file

@ -25,61 +25,6 @@
class="bio resize-height" class="bio resize-height"
/> />
</EmojiInput> </EmojiInput>
<p>
<Checkbox v-model="newLocked">
{{ $t('settings.lock_account_description') }}
</Checkbox>
</p>
<div>
<label for="default-vis">{{ $t('settings.default_vis') }}</label>
<div
id="default-vis"
class="visibility-tray"
>
<scope-selector
:show-all="true"
:user-default="newDefaultScope"
:initial-scope="newDefaultScope"
:on-scope-change="changeVis"
/>
</div>
</div>
<p>
<Checkbox v-model="newNoRichText">
{{ $t('settings.no_rich_text_description') }}
</Checkbox>
</p>
<p>
<Checkbox v-model="hideFollows">
{{ $t('settings.hide_follows_description') }}
</Checkbox>
</p>
<p class="setting-subitem">
<Checkbox
v-model="hideFollowsCount"
:disabled="!hideFollows"
>
{{ $t('settings.hide_follows_count_description') }}
</Checkbox>
</p>
<p>
<Checkbox v-model="hideFollowers">
{{ $t('settings.hide_followers_description') }}
</Checkbox>
</p>
<p class="setting-subitem">
<Checkbox
v-model="hideFollowersCount"
:disabled="!hideFollowers"
>
{{ $t('settings.hide_followers_count_description') }}
</Checkbox>
</p>
<p>
<Checkbox v-model="allowFollowingMove">
{{ $t('settings.allow_following_move') }}
</Checkbox>
</p>
<p v-if="role === 'admin' || role === 'moderator'"> <p v-if="role === 'admin' || role === 'moderator'">
<Checkbox v-model="showRole"> <Checkbox v-model="showRole">
<template v-if="role === 'admin'"> <template v-if="role === 'admin'">
@ -90,11 +35,6 @@
</template> </template>
</Checkbox> </Checkbox>
</p> </p>
<p>
<Checkbox v-model="discoverable">
{{ $t('settings.discoverable') }}
</Checkbox>
</p>
<div v-if="maxFields > 0"> <div v-if="maxFields > 0">
<p>{{ $t('settings.profile_fields.label') }}</p> <p>{{ $t('settings.profile_fields.label') }}</p>
<div <div
@ -269,6 +209,67 @@
{{ $t('settings.save') }} {{ $t('settings.save') }}
</button> </button>
</div> </div>
<div class="setting-item">
<h2>{{ $t('settings.account_privacy') }}</h2>
<ul class="setting-list">
<li>
<BooleanSetting path="serverSide_locked">
{{ $t('settings.lock_account_description') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting path="serverSide_discoverable">
{{ $t('settings.discoverable') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting path="serverSide_allowFollowingMove">
{{ $t('settings.allow_following_move') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting path="serverSide_hideFavorites">
{{ $t('settings.hide_favorites_description') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting path="serverSide_hideFollowers">
{{ $t('settings.hide_followers_description') }}
</BooleanSetting>
<ul
class="setting-list suboptions"
:class="[{disabled: !serverSide_hideFollowers}]"
>
<li>
<BooleanSetting
path="serverSide_hideFollowersCount"
:disabled="!serverSide_hideFollowers"
>
{{ $t('settings.hide_followers_count_description') }}
</BooleanSetting>
</li>
</ul>
</li>
<li>
<BooleanSetting path="serverSide_hideFollows">
{{ $t('settings.hide_follows_description') }}
</BooleanSetting>
<ul
class="setting-list suboptions"
:class="[{disabled: !serverSide_hideFollows}]"
>
<li>
<BooleanSetting
path="serverSide_hideFollowsCount"
:disabled="!serverSide_hideFollows"
>
{{ $t('settings.hide_follows_count_description') }}
</BooleanSetting>
</li>
</ul>
</li>
</ul>
</div>
</div> </div>
</template> </template>

View file

@ -259,13 +259,14 @@
}, },
"settings": { "settings": {
"app_name": "App name", "app_name": "App name",
"expert_mode": "Show advanced",
"save": "Save changes", "save": "Save changes",
"security": "Security", "security": "Security",
"setting_changed": "Setting is different from default", "setting_changed": "Setting is different from default",
"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",
"mentions_new_style": "Fancier mention links", "mention_links": "Mention links",
"mentions_new_place": "Put mentions on a separate line",
"mfa": { "mfa": {
"otp": "OTP", "otp": "OTP",
"setup_otp": "Setup OTP", "setup_otp": "Setup OTP",
@ -402,6 +403,7 @@
"name": "Label", "name": "Label",
"value": "Content" "value": "Content"
}, },
"account_privacy": "Privacy",
"use_contain_fit": "Don't crop the attachment in thumbnails", "use_contain_fit": "Don't crop the attachment in thumbnails",
"name": "Name", "name": "Name",
"name_bio": "Name & bio", "name_bio": "Name & bio",
@ -419,6 +421,7 @@
"no_rich_text_description": "Strip rich text formatting from all posts", "no_rich_text_description": "Strip rich text formatting from all posts",
"no_blocks": "No blocks", "no_blocks": "No blocks",
"no_mutes": "No mutes", "no_mutes": "No mutes",
"hide_favorites_description": "Don't show list of my favorites (people still get notified)",
"hide_follows_description": "Don't show who I'm following", "hide_follows_description": "Don't show who I'm following",
"hide_followers_description": "Don't show who's following me", "hide_followers_description": "Don't show who's following me",
"hide_follows_count_description": "Don't show follow count", "hide_follows_count_description": "Don't show follow count",
@ -432,7 +435,7 @@
"valid_until": "Valid until", "valid_until": "Valid until",
"revoke_token": "Revoke", "revoke_token": "Revoke",
"panelRadius": "Panels", "panelRadius": "Panels",
"pause_on_unfocused": "Pause streaming when tab is not focused", "pause_on_unfocused": "Pause when tab is not focused",
"presets": "Presets", "presets": "Presets",
"profile_background": "Profile background", "profile_background": "Profile background",
"profile_banner": "Profile banner", "profile_banner": "Profile banner",
@ -467,18 +470,10 @@
"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",
"conversation_display": "Conversation display style",
"conversation_display_tree": "Tree-style",
"conversation_display_simple_tree": "Simplified tree-style",
"conversation_display_linear": "Linear-style",
"conversation_other_replies_button": "Show the \"other replies\" button",
"conversation_other_replies_button_below": "Below statuses",
"conversation_other_replies_button_inside": "Inside statuses",
"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",
"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": "Enable automatic streaming of new posts when scrolled to the top", "streaming": "Automatically show new posts when scrolled to the top",
"user_mutes": "Users", "user_mutes": "Users",
"useStreamingApi": "Receive posts and notifications real-time", "useStreamingApi": "Receive posts and notifications real-time",
"useStreamingApiWarning": "(Not recommended, experimental, known to skip posts)", "useStreamingApiWarning": "(Not recommended, experimental, known to skip posts)",
@ -731,7 +726,6 @@
"reply_to": "Reply to", "reply_to": "Reply to",
"mentions": "Mentions", "mentions": "Mentions",
"replies_list": "Replies:", "replies_list": "Replies:",
"replies_list_with_others": "Replies (+{numReplies} other): | Replies (+{numReplies} others):",
"mute_conversation": "Mute conversation", "mute_conversation": "Mute conversation",
"unmute_conversation": "Unmute conversation", "unmute_conversation": "Unmute conversation",
"status_unavailable": "Status unavailable", "status_unavailable": "Status unavailable",
@ -758,18 +752,7 @@
"attachment_stop_flash": "Stop Flash player", "attachment_stop_flash": "Stop Flash player",
"move_up": "Shift attachment left", "move_up": "Shift attachment left",
"move_down": "Shift attachment right", "move_down": "Shift attachment right",
"open_gallery": "Open gallery", "open_gallery": "Open gallery"
"thread_hide": "Hide this thread",
"thread_show": "Show this thread",
"thread_show_full": "Show everything under this thread ({numStatus} status in total, max depth {depth}) | Show everything under this thread ({numStatus} statuses in total, max depth {depth})",
"thread_show_full_with_icon": "{icon} {text}",
"thread_follow": "See the remaining part of this thread ({numStatus} status in total) | See the remaining part of this thread ({numStatus} statuses in total)",
"thread_follow_with_icon": "{icon} {text}",
"ancestor_follow": "See {numReplies} other reply under this status | See {numReplies} other replies under this status",
"ancestor_follow_with_icon": "{icon} {text}",
"show_all_conversation_with_icon": "{icon} {text}",
"show_all_conversation": "Show full conversation ({numStatus} other status) | Show full conversation ({numStatus} other statuses)",
"show_only_conversation_under_this": "Only show replies to this status"
}, },
"user_card": { "user_card": {
"approve": "Approve", "approve": "Approve",

View file

@ -11,6 +11,7 @@ import statusesModule from './modules/statuses.js'
import usersModule from './modules/users.js' import usersModule from './modules/users.js'
import apiModule from './modules/api.js' import apiModule from './modules/api.js'
import configModule from './modules/config.js' import configModule from './modules/config.js'
import serverSideConfigModule from './modules/serverSideConfig.js'
import shoutModule from './modules/shout.js' import shoutModule from './modules/shout.js'
import oauthModule from './modules/oauth.js' import oauthModule from './modules/oauth.js'
import authFlowModule from './modules/auth_flow.js' import authFlowModule from './modules/auth_flow.js'
@ -90,6 +91,7 @@ const persistedStateOptions = {
users: usersModule, users: usersModule,
api: apiModule, api: apiModule,
config: configModule, config: configModule,
serverSideConfig: serverSideConfigModule,
shout: shoutModule, shout: shoutModule,
oauth: oauthModule, oauth: oauthModule,
authFlow: authFlowModule, authFlow: authFlowModule,

View file

@ -18,6 +18,7 @@ export const multiChoiceProperties = [
] ]
export const defaultState = { export const defaultState = {
expertLevel: 0, // used to track which settings to show and hide
colors: {}, colors: {},
theme: undefined, theme: undefined,
customTheme: undefined, customTheme: undefined,
@ -43,7 +44,7 @@ export const defaultState = {
alwaysShowNewPostButton: false, alwaysShowNewPostButton: false,
autohideFloatingPostButton: false, autohideFloatingPostButton: false,
pauseOnUnfocused: true, pauseOnUnfocused: true,
stopGifs: false, stopGifs: true,
replyVisibility: 'all', replyVisibility: 'all',
notificationVisibility: { notificationVisibility: {
follows: true, follows: true,
@ -71,7 +72,7 @@ export const defaultState = {
hideFilteredStatuses: undefined, // instance default hideFilteredStatuses: undefined, // instance default
playVideosInModal: false, playVideosInModal: false,
useOneClickNsfw: false, useOneClickNsfw: false,
useContainFit: false, useContainFit: true,
greentext: undefined, // instance default greentext: undefined, // instance default
useAtIcon: undefined, // instance default useAtIcon: undefined, // instance default
mentionLinkDisplay: undefined, // instance default mentionLinkDisplay: undefined, // instance default

View file

@ -0,0 +1,119 @@
import { get, set } from 'lodash'
export const settingsMapGet = {
'defaultScope': 'source.privacy',
'defaultNSFW': 'source.sensitive', // BROKEN: pleroma/pleroma#2837
'stripRichContent': 'source.pleroma.no_rich_text',
// Privacy
'locked': 'locked',
'acceptChatMessages': 'pleroma.accepts_chat_messages',
'allowFollowingMove': 'pleroma.allow_following_move',
'discoverable': 'source.discoverable',
'hideFavorites': 'pleroma.hide_favorites',
'hideFollowers': 'pleroma.hide_followers',
'hideFollows': 'pleroma.hide_follows',
'hideFollowersCount': 'pleroma.hide_followers_count',
'hideFollowsCount': 'pleroma.hide_follows_count',
// NotificationSettingsAPIs
'webPushHideContents': 'pleroma.notification_settings.hide_notification_contents',
'blockNotificationsFromStrangers': 'pleroma.notification_settings.block_from_strangers'
}
export const settingsMapSet = {
'defaultScope': 'source.privacy',
'defaultNSFW': 'source.sensitive',
'stripRichContent': 'no_rich_text',
// Privacy
'locked': 'locked',
'acceptChatMessages': 'accepts_chat_messages',
'allowFollowingMove': 'allow_following_move',
'discoverable': 'source.discoverable',
'hideFavorites': 'hide_favorites',
'hideFollowers': 'hide_followers',
'hideFollows': 'hide_follows',
'hideFollowersCount': 'hide_followers_count',
'hideFollowsCount': 'hide_follows_count',
// NotificationSettingsAPIs
'webPushHideContents': 'hide_notification_contents',
'blockNotificationsFromStrangers': 'block_from_strangers'
}
export const customAPIs = {
__defaultApi: 'updateProfile',
'webPushHideContents': 'updateNotificationSettings',
'blockNotificationsFromStrangers': 'updateNotificationSettings'
}
export const defaultState = Object.fromEntries(Object.keys(settingsMapGet).map(key => [key, null]))
const serverSideConfig = {
state: { ...defaultState },
mutations: {
confirmServerSideOption (state, { name, value }) {
set(state, name, value)
},
wipeServerSideOption (state, { name }) {
set(state, name, null)
},
wipeAllServerSideOptions (state) {
Object.keys(settingsMapGet).forEach(key => {
set(state, key, null)
})
},
// Set the settings based on their path location
setCurrentUser (state, user) {
Object.entries(settingsMapGet).forEach(([name, path]) => {
set(state, name, get(user._original, path))
})
}
},
actions: {
setServerSideOption ({ rootState, state, commit, dispatch }, { name, value }) {
const oldValue = get(state, name)
const params = {}
const path = settingsMapSet[name]
if (!path) throw new Error('Invalid server-side setting')
commit('wipeServerSideOption', { name })
const customAPIName = customAPIs[name] || customAPIs.__defaultApi
const api = rootState.api.backendInteractor[customAPIName]
let prefix = ''
switch (customAPIName) {
case 'updateNotificationSettings':
prefix = 'settings.'
break
default:
prefix = 'params.'
break
}
set(params, prefix + path, value)
api(params)
.then((result) => {
switch (customAPIName) {
case 'updateNotificationSettings':
console.log(result)
if (result.status === 'success') {
commit('confirmServerSideOption', { name, value })
} else {
commit('confirmServerSideOption', { name, value: oldValue })
}
break
default:
commit('addNewUsers', [result])
commit('setCurrentUser', result)
break
}
console.log(state)
})
.catch((e) => {
console.warn('Error setting server-side option:', e)
commit('confirmServerSideOption', { name, value: oldValue })
})
},
logout ({ commit }) {
commit('wipeAllServerSideOptions')
}
}
}
export default serverSideConfig

View file

@ -44,6 +44,7 @@ export const parseUser = (data) => {
const mastoShort = masto && !data.hasOwnProperty('avatar') const mastoShort = masto && !data.hasOwnProperty('avatar')
output.id = String(data.id) output.id = String(data.id)
output._original = data // used for server-side settings
if (masto) { if (masto) {
output.screen_name = data.acct output.screen_name = data.acct