Merge branch 'setttingssync' into shigusegubu-themes3

This commit is contained in:
Henry Jameson 2026-03-24 21:42:40 +02:00
commit 94570af748
72 changed files with 703 additions and 559 deletions

View file

@ -26,8 +26,8 @@ import { useI18nStore } from 'src/stores/i18n.js'
import { useInstanceStore } from 'src/stores/instance.js' import { useInstanceStore } from 'src/stores/instance.js'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js' import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useInterfaceStore } from 'src/stores/interface.js' import { useInterfaceStore } from 'src/stores/interface.js'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { useShoutStore } from 'src/stores/shout.js' import { useShoutStore } from 'src/stores/shout.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import messages from 'src/i18n/messages' import messages from 'src/i18n/messages'
import localeService from 'src/services/locale/locale.service.js' import localeService from 'src/services/locale/locale.service.js'
@ -80,7 +80,7 @@ export default {
}, },
created() { created() {
// Load the locale from the storage // Load the locale from the storage
const value = useSyncConfigStore().mergedConfig.interfaceLanguage const value = useMergedConfigStore().mergedConfig.interfaceLanguage
useI18nStore().setLanguage(value) useI18nStore().setLanguage(value)
useEmojiStore().loadUnicodeEmojiData(value) useEmojiStore().loadUnicodeEmojiData(value)
@ -132,7 +132,7 @@ export default {
] ]
}, },
navClasses() { navClasses() {
const { navbarColumnStretch } = useSyncConfigStore().mergedConfig const { navbarColumnStretch } = useMergedConfigStore().mergedConfig
return [ return [
'-' + this.layoutType, '-' + this.layoutType,
...(navbarColumnStretch ? ['-column-stretch'] : []), ...(navbarColumnStretch ? ['-column-stretch'] : []),
@ -145,7 +145,7 @@ export default {
return this.currentUser.background_image return this.currentUser.background_image
}, },
instanceBackground() { instanceBackground() {
return useSyncConfigStore().mergedConfig.hideInstanceWallpaper return useMergedConfigStore().mergedConfig.hideInstanceWallpaper
? null ? null
: this.instanceBackgroundUrl : this.instanceBackgroundUrl
}, },
@ -172,19 +172,21 @@ export default {
if (this.isChats) return false if (this.isChats) return false
if (this.isListEdit) return false if (this.isListEdit) return false
return ( return (
useSyncConfigStore().mergedConfig.alwaysShowNewPostButton || useMergedConfigStore().mergedConfig.alwaysShowNewPostButton ||
this.layoutType === 'mobile' this.layoutType === 'mobile'
) )
}, },
shoutboxPosition() { shoutboxPosition() {
return useSyncConfigStore().mergedConfig.alwaysShowNewPostButton || false return (
useMergedConfigStore().mergedConfig.alwaysShowNewPostButton || false
)
}, },
hideShoutbox() { hideShoutbox() {
return useSyncConfigStore().mergedConfig.hideShoutbox return useMergedConfigStore().mergedConfig.hideShoutbox
}, },
reverseLayout() { reverseLayout() {
const { thirdColumnMode, sidebarRight: reverseSetting } = const { thirdColumnMode, sidebarRight: reverseSetting } =
useSyncConfigStore().mergedConfig useMergedConfigStore().mergedConfig
if (this.layoutType !== 'wide') { if (this.layoutType !== 'wide') {
return reverseSetting return reverseSetting
} else { } else {
@ -194,10 +196,10 @@ export default {
} }
}, },
noSticky() { noSticky() {
return useSyncConfigStore().mergedConfig.disableStickyHeaders return useMergedConfigStore().mergedConfig.disableStickyHeaders
}, },
showScrollbars() { showScrollbars() {
return useSyncConfigStore().mergedConfig.showScrollbars return useMergedConfigStore().mergedConfig.showScrollbars
}, },
scrollParent() { scrollParent() {
return window /* this.$refs.appContentRef */ return window /* this.$refs.appContentRef */
@ -205,10 +207,10 @@ export default {
showInstanceSpecificPanel() { showInstanceSpecificPanel() {
return ( return (
this.instanceSpecificPanelPresent && this.instanceSpecificPanelPresent &&
!useSyncConfigStore().mergedConfig.hideISP !useMergedConfigStore().mergedConfig.hideISP
) )
}, },
...mapState(useSyncConfigStore, ['mergedConfig']), ...mapState(useMergedConfigStore, ['mergedConfig']),
...mapState(useInterfaceStore, [ ...mapState(useInterfaceStore, [
'themeApplied', 'themeApplied',
'styleDataUsed', 'styleDataUsed',

View file

@ -33,14 +33,15 @@ import { useInstanceStore } from 'src/stores/instance.js'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js' import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useInterfaceStore } from 'src/stores/interface.js' import { useInterfaceStore } from 'src/stores/interface.js'
import { useLocalConfigStore } from 'src/stores/local_config.js' import { useLocalConfigStore } from 'src/stores/local_config.js'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { useOAuthStore } from 'src/stores/oauth' import { useOAuthStore } from 'src/stores/oauth'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { useUserHighlightStore } from 'src/stores/user_highlight.js' import { useUserHighlightStore } from 'src/stores/user_highlight.js'
import VBodyScrollLock from 'src/directives/body_scroll_lock' import VBodyScrollLock from 'src/directives/body_scroll_lock'
import { import {
instanceDefaultConfigDefinitions, INSTANCE_DEFAULT_CONFIG_DEFINITIONS,
instanceIdentityDefaultDefinitions, INSTANCE_IDENTITY_DEFAULT_DEFINITIONS,
} from 'src/modules/default_config_state.js' } from 'src/modules/default_config_state.js'
let staticInitialResults = null let staticInitialResults = null
@ -83,7 +84,7 @@ const getInstanceConfig = async ({ store }) => {
const res = await preloadFetch('/api/v1/instance') const res = await preloadFetch('/api/v1/instance')
if (res.ok) { if (res.ok) {
const data = await res.json() const data = await res.json()
const textlimit = data.max_toot_chars const textLimit = data.max_toot_chars
const vapidPublicKey = data.pleroma.vapid_public_key const vapidPublicKey = data.pleroma.vapid_public_key
useInstanceCapabilitiesStore().set( useInstanceCapabilitiesStore().set(
@ -91,8 +92,8 @@ const getInstanceConfig = async ({ store }) => {
data.pleroma, data.pleroma,
) )
useInstanceStore().set({ useInstanceStore().set({
path: 'textlimit', path: 'limits.textLimit',
value: textlimit, value: textLimit,
}) })
useInstanceStore().set({ useInstanceStore().set({
path: 'accountApprovalRequired', path: 'accountApprovalRequired',
@ -169,22 +170,19 @@ const setSettings = async ({ apiConfig, staticConfig, store }) => {
config = Object.assign({}, staticConfig, apiConfig) config = Object.assign({}, staticConfig, apiConfig)
} }
const copyInstanceOption = ({ source, definition = { required: true }, destination }) => { Object.keys(INSTANCE_IDENTITY_DEFAULT_DEFINITIONS).forEach((source) =>
const value = config[source] useInstanceStore().set({
let { required, type, default: defaultValue } = definition value: config[source],
if (type == null && defaultValue != null) type = typeof defaultValue path: `instanceIdentity.${source}`,
if (required && value == null) return }),
if (type != null && typeof value !== type) return )
useInstanceStore().set({ path: destination, value }) Object.keys(INSTANCE_DEFAULT_CONFIG_DEFINITIONS).forEach((source) =>
} useInstanceStore().set({
value: config[source],
Object.entries(instanceIdentityDefaultDefinitions) path: `prefsStorage.${source}`,
.map(([source, definition]) => ({ source, definition, destination: `instanceIdentity.${source}` })) }),
.forEach(copyInstanceOption) )
Object.keys(instanceDefaultConfigDefinitions)
.map(([source, definition]) => ({ source, definition, destination: `prefsStorage.${source}` }))
.forEach(copyInstanceOption)
useAuthFlowStore().setInitialStrategy(config.loginMethod) useAuthFlowStore().setInitialStrategy(config.loginMethod)
} }
@ -194,7 +192,7 @@ const getTOS = async ({ store }) => {
const res = await window.fetch('/static/terms-of-service.html') const res = await window.fetch('/static/terms-of-service.html')
if (res.ok) { if (res.ok) {
const html = await res.text() const html = await res.text()
useInstanceStore().set({ name: 'instanceIdentity.tos', value: html }) useInstanceStore().set({ path: 'instanceIdentity.tos', value: html })
} else { } else {
throw res throw res
} }
@ -530,6 +528,7 @@ const afterStoreSetup = async ({ pinia, store, storageError, i18n }) => {
useInterfaceStore().setLayoutWidth(windowWidth()) useInterfaceStore().setLayoutWidth(windowWidth())
useInterfaceStore().setLayoutHeight(windowHeight()) useInterfaceStore().setLayoutHeight(windowHeight())
window.syncConfig = useSyncConfigStore() window.syncConfig = useSyncConfigStore()
window.mergedConfig = useMergedConfigStore()
window.localConfig = useLocalConfigStore() window.localConfig = useLocalConfigStore()
window.highlightConfig = useUserHighlightStore() window.highlightConfig = useUserHighlightStore()
@ -543,7 +542,7 @@ const afterStoreSetup = async ({ pinia, store, storageError, i18n }) => {
typeof overrides.target !== 'undefined' typeof overrides.target !== 'undefined'
? overrides.target ? overrides.target
: window.location.origin : window.location.origin
useInstanceStore().set({ name: 'server', value: server }) useInstanceStore().set({ path: 'server', value: server })
await setConfig({ store }) await setConfig({ store })
try { try {
@ -557,7 +556,7 @@ const afterStoreSetup = async ({ pinia, store, storageError, i18n }) => {
return Promise.reject(e) return Promise.reject(e)
} }
applyStyleConfig(useSyncConfigStore().mergedConfig, i18n.global) applyStyleConfig(useMergedConfigStore().mergedConfig, i18n.global)
// Now we can try getting the server settings and logging in // Now we can try getting the server settings and logging in
// Most of these are preloaded into the index.html so blocking is minimized // Most of these are preloaded into the index.html so blocking is minimized

View file

@ -5,7 +5,7 @@ import StaffPanel from '../staff_panel/staff_panel.vue'
import TermsOfServicePanel from '../terms_of_service_panel/terms_of_service_panel.vue' import TermsOfServicePanel from '../terms_of_service_panel/terms_of_service_panel.vue'
import { useInstanceStore } from 'src/stores/instance.js' import { useInstanceStore } from 'src/stores/instance.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useMergedConfigStore } from 'src/stores/merged_config.js'
const About = { const About = {
components: { components: {
@ -22,7 +22,7 @@ const About = {
showInstanceSpecificPanel() { showInstanceSpecificPanel() {
return ( return (
useInstanceStore().instanceIdentity.showInstanceSpecificPanel && useInstanceStore().instanceIdentity.showInstanceSpecificPanel &&
!useSyncConfigStore().mergedConfig.hideISP && !useMergedConfigStore().mergedConfig.hideISP &&
useInstanceStore().instanceIdentity.instanceSpecificPanelContent useInstanceStore().instanceIdentity.instanceSpecificPanelContent
) )
}, },

View file

@ -7,8 +7,8 @@ import Popover from '../popover/popover.vue'
import ProgressButton from '../progress_button/progress_button.vue' import ProgressButton from '../progress_button/progress_button.vue'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js' import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { useReportsStore } from 'src/stores/reports' import { useReportsStore } from 'src/stores/reports'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { library } from '@fortawesome/fontawesome-svg-core' import { library } from '@fortawesome/fontawesome-svg-core'
import { faEllipsisV } from '@fortawesome/free-solid-svg-icons' import { faEllipsisV } from '@fortawesome/free-solid-svg-icons'
@ -90,10 +90,10 @@ const AccountActions = {
}, },
computed: { computed: {
shouldConfirmBlock() { shouldConfirmBlock() {
return useSyncConfigStore().mergedConfig.modalOnBlock return useMergedConfigStore().mergedConfig.modalOnBlock
}, },
shouldConfirmRemoveUserFromFollowers() { shouldConfirmRemoveUserFromFollowers() {
return useSyncConfigStore().mergedConfig.modalOnRemoveUserFromFollowers return useMergedConfigStore().mergedConfig.modalOnRemoveUserFromFollowers
}, },
...mapState(useInstanceCapabilitiesStore, [ ...mapState(useInstanceCapabilitiesStore, [
'blockExpiration', 'blockExpiration',

View file

@ -8,7 +8,7 @@ import VideoAttachment from '../video_attachment/video_attachment.vue'
import { useInstanceStore } from 'src/stores/instance.js' import { useInstanceStore } from 'src/stores/instance.js'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js' import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useMediaViewerStore } from 'src/stores/media_viewer' import { useMediaViewerStore } from 'src/stores/media_viewer'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { library } from '@fortawesome/fontawesome-svg-core' import { library } from '@fortawesome/fontawesome-svg-core'
import { import {
@ -58,8 +58,8 @@ const Attachment = {
localDescription: this.description || this.attachment.description, localDescription: this.description || this.attachment.description,
nsfwImage: nsfwImage:
useInstanceStore().instanceIdentity.nsfwCensorImage || nsfwImage, useInstanceStore().instanceIdentity.nsfwCensorImage || nsfwImage,
hideNsfwLocal: useSyncConfigStore().mergedConfig.hideNsfw, hideNsfwLocal: useMergedConfigStore().mergedConfig.hideNsfw,
preloadImage: useSyncConfigStore().mergedConfig.preloadImage, preloadImage: useMergedConfigStore().mergedConfig.preloadImage,
loading: false, loading: false,
img: this.attachment.type === 'image' && document.createElement('img'), img: this.attachment.type === 'image' && document.createElement('img'),
modalOpen: false, modalOpen: false,
@ -91,7 +91,7 @@ const Attachment = {
return this.size === 'hide' return this.size === 'hide'
}, },
useContainFit() { useContainFit() {
return useSyncConfigStore().mergedConfig.useContainFit return this.mergedConfig.useContainFit
}, },
placeholderName() { placeholderName() {
if (this.attachment.description === '' || !this.attachment.description) { if (this.attachment.description === '' || !this.attachment.description) {
@ -134,7 +134,7 @@ const Attachment = {
videoTag() { videoTag() {
return this.useModal ? 'button' : 'span' return this.useModal ? 'button' : 'span'
}, },
...mapState(useSyncConfigStore, ['mergedConfig']), ...mapState(useMergedConfigStore, ['mergedConfig']),
}, },
watch: { watch: {
'attachment.description'(newVal) { 'attachment.description'(newVal) {

View file

@ -12,7 +12,7 @@ import UserAvatar from '../user_avatar/user_avatar.vue'
import { useInstanceStore } from 'src/stores/instance.js' import { useInstanceStore } from 'src/stores/instance.js'
import { useInterfaceStore } from 'src/stores/interface' import { useInterfaceStore } from 'src/stores/interface'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { library } from '@fortawesome/fontawesome-svg-core' import { library } from '@fortawesome/fontawesome-svg-core'
import { faEllipsisH, faTimes } from '@fortawesome/free-solid-svg-icons' import { faEllipsisH, faTimes } from '@fortawesome/free-solid-svg-icons'
@ -86,7 +86,7 @@ const ChatMessage = {
return { left: 50 } return { left: 50 }
} }
}, },
...mapPiniaState(useSyncConfigStore, ['mergedConfig', 'findUser']), ...mapPiniaState(useMergedConfigStore, ['mergedConfig', 'findUser']),
}, },
data() { data() {
return { return {

View file

@ -3,7 +3,7 @@ import { mapState } from 'pinia'
import Select from 'src/components/select/select.vue' import Select from 'src/components/select/select.vue'
import ConfirmModal from './confirm_modal.vue' import ConfirmModal from './confirm_modal.vue'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useMergedConfigStore } from 'src/stores/merged_config.js'
export default { export default {
props: ['type', 'user', 'status'], props: ['type', 'user', 'status'],
@ -45,7 +45,7 @@ export default {
} }
} }
}, },
...mapState(useSyncConfigStore, ['mergedConfig']), ...mapState(useMergedConfigStore, ['mergedConfig']),
}, },
methods: { methods: {
optionallyPrompt() { optionallyPrompt() {

View file

@ -9,7 +9,7 @@ import Status from '../status/status.vue'
import ThreadTree from '../thread_tree/thread_tree.vue' import ThreadTree from '../thread_tree/thread_tree.vue'
import { useInterfaceStore } from 'src/stores/interface' import { useInterfaceStore } from 'src/stores/interface'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { library } from '@fortawesome/fontawesome-svg-core' import { library } from '@fortawesome/fontawesome-svg-core'
import { import {
@ -82,7 +82,7 @@ const conversation = {
// maxDepthInThread = max number of depths that is *visible* // maxDepthInThread = max number of depths that is *visible*
// since our depth starts with 0 and "showing" means "showing children" // since our depth starts with 0 and "showing" means "showing children"
// there is a -2 here // there is a -2 here
const maxDepth = useSyncConfigStore().mergedConfig.maxDepthInThread - 2 const maxDepth = this.mergedConfig.maxDepthInThread - 2
return maxDepth >= 1 ? maxDepth : 1 return maxDepth >= 1 ? maxDepth : 1
}, },
streamingEnabled() { streamingEnabled() {
@ -92,22 +92,22 @@ const conversation = {
) )
}, },
displayStyle() { displayStyle() {
return useSyncConfigStore().mergedConfig.conversationDisplay return this.mergedConfig.conversationDisplay
}, },
isTreeView() { isTreeView() {
return !this.isLinearView return !this.isLinearView
}, },
treeViewIsSimple() { treeViewIsSimple() {
return !useSyncConfigStore().mergedConfig.conversationTreeAdvanced return !this.mergedConfig.conversationTreeAdvanced
}, },
isLinearView() { isLinearView() {
return this.displayStyle === 'linear' return this.displayStyle === 'linear'
}, },
shouldFadeAncestors() { shouldFadeAncestors() {
return useSyncConfigStore().mergedConfig.conversationTreeFadeAncestors return this.mergedConfig.conversationTreeFadeAncestors
}, },
otherRepliesButtonPosition() { otherRepliesButtonPosition() {
return useSyncConfigStore().mergedConfig.conversationOtherRepliesButton return this.mergedConfig.conversationOtherRepliesButton
}, },
showOtherRepliesButtonBelowStatus() { showOtherRepliesButtonBelowStatus() {
return this.otherRepliesButtonPosition === 'below' return this.otherRepliesButtonPosition === 'below'
@ -393,7 +393,7 @@ const conversation = {
maybeHighlight() { maybeHighlight() {
return this.isExpanded ? this.highlight : null return this.isExpanded ? this.highlight : null
}, },
...mapPiniaState(useSyncConfigStore, ['mergedConfig']), ...mapPiniaState(useMergedConfigStore, ['mergedConfig']),
...mapState({ ...mapState({
mastoUserSocketStatus: (state) => state.api.mastoUserSocketStatus, mastoUserSocketStatus: (state) => state.api.mastoUserSocketStatus,
}), }),

View file

@ -5,7 +5,7 @@ import ConfirmModal from '../confirm_modal/confirm_modal.vue'
import { useInstanceStore } from 'src/stores/instance.js' import { useInstanceStore } from 'src/stores/instance.js'
import { useInterfaceStore } from 'src/stores/interface' import { useInterfaceStore } from 'src/stores/interface'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { library } from '@fortawesome/fontawesome-svg-core' import { library } from '@fortawesome/fontawesome-svg-core'
import { import {
@ -97,7 +97,7 @@ export default {
return this.$store.state.users.currentUser return this.$store.state.users.currentUser
}, },
shouldConfirmLogout() { shouldConfirmLogout() {
return useSyncConfigStore().mergedConfig.modalOnLogout return useMergedConfigStore().mergedConfig.modalOnLogout
}, },
}, },
methods: { methods: {

View file

@ -1,4 +1,4 @@
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useMergedConfigStore } from 'src/stores/merged_config.js'
const DialogModal = { const DialogModal = {
props: { props: {
@ -15,7 +15,7 @@ const DialogModal = {
}, },
computed: { computed: {
mobileCenter() { mobileCenter() {
return useSyncConfigStore().mergedConfig.modalMobileCenter return useMergedConfigStore().mergedConfig.modalMobileCenter
}, },
}, },
} }

View file

@ -6,7 +6,7 @@ import Gallery from 'src/components/gallery/gallery.vue'
import PostStatusForm from 'src/components/post_status_form/post_status_form.vue' import PostStatusForm from 'src/components/post_status_form/post_status_form.vue'
import StatusContent from 'src/components/status_content/status_content.vue' import StatusContent from 'src/components/status_content/status_content.vue'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { library } from '@fortawesome/fontawesome-svg-core' import { library } from '@fortawesome/fontawesome-svg-core'
import { faPollH } from '@fortawesome/free-solid-svg-icons' import { faPollH } from '@fortawesome/free-solid-svg-icons'
@ -59,7 +59,7 @@ const Draft = {
: undefined : undefined
}, },
localCollapseSubjectDefault() { localCollapseSubjectDefault() {
return useSyncConfigStore().mergedConfig.collapseMessageWithSubject return useMergedConfigStore().mergedConfig.collapseMessageWithSubject
}, },
nsfwClickthrough() { nsfwClickthrough() {
if (!this.draft.nsfw) { if (!this.draft.nsfw) {

View file

@ -1,6 +1,6 @@
import DialogModal from 'src/components/dialog_modal/dialog_modal.vue' import DialogModal from 'src/components/dialog_modal/dialog_modal.vue'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useMergedConfigStore } from 'src/stores/merged_config.js'
const DraftCloser = { const DraftCloser = {
data() { data() {
@ -14,10 +14,10 @@ const DraftCloser = {
emits: ['save', 'discard'], emits: ['save', 'discard'],
computed: { computed: {
action() { action() {
if (useSyncConfigStore().mergedConfig.autoSaveDraft) { if (useMergedConfigStore().mergedConfig.autoSaveDraft) {
return 'save' return 'save'
} else { } else {
return useSyncConfigStore().mergedConfig.unsavedPostAction return useMergedConfigStore().mergedConfig.unsavedPostAction
} }
}, },
shouldConfirm() { shouldConfirm() {

View file

@ -9,7 +9,7 @@ import genRandomSeed from '../../services/random_seed/random_seed.service.js'
import EmojiPicker from '../emoji_picker/emoji_picker.vue' import EmojiPicker from '../emoji_picker/emoji_picker.vue'
import UnicodeDomainIndicator from '../unicode_domain_indicator/unicode_domain_indicator.vue' import UnicodeDomainIndicator from '../unicode_domain_indicator/unicode_domain_indicator.vue'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { library } from '@fortawesome/fontawesome-svg-core' import { library } from '@fortawesome/fontawesome-svg-core'
import { faSmileBeam } from '@fortawesome/free-regular-svg-icons' import { faSmileBeam } from '@fortawesome/free-regular-svg-icons'
@ -133,10 +133,10 @@ const EmojiInput = {
}, },
computed: { computed: {
padEmoji() { padEmoji() {
return useSyncConfigStore().mergedConfig.padEmoji return useMergedConfigStore().mergedConfig.padEmoji
}, },
defaultCandidateIndex() { defaultCandidateIndex() {
return useSyncConfigStore().mergedConfig.autocompleteSelect ? 0 : -1 return useMergedConfigStore().mergedConfig.autocompleteSelect ? 0 : -1
}, },
preText() { preText() {
return this.modelValue.slice(0, this.caret) return this.modelValue.slice(0, this.caret)
@ -165,7 +165,7 @@ const EmojiInput = {
}, },
languages() { languages() {
return ensureFinalFallback( return ensureFinalFallback(
useSyncConfigStore().mergedConfig.interfaceLanguage, useMergedConfigStore().mergedConfig.interfaceLanguage,
) )
}, },
maybeLocalizedEmojiNamesAndKeywords() { maybeLocalizedEmojiNamesAndKeywords() {

View file

@ -8,7 +8,7 @@ import StillImage from '../still-image/still-image.vue'
import { useEmojiStore } from 'src/stores/emoji.js' import { useEmojiStore } from 'src/stores/emoji.js'
import { useInstanceStore } from 'src/stores/instance.js' import { useInstanceStore } from 'src/stores/instance.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { library } from '@fortawesome/fontawesome-svg-core' import { library } from '@fortawesome/fontawesome-svg-core'
import { import {
@ -341,7 +341,7 @@ const EmojiPicker = {
this.$nextTick(() => { this.$nextTick(() => {
this.updateEmojiSize() this.updateEmojiSize()
}) })
return useSyncConfigStore().mergedConfig.fontSize return useMergedConfigStore().mergedConfig.fontSize
}, },
emojiHeight() { emojiHeight() {
return this.emojiSize return this.emojiSize
@ -406,7 +406,7 @@ const EmojiPicker = {
}, },
languages() { languages() {
return ensureFinalFallback( return ensureFinalFallback(
useSyncConfigStore().mergedConfig.interfaceLanguage, useMergedConfigStore().mergedConfig.interfaceLanguage,
) )
}, },
maybeLocalizedEmojiName() { maybeLocalizedEmojiName() {

View file

@ -3,7 +3,7 @@ import { mapGetters } from 'vuex'
import { useAnnouncementsStore } from 'src/stores/announcements.js' import { useAnnouncementsStore } from 'src/stores/announcements.js'
import { useInterfaceStore } from 'src/stores/interface.js' import { useInterfaceStore } from 'src/stores/interface.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { library } from '@fortawesome/fontawesome-svg-core' import { library } from '@fortawesome/fontawesome-svg-core'
import { import {
@ -52,10 +52,11 @@ const ExtraNotifications = {
currentUser() { currentUser() {
return this.$store.state.users.currentUser return this.$store.state.users.currentUser
}, },
...mapGetters(['unreadChatCount', 'followRequestCount', 'mergedConfig']), ...mapGetters(['unreadChatCount', 'followRequestCount']),
...mapPiniaState(useAnnouncementsStore, { ...mapPiniaState(useAnnouncementsStore, {
unreadAnnouncementCount: 'unreadAnnouncementCount', unreadAnnouncementCount: 'unreadAnnouncementCount',
}), }),
...mapPiniaState(useMergedConfigStore, ['mergedConfig']),
}, },
methods: { methods: {
openNotificationSettings() { openNotificationSettings() {

View file

@ -15,7 +15,7 @@ const FeaturesPanel = {
'mediaProxyAvailable', 'mediaProxyAvailable',
]), ]),
...mapState(useInstanceStore, { ...mapState(useInstanceStore, {
textlimit: (store) => store.limits.textlimit, textLimit: (store) => store.limits.textLimit,
uploadlimit: (store) => uploadlimit: (store) =>
fileSizeFormatService.fileSizeFormat(store.limits.uploadlimit), fileSizeFormatService.fileSizeFormat(store.limits.uploadlimit),
}), }),

View file

@ -24,7 +24,7 @@
{{ $t('features_panel.media_proxy') }} {{ $t('features_panel.media_proxy') }}
</li> </li>
<li>{{ $t('features_panel.scope_options') }}</li> <li>{{ $t('features_panel.scope_options') }}</li>
<li>{{ $t('features_panel.text_limit') }} = {{ textlimit }}</li> <li>{{ $t('features_panel.text_limit') }} = {{ textLimit }}</li>
<li>{{ $t('features_panel.upload_limit') }} = {{ uploadlimit.num }} {{ $t('upload.file_size_units.' + uploadlimit.unit) }}</li> <li>{{ $t('features_panel.upload_limit') }} = {{ uploadlimit.num }} {{ $t('upload.file_size_units.' + uploadlimit.unit) }}</li>
</ul> </ul>
</div> </div>

View file

@ -4,7 +4,7 @@ import {
} from '../../services/follow_manipulate/follow_manipulate' } from '../../services/follow_manipulate/follow_manipulate'
import ConfirmModal from '../confirm_modal/confirm_modal.vue' import ConfirmModal from '../confirm_modal/confirm_modal.vue'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useMergedConfigStore } from 'src/stores/merged_config.js'
export default { export default {
props: ['relationship', 'user', 'labelFollowing', 'buttonClass'], props: ['relationship', 'user', 'labelFollowing', 'buttonClass'],
components: { components: {
@ -18,7 +18,7 @@ export default {
}, },
computed: { computed: {
shouldConfirmUnfollow() { shouldConfirmUnfollow() {
return useSyncConfigStore().mergedConfig.modalOnUnfollow return useMergedConfigStore().mergedConfig.modalOnUnfollow
}, },
isPressed() { isPressed() {
return this.inProgress || this.relationship.following return this.inProgress || this.relationship.following

View file

@ -2,7 +2,7 @@ import { notificationsFromStore } from '../../services/notification_utils/notifi
import BasicUserCard from '../basic_user_card/basic_user_card.vue' import BasicUserCard from '../basic_user_card/basic_user_card.vue'
import ConfirmModal from '../confirm_modal/confirm_modal.vue' import ConfirmModal from '../confirm_modal/confirm_modal.vue'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useMergedConfigStore } from 'src/stores/merged_config.js'
const FollowRequestCard = { const FollowRequestCard = {
props: ['user'], props: ['user'],
@ -78,7 +78,7 @@ const FollowRequestCard = {
}, },
computed: { computed: {
mergedConfig() { mergedConfig() {
return useSyncConfigStore().mergedConfig return useMergedConfigStore().mergedConfig
}, },
shouldConfirmApprove() { shouldConfirmApprove() {
return this.mergedConfig.modalOnApproveFollow return this.mergedConfig.modalOnApproveFollow

View file

@ -1,6 +1,6 @@
import { mapState } from 'pinia' import { mapState } from 'pinia'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useMergedConfigStore } from 'src/stores/merged_config.js'
const LinkPreview = { const LinkPreview = {
name: 'LinkPreview', name: 'LinkPreview',
@ -26,7 +26,7 @@ const LinkPreview = {
hideNsfwConfig() { hideNsfwConfig() {
return this.mergedConfig.hideNsfw return this.mergedConfig.hideNsfw
}, },
...mapState(useSyncConfigStore, ['mergedConfig']), ...mapState(useMergedConfigStore, ['mergedConfig']),
}, },
created() { created() {
if (this.useImage) { if (this.useImage) {

View file

@ -2,7 +2,7 @@ import fileSizeFormatService from '../../services/file_size_format/file_size_for
import statusPosterService from '../../services/status_poster/status_poster.service.js' import statusPosterService from '../../services/status_poster/status_poster.service.js'
import { useInstanceStore } from 'src/stores/instance.js' import { useInstanceStore } from 'src/stores/instance.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { library } from '@fortawesome/fontawesome-svg-core' import { library } from '@fortawesome/fontawesome-svg-core'
import { faCircleNotch, faUpload } from '@fortawesome/free-solid-svg-icons' import { faCircleNotch, faUpload } from '@fortawesome/free-solid-svg-icons'
@ -34,7 +34,7 @@ const mediaUpload = {
} }
// Skip if image compression is disabled // Skip if image compression is disabled
if (!useSyncConfigStore().mergedConfig.imageCompression) { if (!useMergedConfigStore().mergedConfig.imageCompression) {
return file return file
} }
@ -79,7 +79,7 @@ const mediaUpload = {
// Convert to WebP if supported and alwaysUseJpeg is false, otherwise JPEG // Convert to WebP if supported and alwaysUseJpeg is false, otherwise JPEG
const type = const type =
!useSyncConfigStore().mergedConfig.alwaysUseJpeg && supportsWebP !useMergedConfigStore().mergedConfig.alwaysUseJpeg && supportsWebP
? 'image/webp' ? 'image/webp'
: 'image/jpeg' : 'image/jpeg'
const extension = type === 'image/webp' ? '.webp' : '.jpg' const extension = type === 'image/webp' ? '.webp' : '.jpg'

View file

@ -9,7 +9,7 @@ import {
import UnicodeDomainIndicator from '../unicode_domain_indicator/unicode_domain_indicator.vue' import UnicodeDomainIndicator from '../unicode_domain_indicator/unicode_domain_indicator.vue'
import UserAvatar from '../user_avatar/user_avatar.vue' import UserAvatar from '../user_avatar/user_avatar.vue'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { useUserHighlightStore } from 'src/stores/user_highlight.js' import { useUserHighlightStore } from 'src/stores/user_highlight.js'
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator' import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
@ -160,7 +160,7 @@ const MentionLink = {
shouldFadeDomain() { shouldFadeDomain() {
return this.mergedConfig.mentionLinkFadeDomain return this.mergedConfig.mentionLinkFadeDomain
}, },
...mapPiniaState(useSyncConfigStore, ['mergedConfig']), ...mapPiniaState(useMergedConfigStore, ['mergedConfig']),
...mapPiniaState(useUserHighlightStore, ['highlight']), ...mapPiniaState(useUserHighlightStore, ['highlight']),
...mapState({ ...mapState({
currentUser: (state) => state.users.currentUser, currentUser: (state) => state.users.currentUser,

View file

@ -2,7 +2,7 @@ import { mapState } from 'pinia'
import MentionLink from 'src/components/mention_link/mention_link.vue' import MentionLink from 'src/components/mention_link/mention_link.vue'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useMergedConfigStore } from 'src/stores/merged_config.js'
export const MENTIONS_LIMIT = 5 export const MENTIONS_LIMIT = 5
@ -28,7 +28,7 @@ const MentionsLine = {
manyMentions() { manyMentions() {
return this.extraMentions.length > 0 return this.extraMentions.length > 0
}, },
...mapState(useSyncConfigStore, ['mergedConfig']), ...mapState(useMergedConfigStore, ['mergedConfig']),
}, },
methods: { methods: {
toggleShowMore() { toggleShowMore() {

View file

@ -13,7 +13,7 @@ import SideDrawer from '../side_drawer/side_drawer.vue'
import { useAnnouncementsStore } from 'src/stores/announcements.js' import { useAnnouncementsStore } from 'src/stores/announcements.js'
import { useInstanceStore } from 'src/stores/instance.js' import { useInstanceStore } from 'src/stores/instance.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { library } from '@fortawesome/fontawesome-svg-core' import { library } from '@fortawesome/fontawesome-svg-core'
import { import {
@ -54,14 +54,17 @@ const MobileNav = {
unseenNotifications() { unseenNotifications() {
return unseenNotificationsFromStore( return unseenNotificationsFromStore(
this.$store, this.$store,
useSyncConfigStore().mergedConfig.notificationVisibility, useMergedConfigStore().mergedConfig.notificationVisibility,
useSyncConfigStore().mergedConfig.ignoreInactionableSeen, useMergedConfigStore().mergedConfig.ignoreInactionableSeen,
) )
}, },
unseenNotificationsCount() { unseenNotificationsCount() {
return ( return (
this.unseenNotifications.length + this.unseenNotifications.length +
countExtraNotifications(this.$store, useSyncConfigStore().mergedConfig) countExtraNotifications(
this.$store,
useMergedConfigStore().mergedConfig,
)
) )
}, },
unseenCount() { unseenCount() {
@ -80,15 +83,15 @@ const MobileNav = {
return this.$route.name === 'chat' return this.$route.name === 'chat'
}, },
...mapState(useAnnouncementsStore, ['unreadAnnouncementCount']), ...mapState(useAnnouncementsStore, ['unreadAnnouncementCount']),
...mapState(useSyncConfigStore, { ...mapState(useMergedConfigStore, {
pinnedItems: (store) => pinnedItems: (store) =>
new Set(store.prefsStorage.collections.pinnedNavItems).has('chats'), new Set(store.prefsStorage.collections.pinnedNavItems).has('chats'),
}), }),
shouldConfirmLogout() { shouldConfirmLogout() {
return useSyncConfigStore().mergedConfig.modalOnLogout return useMergedConfigStore().mergedConfig.modalOnLogout
}, },
closingDrawerMarksAsSeen() { closingDrawerMarksAsSeen() {
return useSyncConfigStore().mergedConfig.closingDrawerMarksAsSeen return useMergedConfigStore().mergedConfig.closingDrawerMarksAsSeen
}, },
...mapGetters(['unreadChatCount']), ...mapGetters(['unreadChatCount']),
}, },

View file

@ -1,7 +1,7 @@
import { debounce } from 'lodash' import { debounce } from 'lodash'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { usePostStatusStore } from 'src/stores/post_status.js' import { usePostStatusStore } from 'src/stores/post_status.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { library } from '@fortawesome/fontawesome-svg-core' import { library } from '@fortawesome/fontawesome-svg-core'
import { faPen } from '@fortawesome/free-solid-svg-icons' import { faPen } from '@fortawesome/free-solid-svg-icons'
@ -46,10 +46,10 @@ const MobilePostStatusButton = {
) )
}, },
isPersistent() { isPersistent() {
return !!useSyncConfigStore().mergedConfig.alwaysShowNewPostButton return !!useMergedConfigStore().mergedConfig.alwaysShowNewPostButton
}, },
autohideFloatingPostButton() { autohideFloatingPostButton() {
return !!useSyncConfigStore().mergedConfig.autohideFloatingPostButton return !!useMergedConfigStore().mergedConfig.autohideFloatingPostButton
}, },
}, },
watch: { watch: {

View file

@ -17,7 +17,7 @@ import UserLink from '../user_link/user_link.vue'
import UserPopover from '../user_popover/user_popover.vue' import UserPopover from '../user_popover/user_popover.vue'
import { useInstanceStore } from 'src/stores/instance.js' import { useInstanceStore } from 'src/stores/instance.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { useUserHighlightStore } from 'src/stores/user_highlight.js' import { useUserHighlightStore } from 'src/stores/user_highlight.js'
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator' import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
@ -210,7 +210,7 @@ const Notification = {
return isStatusNotification(this.notification.type) return isStatusNotification(this.notification.type)
}, },
mergedConfig() { mergedConfig() {
return useSyncConfigStore().mergedConfig return useMergedConfigStore().mergedConfig
}, },
shouldConfirmApprove() { shouldConfirmApprove() {
return this.mergedConfig.modalOnApproveFollow return this.mergedConfig.modalOnApproveFollow

View file

@ -108,6 +108,7 @@
<script> <script>
import Popover from '../popover/popover.vue' import Popover from '../popover/popover.vue'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { library } from '@fortawesome/fontawesome-svg-core' import { library } from '@fortawesome/fontawesome-svg-core'
@ -119,7 +120,7 @@ export default {
components: { Popover }, components: { Popover },
computed: { computed: {
filters() { filters() {
return useSyncConfigStore().mergedConfig.notificationVisibility return useMergedConfigStore().mergedConfig.notificationVisibility
}, },
}, },
methods: { methods: {

View file

@ -17,7 +17,7 @@ import NotificationFilters from './notification_filters.vue'
import { useAnnouncementsStore } from 'src/stores/announcements.js' import { useAnnouncementsStore } from 'src/stores/announcements.js'
import { useInterfaceStore } from 'src/stores/interface.js' import { useInterfaceStore } from 'src/stores/interface.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { library } from '@fortawesome/fontawesome-svg-core' import { library } from '@fortawesome/fontawesome-svg-core'
import { import {
@ -78,7 +78,7 @@ const Notifications = {
unseenNotifications() { unseenNotifications() {
return unseenNotificationsFromStore( return unseenNotificationsFromStore(
this.$store, this.$store,
useSyncConfigStore().mergedConfig.notificationVisibility, useMergedConfigStore().mergedConfig.notificationVisibility,
) )
}, },
filteredNotifications() { filteredNotifications() {
@ -86,17 +86,17 @@ const Notifications = {
return [ return [
...filteredNotificationsFromStore( ...filteredNotificationsFromStore(
this.$store, this.$store,
useSyncConfigStore().mergedConfig.notificationVisibility, useMergedConfigStore().mergedConfig.notificationVisibility,
).filter((n) => this.shouldShowUnseen(n)), ).filter((n) => this.shouldShowUnseen(n)),
...filteredNotificationsFromStore( ...filteredNotificationsFromStore(
this.$store, this.$store,
useSyncConfigStore().mergedConfig.notificationVisibility, useMergedConfigStore().mergedConfig.notificationVisibility,
).filter((n) => !this.shouldShowUnseen(n)), ).filter((n) => !this.shouldShowUnseen(n)),
] ]
} else { } else {
return filteredNotificationsFromStore( return filteredNotificationsFromStore(
this.$store, this.$store,
useSyncConfigStore().mergedConfig.notificationVisibility, useMergedConfigStore().mergedConfig.notificationVisibility,
this.filterMode, this.filterMode,
) )
} }
@ -108,12 +108,12 @@ const Notifications = {
return this.unseenNotifications.length return this.unseenNotifications.length
}, },
ignoreInactionableSeen() { ignoreInactionableSeen() {
return useSyncConfigStore().mergedConfig.ignoreInactionableSeen return useMergedConfigStore().mergedConfig.ignoreInactionableSeen
}, },
extraNotificationsCount() { extraNotificationsCount() {
return countExtraNotifications( return countExtraNotifications(
this.$store, this.$store,
useSyncConfigStore().mergedConfig, useMergedConfigStore().mergedConfig,
) )
}, },
unseenCountTitle() { unseenCountTitle() {
@ -149,10 +149,10 @@ const Notifications = {
) )
}, },
noSticky() { noSticky() {
return useSyncConfigStore().mergedConfig.disableStickyHeaders return useMergedConfigStore().mergedConfig.disableStickyHeaders
}, },
unseenAtTop() { unseenAtTop() {
return useSyncConfigStore().mergedConfig.unseenAtTop return useMergedConfigStore().mergedConfig.unseenAtTop
}, },
showExtraNotifications() { showExtraNotifications() {
return !this.noExtra return !this.noExtra

View file

@ -4,8 +4,8 @@ import Timeago from 'components/timeago/timeago.vue'
import genRandomSeed from '../../services/random_seed/random_seed.service.js' import genRandomSeed from '../../services/random_seed/random_seed.service.js'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { usePollsStore } from 'src/stores/polls.js' import { usePollsStore } from 'src/stores/polls.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
export default { export default {
name: 'Poll', name: 'Poll',
@ -49,7 +49,7 @@ export default {
return (this.poll && this.poll.expired) || false return (this.poll && this.poll.expired) || false
}, },
expirationLabel() { expirationLabel() {
if (useSyncConfigStore().mergedConfig.useAbsoluteTimeFormat) { if (useMergedConfigStore().mergedConfig.useAbsoluteTimeFormat) {
return this.expired ? 'polls.expired_at' : 'polls.expires_at' return this.expired ? 'polls.expired_at' : 'polls.expires_at'
} else { } else {
return this.expired ? 'polls.expired' : 'polls.expires_in' return this.expired ? 'polls.expired' : 'polls.expires_in'

View file

@ -24,6 +24,7 @@ import { useInstanceStore } from 'src/stores/instance.js'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js' import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useInterfaceStore } from 'src/stores/interface.js' import { useInterfaceStore } from 'src/stores/interface.js'
import { useMediaViewerStore } from 'src/stores/media_viewer.js' import { useMediaViewerStore } from 'src/stores/media_viewer.js'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { pollFormToMasto } from 'src/services/poll/poll.service.js' import { pollFormToMasto } from 'src/services/poll/poll.service.js'
@ -163,7 +164,7 @@ const PostStatusForm = {
const preset = this.$route.query.message const preset = this.$route.query.message
let statusText = preset || '' let statusText = preset || ''
const { scopeCopy } = useSyncConfigStore().mergedConfig const { scopeCopy } = useMergedConfigStore().mergedConfig
const [statusType, refId] = typeAndRefId({ const [statusType, refId] = typeAndRefId({
replyTo: this.replyTo, replyTo: this.replyTo,
@ -193,7 +194,7 @@ const PostStatusForm = {
: this.$store.state.users.currentUser.default_scope : this.$store.state.users.currentUser.default_scope
const { postContentType: contentType, sensitiveByDefault } = const { postContentType: contentType, sensitiveByDefault } =
useSyncConfigStore().mergedConfig useMergedConfigStore().mergedConfig
statusParams = { statusParams = {
type: statusType, type: statusType,
@ -290,7 +291,7 @@ const PostStatusForm = {
return this.newStatus.spoilerText.length return this.newStatus.spoilerText.length
}, },
statusLengthLimit() { statusLengthLimit() {
return useInstanceStore().textlimit return useInstanceStore().limits.textLimit
}, },
hasStatusLengthLimit() { hasStatusLengthLimit() {
return this.statusLengthLimit > 0 return this.statusLengthLimit > 0
@ -324,7 +325,7 @@ const PostStatusForm = {
}, },
hideScopeNotice() { hideScopeNotice() {
return ( return (
this.disableNotice || useSyncConfigStore().mergedConfig.hideScopeNotice this.disableNotice || useMergedConfigStore().mergedConfig.hideScopeNotice
) )
}, },
pollContentError() { pollContentError() {
@ -380,7 +381,7 @@ const PostStatusForm = {
return this.newStatus.hasPoll return this.newStatus.hasPoll
}, },
shouldAutoSaveDraft() { shouldAutoSaveDraft() {
return useSyncConfigStore().mergedConfig.autoSaveDraft return useMergedConfigStore().mergedConfig.autoSaveDraft
}, },
autoSaveState() { autoSaveState() {
if (this.saveable) { if (this.saveable) {
@ -411,7 +412,7 @@ const PostStatusForm = {
) )
) )
}, },
...mapState(useSyncConfigStore, ['mergedConfig']), ...mapState(useMergedConfigStore, ['mergedConfig']),
...mapState(useInterfaceStore, { ...mapState(useInterfaceStore, {
mobileLayout: (store) => store.mobileLayout, mobileLayout: (store) => store.mobileLayout,
}), }),

View file

@ -4,6 +4,7 @@ import Popover from '../popover/popover.vue'
import { useInterfaceStore } from 'src/stores/interface.js' import { useInterfaceStore } from 'src/stores/interface.js'
import { useLocalConfigStore } from 'src/stores/local_config.js' import { useLocalConfigStore } from 'src/stores/local_config.js'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { library } from '@fortawesome/fontawesome-svg-core' import { library } from '@fortawesome/fontawesome-svg-core'
@ -32,7 +33,7 @@ const QuickFilterSettings = {
}, },
}, },
computed: { computed: {
...mapState(useSyncConfigStore, ['mergedConfig']), ...mapState(useMergedConfigStore, ['mergedConfig']),
...mapState(useInterfaceStore, { ...mapState(useInterfaceStore, {
mobileLayout: (state) => state.layoutType === 'mobile', mobileLayout: (state) => state.layoutType === 'mobile',
}), }),

View file

@ -4,6 +4,7 @@ import Popover from 'src/components/popover/popover.vue'
import QuickFilterSettings from 'src/components/quick_filter_settings/quick_filter_settings.vue' import QuickFilterSettings from 'src/components/quick_filter_settings/quick_filter_settings.vue'
import { useInterfaceStore } from 'src/stores/interface.js' import { useInterfaceStore } from 'src/stores/interface.js'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { library } from '@fortawesome/fontawesome-svg-core' import { library } from '@fortawesome/fontawesome-svg-core'
@ -30,7 +31,7 @@ const QuickViewSettings = {
}, },
}, },
computed: { computed: {
...mapState(useSyncConfigStore, ['mergedConfig']), ...mapState(useMergedConfigStore, ['mergedConfig']),
...mapState(useInterfaceStore, { ...mapState(useInterfaceStore, {
mobileLayout: (state) => state.layoutType === 'mobile', mobileLayout: (state) => state.layoutType === 'mobile',
}), }),

View file

@ -1,6 +1,6 @@
import ConfirmModal from '../confirm_modal/confirm_modal.vue' import ConfirmModal from '../confirm_modal/confirm_modal.vue'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useMergedConfigStore } from 'src/stores/merged_config.js'
export default { export default {
props: ['user', 'relationship'], props: ['user', 'relationship'],
@ -22,7 +22,7 @@ export default {
} }
}, },
shouldConfirmRemoveUserFromFollowers() { shouldConfirmRemoveUserFromFollowers() {
return useSyncConfigStore().mergedConfig.modalOnRemoveUserFromFollowers return useMergedConfigStore().mergedConfig.modalOnRemoveUserFromFollowers
}, },
}, },
methods: { methods: {

View file

@ -1,7 +1,7 @@
import Checkbox from 'src/components/checkbox/checkbox.vue' import Checkbox from 'src/components/checkbox/checkbox.vue'
import Setting from './setting.js' import Setting from './setting.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useMergedConfigStore } from 'src/stores/merged_config.js'
export default { export default {
...Setting, ...Setting,
@ -45,7 +45,7 @@ export default {
if (this.forceNew) return true if (this.forceNew) return true
if (!this.allowNew) return false if (!this.allowNew) return false
const isExpert = useSyncConfigStore().mergedConfig.expertLevel > 0 const isExpert = useMergedConfigStore().mergedConfig.expertLevel > 0
const hasBuiltins = this.builtinEntries.length > 0 const hasBuiltins = this.builtinEntries.length > 0
if (hasBuiltins) { if (hasBuiltins) {

View file

@ -7,6 +7,7 @@ import ModifiedIndicator from './modified_indicator.vue'
import { useInstanceStore } from 'src/stores/instance.js' import { useInstanceStore } from 'src/stores/instance.js'
import { useInterfaceStore } from 'src/stores/interface.js' import { useInterfaceStore } from 'src/stores/interface.js'
import { useLocalConfigStore } from 'src/stores/local_config.js' import { useLocalConfigStore } from 'src/stores/local_config.js'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useSyncConfigStore } from 'src/stores/sync_config.js'
export default { export default {
@ -244,7 +245,7 @@ export default {
case 'admin': case 'admin':
return this.$store.state.adminSettings.config return this.$store.state.adminSettings.config
default: default:
return useSyncConfigStore().mergedConfig return useMergedConfigStore().mergedConfig
} }
}, },
configSink() { configSink() {
@ -323,7 +324,7 @@ export default {
case 'profile': case 'profile':
return {} return {}
default: { default: {
return get(useSyncConfigStore().mergedConfigDefault, this.path) return get(useMergedConfigStore().mergedConfigDefault, this.path)
} }
} }
}, },
@ -379,7 +380,7 @@ export default {
matchesExpertLevel() { matchesExpertLevel() {
const settingExpertLevel = this.expert || 0 const settingExpertLevel = this.expert || 0
const userToggleExpert = const userToggleExpert =
useSyncConfigStore().mergedConfig.expertLevel || 0 useMergedConfigStore().mergedConfig.expertLevel || 0
return settingExpertLevel <= userToggleExpert return settingExpertLevel <= userToggleExpert
}, },
@ -405,7 +406,7 @@ export default {
this.draft = cloneDeep(this.state) this.draft = cloneDeep(this.state)
} else { } else {
set( set(
useSyncConfigStore().mergedConfig, useMergedConfigStore().mergedConfig,
this.path, this.path,
cloneDeep(this.defaultState), cloneDeep(this.defaultState),
) )

View file

@ -1,11 +1,11 @@
import { mapState as mapPiniaState } from 'pinia' import { mapState as mapPiniaState } from 'pinia'
import { mapState } from 'vuex' import { mapState } from 'vuex'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useMergedConfigStore } from 'src/stores/merged_config.js'
const SharedComputedObject = () => ({ const SharedComputedObject = () => ({
...mapPiniaState(useSyncConfigStore, ['mergedConfig']), ...mapPiniaState(useMergedConfigStore, ['mergedConfig']),
...mapPiniaState(useSyncConfigStore, { ...mapPiniaState(useMergedConfigStore, {
expertLevel: (store) => store.mergedConfig.expertLevel, expertLevel: (store) => store.mergedConfig.expertLevel,
}), }),
...mapState({ ...mapState({

View file

@ -16,7 +16,7 @@ import SecurityTab from './tabs/security_tab/security_tab.vue'
import StyleTab from './tabs/style_tab/style_tab.vue' import StyleTab from './tabs/style_tab/style_tab.vue'
import { useInterfaceStore } from 'src/stores/interface.js' import { useInterfaceStore } from 'src/stores/interface.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { library } from '@fortawesome/fontawesome-svg-core' import { library } from '@fortawesome/fontawesome-svg-core'
import { import {
@ -84,7 +84,7 @@ const SettingsModalContent = {
return useInterfaceStore().settingsModalState === 'visible' return useInterfaceStore().settingsModalState === 'visible'
}, },
expertLevel() { expertLevel() {
return useSyncConfigStore().mergedConfig.expertLevel return useMergedConfigStore().mergedConfig.expertLevel
}, },
}, },
data() { data() {

View file

@ -13,6 +13,7 @@ import UnitSetting from '../helpers/unit_setting.vue'
import { useInstanceStore } from 'src/stores/instance.js' import { useInstanceStore } from 'src/stores/instance.js'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js' import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useSyncConfigStore } from 'src/stores/sync_config.js'
import localeService from 'src/services/locale/locale.service.js' import localeService from 'src/services/locale/locale.service.js'
@ -116,7 +117,7 @@ const ComposingTab = {
}, },
language: { language: {
get: function () { get: function () {
return useSyncConfigStore().mergedConfig.interfaceLanguage return useMergedConfigStore().mergedConfig.interfaceLanguage
}, },
set: function (val) { set: function (val) {
useSyncConfigStore().setSimplePrefAndSave({ useSyncConfigStore().setSimplePrefAndSave({

View file

@ -13,6 +13,7 @@ import UnitSetting from '../helpers/unit_setting.vue'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js' import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useInterfaceStore } from 'src/stores/interface' import { useInterfaceStore } from 'src/stores/interface'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { import {
@ -36,7 +37,7 @@ const FilteringTab = {
label: this.$t(`user_card.mute_block_${mode}`), label: this.$t(`user_card.mute_block_${mode}`),
})), })),
muteFiltersDraftObject: cloneDeep( muteFiltersDraftObject: cloneDeep(
useSyncConfigStore().mergedConfig.muteFilters, useMergedConfigStore().mergedConfig.muteFilters,
), ),
muteFiltersDraftDirty: Object.fromEntries( muteFiltersDraftDirty: Object.fromEntries(
Object.entries( Object.entries(
@ -100,7 +101,7 @@ const FilteringTab = {
...mapState(useInstanceCapabilitiesStore, ['blockExpiration']), ...mapState(useInstanceCapabilitiesStore, ['blockExpiration']),
onMuteDefaultActionLv1: { onMuteDefaultActionLv1: {
get() { get() {
const value = useSyncConfigStore().mergedConfig.onMuteDefaultAction const value = useMergedConfigStore().mergedConfig.onMuteDefaultAction
if (value === 'ask' || value === 'forever') { if (value === 'ask' || value === 'forever') {
return value return value
} else { } else {
@ -120,7 +121,7 @@ const FilteringTab = {
}, },
onBlockDefaultActionLv1: { onBlockDefaultActionLv1: {
get() { get() {
const value = useSyncConfigStore().mergedConfig.onBlockDefaultAction const value = useMergedConfigStore().mergedConfig.onBlockDefaultAction
if (value === 'ask' || value === 'forever') { if (value === 'ask' || value === 'forever') {
return value return value
} else { } else {
@ -263,7 +264,7 @@ const FilteringTab = {
}, },
muteFiltersObject() { muteFiltersObject() {
this.muteFiltersDraftObject = cloneDeep( this.muteFiltersDraftObject = cloneDeep(
useSyncConfigStore().mergedConfig.muteFilters, useMergedConfigStore().mergedConfig.muteFilters,
) )
}, },
}, },

View file

@ -11,6 +11,7 @@ import UnitSetting from '../helpers/unit_setting.vue'
import { useInstanceStore } from 'src/stores/instance.js' import { useInstanceStore } from 'src/stores/instance.js'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js' import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useLocalConfigStore } from 'src/stores/local_config.js' import { useLocalConfigStore } from 'src/stores/local_config.js'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useSyncConfigStore } from 'src/stores/sync_config.js'
import localeService from 'src/services/locale/locale.service.js' import localeService from 'src/services/locale/locale.service.js'
@ -37,7 +38,7 @@ const GeneralTab = {
computed: { computed: {
language: { language: {
get: function () { get: function () {
return useSyncConfigStore().mergedConfig.interfaceLanguage return useMergedConfigStore().mergedConfig.interfaceLanguage
}, },
set: function (val) { set: function (val) {
useSyncConfigStore().setSimplePrefAndSave({ useSyncConfigStore().setSimplePrefAndSave({

View file

@ -6,7 +6,7 @@ import SharedComputedObject from '../helpers/shared_computed_object.js'
import UnitSetting from '../helpers/unit_setting.vue' import UnitSetting from '../helpers/unit_setting.vue'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js' import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useMergedConfigStore } from 'src/stores/merged_config.js'
const GeneralTab = { const GeneralTab = {
data() { data() {
@ -31,12 +31,12 @@ const GeneralTab = {
'suggestionsEnabled', 'suggestionsEnabled',
]), ]),
columns() { columns() {
const mode = useSyncConfigStore().mergedConfig.thirdColumnMode const mode = useMergedConfigStore().mergedConfig.thirdColumnMode
const notif = mode === 'none' ? [] : ['notifs'] const notif = mode === 'none' ? [] : ['notifs']
if ( if (
useSyncConfigStore().mergedConfig.sidebarRight || useMergedConfigStore().mergedConfig.sidebarRight ||
mode === 'postform' mode === 'postform'
) { ) {
return [...notif, 'content', 'sidebar'] return [...notif, 'content', 'sidebar']

View file

@ -11,7 +11,7 @@ import Preview from './theme_preview.vue'
import { useInstanceStore } from 'src/stores/instance.js' import { useInstanceStore } from 'src/stores/instance.js'
import { useInterfaceStore } from 'src/stores/interface.js' import { useInterfaceStore } from 'src/stores/interface.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { import {
getContrastRatioLayers, getContrastRatioLayers,
@ -82,7 +82,7 @@ export default {
}), }),
availableStyles: [], availableStyles: [],
selected: '', selected: '',
selectedTheme: useSyncConfigStore().mergedConfig.theme, selectedTheme: useMergedConfigStore().mergedConfig.theme,
themeWarning: undefined, themeWarning: undefined,
tempImportFile: undefined, tempImportFile: undefined,
engineVersion: 0, engineVersion: 0,

View file

@ -10,8 +10,8 @@ import { useAnnouncementsStore } from 'src/stores/announcements'
import { useInstanceStore } from 'src/stores/instance.js' import { useInstanceStore } from 'src/stores/instance.js'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js' import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useInterfaceStore } from 'src/stores/interface' import { useInterfaceStore } from 'src/stores/interface'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { useShoutStore } from 'src/stores/shout' import { useShoutStore } from 'src/stores/shout'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { library } from '@fortawesome/fontawesome-svg-core' import { library } from '@fortawesome/fontawesome-svg-core'
import { import {
@ -75,7 +75,7 @@ const SideDrawer = {
unseenNotifications() { unseenNotifications() {
return unseenNotificationsFromStore( return unseenNotificationsFromStore(
this.$store, this.$store,
useSyncConfigStore().mergedConfig.notificationVisibility, useMergedConfigStore().mergedConfig.notificationVisibility,
) )
}, },
unseenNotificationsCount() { unseenNotificationsCount() {

View file

@ -22,6 +22,7 @@ import UserPopover from '../user_popover/user_popover.vue'
import { useInstanceStore } from 'src/stores/instance.js' import { useInstanceStore } from 'src/stores/instance.js'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js' import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { useUserHighlightStore } from 'src/stores/user_highlight.js' import { useUserHighlightStore } from 'src/stores/user_highlight.js'
@ -477,7 +478,7 @@ const Status = {
return this.$store.state.users.currentUser return this.$store.state.users.currentUser
}, },
mergedConfig() { mergedConfig() {
return useSyncConfigStore().mergedConfig return useMergedConfigStore().mergedConfig
}, },
isSuspendable() { isSuspendable() {
return !this.replying && this.mediaPlaying.length === 0 return !this.replying && this.mediaPlaying.length === 0

View file

@ -3,7 +3,7 @@ import { useInstanceStore } from 'src/stores/instance.js'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js' import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useReportsStore } from 'src/stores/reports.js' import { useReportsStore } from 'src/stores/reports.js'
import { useStatusHistoryStore } from 'src/stores/statusHistory.js' import { useStatusHistoryStore } from 'src/stores/statusHistory.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useMergedConfigStore } from 'src/stores/merged_config.js'
const PRIVATE_SCOPES = new Set(['private', 'direct']) const PRIVATE_SCOPES = new Set(['private', 'direct'])
const PUBLIC_SCOPES = new Set(['public', 'unlisted']) const PUBLIC_SCOPES = new Set(['public', 'unlisted'])
@ -53,7 +53,7 @@ export const BUTTONS = [
!PRIVATE_SCOPES.has(status.visibility)), !PRIVATE_SCOPES.has(status.visibility)),
toggleable: true, toggleable: true,
confirm: ({ status, getters }) => confirm: ({ status, getters }) =>
!status.repeated && useSyncConfigStore().mergedConfig.modalOnRepeat, !status.repeated && useMergedConfigStore().mergedConfig.modalOnRepeat,
confirmStrings: { confirmStrings: {
title: 'status.repeat_confirm_title', title: 'status.repeat_confirm_title',
body: 'status.repeat_confirm', body: 'status.repeat_confirm',
@ -228,7 +228,7 @@ export const BUTTONS = [
currentUser.privileges.includes('messages_delete')) currentUser.privileges.includes('messages_delete'))
) )
}, },
confirm: ({ getters }) => useSyncConfigStore().mergedConfig.modalOnDelete, confirm: ({ getters }) => useMergedConfigStore().mergedConfig.modalOnDelete,
confirmStrings: { confirmStrings: {
title: 'status.delete_confirm_title', title: 'status.delete_confirm_title',
body: 'status.delete_confirm', body: 'status.delete_confirm',

View file

@ -2,7 +2,7 @@ import { mapState } from 'pinia'
import RichContent from 'src/components/rich_content/rich_content.jsx' import RichContent from 'src/components/rich_content/rich_content.jsx'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { library } from '@fortawesome/fontawesome-svg-core' import { library } from '@fortawesome/fontawesome-svg-core'
import { import {
@ -108,7 +108,7 @@ const StatusBody = {
collapsedStatus() { collapsedStatus() {
return this.status.raw_html.replace(/(\n|<br\s?\/?>)/g, ' ') return this.status.raw_html.replace(/(\n|<br\s?\/?>)/g, ' ')
}, },
...mapState(useSyncConfigStore, ['mergedConfig']), ...mapState(useMergedConfigStore, ['mergedConfig']),
}, },
components: { components: {
RichContent, RichContent,

View file

@ -8,7 +8,7 @@ import LinkPreview from '../link-preview/link-preview.vue'
import Poll from '../poll/poll.vue' import Poll from '../poll/poll.vue'
import { useMediaViewerStore } from 'src/stores/media_viewer.js' import { useMediaViewerStore } from 'src/stores/media_viewer.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { library } from '@fortawesome/fontawesome-svg-core' import { library } from '@fortawesome/fontawesome-svg-core'
import { import {
@ -76,7 +76,7 @@ const StatusContent = {
uncontrolledShowingLongSubject: false, uncontrolledShowingLongSubject: false,
// not as computed because it sets the initial state which will be changed later // not as computed because it sets the initial state which will be changed later
uncontrolledExpandingSubject: uncontrolledExpandingSubject:
!useSyncConfigStore().mergedConfig.collapseMessageWithSubject, !useMergedConfigStore().mergedConfig.collapseMessageWithSubject,
} }
}, },
computed: { computed: {
@ -124,7 +124,7 @@ const StatusContent = {
maxThumbnails() { maxThumbnails() {
return this.mergedConfig.maxThumbnails return this.mergedConfig.maxThumbnails
}, },
...mapPiniaState(useSyncConfigStore, ['mergedConfig']), ...mapPiniaState(useMergedConfigStore, ['mergedConfig']),
...mapState({ ...mapState({
currentUser: (state) => state.users.currentUser, currentUser: (state) => state.users.currentUser,
}), }),

View file

@ -1,4 +1,4 @@
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useMergedConfigStore } from 'src/stores/merged_config.js'
const StillImage = { const StillImage = {
props: [ props: [
@ -17,7 +17,7 @@ const StillImage = {
return { return {
// for lazy loading, see loadLazy() // for lazy loading, see loadLazy()
realSrc: this.src, realSrc: this.src,
stopGifs: useSyncConfigStore().mergedConfig.stopGifs, stopGifs: useMergedConfigStore().mergedConfig.stopGifs,
} }
}, },
computed: { computed: {

View file

@ -1,4 +1,4 @@
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useMergedConfigStore } from 'src/stores/merged_config.js'
import * as DateUtils from 'src/services/date_utils/date_utils.js' import * as DateUtils from 'src/services/date_utils/date_utils.js'
import localeService from 'src/services/locale/locale.service.js' import localeService from 'src/services/locale/locale.service.js'
@ -15,17 +15,17 @@ export default {
}, },
computed: { computed: {
shouldUseAbsoluteTimeFormat() { shouldUseAbsoluteTimeFormat() {
if (!useSyncConfigStore().mergedConfig.useAbsoluteTimeFormat) { if (!useMergedConfigStore().mergedConfig.useAbsoluteTimeFormat) {
return false return false
} }
return ( return (
DateUtils.durationStrToMs( DateUtils.durationStrToMs(
useSyncConfigStore().mergedConfig.absoluteTimeFormatMinAge, useMergedConfigStore().mergedConfig.absoluteTimeFormatMinAge,
) <= this.relativeTimeMs ) <= this.relativeTimeMs
) )
}, },
time12hFormat() { time12hFormat() {
return useSyncConfigStore().mergedConfig.absoluteTimeFormat12h === '12h' return useMergedConfigStore().mergedConfig.absoluteTimeFormat12h === '12h'
}, },
browserLocale() { browserLocale() {
return localeService.internalToBrowserLocale(this.$i18n.locale) return localeService.internalToBrowserLocale(this.$i18n.locale)

View file

@ -9,7 +9,7 @@ import Status from '../status/status.vue'
import TimelineMenu from '../timeline_menu/timeline_menu.vue' import TimelineMenu from '../timeline_menu/timeline_menu.vue'
import { useInterfaceStore } from 'src/stores/interface.js' import { useInterfaceStore } from 'src/stores/interface.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useMergedConfigStore } from 'src/stores/merged_config.js'
import timelineFetcher from 'src/services/timeline_fetcher/timeline_fetcher.service.js' import timelineFetcher from 'src/services/timeline_fetcher/timeline_fetcher.service.js'
@ -126,7 +126,7 @@ const Timeline = {
return this.timeline.visibleStatuses.slice(min, max).map((_) => _.id) return this.timeline.visibleStatuses.slice(min, max).map((_) => _.id)
}, },
virtualScrollingEnabled() { virtualScrollingEnabled() {
return useSyncConfigStore().mergedConfig.virtualScrolling return useMergedConfigStore().mergedConfig.virtualScrolling
}, },
...mapState(useInterfaceStore, { ...mapState(useInterfaceStore, {
mobileLayout: (store) => store.layoutType === 'mobile', mobileLayout: (store) => store.layoutType === 'mobile',
@ -314,7 +314,7 @@ const Timeline = {
}, },
watch: { watch: {
newStatusCount(count) { newStatusCount(count) {
if (!useSyncConfigStore().mergedConfig.streaming) { if (!useMergedConfigStore().mergedConfig.streaming) {
return return
} }
if (count > 0) { if (count > 0) {
@ -325,7 +325,8 @@ const Timeline = {
top < 15 && top < 15 &&
!this.paused && !this.paused &&
!( !(
this.unfocused && useSyncConfigStore().mergedConfig.pauseOnUnfocused this.unfocused &&
useMergedConfigStore().mergedConfig.pauseOnUnfocused
) )
) { ) {
this.showNewStatuses() this.showNewStatuses()

View file

@ -1,6 +1,7 @@
import Modal from 'src/components/modal/modal.vue' import Modal from 'src/components/modal/modal.vue'
import { useInstanceStore } from 'src/stores/instance.js' import { useInstanceStore } from 'src/stores/instance.js'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useSyncConfigStore } from 'src/stores/sync_config.js'
import pleromaTanFoxMask from 'src/assets/pleromatan_apology_fox_mask.png' import pleromaTanFoxMask from 'src/assets/pleromatan_apology_fox_mask.png'
@ -43,7 +44,7 @@ const UpdateNotification = {
this.$store.state.users.currentUser && this.$store.state.users.currentUser &&
useSyncConfigStore().flagStorage.updateCounter < useSyncConfigStore().flagStorage.updateCounter <
CURRENT_UPDATE_COUNTER && CURRENT_UPDATE_COUNTER &&
!useSyncConfigStore().mergedConfig.dontShowUpdateNotifs !useMergedConfigStore().mergedConfig.dontShowUpdateNotifs
) )
}, },
}, },

View file

@ -12,8 +12,6 @@ import suggestor from 'src/components/emoji_input/suggestor.js'
import ImageCropper from 'src/components/image_cropper/image_cropper.vue' import ImageCropper from 'src/components/image_cropper/image_cropper.vue'
import RichContent from 'src/components/rich_content/rich_content.jsx' import RichContent from 'src/components/rich_content/rich_content.jsx'
import UserTimedFilterModal from 'src/components/user_timed_filter_modal/user_timed_filter_modal.vue' import UserTimedFilterModal from 'src/components/user_timed_filter_modal/user_timed_filter_modal.vue'
import { useInterfaceStore } from '../../stores/interface'
import { useMediaViewerStore } from '../../stores/media_viewer'
import AccountActions from '../account_actions/account_actions.vue' import AccountActions from '../account_actions/account_actions.vue'
import FollowButton from '../follow_button/follow_button.vue' import FollowButton from '../follow_button/follow_button.vue'
import ModerationTools from '../moderation_tools/moderation_tools.vue' import ModerationTools from '../moderation_tools/moderation_tools.vue'
@ -27,8 +25,10 @@ import UserNote from '../user_note/user_note.vue'
import { useEmojiStore } from 'src/stores/emoji.js' import { useEmojiStore } from 'src/stores/emoji.js'
import { useInstanceStore } from 'src/stores/instance.js' import { useInstanceStore } from 'src/stores/instance.js'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js' import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useInterfaceStore } from 'src/stores/interface'
import { useMediaViewerStore } from 'src/stores/media_viewer'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { usePostStatusStore } from 'src/stores/post_status' import { usePostStatusStore } from 'src/stores/post_status'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { useUserHighlightStore } from 'src/stores/user_highlight.js' import { useUserHighlightStore } from 'src/stores/user_highlight.js'
import { propsToNative } from 'src/services/attributes_helper/attributes_helper.service.js' import { propsToNative } from 'src/services/attributes_helper/attributes_helper.service.js'
@ -385,7 +385,7 @@ export default {
], ],
}) })
}, },
...mapState(useSyncConfigStore, ['mergedConfig']), ...mapState(useMergedConfigStore, ['mergedConfig']),
}, },
methods: { methods: {
muteUser() { muteUser() {

View file

@ -3,7 +3,7 @@ import { defineAsyncComponent } from 'vue'
import UserCard from '../user_card/user_card.vue' import UserCard from '../user_card/user_card.vue'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useMergedConfigStore } from 'src/stores/merged_config.js'
const UserPopover = { const UserPopover = {
name: 'UserPopover', name: 'UserPopover',
@ -12,7 +12,7 @@ const UserPopover = {
UserCard, UserCard,
Popover: defineAsyncComponent(() => import('../popover/popover.vue')), Popover: defineAsyncComponent(() => import('../popover/popover.vue')),
}, },
computed: mapState(useSyncConfigStore, { computed: mapState(useMergedConfigStore, {
userPopoverAvatarAction: (state) => userPopoverAvatarAction: (state) =>
state.mergedConfig.userPopoverAvatarAction, state.mergedConfig.userPopoverAvatarAction,
userPopoverOverlay: (state) => state.mergedConfig.userPopoverOverlay, userPopoverOverlay: (state) => state.mergedConfig.userPopoverOverlay,

View file

@ -2,6 +2,7 @@ import Checkbox from 'src/components/checkbox/checkbox.vue'
import ConfirmModal from 'src/components/confirm_modal/confirm_modal.vue' import ConfirmModal from 'src/components/confirm_modal/confirm_modal.vue'
import Select from 'src/components/select/select.vue' import Select from 'src/components/select/select.vue'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { durationStrToMs } from 'src/services/date_utils/date_utils.js' import { durationStrToMs } from 'src/services/date_utils/date_utils.js'
@ -9,8 +10,8 @@ import { durationStrToMs } from 'src/services/date_utils/date_utils.js'
const UserTimedFilterModal = { const UserTimedFilterModal = {
data() { data() {
const action = this.isMute const action = this.isMute
? useSyncConfigStore().mergedConfig.onMuteDefaultAction ? useMergedConfigStore().mergedConfig.onMuteDefaultAction
: useSyncConfigStore().mergedConfig.onBlockDefaultAction : useMergedConfigStore().mergedConfig.onBlockDefaultAction
const doAsk = action === 'ask' const doAsk = action === 'ask'
const defaultValues = {} const defaultValues = {}
@ -46,9 +47,11 @@ const UserTimedFilterModal = {
computed: { computed: {
shouldConfirm() { shouldConfirm() {
if (this.isMute) { if (this.isMute) {
return useSyncConfigStore().mergedConfig.onMuteDefaultAction === 'ask' return useMergedConfigStore().mergedConfig.onMuteDefaultAction === 'ask'
} else { } else {
return useSyncConfigStore().mergedConfig.onBlockDefaultAction === 'ask' return (
useMergedConfigStore().mergedConfig.onBlockDefaultAction === 'ask'
)
} }
}, },
expiryString() { expiryString() {

View file

@ -1,4 +1,4 @@
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useMergedConfigStore } from 'src/stores/merged_config.js'
const VideoAttachment = { const VideoAttachment = {
props: ['attachment', 'controls'], props: ['attachment', 'controls'],
@ -11,10 +11,10 @@ const VideoAttachment = {
}, },
computed: { computed: {
loopVideo() { loopVideo() {
if (useSyncConfigStore().mergedConfig.loopVideoSilentOnly) { if (useMergedConfigStore().mergedConfig.loopVideoSilentOnly) {
return !this.hasAudio return !this.hasAudio
} }
return useSyncConfigStore().mergedConfig.loopVideo return useMergedConfigStore().mergedConfig.loopVideo
}, },
}, },
methods: { methods: {

View file

@ -1,6 +1,6 @@
import { useInstanceStore } from 'src/stores/instance.js' import { useInstanceStore } from 'src/stores/instance.js'
import { useInterfaceStore } from 'src/stores/interface.js' import { useInterfaceStore } from 'src/stores/interface.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useMergedConfigStore } from 'src/stores/merged_config.js'
export const piniaPushNotificationsPlugin = ({ store }) => { export const piniaPushNotificationsPlugin = ({ store }) => {
if ( if (
@ -20,7 +20,7 @@ export const piniaPushNotificationsPlugin = ({ store }) => {
// Initial state // Initial state
let vapidPublicKey = useInstanceStore().vapidPublicKey let vapidPublicKey = useInstanceStore().vapidPublicKey
let enabled = useSyncConfigStore().mergedConfig.webPushNotifications let enabled = useMergedConfigStore().mergedConfig.webPushNotifications
let permissionGranted = let permissionGranted =
useInterfaceStore().notificationPermission === 'granted' useInterfaceStore().notificationPermission === 'granted'
let permissionPresent = let permissionPresent =
@ -70,7 +70,7 @@ export const vuexPushNotificationsPlugin = (store) => {
store.subscribe((mutation, state) => { store.subscribe((mutation, state) => {
// Initial state // Initial state
const vapidPublicKey = useInstanceStore().vapidPublicKey const vapidPublicKey = useInstanceStore().vapidPublicKey
const enabled = useSyncConfigStore().mergedConfig.webPushNotifications const enabled = useMergedConfigStore().mergedConfig.webPushNotifications
const permissionGranted = const permissionGranted =
useInterfaceStore().notificationPermission === 'granted' useInterfaceStore().notificationPermission === 'granted'
const permissionPresent = const permissionPresent =

View file

@ -1,5 +1,5 @@
import { useInterfaceStore } from 'src/stores/interface.js' import { useInterfaceStore } from 'src/stores/interface.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { applyStyleConfig } from 'src/services/style_setter/style_setter.js' import { applyStyleConfig } from 'src/services/style_setter/style_setter.js'
@ -44,7 +44,7 @@ export const piniaStylePlugin = ({ store, options }) => {
if (ACTIONS.has(name)) { if (ACTIONS.has(name)) {
const { path } = args[0] const { path } = args[0]
if (MIXED_KEYS.has(path)) { if (MIXED_KEYS.has(path)) {
after(() => applyStyleConfig(useSyncConfigStore().mergedConfig)) after(() => applyStyleConfig(useMergedConfigStore().mergedConfig))
} }
if (HACKS_KEYS.has(path)) { if (HACKS_KEYS.has(path)) {
after(() => useInterfaceStore().applyTheme({ recompile: true })) after(() => useInterfaceStore().applyTheme({ recompile: true }))

View file

@ -1,200 +0,0 @@
import Cookies from 'js-cookie'
import { set } from 'lodash'
import messages from '../i18n/messages'
import localeService from '../services/locale/locale.service.js'
import { applyStyleConfig } from '../services/style_setter/style_setter.js'
import { defaultState, instanceDefaultConfig } from './default_config_state.js'
import { useEmojiStore } from 'src/stores/emoji.js'
import { useI18nStore } from 'src/stores/i18n.js'
import { useInstanceStore } from 'src/stores/instance.js'
import { useInterfaceStore } from 'src/stores/interface.js'
const BACKEND_LANGUAGE_COOKIE_NAME = 'userLanguage'
const APPEARANCE_SETTINGS_KEYS = new Set([
'sidebarColumnWidth',
'contentColumnWidth',
'notifsColumnWidth',
'themeEditorMinWidth',
'textSize',
'navbarSize',
'panelHeaderSize',
'forcedRoundness',
'emojiSize',
'emojiReactionsScale',
])
/* TODO this is a bit messy.
* We need to declare settings with their types and also deal with
* instance-default settings in some way, hopefully try to avoid copy-pasta
* in general.
*/
export const multiChoiceProperties = [
'postContentType',
'subjectLineBehavior',
'conversationDisplay', // tree | linear
'conversationOtherRepliesButton', // below | inside
'mentionLinkDisplay', // short | full_for_remote | full
'userPopoverAvatarAction', // close | zoom | open
'unsavedPostAction', // save | discard | confirm
]
// caching the instance default properties
export const instanceDefaultProperties = Object.keys(instanceDefaultConfig)
const config = {
state: { ...defaultState },
getters: {
defaultConfig() {
return {
...defaultState,
...Object.fromEntries(
instanceDefaultProperties.map((key) => [
key,
useInstanceStore().prefsStorage[key],
]),
),
}
},
mergedConfig(state) {
const instancePrefs = useInstanceStore().prefsStorage
const result = Object.fromEntries(
Object.keys(defaultState).map((key) => [
key,
state[key] ?? instancePrefs[key],
]),
)
return result
},
},
mutations: {
setOptionTemporarily(state, { name, value }) {
set(state, name, value)
applyStyleConfig(state)
},
setOption(state, { name, value }) {
set(state, name, value)
},
setHighlight(state, { user, color, type }) {
const data = this.state.config.highlight[user]
if (color || type) {
state.highlight[user] = {
color: color || data.color,
type: type || data.type,
}
} else {
delete state.highlight[user]
}
},
},
actions: {
loadSettings({ dispatch }, data) {
const knownKeys = new Set(Object.keys(defaultState))
const presentKeys = new Set(Object.keys(data))
const intersection = new Set()
for (const elem of presentKeys) {
if (knownKeys.has(elem)) {
intersection.add(elem)
}
}
intersection.forEach((name) =>
dispatch('setOption', { name, value: data[name] }),
)
},
setHighlight({ commit }, { user, color, type }) {
commit('setHighlight', { user, color, type })
},
setOptionTemporarily({ commit, dispatch, state }, { name, value }) {
if (useInterfaceStore().temporaryChangesTimeoutId !== null) {
console.warn("Can't track more than one temporary change")
return
}
const oldValue = state[name]
commit('setOptionTemporarily', { name, value })
const confirm = () => {
dispatch('setOption', { name, value })
useInterfaceStore().clearTemporaryChanges()
}
const revert = () => {
commit('setOptionTemporarily', { name, value: oldValue })
useInterfaceStore().clearTemporaryChanges()
}
useInterfaceStore().setTemporaryChanges({
confirm,
revert,
})
},
setThemeV2({ commit, dispatch }, { customTheme, customThemeSource }) {
commit('setOption', { name: 'theme', value: 'custom' })
commit('setOption', { name: 'customTheme', value: customTheme })
commit('setOption', {
name: 'customThemeSource',
value: customThemeSource,
})
dispatch('setTheme', { themeData: customThemeSource, recompile: true })
},
setOption({ commit, dispatch, state }, { name, value }) {
const exceptions = new Set(['useStreamingApi'])
if (exceptions.has(name)) {
switch (name) {
case 'useStreamingApi': {
const action = value ? 'enableMastoSockets' : 'disableMastoSockets'
dispatch(action)
.then(() => {
commit('setOption', { name: 'useStreamingApi', value })
})
.catch((e) => {
console.error('Failed starting MastoAPI Streaming socket', e)
dispatch('disableMastoSockets')
dispatch('setOption', { name: 'useStreamingApi', value: false })
})
break
}
}
} else {
commit('setOption', { name, value })
if (APPEARANCE_SETTINGS_KEYS.has(name)) {
applyStyleConfig(state)
}
if (name.startsWith('theme3hacks')) {
dispatch('applyTheme', { recompile: true })
}
switch (name) {
case 'theme':
if (value === 'custom') break
dispatch('setTheme', {
themeName: value,
recompile: true,
saveData: true,
})
break
case 'themeDebug': {
dispatch('setTheme', { recompile: true })
break
}
case 'interfaceLanguage':
messages.setLanguage(useI18nStore().i18n, value)
useEmojiStore().loadUnicodeEmojiData(value)
Cookies.set(
BACKEND_LANGUAGE_COOKIE_NAME,
localeService.internalToBackendLocaleMulti(value),
)
break
case 'thirdColumnMode':
useInterfaceStore().setLayoutWidth(undefined)
break
}
}
},
},
}
export default config

View file

@ -1,4 +1,4 @@
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useMergedConfigStore } from 'src/stores/merged_config.js'
export const CONFIG_MIGRATION = 1 export const CONFIG_MIGRATION = 1
@ -24,7 +24,7 @@ export const declarations = [
description: 'Mute filters, wordfilter/regexp/etc', description: 'Mute filters, wordfilter/regexp/etc',
valueType: 'complex', valueType: 'complex',
migration(serverside, rootState) { migration(serverside, rootState) {
useSyncConfigStore().mergedConfig.muteWords.forEach((word, order) => { useMergedConfigStore().mergedConfig.muteWords.forEach((word, order) => {
const uniqueId = uuidv4() const uniqueId = uuidv4()
serverside.setPreference({ serverside.setPreference({

View file

@ -1,16 +1,19 @@
import { get, set } from 'lodash'
const browserLocale = (navigator.language || 'en').split('-')[0] const browserLocale = (navigator.language || 'en').split('-')[0]
const convertDefinitions = definitions => Object.fromEntries( export const convertDefinitions = (definitions) =>
Object.entries(definitions).map(([k, v]) => [ Object.fromEntries(
k, Object.entries(definitions).map(([k, v]) => {
v.default == null ? null : v.default, const defaultValue = v.default ?? null
]), return [k, defaultValue]
) }),
)
/// Instance config entries provided by static config or pleroma api /// Instance config entries provided by static config or pleroma api
/// Put settings here only if it does not make sense for a normal user /// Put settings here only if it does not make sense for a normal user
/// to override it. /// to override it.
export const instanceIdentityDefaultDefinitions = { export const INSTANCE_IDENTITY_DEFAULT_DEFINITIONS = {
style: { style: {
description: 'Instance default style name', description: 'Instance default style name',
type: 'string', type: 'string',
@ -110,14 +113,17 @@ export const instanceIdentityDefaultDefinitions = {
required: false, required: false,
}, },
} }
export const instanceIdentityDefault = convertDefinitions(instanceIdentityDefaultDefinitions) export const INSTANCE_IDENTITY_DEFAULT = convertDefinitions(
INSTANCE_IDENTITY_DEFAULT_DEFINITIONS,
)
/// This object contains setting entries that makes sense /// This object contains setting entries that makes sense
/// at the user level. The defaults can also be overriden by /// at the user level. The defaults can also be overriden by
/// instance admins in the frontend_configuration endpoint or static config. /// instance admins in the frontend_configuration endpoint or static config.
export const instanceDefaultConfigDefinitions = { export const INSTANCE_DEFAULT_CONFIG_DEFINITIONS = {
expertLevel: { expertLevel: {
description: 'Used to track which settings to show and hide in settings modal', description:
'Used to track which settings to show and hide in settings modal',
type: 'number', // not a boolean so we could potentially make multiple levels of expert-ness type: 'number', // not a boolean so we could potentially make multiple levels of expert-ness
default: 0, default: 0,
}, },
@ -133,7 +139,8 @@ export const instanceDefaultConfigDefinitions = {
description: 'Hide shoutbox if present', description: 'Hide shoutbox if present',
default: false, default: false,
}, },
hideMutedPosts: { // bad name hideMutedPosts: {
// bad name
description: 'Hide posts of muted users entirely', description: 'Hide posts of muted users entirely',
default: false, default: false,
}, },
@ -205,7 +212,8 @@ export const instanceDefaultConfigDefinitions = {
default: false, default: false,
}, },
autohideFloatingPostButton: { autohideFloatingPostButton: {
description: 'Automatically hide mobile "new post" button when scrolling down', description:
'Automatically hide mobile "new post" button when scrolling down',
default: false, default: false,
}, },
stopGifs: { stopGifs: {
@ -400,7 +408,8 @@ export const instanceDefaultConfigDefinitions = {
default: false, default: false,
}, },
mentionLinkFadeDomain: { mentionLinkFadeDomain: {
description: 'Mute (fade) domain name in mention links if configured to show it', description:
'Mute (fade) domain name in mention links if configured to show it',
default: true, default: true,
}, },
mentionLinkShowYous: { mentionLinkShowYous: {
@ -448,7 +457,8 @@ export const instanceDefaultConfigDefinitions = {
default: false, default: false,
}, },
showExtraNotifications: { showExtraNotifications: {
description: 'Show extra notifications (chats, announcements etc) in notification panel', description:
'Show extra notifications (chats, announcements etc) in notification panel',
default: true, default: true,
}, },
showExtraNotificationsTip: { showExtraNotificationsTip: {
@ -507,41 +517,142 @@ export const instanceDefaultConfigDefinitions = {
description: 'Use 24h time format', description: 'Use 24h time format',
default: '24h', default: '24h',
}, },
themeChecksum: {
description: 'Checksum of theme used',
type: 'string',
required: false,
},
} }
export const instanceDefaultConfig = convertDefinitions(instanceDefaultConfigDefinitions) export const INSTANCE_DEFAULT_CONFIG = convertDefinitions(
INSTANCE_DEFAULT_CONFIG_DEFINITIONS,
)
export const defaultConfigLocal = { export const LOCAL_DEFAULT_CONFIG_DEFINITIONS = {
hideAttachments: false, // TODO these two used to be separate but since separation feature got broken it doesn't matter
hideAttachmentsInConv: false, hideAttachments: {
hideNsfw: true, description: 'Hide attachments in timeline',
useOneClickNsfw: false, default: false,
preloadImage: true, },
postContentType: 'text/plain', hideAttachmentsInConv: {
sidebarRight: false, description: 'Hide attachments in coversation',
sidebarColumnWidth: '25rem', default: false,
contentColumnWidth: '45rem', },
notifsColumnWidth: '25rem', hideNsfw: {
themeEditorMinWidth: '0rem', description: 'Hide nsfw posts',
emojiReactionsScale: 0.5, default: true,
textSize: '1rem', },
emojiSize: '2.2rem', useOneClickNsfw: {
navbarSize: '3.5rem', description: 'Open NSFW images directly in media modal',
panelHeaderSize: '3.2rem', default: false,
navbarColumnStretch: false, },
mentionLinkDisplay: 'short', preloadImage: {
alwaysUseJpeg: false, description: 'Preload images for NSFW',
imageCompression: true, default: true,
useStreamingApi: false, },
underlay: 'none', postContentType: {
fontInterface: undefined, description: 'Default post content type',
fontInput: undefined, default: 'text/plain',
fontPosts: undefined, },
fontMonospace: undefined, sidebarRight: {
themeDebug: false, // debug mode that uses computed backgrounds instead of real ones to debug contrast functions description: 'Reverse order of columns',
forceThemeRecompilation: false, // flag that forces recompilation on boot even if cache exists default: false,
},
sidebarColumnWidth: {
description: 'Sidebar column width',
default: '25rem',
},
contentColumnWidth: {
description: 'Middle column width',
default: '45rem',
},
notifsColumnWidth: {
description: 'Notifications column width',
default: '25rem',
},
themeEditorMinWidth: {
description: 'Hack for theme editor on mobile',
default: '0rem',
},
emojiReactionsScale: {
description: 'Emoji reactions scale factor',
default: 0.5,
},
textSize: {
description: 'Font size',
default: '1rem',
},
emojiSize: {
description: 'Emoji size',
default: '2.2rem',
},
navbarSize: {
description: 'Navbar size',
default: '3.5rem',
},
panelHeaderSize: {
description: 'Panel header size',
default: '3.2rem',
},
navbarColumnStretch: {
description: 'Stretch navbar to match columns width',
default: false,
},
mentionLinkDisplay: {
description: 'How to display mention links',
default: 'short',
},
imageCompression: {
description: 'Image compression (WebP/JPEG)',
default: true,
},
alwaysUseJpeg: {
description: 'Compress images using JPEG only',
default: false,
},
useStreamingApi: {
description: 'Streaming API (WebSocket)',
default: false,
},
underlay: {
description: 'Underlay override',
required: true,
default: 'none',
},
fontInterface: {
description: 'Interface font override',
type: 'string',
default: null,
},
fontInput: {
description: 'Input font override',
type: 'string',
default: null,
},
fontPosts: {
description: 'Post font override',
type: 'string',
default: null,
},
fontMonospace: {
description: 'Monospace font override',
type: 'string',
default: null,
},
themeDebug: {
description:
'Debug mode that uses computed backgrounds instead of real ones to debug contrast functions',
default: false,
},
forceThemeRecompilation: {
description: 'Flag that forces recompilation on boot even if cache exists',
default: false,
},
} }
export const LOCAL_DEFAULT_CONFIG = convertDefinitions(
LOCAL_DEFAULT_CONFIG_DEFINITIONS,
)
export const LOCAL_ONLY_KEYS = new Set(Object.keys(defaultConfigLocal)) export const LOCAL_ONLY_KEYS = new Set(Object.keys(LOCAL_DEFAULT_CONFIG))
export const makeUndefined = (c) => export const makeUndefined = (c) =>
Object.fromEntries(Object.keys(c).map((key) => [key, undefined])) Object.fromEntries(Object.keys(c).map((key) => [key, undefined]))
@ -550,8 +661,8 @@ export const makeUndefined = (c) =>
/// make sense to be overriden on a instance-wide level. /// make sense to be overriden on a instance-wide level.
export const defaultState = { export const defaultState = {
// Set these to undefined so it does not interfere with default settings check // Set these to undefined so it does not interfere with default settings check
...makeUndefined(instanceDefaultConfig), ...makeUndefined(INSTANCE_DEFAULT_CONFIG),
...makeUndefined(defaultConfigLocal), ...makeUndefined(LOCAL_DEFAULT_CONFIG),
// If there are any configurations that does not make sense to // If there are any configurations that does not make sense to
// have instance-wide default, put it here and explain why. // have instance-wide default, put it here and explain why.
@ -572,3 +683,53 @@ export const defaultState = {
palette: null, palette: null,
paletteCustomData: null, paletteCustomData: null,
} }
export const validateSetting = ({
value,
path,
definition,
throwError,
defaultState,
}) => {
if (value === undefined) return // only null is allowed as missing value
if (get(defaultState, path) === undefined) {
const string = `Unknown instance option ${path}, value: ${value}`
if (throwError) {
throw new Error(string)
} else {
console.error(string)
return value
}
}
let { required, type, default: defaultValue } = definition
if (type == null && defaultValue != null) {
type = typeof defaultValue
}
if (required && value == null) {
const string = `Value required for setting ${path} but was provided nullish; defaulting`
if (throwError) {
throw new Error(string)
} else {
console.error(string)
return defaultValue
}
}
if (value !== null && type != null && typeof value !== type) {
const string = `Invalid type for setting ${path}: expected type ${type}, got ${typeof value}, value ${value}; defaulting`
if (throwError) {
throw new Error(string)
} else {
console.error(string)
return defaultValue
}
}
return value
}

View file

@ -1,7 +1,6 @@
import adminSettings from './adminSettings.js' import adminSettings from './adminSettings.js'
import api from './api.js' import api from './api.js'
import chats from './chats.js' import chats from './chats.js'
import config from './config.js'
import drafts from './drafts.js' import drafts from './drafts.js'
import notifications from './notifications.js' import notifications from './notifications.js'
import profileConfig from './profileConfig.js' import profileConfig from './profileConfig.js'
@ -13,7 +12,6 @@ export default {
notifications, notifications,
users, users,
api, api,
config,
profileConfig, profileConfig,
adminSettings, adminSettings,
drafts, drafts,

View file

@ -9,6 +9,7 @@ import {
maybeShowNotification, maybeShowNotification,
} from '../services/notification_utils/notification_utils.js' } from '../services/notification_utils/notification_utils.js'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { useReportsStore } from 'src/stores/reports.js' import { useReportsStore } from 'src/stores/reports.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useSyncConfigStore } from 'src/stores/sync_config.js'
@ -118,8 +119,8 @@ export const notifications = {
commit('addNewNotifications', { notifications: [notification] }) commit('addNewNotifications', { notifications: [notification] })
maybeShowNotification( maybeShowNotification(
useSyncConfigStore().mergedConfig.notificationVisibility,
store, store,
useMergedConfigStore().mergedConfig.notificationVisibility,
Object.values(useSyncConfigStore().prefsStorage.simple.muteFilters), Object.values(useSyncConfigStore().prefsStorage.simple.muteFilters),
notification, notification,
) )

View file

@ -25,6 +25,7 @@ import { useEmojiStore } from 'src/stores/emoji.js'
import { useInstanceStore } from 'src/stores/instance.js' import { useInstanceStore } from 'src/stores/instance.js'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js' import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useInterfaceStore } from 'src/stores/interface.js' import { useInterfaceStore } from 'src/stores/interface.js'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { useOAuthStore } from 'src/stores/oauth.js' import { useOAuthStore } from 'src/stores/oauth.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { useUserHighlightStore } from 'src/stores/user_highlight.js' import { useUserHighlightStore } from 'src/stores/user_highlight.js'
@ -554,9 +555,9 @@ const users = {
registerPushNotifications(store) { registerPushNotifications(store) {
const token = store.state.currentUser.credentials const token = store.state.currentUser.credentials
const vapidPublicKey = useInstanceStore().vapidPublicKey const vapidPublicKey = useInstanceStore().vapidPublicKey
const isEnabled = useSyncConfigStore().mergedConfig.webPushNotifications const isEnabled = useMergedConfigStore().mergedConfig.webPushNotifications
const notificationVisibility = const notificationVisibility =
useSyncConfigStore().mergedConfig.notificationVisibility useMergedConfigStore().mergedConfig.notificationVisibility
registerPushNotifications( registerPushNotifications(
isEnabled, isEnabled,
@ -789,7 +790,7 @@ const users = {
dispatch('startFetchingFollowRequests') dispatch('startFetchingFollowRequests')
} }
if (useSyncConfigStore().mergedConfig.useStreamingApi) { if (useMergedConfigStore().mergedConfig.useStreamingApi) {
dispatch('fetchTimeline', { timeline: 'friends', since: null }) dispatch('fetchTimeline', { timeline: 'friends', since: null })
dispatch('fetchNotifications', { since: null }) dispatch('fetchNotifications', { since: null })
dispatch('enableMastoSockets', true) dispatch('enableMastoSockets', true)

View file

@ -4,7 +4,7 @@ import { promiseInterval } from '../promise_interval/promise_interval.js'
import { useInstanceStore } from 'src/stores/instance.js' import { useInstanceStore } from 'src/stores/instance.js'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js' import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useInterfaceStore } from 'src/stores/interface.js' import { useInterfaceStore } from 'src/stores/interface.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useMergedConfigStore } from 'src/stores/merged_config.js'
const update = ({ store, notifications, older }) => { const update = ({ store, notifications, older }) => {
store.dispatch('addNewNotifications', { notifications, older }) store.dispatch('addNewNotifications', { notifications, older })
@ -29,7 +29,7 @@ const fetchAndUpdate = ({ store, credentials, older = false, since }) => {
const args = { credentials } const args = { credentials }
const rootState = store.rootState || store.state const rootState = store.rootState || store.state
const timelineData = rootState.notifications const timelineData = rootState.notifications
const hideMutedPosts = useSyncConfigStore().mergedConfig.hideMutedPosts const hideMutedPosts = useMergedConfigStore().mergedConfig.hideMutedPosts
if (useInstanceCapabilitiesStore().pleromaChatMessagesAvailable) { if (useInstanceCapabilitiesStore().pleromaChatMessagesAvailable) {
mastoApiNotificationTypes.add('pleroma:chat_mention') mastoApiNotificationTypes.add('pleroma:chat_mention')

View file

@ -5,6 +5,7 @@ import { chunk, throttle } from 'lodash'
import { getCssRules } from '../theme_data/css_utils.js' import { getCssRules } from '../theme_data/css_utils.js'
import { getEngineChecksum, init } from '../theme_data/theme_data_3.service.js' import { getEngineChecksum, init } from '../theme_data/theme_data_3.service.js'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { defaultState } from 'src/modules/default_config_state.js' import { defaultState } from 'src/modules/default_config_state.js'
@ -142,7 +143,7 @@ export const tryLoadCache = async () => {
if ( if (
cache.engineChecksum === getEngineChecksum() && cache.engineChecksum === getEngineChecksum() &&
cache.checksum !== undefined && cache.checksum !== undefined &&
cache.checksum === useSyncConfigStore().mergedConfig.themeChecksum cache.checksum === useMergedConfigStore().mergedConfig.themeChecksum
) { ) {
const eagerStyles = createStyleSheet(EAGER_STYLE_ID, 10) const eagerStyles = createStyleSheet(EAGER_STYLE_ID, 10)
const lazyStyles = createStyleSheet(LAZY_STYLE_ID, 20) const lazyStyles = createStyleSheet(LAZY_STYLE_ID, 20)

View file

@ -6,7 +6,7 @@ import { promiseInterval } from '../promise_interval/promise_interval.js'
import { useInstanceStore } from 'src/stores/instance.js' import { useInstanceStore } from 'src/stores/instance.js'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js' import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useInterfaceStore } from 'src/stores/interface.js' import { useInterfaceStore } from 'src/stores/interface.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useMergedConfigStore } from 'src/stores/merged_config.js'
const update = ({ const update = ({
store, store,
@ -46,7 +46,8 @@ const fetchAndUpdate = ({
const args = { timeline, credentials } const args = { timeline, credentials }
const rootState = store.rootState || store.state const rootState = store.rootState || store.state
const timelineData = rootState.statuses.timelines[camelCase(timeline)] const timelineData = rootState.statuses.timelines[camelCase(timeline)]
const { hideMutedPosts, replyVisibility } = useSyncConfigStore().mergedConfig const { hideMutedPosts, replyVisibility } =
useMergedConfigStore().mergedConfig
const loggedIn = !!rootState.users.currentUser const loggedIn = !!rootState.users.currentUser
if (older) { if (older) {

View file

@ -1,41 +1,146 @@
import { get, set } from 'lodash' import { get, set } from 'lodash'
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
import { instanceDefaultProperties } from '../modules/config.js'
import { import {
defaultConfigLocal, convertDefinitions,
instanceDefaultConfig, INSTANCE_DEFAULT_CONFIG,
instanceIdentityDefault, INSTANCE_DEFAULT_CONFIG_DEFINITIONS,
INSTANCE_IDENTITY_DEFAULT,
INSTANCE_IDENTITY_DEFAULT_DEFINITIONS,
LOCAL_DEFAULT_CONFIG,
LOCAL_DEFAULT_CONFIG_DEFINITIONS,
validateSetting,
} from '../modules/default_config_state.js' } from '../modules/default_config_state.js'
import apiService from '../services/api/api.service.js' import apiService from '../services/api/api.service.js'
import { useInterfaceStore } from 'src/stores/interface.js' import { useInterfaceStore } from 'src/stores/interface.js'
import { ensureFinalFallback } from 'src/i18n/languages.js'
const REMOTE_INTERACTION_URL = '/main/ostatus' const REMOTE_INTERACTION_URL = '/main/ostatus'
const defaultState = { const ROOT_STATE_DEFINITIONS = {
name: 'Pleroma FE', name: {
registrationOpen: true, type: 'string',
server: 'http://localhost:4040/', default: 'PleromaFE',
textlimit: 5000, },
privateMode: false, registrationOpen: {
federating: true, required: true,
federationPolicy: null, type: 'boolean',
themesIndex: null, },
stylesIndex: null, server: {
palettesIndex: null, description: 'Server URL',
themeData: null, // used for theme editor v2 required: true,
vapidPublicKey: null, type: 'string',
},
privateMode: {
description: 'Private instance?',
required: true,
type: 'boolean',
},
federating: {
description: 'Is federation enabled?',
required: true,
type: 'boolean',
},
federationPolicy: {
description: '????',
required: true,
type: 'object',
},
// Indexes of themes/styles/palettes
themesIndex: {
required: true,
type: 'object',
},
stylesIndex: {
required: true,
type: 'object',
},
palettesIndex: {
required: true,
type: 'object',
},
themeData: {
description: 'Used for theme v2 editor',
required: true,
type: 'object',
},
vapidPublicKey: {
description: 'Used for WebPush',
required: true,
type: 'string',
},
// Stuff from static/config.json // Stuff from static/config.json
loginMethod: 'password', loginMethod: {
disableUpdateNotification: false, description: 'Login method (token/password)',
default: 'password',
},
disableUpdateNotification: {
description: 'Disable update notification (pleroma-tan one)',
default: false,
},
knownDomains: {
description: 'List of known domains; used for domain list for domain mutes',
default: [],
},
// Moderation stuff
staffAccounts: {
description: 'List of staff accounts',
default: [],
},
accountActivationRequired: {
description:
'Account activation (by email or admin) required after registration',
required: true,
type: 'boolean',
},
accountApprovalRequired: {
description: 'Admin approval required after registration',
required: true,
type: 'boolean',
},
birthdayRequired: {
description: 'Require birthday entry when registering',
required: true,
type: 'boolean',
},
birthdayMinAge: {
description: 'Minimum age required for registration',
default: 0,
},
restrictedNicknames: {
description: 'List of nicknames that are not allowed',
default: [],
},
localBubbleInstances: {
description: "Akkoma's bubble feature, list of instances",
default: [],
}, // Akkoma
// Version Information
backendVersion: {
required: true,
type: 'string',
},
backendRepository: {
required: true,
type: 'string',
},
frontendVersion: {
required: true,
type: 'string',
},
}
const ROOT_STATE = convertDefinitions(ROOT_STATE_DEFINITIONS)
const DEFAULT_STATE = {
...ROOT_STATE,
// Instance-wide configurations that should not be changed by individual users // Instance-wide configurations that should not be changed by individual users
instanceIdentity: { instanceIdentity: {
...instanceIdentityDefault, ...INSTANCE_IDENTITY_DEFAULT,
}, },
limits: { limits: {
@ -44,6 +149,7 @@ const defaultState = {
backgroundlimit: null, backgroundlimit: null,
uploadlimit: null, uploadlimit: null,
fieldsLimits: null, fieldsLimits: null,
textLimit: null,
pollLimits: { pollLimits: {
max_options: 4, max_options: 4,
max_option_chars: 255, max_option_chars: 255,
@ -54,50 +160,53 @@ const defaultState = {
// Instance admins can override default settings for the whole instance // Instance admins can override default settings for the whole instance
prefsStorage: { prefsStorage: {
...instanceDefaultConfig, ...INSTANCE_DEFAULT_CONFIG,
...defaultConfigLocal, ...LOCAL_DEFAULT_CONFIG,
}, },
// Known domains list for user's domain-muting
knownDomains: [],
// Moderation stuff
staffAccounts: [],
accountActivationRequired: null,
accountApprovalRequired: null,
birthdayRequired: false,
birthdayMinAge: 0,
restrictedNicknames: [],
localBubbleInstances: [], // Akkoma
// Version Information
backendVersion: '',
backendRepository: '',
frontendVersion: '',
} }
console.log('===', ROOT_STATE_DEFINITIONS)
export const useInstanceStore = defineStore('instance', { export const useInstanceStore = defineStore('instance', {
state: () => ({ ...defaultState }), state: () => ({ ...DEFAULT_STATE }),
getters: { getters: {
instanceDefaultConfig(state) {
return instanceDefaultProperties
.map((key) => [key, state[key]])
.reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {})
},
instanceDomain(state) { instanceDomain(state) {
return new URL(this.server).hostname return new URL(this.server).hostname
}, },
}, },
actions: { actions: {
set({ path, name, value }) { set({ path, value }) {
if (get(defaultState, path ?? name) === undefined) let definition
console.error( const pathArray = path.split('.')
`Unknown instance option ${path ?? name}, value: ${value}`, const subpath = pathArray[1] ?? pathArray[0]
)
set(this, path ?? name, value) if (path.startsWith('instanceIdentity.')) {
definition = INSTANCE_IDENTITY_DEFAULT_DEFINITIONS[subpath]
} else if (path.startsWith('prefsStorage.')) {
definition = {
...LOCAL_DEFAULT_CONFIG_DEFINITIONS,
...INSTANCE_DEFAULT_CONFIG_DEFINITIONS,
}[subpath]
} else if (path.startsWith('limits.')) {
definition =
path === 'limits.pollLimits' || path === 'limits.fieldsLimits'
? { required: true, type: 'object' }
: { required: true, type: 'number' }
} else {
const definitions = ROOT_STATE_DEFINITIONS
definition = definitions[subpath]
}
if ((path ?? name) === 'name') useInterfaceStore().setPageTitle() const finalValue = validateSetting({
path,
value,
definition,
throwError: true,
defaultState: DEFAULT_STATE,
})
set(this, path, finalValue)
if (path === 'name') useInterfaceStore().setPageTitle()
}, },
async getKnownDomains() { async getKnownDomains() {
try { try {

View file

@ -8,6 +8,7 @@ import {
import { deserialize } from '../services/theme_data/iss_deserializer.js' import { deserialize } from '../services/theme_data/iss_deserializer.js'
import { useInstanceStore } from 'src/stores/instance.js' import { useInstanceStore } from 'src/stores/instance.js'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { import {
@ -186,7 +187,7 @@ export const useInterfaceStore = defineStore('interface', {
const mobileLayout = width <= 800 const mobileLayout = width <= 800
const normalOrMobile = mobileLayout ? 'mobile' : 'normal' const normalOrMobile = mobileLayout ? 'mobile' : 'normal'
const { thirdColumnMode } = useSyncConfigStore().mergedConfig const { thirdColumnMode } = useMergedConfigStore().mergedConfig
if (thirdColumnMode === 'none' || !window.vuex.state.users.currentUser) { if (thirdColumnMode === 'none' || !window.vuex.state.users.currentUser) {
this.layoutType = normalOrMobile this.layoutType = normalOrMobile
} else { } else {
@ -425,13 +426,13 @@ export const useInterfaceStore = defineStore('interface', {
styleCustomData: userStyleCustomData, styleCustomData: userStyleCustomData,
palette: userPaletteName, palette: userPaletteName,
paletteCustomData: userPaletteCustomData, paletteCustomData: userPaletteCustomData,
} = useSyncConfigStore().mergedConfig } = useMergedConfigStore().mergedConfig
let { let {
theme: userThemeV2Name, theme: userThemeV2Name,
customTheme: userThemeV2Snapshot, customTheme: userThemeV2Snapshot,
customThemeSource: userThemeV2Source, customThemeSource: userThemeV2Source,
} = useSyncConfigStore().mergedConfig } = useMergedConfigStore().mergedConfig
let majorVersionUsed let majorVersionUsed
@ -596,7 +597,7 @@ export const useInterfaceStore = defineStore('interface', {
this.themeApplied = true this.themeApplied = true
}, },
async applyTheme({ recompile = false } = {}) { async applyTheme({ recompile = false } = {}) {
const { mergedConfig } = useSyncConfigStore() const { mergedConfig } = useMergedConfigStore()
const { forceThemeRecompilation, themeDebug } = mergedConfig const { forceThemeRecompilation, themeDebug } = mergedConfig
this.themeChangeInProgress = true this.themeChangeInProgress = true

View file

@ -4,14 +4,18 @@ import { toRaw } from 'vue'
import { useInstanceStore } from 'src/stores/instance' import { useInstanceStore } from 'src/stores/instance'
import { defaultState as configDefaultState } from 'src/modules/default_config_state' import {
LOCAL_DEFAULT_CONFIG,
LOCAL_DEFAULT_CONFIG_DEFINITIONS,
validateSetting,
} from 'src/modules/default_config_state'
export const defaultState = { export const defaultState = {
prefsStorage: { prefsStorage: {
...configDefaultState, ...LOCAL_DEFAULT_CONFIG,
}, },
tempStorage: { tempStorage: {
...configDefaultState, ...LOCAL_DEFAULT_CONFIG,
}, },
} }
@ -21,7 +25,17 @@ export const useLocalConfigStore = defineStore('local_config', {
}, },
actions: { actions: {
set({ path, value }) { set({ path, value }) {
set(this.prefsStorage, path, value) const definition = LOCAL_DEFAULT_CONFIG_DEFINITIONS[path]
const finalValue = validateSetting({
path,
value,
definition,
throwError: false,
defaultState: LOCAL_DEFAULT_CONFIG,
})
set(this.prefsStorage, path, finalValue)
}, },
setTemporarily({ path, value }) { setTemporarily({ path, value }) {
set(this.tempStorage, path, value) set(this.tempStorage, path, value)
@ -42,8 +56,8 @@ export const useLocalConfigStore = defineStore('local_config', {
persist: { persist: {
afterLoad(state) { afterLoad(state) {
return { return {
prefsStorage: state.prefsStorage ?? { ...configDefaultState }, prefsStorage: state.prefsStorage ?? { ...LOCAL_DEFAULT_CONFIG },
tempStorage: { ...configDefaultState }, tempStorage: { ...LOCAL_DEFAULT_CONFIG },
} }
}, },
}, },

View file

@ -0,0 +1,69 @@
import { defineStore } from 'pinia'
import { useInstanceStore } from 'src/stores/instance.js'
import { useLocalConfigStore } from 'src/stores/local_config.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import {
INSTANCE_DEFAULT_CONFIG,
LOCAL_DEFAULT_CONFIG,
LOCAL_ONLY_KEYS,
} from 'src/modules/default_config_state.js'
const ROOT_CONFIG = {
...INSTANCE_DEFAULT_CONFIG,
...LOCAL_DEFAULT_CONFIG,
}
export const useMergedConfigStore = defineStore('merged_config', {
getters: {
mergedConfig: () => {
const instancePrefs = useInstanceStore().prefsStorage
const tempPrefs = useLocalConfigStore().tempStorage
const localPrefs = useLocalConfigStore().prefsStorage
const syncPrefs = useSyncConfigStore().prefsStorage
const getValue = (k) =>
tempPrefs[k] ?? localPrefs[k] ?? syncPrefs.simple[k]
const getDefault = (k) => instancePrefs[k] ?? ROOT_CONFIG[k]
const result = Object.fromEntries(
Object.keys(INSTANCE_DEFAULT_CONFIG).map((k) => [
k,
getValue(k) ?? getDefault(k),
]),
)
return result
},
mergedConfigDefault: () => {
const instancePrefs = useInstanceStore().prefsStorage
const getDefault = (k) => instancePrefs[k] ?? ROOT_CONFIG[k]
const result = Object.fromEntries(
Object.keys(INSTANCE_DEFAULT_CONFIG).map((k) => [
k,
getDefault(k),
]),
)
return result
},
mergedConfigWithoutDefaults: () => {
const instancePrefs = useInstanceStore().prefsStorage
const tempPrefs = useLocalConfigStore().tempStorage
const localPrefs = useLocalConfigStore().prefsStorage
const syncPrefs = useSyncConfigStore().prefsStorage
const getValue = (k) =>
tempPrefs[k] ?? localPrefs[k] ?? syncPrefs.simple[k] ?? instancePrefs[k]
const result = Object.fromEntries(
Object.keys(INSTANCE_DEFAULT_CONFIG).map(([k, value]) => [
k,
getValue(k),
]),
)
return result
},
},
})

View file

@ -25,9 +25,11 @@ import { useLocalConfigStore } from 'src/stores/local_config.js'
import { storage } from 'src/lib/storage.js' import { storage } from 'src/lib/storage.js'
import { import {
defaultState as configDefaultState, defaultState as configDefaultState,
defaultConfigLocal, INSTANCE_DEFAULT_CONFIG,
instanceDefaultConfig, INSTANCE_DEFAULT_CONFIG_DEFINITIONS,
LOCAL_DEFAULT_CONFIG,
LOCAL_ONLY_KEYS, LOCAL_ONLY_KEYS,
validateSetting,
} from 'src/modules/default_config_state.js' } from 'src/modules/default_config_state.js'
import { oldDefaultConfigSync } from 'src/modules/old_default_config_state.js' import { oldDefaultConfigSync } from 'src/modules/old_default_config_state.js'
@ -488,7 +490,19 @@ export const useSyncConfigStore = defineStore('sync_config', {
`Calling set on depth > 3 (path: ${path}) is not allowed`, `Calling set on depth > 3 (path: ${path}) is not allowed`,
) )
} }
set(this.prefsStorage, path, value)
const definition = INSTANCE_DEFAULT_CONFIG_DEFINITIONS[path.split('.')[1]]
const finalValue = validateSetting({
path: path.split('.')[1],
value,
definition,
throwError: false,
defaultState: INSTANCE_DEFAULT_CONFIG,
})
set(this.prefsStorage, path, finalValue)
this.prefsStorage._journal = [ this.prefsStorage._journal = [
...this.prefsStorage._journal, ...this.prefsStorage._journal,
{ operation: 'set', path, args: [value], timestamp: Date.now() }, { operation: 'set', path, args: [value], timestamp: Date.now() },
@ -738,51 +752,6 @@ export const useSyncConfigStore = defineStore('sync_config', {
window.vuex.state.api.backendInteractor.updateProfileJSON({ params }) window.vuex.state.api.backendInteractor.updateProfileJSON({ params })
}, },
}, },
getters: {
mergedConfig: (state) => {
const instancePrefs = useInstanceStore().prefsStorage
const localPrefs = useLocalConfigStore().prefsStorage
const tempPrefs = useLocalConfigStore().tempStorage
const result = Object.fromEntries(
Object.entries(state.prefsStorage.simple).map(([k, value]) => [
k,
LOCAL_ONLY_KEYS.has(k)
? (tempPrefs[k] ??
localPrefs[k] ??
instancePrefs[k] ??
defaultConfigLocal[k])
: (tempPrefs[k] ??
localPrefs[k] ??
value ??
instancePrefs[k] ??
instanceDefaultConfig[k]),
]),
)
return result
},
mergedConfigDefault: (state) => {
const instancePrefs = useInstanceStore().prefsStorage
const result = Object.fromEntries(
Object.entries(state.prefsStorage.simple).map(([k, value]) => [
k,
LOCAL_ONLY_KEYS.has(k)
? (instancePrefs[k] ?? defaultConfigLocal[k])
: (instancePrefs[k] ?? instanceDefaultConfig[k]),
]),
)
return result
},
mergedConfigWithoutDefaults: (state) => {
const localPrefs = useLocalConfigStore().prefsStorage
const result = Object.fromEntries(
Object.entries(state.prefsStorage.simple).map(([k, value]) => [
k,
LOCAL_ONLY_KEYS.has(k) ? localPrefs[k] : value,
]),
)
return result
},
},
persist: { persist: {
afterLoad(state) { afterLoad(state) {
return state return state

View file

@ -5,7 +5,7 @@ import 'virtual:pleroma-fe/service_worker_env'
import { createI18n } from 'vue-i18n' import { createI18n } from 'vue-i18n'
import { storage } from 'src/lib/storage.js' import { storage } from 'src/lib/storage.js'
import { instanceDefaultConfig } from 'src/modules/default_config_state.js' import { INSTANCE_DEFAULT_CONFIG } from 'src/modules/default_config_state.js'
import { parseNotification } from 'src/services/entity_normalizer/entity_normalizer.service.js' import { parseNotification } from 'src/services/entity_normalizer/entity_normalizer.service.js'
import { prepareNotificationObject } from 'src/services/notification_utils/notification_utils.js' import { prepareNotificationObject } from 'src/services/notification_utils/notification_utils.js'
import { cacheKey, emojiCacheKey, shouldCache } from 'src/services/sw/sw.js' import { cacheKey, emojiCacheKey, shouldCache } from 'src/services/sw/sw.js'
@ -40,7 +40,7 @@ const setSettings = async () => {
i18n.locale = locale i18n.locale = locale
const notificationsNativeArray = Object.entries( const notificationsNativeArray = Object.entries(
piniaState.prefsStorage.simple.notificationNative || piniaState.prefsStorage.simple.notificationNative ||
instanceDefaultConfig.notificationNative, INSTANCE_DEFAULT_CONFIG.notificationNative,
) )
state.webPushAlwaysShowNotifications = state.webPushAlwaysShowNotifications =
piniaState.prefsStorage.simple.webPushAlwaysShowNotifications piniaState.prefsStorage.simple.webPushAlwaysShowNotifications