-
-
- {{ ' ' }}
-
{{ backendDescriptionLabel + ' ' }}
@@ -36,6 +29,13 @@
:value="realDraftMode ? draft :state"
@change="update"
>
+ {{ ' ' }}
+
+
+
setMediaFile({ event, index })"
/>
diff --git a/src/components/settings_modal/tabs/clutter_tab.vue b/src/components/settings_modal/tabs/clutter_tab.vue
index 8ae416ff8..fe75582ed 100644
--- a/src/components/settings_modal/tabs/clutter_tab.vue
+++ b/src/components/settings_modal/tabs/clutter_tab.vue
@@ -62,18 +62,12 @@
-
+
{{ $t('settings.hide_attachments_in_tl') }}
-
+
{{ $t('settings.hide_attachments_in_convo') }}
diff --git a/src/components/settings_modal/tabs/composing_tab.js b/src/components/settings_modal/tabs/composing_tab.js
index b2ddbe54a..908582659 100644
--- a/src/components/settings_modal/tabs/composing_tab.js
+++ b/src/components/settings_modal/tabs/composing_tab.js
@@ -12,7 +12,6 @@ import SharedComputedObject from '../helpers/shared_computed_object.js'
import UnitSetting from '../helpers/unit_setting.vue'
import { useInstanceStore } from 'src/stores/instance.js'
-import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import localeService from 'src/services/locale/locale.service.js'
@@ -105,7 +104,7 @@ const ComposingTab = {
},
computed: {
postFormats() {
- return useInstanceCapabilitiesStore().postFormats
+ return useInstanceStore().postFormats || []
},
postContentOptions() {
return this.postFormats.map((format) => ({
diff --git a/src/components/settings_modal/tabs/composing_tab.vue b/src/components/settings_modal/tabs/composing_tab.vue
index 755539096..4b6c0bb51 100644
--- a/src/components/settings_modal/tabs/composing_tab.vue
+++ b/src/components/settings_modal/tabs/composing_tab.vue
@@ -29,7 +29,6 @@
id="postContentType"
path="postContentType"
:options="postContentOptions"
- :local="true"
>
{{ $t('settings.default_post_status_content_type') }}
@@ -91,7 +90,6 @@
{{ $t('settings.image_compression') }}
@@ -100,7 +98,6 @@
diff --git a/src/components/settings_modal/tabs/general_tab.vue b/src/components/settings_modal/tabs/general_tab.vue
index a3cb5be07..905a2baec 100644
--- a/src/components/settings_modal/tabs/general_tab.vue
+++ b/src/components/settings_modal/tabs/general_tab.vue
@@ -68,6 +68,7 @@
name="ui"
:label="$t('settings.style.fonts.components_inline.interface')"
:fallback="{ family: 'sans-serif' }"
+ :is-local="true"
no-inherit="1"
@update:model-value="v => updateFont('interface', v)"
/>
@@ -76,6 +77,7 @@
updateFont('input', v)"
@@ -98,7 +100,6 @@
{{ $t('settings.emoji_reactions_scale') }}
diff --git a/src/components/settings_modal/tabs/layout_tab.vue b/src/components/settings_modal/tabs/layout_tab.vue
index ca514e0cb..acae859a0 100644
--- a/src/components/settings_modal/tabs/layout_tab.vue
+++ b/src/components/settings_modal/tabs/layout_tab.vue
@@ -40,7 +40,6 @@
@@ -84,18 +83,12 @@
-
+
{{ $t('settings.right_sidebar') }}
-
+
{{ $t('settings.navbar_column_stretch') }}
diff --git a/src/components/user_avatar/user_avatar.js b/src/components/user_avatar/user_avatar.js
index d484303c1..fdf766f58 100644
--- a/src/components/user_avatar/user_avatar.js
+++ b/src/components/user_avatar/user_avatar.js
@@ -37,7 +37,7 @@ const UserAvatar = {
data() {
return {
showPlaceholder: false,
- defaultAvatar: `${useInstanceStore().server + useInstanceStore().instanceIdentity.defaultAvatar}`,
+ defaultAvatar: `${useInstanceStore().server + useInstanceStore().defaultAvatar}`,
betterShadow: useInterfaceStore().browserSupport.cssFilter,
}
},
diff --git a/src/modules/api.js b/src/modules/api.js
index 6f4b8b15f..d6bf27f23 100644
--- a/src/modules/api.js
+++ b/src/modules/api.js
@@ -345,7 +345,7 @@ const api = {
// Set up websocket connection
const token = state.wsToken
if (
- useInstanceCapabilitiesStore().shoutAvailable &&
+ useInstanceStore().shoutAvailable &&
typeof token !== 'undefined' &&
state.socket === null
) {
diff --git a/src/modules/default_config_state.js b/src/modules/default_config_state.js
index fbfaf08a3..af2f60ac4 100644
--- a/src/modules/default_config_state.js
+++ b/src/modules/default_config_state.js
@@ -45,6 +45,7 @@ export const instanceDefaultConfig = {
muteSensitiveStatuses: false,
collapseMessageWithSubject: false,
padEmoji: true,
+ hideAttachments: false,
hideAttachmentsInConv: false,
hideScrobbles: false,
hideScrobblesAfter: '2d',
@@ -94,9 +95,12 @@ export const instanceDefaultConfig = {
webPushAlwaysShowNotifications: false,
interfaceLanguage: browserLocale,
hideScopeNotice: false,
+ useStreamingApi: false,
+ sidebarRight: false,
scopeCopy: true,
subjectLineBehavior: 'email',
alwaysShowSubjectInput: true,
+ postContentType: 'text/plain',
minimalScopesMode: false,
// This hides statuses filtered via a word filter
@@ -129,8 +133,19 @@ export const instanceDefaultConfig = {
userPopoverOverlay: false,
userCardLeftJustify: false,
userCardHidePersonalMarks: false,
+ sidebarColumnWidth: '25rem',
+ contentColumnWidth: '45rem',
+ notifsColumnWidth: '25rem',
+ themeEditorMinWidth: '0rem',
+ emojiReactionsScale: 0.5,
+ textSize: '1rem',
+ emojiSize: '2.2rem',
+ navbarSize: '3.5rem',
+ panelHeaderSize: '3.2rem',
forcedRoundness: -1,
+ navbarColumnStretch: false,
greentext: false,
+ mentionLinkDisplay: 'short',
mentionLinkShowTooltip: true,
mentionLinkShowAvatar: false,
mentionLinkFadeDomain: true,
@@ -160,27 +175,8 @@ export const instanceDefaultConfig = {
useAbsoluteTimeFormat: false,
absoluteTimeFormatMinAge: '0d',
absoluteTime12h: '24h',
-}
-
-export const defaultConfigLocal = {
- hideAttachments: false,
- hideAttachmentsInConv: false,
- postContentType: 'text/plain',
- sidebarRight: false,
- sidebarColumnWidth: '25rem',
- contentColumnWidth: '45rem',
- notifsColumnWidth: '25rem',
- themeEditorMinWidth: '0rem',
- emojiReactionsScale: 0.5,
- textSize: '1rem',
- emojiSize: '2.2rem',
- navbarSize: '3.5rem',
- panelHeaderSize: '3.2rem',
- navbarColumnStretch: false,
- mentionLinkDisplay: 'short',
- alwaysUseJpeg: false,
imageCompression: true,
- useStreamingApi: false,
+ alwaysUseJpeg: false,
}
export const makeUndefined = (c) =>
diff --git a/src/modules/old_default_config_state.js b/src/modules/old_default_config_state.js
index e53cafe29..3977a5d89 100644
--- a/src/modules/old_default_config_state.js
+++ b/src/modules/old_default_config_state.js
@@ -1,187 +1,129 @@
// this is a snapshot of config keys used prior to sync config.
// used to migrate from old config.
+export const defaultStateKeys = [
+ 'expertLevel',
+ 'hideISP',
+ 'hideInstanceWallpaper',
+ 'hideShoutbox',
+ 'hideMutedPosts',
+ 'hideMutedThreads',
+ 'hideWordFilteredPosts',
+ 'muteBotStatuses',
+ 'muteSensitiveStatuses',
+ 'collapseMessageWithSubject',
+ 'padEmoji',
+ 'hideAttachments',
+ 'hideAttachmentsInConv',
+ 'hideScrobbles',
+ 'hideScrobblesAfter',
+ 'maxThumbnails',
+ 'hideNsfw',
+ 'preloadImage',
+ 'loopVideo',
+ 'loopVideoSilentOnly',
+ 'streaming',
+ 'emojiReactionsOnTimeline',
+ 'alwaysShowNewPostButton',
+ 'autohideFloatingPostButton',
+ 'pauseOnUnfocused',
+ 'stopGifs',
+ 'replyVisibility',
+ 'thirdColumnMode',
+ 'notificationVisibility',
+ 'notificationNative',
+ 'webPushNotifications',
+ 'webPushAlwaysShowNotifications',
+ 'interfaceLanguage',
+ 'hideScopeNotice',
+ 'useStreamingApi',
+ 'sidebarRight',
+ 'scopeCopy',
+ 'subjectLineBehavior',
+ 'alwaysShowSubjectInput',
+ 'postContentType',
+ 'minimalScopesMode',
+ 'hideFilteredStatuses',
+ 'modalOnRepeat',
+ 'modalOnUnfollow',
+ 'modalOnBlock',
+ 'modalOnMute',
+ 'modalOnMuteConversation',
+ 'modalOnMuteDomain',
+ 'modalOnDelete',
+ 'modalOnLogout',
+ 'modalOnApproveFollow',
+ 'modalOnDenyFollow',
+ 'modalOnRemoveUserFromFollowers',
+ 'onMuteDefaultAction',
+ 'onBlockDefaultAction',
+ 'modalMobileCenter',
+ 'playVideosInModal',
+ 'useOneClickNsfw',
+ 'useContainFit',
+ 'disableStickyHeaders',
+ 'showScrollbars',
+ 'userPopoverAvatarAction',
+ 'userPopoverOverlay',
+ 'userCardLeftJustify',
+ 'userCardHidePersonalMarks',
+ 'sidebarColumnWidth',
+ 'contentColumnWidth',
+ 'notifsColumnWidth',
+ 'themeEditorMinWidth',
+ 'emojiReactionsScale',
+ 'textSize',
+ 'emojiSize',
+ 'navbarSize',
+ 'panelHeaderSize',
+ 'forcedRoundness',
+ 'navbarColumnStretch',
+ 'greentext',
+ 'mentionLinkDisplay',
+ 'mentionLinkShowTooltip',
+ 'mentionLinkShowAvatar',
+ 'mentionLinkFadeDomain',
+ 'mentionLinkShowYous',
+ 'mentionLinkBoldenYou',
+ 'hidePostStats',
+ 'hideBotIndication',
+ 'hideUserStats',
+ 'virtualScrolling',
+ 'sensitiveByDefault',
+ 'conversationDisplay',
+ 'conversationTreeAdvanced',
+ 'conversationOtherRepliesButton',
+ 'conversationTreeFadeAncestors',
+ 'showExtraNotifications',
+ 'showExtraNotificationsTip',
+ 'showChatsInExtraNotifications',
+ 'showAnnouncementsInExtraNotifications',
+ 'showFollowRequestsInExtraNotifications',
+ 'maxDepthInThread',
+ 'autocompleteSelect',
+ 'closingDrawerMarksAsSeen',
+ 'unseenAtTop',
+ 'ignoreInactionableSeen',
+ 'unsavedPostAction',
+ 'autoSaveDraft',
+ 'useAbsoluteTimeFormat',
+ 'absoluteTimeFormatMinAge',
+ 'absoluteTime12h',
+ 'imageCompression',
+ 'alwaysUseJpeg',
+ 'theme',
-// commented entries are unsynced stuff
-export const defaultConfigSync = {
- expertLevel: 0, // used to track which settings to show and hide
- hideISP: false,
- hideInstanceWallpaper: false,
- hideShoutbox: false,
- // bad name: actually hides posts of muted USERS
- hideMutedPosts: false,
- hideMutedThreads: true,
- hideWordFilteredPosts: false,
- muteBotStatuses: false,
- muteSensitiveStatuses: false,
- collapseMessageWithSubject: false,
- padEmoji: true,
- hideScrobbles: false,
- hideScrobblesAfter: '2d',
- maxThumbnails: 16,
- hideNsfw: true,
- preloadImage: true,
- loopVideo: true,
- loopVideoSilentOnly: true,
- /// This is not the streaming API configuration, but rather an option
- /// for automatically loading new posts into the timeline without
- /// the user clicking the Show New button.
- streaming: false,
- emojiReactionsOnTimeline: true,
- alwaysShowNewPostButton: false,
- autohideFloatingPostButton: false,
- pauseOnUnfocused: true,
- stopGifs: true,
- replyVisibility: 'all',
- thirdColumnMode: 'notifications',
- notificationVisibility: {
- follows: true,
- mentions: true,
- statuses: true,
- likes: true,
- repeats: true,
- moves: true,
- emojiReactions: true,
- followRequest: true,
- reports: true,
- chatMention: true,
- polls: true,
- },
- notificationNative: {
- follows: true,
- mentions: true,
- statuses: true,
- likes: false,
- repeats: false,
- moves: false,
- emojiReactions: false,
- followRequest: true,
- reports: true,
- chatMention: true,
- polls: true,
- },
- webPushNotifications: false,
- webPushAlwaysShowNotifications: false,
- //interfaceLanguage: '',
- hideScopeNotice: false,
- useStreamingApi: false,
- sidebarRight: false,
- scopeCopy: true,
- subjectLineBehavior: 'email',
- alwaysShowSubjectInput: true,
- postContentType: 'text/plain',
- minimalScopesMode: false,
+ 'colors',
- // This hides statuses filtered via a word filter
- hideFilteredStatuses: false,
+ 'customTheme',
+ 'customThemeSource',
- // Confirmations
- modalOnRepeat: false,
- modalOnUnfollow: false,
- modalOnBlock: true,
- modalOnMute: false,
- modalOnMuteConversation: false,
- modalOnMuteDomain: true,
- modalOnDelete: true,
- modalOnLogout: true,
- modalOnApproveFollow: false,
- modalOnDenyFollow: false,
- modalOnRemoveUserFromFollowers: false,
-
- // Expiry confirmations/default actions
- onMuteDefaultAction: 'ask',
- onBlockDefaultAction: 'ask',
-
- modalMobileCenter: false,
- playVideosInModal: false,
- useOneClickNsfw: false,
- useContainFit: true,
- disableStickyHeaders: false,
- showScrollbars: false,
- userPopoverAvatarAction: 'open',
- userPopoverOverlay: false,
- userCardLeftJustify: false,
- userCardHidePersonalMarks: false,
- forcedRoundness: -1,
- greentext: false,
- mentionLinkShowTooltip: true,
- mentionLinkShowAvatar: false,
- mentionLinkFadeDomain: true,
- mentionLinkShowYous: false,
- mentionLinkBoldenYou: true,
- hidePostStats: false,
- hideBotIndication: false,
- hideUserStats: false,
- virtualScrolling: true,
- sensitiveByDefault: false,
- conversationDisplay: 'linear',
- conversationTreeAdvanced: false,
- conversationOtherRepliesButton: 'below',
- conversationTreeFadeAncestors: false,
- showExtraNotifications: true,
- showExtraNotificationsTip: true,
- showChatsInExtraNotifications: true,
- showAnnouncementsInExtraNotifications: true,
- showFollowRequestsInExtraNotifications: true,
- maxDepthInThread: 6,
- autocompleteSelect: false,
- closingDrawerMarksAsSeen: true,
- unseenAtTop: false,
- ignoreInactionableSeen: false,
- unsavedPostAction: 'confirm',
- autoSaveDraft: false,
- useAbsoluteTimeFormat: false,
- absoluteTimeFormatMinAge: '0d',
- absoluteTime12h: '24h',
- theme3hacks: {
- // Hacks, user overrides that are independent of theme used
- underlay: 'none',
- fonts: {
- interface: undefined,
- input: undefined,
- post: undefined,
- monospace: undefined,
- },
- },
- // Special processing
- // Theme stuff
- theme: undefined, // Very old theme store, stores preset name, still in use
-
- // V1
- colors: {}, // VERY old theme store, just colors of V1, probably not even used anymore
-
- // V2
- customTheme: undefined, // "snapshot", previously was used as actual theme store for V2 so it's still used in case of PleromaFE downgrade event.
- customThemeSource: undefined, // "source", stores original theme data
-
- // V3
- style: null,
- styleCustomData: null,
- palette: null,
- paletteCustomData: null,
- themeDebug: false, // debug mode that uses computed backgrounds instead of real ones to debug contrast functions
- forceThemeRecompilation: false, // flag that forces recompilation on boot even if cache exists
-
- // Those are handled outside config now
- // muteWords: [],
- // highlight: {},
-}
-
-export const defaultConfigLocal = {
- hideAttachments: false,
- hideAttachmentsInConv: false,
- sidebarColumnWidth: '25rem',
- contentColumnWidth: '45rem',
- notifsColumnWidth: '25rem',
- themeEditorMinWidth: '0rem',
- emojiReactionsScale: 0.5,
- textSize: '1rem',
- emojiSize: '2.2rem',
- navbarSize: '3.5rem',
- panelHeaderSize: '3.2rem',
- navbarColumnStretch: false,
- mentionLinkDisplay: 'short',
- imageCompression: true,
- alwaysUseJpeg: false,
- imageCompression: true,
- alwaysUseJpeg: false,
-}
+ 'style',
+ 'styleCustomData',
+ 'palette',
+ 'paletteCustomData',
+ 'themeDebug',
+ 'forceThemeRecompilation',
+ 'theme3hacks',
+ // 'muteWords', // mutes migrated separately
+ // 'highlight', // highlight migration is done separately
+]
diff --git a/src/stores/sync_config.js b/src/stores/sync_config.js
index e43356e8e..c460b38b0 100644
--- a/src/stores/sync_config.js
+++ b/src/stores/sync_config.js
@@ -22,7 +22,7 @@ import { useLocalConfigStore } from 'src/stores/local_config.js'
import { storage } from 'src/lib/storage.js'
import { defaultState as configDefaultState } from 'src/modules/default_config_state.js'
-import { defaultConfigSync } from 'src/modules/old_default_config_state.js'
+import { defaultStateKeys } from 'src/modules/old_default_config_state.js'
export const VERSION = 2
export const NEW_USER_DATE = new Date('2022-08-04') // date of writing this, basically
@@ -38,6 +38,7 @@ export const defaultState = {
// storage of flags - stuff that can only be set and incremented
flagStorage: {
updateCounter: 0, // Counter for most recent update notification seen
+ configMigration: 0, // Counter for config -> server-side migrations
reset: 0, // special flag that can be used to force-reset all data, debug purposes only
// special reset codes:
// 1000: trim keys to those known by currently running FE
@@ -416,6 +417,14 @@ export const _doMigrations = async (data, setPreference) => {
console.debug(
'Data has older version, seeing if there any migrations that can be applied',
)
+
+ if (data._version === 1) {
+ // Migrate old config to sync config
+ const vuexState = await storage.getItem('vuex-lz')
+ defaultStateKeys.forEach((key) => {
+ setPreference({ path: `simple.${key}`, value: vuexState.config[key] })
+ })
+ }
}
if (data._version > VERSION) {
@@ -614,31 +623,6 @@ export const useSyncConfigStore = defineStore('sync_config', {
const flagsTemplate = userNew ? newUserFlags : defaultState.flagStorage
let dirty = false
- console.debug('Migrating from old config')
- const vuexState = await storage.getItem('vuex-lz')
- const { config } = vuexState
-
- const migratedEntries = new Set(config._syncMigration ?? [])
- console.debug(`Already migrated Values: ${[...migratedEntries].join()}`)
-
- Object.entries(defaultConfigSync).forEach(([key, value]) => {
- const oldValue = config[key]
- const defaultValue = value
-
- const present = oldValue !== undefined
- const migrated = migratedEntries.has(key)
- const different = !isEqual(oldValue, defaultValue)
-
- if (present && !migrated && different) {
- console.debug(`Migrating config ${key}: ${oldValue}`,)
- this.setPreference({ path: `simple.${key}`, oldValue })
- migratedEntries.add(key)
- needUpload = true
- }
- })
- vuexState.config._syncMigration = [...migratedEntries]
- storage.setItem('vuex-lz', vuexState)
-
if (recent === null) {
console.debug(
`Data is empty, initializing for ${userNew ? 'new' : 'existing'} user`,
@@ -657,12 +641,7 @@ export const useSyncConfigStore = defineStore('sync_config', {
// discarding timestamps and versions
const { _timestamp: _0, _version: _1, ...recentData } = recent
const { _timestamp: _2, _version: _3, ...staleData } = stale
- dirty = !isEqual(
- // Something wrong happens if we compare both objects directly
- // or with cloneDeep()
- JSON.parse(JSON.stringify(recentData)),
- JSON.parse(JSON.stringify(staleData)),
- )
+ dirty = !isEqual(recentData, staleData)
console.debug(`Data ${dirty ? 'needs' : "doesn't need"} merging`)
}