diff --git a/src/components/settings_modal/tabs/appearance_tab.vue b/src/components/settings_modal/tabs/appearance_tab.vue index a0439ed4a..cd463a34a 100644 --- a/src/components/settings_modal/tabs/appearance_tab.vue +++ b/src/components/settings_modal/tabs/appearance_tab.vue @@ -235,7 +235,7 @@
  • {{ $t('settings.style.themes3.hacks.underlay_overrides') }} diff --git a/src/lib/style.js b/src/lib/style.js index 534d120e3..e91362c24 100644 --- a/src/lib/style.js +++ b/src/lib/style.js @@ -23,12 +23,15 @@ const APPEARANCE_SETTINGS_KEYS = [ 'forcedRoundness', 'emojiSize', 'emojiReactionsScale', +] + +const HACKS_KEYS = new Set([ 'fontInterface', 'fontPosts', 'fontInput', 'fontMonospace', 'underlay', -] +]) const MIXED_KEYS = new Set([ ...APPEARANCE_SETTINGS_KEYS, @@ -42,6 +45,8 @@ export const piniaStylePlugin = ({ store, options }) => { const { path } = args[0] if (MIXED_KEYS.has(path)) { after(() => applyStyleConfig(useMergedConfigStore().mergedConfig)) + } + if (HACKS_KEYS.has(path)) { after(() => useInterfaceStore().applyTheme({ recompile: true })) } } diff --git a/src/main.js b/src/main.js index 44b01aabb..ceb8c0878 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', 'config'], + paths: ['users.lastLoginName', 'oauth'], } ;(async () => { diff --git a/src/modules/config_declaration.js b/src/modules/config_declaration.js new file mode 100644 index 000000000..38619f4fb --- /dev/null +++ b/src/modules/config_declaration.js @@ -0,0 +1,45 @@ +import { useMergedConfigStore } from 'src/stores/merged_config.js' + +export const CONFIG_MIGRATION = 1 + +import { v4 as uuidv4 } from 'uuid' + +// for future use +/* +const simpleDeclaration = { + store: 'server-side', + migrationFlag: 'configMigration', + migration(serverside, rootState) { + serverside.setSimplePrefAndSave({ path: field, value: rootState.config[oldField ?? field] }) + } +} +*/ + +export const declarations = [ + { + field: 'muteFilters', + store: 'server-side', + migrationFlag: 'configMigration', + migrationNum: 1, + description: 'Mute filters, wordfilter/regexp/etc', + valueType: 'complex', + migration(serverside, rootState) { + useMergedConfigStore().mergedConfig.muteWords.forEach((word, order) => { + const uniqueId = uuidv4() + + serverside.setPreference({ + path: 'simple.muteFilters.' + uniqueId, + value: { + type: 'word', + value: word, + name: word, + enabled: true, + expires: null, + hide: false, + order, + }, + }) + }) + }, + }, +] diff --git a/src/modules/default_config_state.js b/src/modules/default_config_state.js index 5f797126d..1d7873309 100644 --- a/src/modules/default_config_state.js +++ b/src/modules/default_config_state.js @@ -531,17 +531,18 @@ export const INSTANCE_DEFAULT_CONFIG_DEFINITIONS = { type: 'string', required: false, }, + theme3hacks: { + description: 'Theme 3 hacks (need separation)', + type: 'object', + required: false, + default: {}, + }, highlights: { description: 'User highlights', type: 'object', required: false, default: {}, }, - underlay: { - description: 'Underlay override', - required: true, - default: 'none', - }, } export const INSTANCE_DEFAULT_CONFIG = convertDefinitions( INSTANCE_DEFAULT_CONFIG_DEFINITIONS, @@ -633,6 +634,11 @@ export const LOCAL_DEFAULT_CONFIG_DEFINITIONS = { description: 'Streaming API (WebSocket)', default: false, }, + underlay: { + description: 'Underlay override', + required: true, + default: 'none', + }, fontInterface: { description: 'Interface font override', type: 'object', @@ -760,7 +766,6 @@ export const validateSetting = ({ if (value === undefined) return undefined // only null is allowed as missing value if (definition === undefined) return undefined // invalid definition const path = fullPath.replace(/^simple./, '') - const depth = path.split('.') if ( validateObjects && definition.type === 'object' && @@ -772,6 +777,12 @@ export const validateSetting = ({ return undefined } + if (path.includes('muteFilters')) { + console.log('##', path, value, definition) + console.log(value) + console.log(path) + console.log('====') + } if (get(defaultState, path.split('.')[0]) === undefined) { const string = `Unknown option ${fullPath}, value: ${value}` @@ -800,7 +811,7 @@ export const validateSetting = ({ } } - if (depth > 2 && value !== null && type != null && typeof value !== type) { + 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) { diff --git a/src/modules/users.js b/src/modules/users.js index db5b16ccc..8b2a991c5 100644 --- a/src/modules/users.js +++ b/src/modules/users.js @@ -30,6 +30,8 @@ import { useOAuthStore } from 'src/stores/oauth.js' import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useUserHighlightStore } from 'src/stores/user_highlight.js' +import { declarations } from 'src/modules/config_declaration' + // TODO: Unify with mergeOrAdd in statuses.js export const mergeOrAdd = (arr, obj, item) => { if (!item) { @@ -740,6 +742,25 @@ const users = { useSyncConfigStore().setFlag({ flag: 'configMigration', value: 0 }) /**/ + const { configMigration } = useSyncConfigStore().flagStorage + declarations + .filter((x) => { + return ( + x.store === 'server-side' && + x.migrationNum > 0 && + x.migrationNum > configMigration + ) + }) + .toSorted((a, b) => a.configMigration - b.configMigration) + .forEach((value) => { + value.migration(useSyncConfigStore(), store.rootState) + useSyncConfigStore().setFlag({ + flag: 'configMigration', + value: value.migrationNum, + }) + useSyncConfigStore().pushSyncConfig() + }) + if (user.token) { dispatch('setWsToken', user.token) diff --git a/src/stores/sync_config.js b/src/stores/sync_config.js index 722dd7f16..d7422d0a9 100644 --- a/src/stores/sync_config.js +++ b/src/stores/sync_config.js @@ -14,7 +14,6 @@ import { uniqWith, unset, } from 'lodash' -import { v4 as uuidv4 } from 'uuid' import { defineStore } from 'pinia' import { toRaw } from 'vue' @@ -677,17 +676,15 @@ export const useSyncConfigStore = defineStore('sync_config', { // Various migrations console.debug('Migrating from old config') const vuexState = (await storage.getItem('vuex-lz')) ?? {} - const config = vuexState.config ?? {} + vuexState.config = vuexState.config ?? {} - const migratedEntries = new Set(config._syncMigration ?? []) + const migratedEntries = new Set(vuexState.config._syncMigration ?? []) console.debug( `Already migrated Values: ${[...migratedEntries].join() || '[none]'}`, ) - const { configMigration } = useSyncConfigStore().flagStorage - Object.entries(oldDefaultConfigSync).forEach(([key, value]) => { - const oldValue = config[key] + const oldValue = vuexState.config[key] const defaultValue = value const present = oldValue !== undefined @@ -713,27 +710,10 @@ export const useSyncConfigStore = defineStore('sync_config', { path: 'fontMonospace', value: oldValue.fonts.monospace, }) - useSyncConfigStore().setSimplePrefAndSave({ + useLocalConfigStore().set({ path: 'underlay', value: oldValue.underlay, }) - } else if (key == 'muteWords') { - oldValue.forEach((word, order) => { - const uniqueId = uuidv4() - - useSyncConfigStore().setPreference({ - path: 'simple.muteFilters.' + uniqueId, - value: { - type: 'word', - value: word, - name: word, - enabled: true, - expires: null, - hide: false, - order, - }, - }) - }) } else { this.setPreference({ path: `simple.${key}`, value: oldValue }) } @@ -742,8 +722,7 @@ export const useSyncConfigStore = defineStore('sync_config', { } }) - config._syncMigration = [...migratedEntries] - vuexState.config = config + vuexState.config._syncMigration = [...migratedEntries] storage.setItem('vuex-lz', vuexState) if (!needUpload && recent && stale) { @@ -810,7 +789,7 @@ export const useSyncConfigStore = defineStore('sync_config', { }) return finalValue === undefined - ? [path, definition.default] + ? definition.default : [path, finalValue] }) newState.prefsStorage.simple = Object.fromEntries( diff --git a/src/stores/user_highlight.js b/src/stores/user_highlight.js index 5ca13b6a9..ca61c6e4e 100644 --- a/src/stores/user_highlight.js +++ b/src/stores/user_highlight.js @@ -278,21 +278,21 @@ export const useUserHighlightStore = defineStore('user_highlight', { let dirty = false const vuexState = (await storage.getItem('vuex-lz')) ?? {} - const config = vuexState.config ?? {} - const highlight = config.highlight ?? {} + vuexState.config = vuexState.config ?? {} + const highlight = vuexState.config.highlight ?? {} Object.entries(highlight).forEach(([user, value]) => { if ((highlight[user]._migrated || 0) < 1) { dirty = true needUpload = true this.set({ user, value: clone(value) }) - highlight[user]._migrated = 1 + vuexState.config.highlight[user]._migrated = 1 console.debug( `[HIGHLIGHT] Migrating user ${user}: ${JSON.stringify(value)}`, ) } }) - storage.setItem('vuex-lz', { ...vuexState, config: { ...config, highlight } }) + storage.setItem('vuex-lz', vuexState) if (recent === null) { console.debug(