diff --git a/src/components/emoji_reactions/emoji_reactions.js b/src/components/emoji_reactions/emoji_reactions.js index e1a28a8f1..8a121befc 100644 --- a/src/components/emoji_reactions/emoji_reactions.js +++ b/src/components/emoji_reactions/emoji_reactions.js @@ -2,8 +2,6 @@ import StillImage from 'src/components/still-image/still-image.vue' import UserAvatar from '../user_avatar/user_avatar.vue' import UserListPopover from '../user_list_popover/user_list_popover.vue' -import { useInstanceStore } from 'src/stores/instance.js' - import { library } from '@fortawesome/fontawesome-svg-core' import { faCheck, faMinus, faPlus } from '@fortawesome/free-solid-svg-icons' @@ -44,7 +42,7 @@ const EmojiReactions = { return !!this.$store.state.users.currentUser }, remoteInteractionLink() { - return useInstanceStore().getRemoteInteractionLink({ + return this.$store.getters.remoteInteractionLink({ statusId: this.status.id, }) }, diff --git a/src/components/settings_modal/tabs/general_tab.js b/src/components/settings_modal/tabs/general_tab.js index d94191c9d..b0eac97c0 100644 --- a/src/components/settings_modal/tabs/general_tab.js +++ b/src/components/settings_modal/tabs/general_tab.js @@ -48,6 +48,9 @@ const GeneralTab = { }, ...SharedComputedObject(), ...mapState(useInstanceCapabilitiesStore, ['blockExpiration']), + ...mapState(useSyncConfigStore, { + theme3hacks: (store) => store.mergedConfig.theme3hacks, + }), }, methods: { updateProfile() { @@ -64,8 +67,17 @@ const GeneralTab = { this.$store.commit('setCurrentUser', user) }) }, - updateFont(path, value) { - useLocalConfigStore().set({ path, value }) + updateFont(key, value) { + useLocalConfigStore().set({ + path: 'theme3hacks', + value: { + ...this.mergedConfig.theme3hacks, + fonts: { + ...this.mergedConfig.theme3hacks.fonts, + [key]: value, + }, + }, + }) }, }, } diff --git a/src/components/settings_modal/tabs/general_tab.vue b/src/components/settings_modal/tabs/general_tab.vue index 19800e0dd..a3cb5be07 100644 --- a/src/components/settings_modal/tabs/general_tab.vue +++ b/src/components/settings_modal/tabs/general_tab.vue @@ -64,21 +64,21 @@
  • diff --git a/src/components/settings_modal/tabs/posts_tab.js b/src/components/settings_modal/tabs/posts_tab.js index ab00e52e7..467c2a4da 100644 --- a/src/components/settings_modal/tabs/posts_tab.js +++ b/src/components/settings_modal/tabs/posts_tab.js @@ -4,10 +4,9 @@ import ChoiceSetting from '../helpers/choice_setting.vue' import IntegerSetting from '../helpers/integer_setting.vue' import SharedComputedObject from '../helpers/shared_computed_object.js' -import { useLocalConfigStore } from 'src/stores/local_config.js' import { useSyncConfigStore } from 'src/stores/sync_config.js' -const PostsTab = { +const GeneralTab = { data() { return { conversationDisplayOptions: ['tree', 'linear'].map((mode) => ({ @@ -67,10 +66,19 @@ const PostsTab = { ...SharedComputedObject(), }, methods: { - updateFont(path, value) { - useLocalConfigStore().set({ path, value }) + updateFont(key, value) { + useSyncConfigStore().setSimplePrefAndSave({ + path: 'theme3hacks', + value: { + ...this.mergedConfig.theme3hacks, + fonts: { + ...this.mergedConfig.theme3hacks.fonts, + [key]: value, + }, + }, + }) }, }, } -export default PostsTab +export default GeneralTab diff --git a/src/components/settings_modal/tabs/posts_tab.vue b/src/components/settings_modal/tabs/posts_tab.vue index 1e684246d..444f96392 100644 --- a/src/components/settings_modal/tabs/posts_tab.vue +++ b/src/components/settings_modal/tabs/posts_tab.vue @@ -56,20 +56,22 @@
  • diff --git a/src/lib/style.js b/src/lib/style.js index 343d24aea..50120b37b 100644 --- a/src/lib/style.js +++ b/src/lib/style.js @@ -1,4 +1,3 @@ -import { useInterfaceStore } from 'src/stores/interface.js' import { useSyncConfigStore } from 'src/stores/sync_config.js' import { applyStyleConfig } from 'src/services/style_setter/style_setter.js' @@ -24,15 +23,6 @@ const APPEARANCE_SETTINGS_KEYS = [ 'emojiSize', 'emojiReactionsScale', ] - -const HACKS_KEYS = new Set([ - 'fontInterface', - 'fontPosts', - 'fontInput', - 'fontMonospace', - 'underlay', -]) - const MIXED_KEYS = new Set([ ...APPEARANCE_SETTINGS_KEYS, ...APPEARANCE_SETTINGS_KEYS.map((x) => 'simple.' + x), @@ -46,9 +36,6 @@ export const piniaStylePlugin = ({ store, options }) => { if (MIXED_KEYS.has(path)) { after(() => applyStyleConfig(useSyncConfigStore().mergedConfig)) } - if (HACKS_KEYS.has(path)) { - after(() => useInterfaceStore().applyTheme({ recompile: true })) - } } }) } diff --git a/src/modules/default_config_state.js b/src/modules/default_config_state.js index 8634752bd..7823777a9 100644 --- a/src/modules/default_config_state.js +++ b/src/modules/default_config_state.js @@ -181,13 +181,6 @@ export const defaultConfigLocal = { alwaysUseJpeg: false, imageCompression: true, useStreamingApi: false, - underlay: 'none', - fontInterface: undefined, - fontInput: undefined, - fontPosts: undefined, - fontMonospace: undefined, - 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 } export const LOCAL_ONLY_KEYS = new Set(Object.keys(defaultConfigLocal)) @@ -219,4 +212,16 @@ export const defaultState = { 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 + theme3hacks: { + // Hacks, user overrides that are independent of theme used + underlay: 'none', + fonts: { + interface: undefined, + input: undefined, + post: undefined, + monospace: undefined, + }, + }, } diff --git a/src/modules/old_default_config_state.js b/src/modules/old_default_config_state.js index 935239d16..dc15e1c24 100644 --- a/src/modules/old_default_config_state.js +++ b/src/modules/old_default_config_state.js @@ -2,7 +2,7 @@ // used to migrate from old config. // commented entries are unsynced stuff -export const oldDefaultConfigSync = { +export const defaultConfigSync = { expertLevel: 0, // used to track which settings to show and hide hideISP: false, hideInstanceWallpaper: false, diff --git a/src/modules/users.js b/src/modules/users.js index d9e42ea76..e741877a6 100644 --- a/src/modules/users.js +++ b/src/modules/users.js @@ -702,15 +702,13 @@ const users = { user.domainMutes = [] commit('setCurrentUser', user) - useSyncConfigStore() - .initSyncConfig(user) - .then(() => { - useInterfaceStore() - .applyTheme() - .catch((e) => { - console.error('Error setting theme', e) - }) - }) + useSyncConfigStore().initSyncConfig(user).then(() => { + useInterfaceStore() + .applyTheme() + .catch((e) => { + console.error('Error setting theme', e) + }) + }) useUserHighlightStore().initUserHighlight(user) commit('addNewUsers', [user]) diff --git a/src/stores/interface.js b/src/stores/interface.js index 32a8226b4..5840d6b34 100644 --- a/src/stores/interface.js +++ b/src/stores/interface.js @@ -598,9 +598,8 @@ export const useInterfaceStore = defineStore('interface', { this.themeApplied = true }, async applyTheme({ recompile = false } = {}) { - const { mergedConfig } = useSyncConfigStore() - const { forceThemeRecompilation, themeDebug } = mergedConfig - + const { forceThemeRecompilation, themeDebug, theme3hacks } = + useSyncConfigStore().mergedConfig this.themeChangeInProgress = true // If we're not forced to recompile try using // cache (tryLoadCache return true if load successful) @@ -647,41 +646,68 @@ export const useInterfaceStore = defineStore('interface', { convertTheme2To3(normalizeThemeData(this.themeDataUsed)) const hacks = [] - const fontMap = { - Interface: 'Root', - Input: 'Input', - Posts: 'Post', - Monospace: 'Root', - } - - Object.entries(fontMap).forEach(([font, component]) => { - const family = mergedConfig[`font${font}`]?.family - const variable = font === 'Monospace' ? '--monoFont' : '--font' - if (family) { - hacks.push({ - component, - directives: { - [variable]: `generic | "${family}"`, - }, - }) + Object.entries(theme3hacks).forEach(([key, value]) => { + switch (key) { + case 'fonts': { + Object.entries(theme3hacks.fonts).forEach(([fontKey, font]) => { + if (!font?.family) return + switch (fontKey) { + case 'interface': + hacks.push({ + component: 'Root', + directives: { + '--font': 'generic | ' + font.family, + }, + }) + break + case 'input': + hacks.push({ + component: 'Input', + directives: { + '--font': 'generic | ' + font.family, + }, + }) + break + case 'post': + hacks.push({ + component: 'RichContent', + directives: { + '--font': 'generic | ' + font.family, + }, + }) + break + case 'monospace': + hacks.push({ + component: 'Root', + directives: { + '--monoFont': 'generic | ' + font.family, + }, + }) + break + } + }) + break + } + case 'underlay': { + if (value !== 'none') { + const newRule = { + component: 'Underlay', + directives: {}, + } + if (value === 'opaque') { + newRule.directives.opacity = 1 + newRule.directives.background = '--wallpaper' + } + if (value === 'transparent') { + newRule.directives.opacity = 0 + } + hacks.push(newRule) + } + break + } } }) - if (mergedConfig.underlay !== 'none') { - const newRule = { - component: 'Underlay', - directives: {}, - } - if (mergedConfig.underlay === 'opaque') { - newRule.directives.opacity = 1 - newRule.directives.background = '--wallpaper' - } - if (mergedConfig.underlay === 'transparent') { - newRule.directives.opacity = 0 - } - hacks.push(newRule) - } - const rulesetArray = [ theme2ruleset, this.styleDataUsed, @@ -698,7 +724,6 @@ export const useInterfaceStore = defineStore('interface', { themeDebug, ) } catch (e) { - console.error(e) window.splashError(e) } }, diff --git a/src/stores/local_config.js b/src/stores/local_config.js index 096d0b3f1..73ea1d7d4 100644 --- a/src/stores/local_config.js +++ b/src/stores/local_config.js @@ -33,9 +33,9 @@ export const useLocalConfigStore = defineStore('local_config', { set(this.prefsStorage, path, undefined) }, clearLocalConfig() { + const blankState = { ...cloneDeep(defaultState) } Object.keys(this).forEach((k) => { - this.prefsStorage[k] = undefined - this.tempStorage[k] = undefined + this.prefsStorage[k] = blankState[k] }) }, }, diff --git a/src/stores/sync_config.js b/src/stores/sync_config.js index ba4031e9a..e9a4a278e 100644 --- a/src/stores/sync_config.js +++ b/src/stores/sync_config.js @@ -28,7 +28,7 @@ import { instanceDefaultConfig, LOCAL_ONLY_KEYS, } from 'src/modules/default_config_state.js' -import { oldDefaultConfigSync } from 'src/modules/old_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 @@ -628,7 +628,7 @@ export const useSyncConfigStore = defineStore('sync_config', { const migratedEntries = new Set(vuexState.config._syncMigration ?? []) console.debug(`Already migrated Values: ${[...migratedEntries].join()}`) - Object.entries(oldDefaultConfigSync).forEach(([key, value]) => { + Object.entries(defaultConfigSync).forEach(([key, value]) => { const oldValue = vuexState.config[key] const defaultValue = value @@ -638,30 +638,7 @@ export const useSyncConfigStore = defineStore('sync_config', { if (present && !migrated && different) { console.debug(`Migrating config ${key}: ${oldValue}`) - if (key === 'theme3hacks') { - useLocalConfigStore().set({ - path: 'fontInterface', - value: oldValue.fonts.interface, - }) - useLocalConfigStore().set({ - path: 'fontInput', - value: oldValue.fonts.input, - }) - useLocalConfigStore().set({ - path: 'fontPost', - value: oldValue.fonts.post, - }) - useLocalConfigStore().set({ - path: 'fontMonospace', - value: oldValue.fonts.monospace, - }) - useLocalConfigStore().set({ - path: 'underlay', - value: oldValue.underlay, - }) - } else { - this.setPreference({ path: `simple.${key}`, value: oldValue }) - } + this.setPreference({ path: `simple.${key}`, oldValue }) migratedEntries.add(key) needUpload = true } @@ -728,7 +705,8 @@ export const useSyncConfigStore = defineStore('sync_config', { if (!needPush) return this.updateCache({ username: window.vuex.state.users.currentUser.fqn }) const params = { pleroma_settings_store: { 'pleroma-fe': this.cache } } - window.vuex.state.api.backendInteractor.updateProfileJSON({ params }) + window.vuex.state.api.backendInteractor + .updateProfileJSON({ params }) }, }, getters: {