diff --git a/src/components/font_control/font_control.js b/src/components/font_control/font_control.js
index d7c5aa225..d1f3390cc 100644
--- a/src/components/font_control/font_control.js
+++ b/src/components/font_control/font_control.js
@@ -21,7 +21,14 @@ export default {
Popover,
LocalSettingIndicator,
},
- props: ['name', 'label', 'modelValue', 'fallback', 'options', 'no-inherit'],
+ props: [
+ 'name',
+ 'label',
+ 'modelValue',
+ 'fallback',
+ 'options',
+ 'no-inherit',
+ ],
mounted() {
useInterfaceStore().queryLocalFonts()
},
diff --git a/src/components/settings_modal/helpers/list_setting.js b/src/components/settings_modal/helpers/list_setting.js
index 232ea123f..c1d504cd5 100644
--- a/src/components/settings_modal/helpers/list_setting.js
+++ b/src/components/settings_modal/helpers/list_setting.js
@@ -1,8 +1,6 @@
import Checkbox from 'src/components/checkbox/checkbox.vue'
import Setting from './setting.js'
-import { useSyncConfigStore } from 'src/stores/sync_config.js'
-
export default {
...Setting,
data() {
@@ -45,7 +43,7 @@ export default {
if (this.forceNew) return true
if (!this.allowNew) return false
- const isExpert = useSyncConfigStore().mergedConfig.expertLevel > 0
+ const isExpert = this.$store.state.config.expertLevel > 0
const hasBuiltins = this.builtinEntries.length > 0
if (hasBuiltins) {
diff --git a/src/components/settings_modal/settings_modal.js b/src/components/settings_modal/settings_modal.js
index a99067f36..25c508bef 100644
--- a/src/components/settings_modal/settings_modal.js
+++ b/src/components/settings_modal/settings_modal.js
@@ -9,10 +9,6 @@ import PanelLoading from 'src/components/panel_loading/panel_loading.vue'
import Popover from '../popover/popover.vue'
import { useInterfaceStore } from 'src/stores/interface.js'
-import {
- LOCAL_ONLY_KEYS,
- useLocalConfigStore,
-} from 'src/stores/local_config.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import {
@@ -141,34 +137,7 @@ const SettingsModal = {
},
onImport(data) {
if (data) {
- Object.entries(data).forEach(([path, value]) => {
- if (LOCAL_ONLY_KEYS.has(path)) {
- useLocalConfigStore().set({ path, value })
- } else {
- if (path.startsWith('muteFilters')) {
- Object.keys(
- useSyncConfigStore().mergedConfig.muteFilters,
- ).forEach((key) => {
- useSyncConfigStore().unsetPreference({
- path: `simple.${path}.${key}`,
- })
- })
-
- Object.entries(value).forEach(([key, filter]) => {
- useSyncConfigStore().setPreference({
- path: `simple.${path}.${key}`,
- value: filter,
- })
- })
- } else {
- useSyncConfigStore().setPreference({
- path: `simple.${path}`,
- value,
- })
- }
- }
- })
- useSyncConfigStore().pushSyncConfig()
+ this.$store.dispatch('loadSettings', data)
}
},
restore() {
@@ -181,7 +150,7 @@ const SettingsModal = {
this.dataThemeExporter.exportData()
},
generateExport(theme = false) {
- const config = useSyncConfigStore().mergedConfigWithoutDefaults
+ const { config } = this.$store.state
let sample = config
if (!theme) {
const ignoreList = new Set([
@@ -190,9 +159,7 @@ const SettingsModal = {
'colors',
])
sample = Object.fromEntries(
- Object.entries(sample).filter(
- ([key, value]) => !ignoreList.has(key) && value !== undefined,
- ),
+ Object.entries(sample).filter(([key]) => !ignoreList.has(key)),
)
}
const clone = cloneDeep(sample)
diff --git a/src/components/settings_modal/settings_modal_user_content.js b/src/components/settings_modal/settings_modal_user_content.js
index 6c33b4fa6..ddee812ca 100644
--- a/src/components/settings_modal/settings_modal_user_content.js
+++ b/src/components/settings_modal/settings_modal_user_content.js
@@ -16,7 +16,6 @@ import SecurityTab from './tabs/security_tab/security_tab.vue'
import StyleTab from './tabs/style_tab/style_tab.vue'
import { useInterfaceStore } from 'src/stores/interface.js'
-import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
@@ -84,7 +83,7 @@ const SettingsModalContent = {
return useInterfaceStore().settingsModalState === 'visible'
},
expertLevel() {
- return useSyncConfigStore().mergedConfig.expertLevel
+ return this.$store.state.config.expertLevel
},
},
data() {
diff --git a/src/components/settings_modal/tabs/clutter_tab.js b/src/components/settings_modal/tabs/clutter_tab.js
index 85749ab3f..510425e2d 100644
--- a/src/components/settings_modal/tabs/clutter_tab.js
+++ b/src/components/settings_modal/tabs/clutter_tab.js
@@ -38,6 +38,55 @@ const ClutterTab = {
Object.entries(store.prefsStorage.simple.muteFilters),
muteFiltersObject: (store) => store.prefsStorage.simple.muteFilters,
}),
+ onMuteDefaultActionLv1: {
+ get() {
+ const value = this.$store.state.config.onMuteDefaultAction
+ if (value === 'ask' || value === 'forever') {
+ return value
+ } else {
+ return 'temporarily'
+ }
+ },
+ set(value) {
+ let realValue = value
+ if (value !== 'ask' && value !== 'forever') {
+ realValue = '14d'
+ }
+ useSyncConfigStore().setSimplePrefAndSave({
+ path: 'onMuteDefaultAction',
+ value: realValue,
+ })
+ },
+ },
+ onBlockDefaultActionLv1: {
+ get() {
+ const value = this.$store.state.config.onBlockDefaultAction
+ if (value === 'ask' || value === 'forever') {
+ return value
+ } else {
+ return 'temporarily'
+ }
+ },
+ set(value) {
+ let realValue = value
+ if (value !== 'ask' && value !== 'forever') {
+ realValue = '14d'
+ }
+ useSyncConfigStore().setSimplePrefAndSave({
+ path: 'onBlockDefaultAction',
+ value: realValue,
+ })
+ },
+ },
+ muteFiltersDraft() {
+ return Object.entries(this.muteFiltersDraftObject)
+ },
+ muteFiltersExpired() {
+ const now = Date.now()
+ return Object.entries(this.muteFiltersDraftObject).filter(
+ ([, { expires }]) => expires != null && expires <= now,
+ )
+ },
},
methods: {
...mapActions(useSyncConfigStore, [
diff --git a/src/components/settings_modal/tabs/clutter_tab.vue b/src/components/settings_modal/tabs/clutter_tab.vue
index 533cd85c6..8ae416ff8 100644
--- a/src/components/settings_modal/tabs/clutter_tab.vue
+++ b/src/components/settings_modal/tabs/clutter_tab.vue
@@ -83,7 +83,9 @@
-
+
{{ $t('settings.hide_shoutbox') }}
diff --git a/src/components/settings_modal/tabs/filtering_tab.js b/src/components/settings_modal/tabs/filtering_tab.js
index 3598de757..facc6073f 100644
--- a/src/components/settings_modal/tabs/filtering_tab.js
+++ b/src/components/settings_modal/tabs/filtering_tab.js
@@ -93,12 +93,14 @@ const FilteringTab = {
computed: {
...SharedComputedObject(),
...mapState(useSyncConfigStore, {
+ muteFilters: (store) =>
+ Object.entries(store.prefsStorage.simple.muteFilters),
muteFiltersObject: (store) => store.prefsStorage.simple.muteFilters,
}),
...mapState(useInstanceCapabilitiesStore, ['blockExpiration']),
onMuteDefaultActionLv1: {
get() {
- const value = useSyncConfigStore().mergedConfig.onMuteDefaultAction
+ const value = this.$store.state.config.onMuteDefaultAction
if (value === 'ask' || value === 'forever') {
return value
} else {
@@ -118,7 +120,7 @@ const FilteringTab = {
},
onBlockDefaultActionLv1: {
get() {
- const value = useSyncConfigStore().mergedConfig.onBlockDefaultAction
+ const value = this.$store.state.config.onBlockDefaultAction
if (value === 'ask' || value === 'forever') {
return value
} else {
@@ -149,7 +151,7 @@ const FilteringTab = {
methods: {
...mapActions(useSyncConfigStore, [
'setPreference',
- 'setSimplePrefAndSave',
+ 'setPrefAndSave',
'unsetPreference',
'unsetPrefAndSave',
'pushSyncConfig',
@@ -258,12 +260,6 @@ const FilteringTab = {
replyVisibility() {
this.$store.dispatch('queueFlushAll')
},
- muteFiltersObject() {
- console.log('UPDATE')
- this.muteFiltersDraftObject = cloneDeep(
- useSyncConfigStore().prefsStorage.simple.muteFilters,
- )
- },
},
}
diff --git a/src/components/settings_modal/tabs/posts_tab.vue b/src/components/settings_modal/tabs/posts_tab.vue
index 444f96392..d14475fc3 100644
--- a/src/components/settings_modal/tabs/posts_tab.vue
+++ b/src/components/settings_modal/tabs/posts_tab.vue
@@ -101,7 +101,6 @@
{{ $t('settings.mention_link_display') }}
@@ -172,10 +171,7 @@
-
+
{{ $t('settings.nsfw_clickthrough') }}
@@ -183,7 +179,6 @@
{{ $t('settings.preload_images') }}
@@ -193,7 +188,6 @@
{{ $t('settings.use_one_click_nsfw') }}
diff --git a/src/i18n/en.json b/src/i18n/en.json
index 0165af240..70c099932 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -381,7 +381,6 @@
"select_all": "Select all"
},
"settings": {
- "invalid_settings_imported": "Error importing settings",
"add_language": "Add fallback language",
"remove_language": "Remove",
"primary_language": "Primary language:",
diff --git a/src/main.js b/src/main.js
index ceb8c0878..a4269b4a7 100644
--- a/src/main.js
+++ b/src/main.js
@@ -41,7 +41,7 @@ const i18n = createI18n({
messages.setLanguage(i18n.global, currentLocale)
const persistedStateOptions = {
- paths: ['users.lastLoginName', 'oauth'],
+ paths: ['syncConfig.cache', 'config', 'users.lastLoginName', 'oauth'],
}
;(async () => {
diff --git a/src/modules/default_config_state.js b/src/modules/default_config_state.js
index a391e9b21..fbfaf08a3 100644
--- a/src/modules/default_config_state.js
+++ b/src/modules/default_config_state.js
@@ -49,6 +49,8 @@ export const instanceDefaultConfig = {
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
@@ -119,6 +121,7 @@ export const instanceDefaultConfig = {
modalMobileCenter: false,
playVideosInModal: false,
+ useOneClickNsfw: false,
useContainFit: true,
disableStickyHeaders: false,
showScrollbars: false,
@@ -162,9 +165,6 @@ export const instanceDefaultConfig = {
export const defaultConfigLocal = {
hideAttachments: false,
hideAttachmentsInConv: false,
- hideNsfw: true,
- useOneClickNsfw: false,
- preloadImage: true,
postContentType: 'text/plain',
sidebarRight: false,
sidebarColumnWidth: '25rem',
@@ -191,12 +191,9 @@ export const makeUndefined = (c) =>
export const defaultState = {
// Set these to undefined so it does not interfere with default settings check
...makeUndefined(instanceDefaultConfig),
- ...makeUndefined(defaultConfigLocal),
- // If there are any configurations that does not make sense to
- // have instance-wide default, put it here and explain why.
- // # Special processing
- // ## Theme stuff
+ // Special processing
+ // Theme stuff
theme: undefined, // Very old theme store, stores preset name, still in use
// V1
@@ -223,4 +220,15 @@ export const defaultState = {
monospace: undefined,
},
},
+
+ // Special handling: These fields are not of a primitive type, and
+ // might cause problems with current code because it specifically checks
+ // them in state.config (not getters.mergedConfig).
+
+ // Specifically, muteWords is now deprecated in favour of a server-side configuration.
+ muteWords: [],
+ highlight: {},
+
+ // If there are any configurations that does not make sense to
+ // have instance-wide default, put it here and explain why.
}
diff --git a/src/modules/old_default_config_state.js b/src/modules/old_default_config_state.js
index dc15e1c24..e53cafe29 100644
--- a/src/modules/old_default_config_state.js
+++ b/src/modules/old_default_config_state.js
@@ -18,6 +18,8 @@ export const defaultConfigSync = {
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
@@ -91,6 +93,7 @@ export const defaultConfigSync = {
modalMobileCenter: false,
playVideosInModal: false,
+ useOneClickNsfw: false,
useContainFit: true,
disableStickyHeaders: false,
showScrollbars: false,
@@ -166,9 +169,6 @@ export const defaultConfigSync = {
export const defaultConfigLocal = {
hideAttachments: false,
hideAttachmentsInConv: false,
- hideNsfw: true,
- useOneClickNsfw: false,
- preloadImage: true,
sidebarColumnWidth: '25rem',
contentColumnWidth: '45rem',
notifsColumnWidth: '25rem',
@@ -182,4 +182,6 @@ export const defaultConfigLocal = {
mentionLinkDisplay: 'short',
imageCompression: true,
alwaysUseJpeg: false,
+ imageCompression: true,
+ alwaysUseJpeg: false,
}
diff --git a/src/stores/local_config.js b/src/stores/local_config.js
index 3611b559e..117be393d 100644
--- a/src/stores/local_config.js
+++ b/src/stores/local_config.js
@@ -6,8 +6,6 @@ import { useInstanceStore } from 'src/stores/instance'
import { defaultState as configDefaultState } from 'src/modules/default_config_state'
-export const LOCAL_ONLY_KEYS = new Set(Object.keys(configDefaultState))
-
export const defaultState = {
prefsStorage: {
...configDefaultState,
@@ -34,7 +32,7 @@ export const useLocalConfigStore = defineStore('local_config', {
unset({ path, value }) {
set(this.prefsStorage, path, undefined)
},
- clearLocalConfig() {
+ clearSyncConfig() {
const blankState = { ...cloneDeep(defaultState) }
Object.keys(this).forEach((k) => {
this.prefsStorage[k] = blankState[k]
diff --git a/src/stores/sync_config.js b/src/stores/sync_config.js
index 996f32979..e43356e8e 100644
--- a/src/stores/sync_config.js
+++ b/src/stores/sync_config.js
@@ -18,21 +18,14 @@ import { toRaw } from 'vue'
import { CURRENT_UPDATE_COUNTER } from 'src/components/update_notification/update_notification.js'
import { useInstanceStore } from 'src/stores/instance.js'
-import {
- LOCAL_ONLY_KEYS,
- useLocalConfigStore,
-} from 'src/stores/local_config.js'
+import { useLocalConfigStore } from 'src/stores/local_config.js'
import { storage } from 'src/lib/storage.js'
-import {
- defaultState as configDefaultState,
- defaultConfigLocal,
- instanceDefaultConfig,
-} from 'src/modules/default_config_state.js'
+import { defaultState as configDefaultState } from 'src/modules/default_config_state.js'
import { defaultConfigSync } from 'src/modules/old_default_config_state.js'
export const VERSION = 2
-export const NEW_USER_DATE = new Date('2026-03-16') // date of writing this, basically
+export const NEW_USER_DATE = new Date('2022-08-04') // date of writing this, basically
export const COMMAND_TRIM_FLAGS = 1000
export const COMMAND_TRIM_FLAGS_AND_RESET = 1001
@@ -56,7 +49,6 @@ export const defaultState = {
dontShowUpdateNotifs: false,
collapseNav: false,
muteFilters: {},
-
...configDefaultState,
},
collections: {
@@ -623,14 +615,14 @@ export const useSyncConfigStore = defineStore('sync_config', {
let dirty = false
console.debug('Migrating from old config')
- const vuexState = (await storage.getItem('vuex-lz')) ?? {}
- vuexState.config = vuexState.config ?? {}
+ const vuexState = await storage.getItem('vuex-lz')
+ const { config } = vuexState
- const migratedEntries = new Set(vuexState.config._syncMigration ?? [])
+ const migratedEntries = new Set(config._syncMigration ?? [])
console.debug(`Already migrated Values: ${[...migratedEntries].join()}`)
Object.entries(defaultConfigSync).forEach(([key, value]) => {
- const oldValue = vuexState.config[key]
+ const oldValue = config[key]
const defaultValue = value
const present = oldValue !== undefined
@@ -638,13 +630,12 @@ export const useSyncConfigStore = defineStore('sync_config', {
const different = !isEqual(oldValue, defaultValue)
if (present && !migrated && different) {
- console.debug(`Migrating config ${key}: ${oldValue}`)
+ 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)
@@ -725,28 +716,9 @@ export const useSyncConfigStore = defineStore('sync_config', {
const localPrefs = useLocalConfigStore().prefsStorage
const tempPrefs = useLocalConfigStore().tempStorage
const result = Object.fromEntries(
- Object.entries(state.prefsStorage.simple).map(([k, value]) => [
+ Object.entries(state.prefsStorage.simple).map(([k, v]) => [
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
- },
- 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,
+ tempPrefs[k] ?? localPrefs[k] ?? v ?? instancePrefs[k],
]),
)
return result
diff --git a/src/stores/user_highlight.js b/src/stores/user_highlight.js
index ae2bd4d4c..c8868921a 100644
--- a/src/stores/user_highlight.js
+++ b/src/stores/user_highlight.js
@@ -278,10 +278,8 @@ export const useUserHighlightStore = defineStore('user_highlight', {
const userNew = userData.created_at > NEW_USER_DATE
let dirty = false
- const vuexState = (await storage.getItem('vuex-lz')) ?? {}
- vuexState.config = vuexState.config ?? {}
- const highlight = vuexState.config.highlight ?? {}
-
+ const vuexState = await storage.getItem('vuex-lz')
+ const { highlight } = vuexState.config
Object.entries(highlight).forEach(([user, value]) => {
if ((highlight[user]._migrated || 0) < 1) {
dirty = true
diff --git a/src/sw.js b/src/sw.js
index bfe35d3c5..e3225c91d 100644
--- a/src/sw.js
+++ b/src/sw.js
@@ -34,14 +34,14 @@ function getWindowClients() {
}
const setSettings = async () => {
- const piniaState = await storage.getItem('pinia-local-sync_config')
- const locale = piniaState.prefsStorage.simple.interfaceLanguage || 'en'
+ const vuexState = await storage.getItem('vuex-lz')
+ const locale = vuexState.config.interfaceLanguage || 'en'
i18n.locale = locale
const notificationsNativeArray = Object.entries(
- piniaState.prefsStorage.simple.notificationNative,
+ vuexState.config.notificationNative,
)
state.webPushAlwaysShowNotifications =
- piniaState.prefsStorage.simple.webPushAlwaysShowNotifications
+ vuexState.config.webPushAlwaysShowNotifications
state.allowedNotificationTypes = new Set(
notificationsNativeArray