From 63b4586c0f1f743823e2c77a218fc3e433ae83d6 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Wed, 18 Mar 2026 12:45:56 +0200 Subject: [PATCH 1/4] fix remote interaction link --- src/components/emoji_reactions/emoji_reactions.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/emoji_reactions/emoji_reactions.js b/src/components/emoji_reactions/emoji_reactions.js index 8a121befc..eda8bf4c1 100644 --- a/src/components/emoji_reactions/emoji_reactions.js +++ b/src/components/emoji_reactions/emoji_reactions.js @@ -4,6 +4,7 @@ import UserListPopover from '../user_list_popover/user_list_popover.vue' import { library } from '@fortawesome/fontawesome-svg-core' import { faCheck, faMinus, faPlus } from '@fortawesome/free-solid-svg-icons' +import { useInstanceStore } from 'src/stores/instance.js' library.add(faPlus, faMinus, faCheck) @@ -42,7 +43,7 @@ const EmojiReactions = { return !!this.$store.state.users.currentUser }, remoteInteractionLink() { - return this.$store.getters.remoteInteractionLink({ + return useInstanceStore().getRemoteInteractionLink({ statusId: this.status.id, }) }, From b2ec9cb890d2f1372a90c373e50354926de9d5fd Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Wed, 18 Mar 2026 15:08:52 +0200 Subject: [PATCH 2/4] fix font settings --- src/components/settings_modal/tabs/general_tab.js | 10 ++-------- src/stores/local_config.js | 4 ++-- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/src/components/settings_modal/tabs/general_tab.js b/src/components/settings_modal/tabs/general_tab.js index b0eac97c0..4a5071647 100644 --- a/src/components/settings_modal/tabs/general_tab.js +++ b/src/components/settings_modal/tabs/general_tab.js @@ -69,14 +69,8 @@ const GeneralTab = { }, updateFont(key, value) { useLocalConfigStore().set({ - path: 'theme3hacks', - value: { - ...this.mergedConfig.theme3hacks, - fonts: { - ...this.mergedConfig.theme3hacks.fonts, - [key]: value, - }, - }, + path: `theme3hacks.fonts.${key}`, + value, }) }, }, diff --git a/src/stores/local_config.js b/src/stores/local_config.js index 73ea1d7d4..096d0b3f1 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] = blankState[k] + this.prefsStorage[k] = undefined + this.tempStorage[k] = undefined }) }, }, From e6649c7c25350153c3143cc9b6c428adbe75e873 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Wed, 18 Mar 2026 16:46:39 +0200 Subject: [PATCH 3/4] fixed fonts (post fonts seem to be broken in develop) --- .../emoji_reactions/emoji_reactions.js | 3 +- .../settings_modal/tabs/general_tab.js | 10 +- .../settings_modal/tabs/general_tab.vue | 8 +- .../settings_modal/tabs/posts_tab.js | 18 +--- .../settings_modal/tabs/posts_tab.vue | 10 +- src/lib/style.js | 13 +++ src/modules/default_config_state.js | 19 ++-- src/modules/old_default_config_state.js | 2 +- src/modules/users.js | 16 +-- src/stores/interface.js | 97 +++++++------------ src/stores/sync_config.js | 32 +++++- 11 files changed, 110 insertions(+), 118 deletions(-) diff --git a/src/components/emoji_reactions/emoji_reactions.js b/src/components/emoji_reactions/emoji_reactions.js index eda8bf4c1..e1a28a8f1 100644 --- a/src/components/emoji_reactions/emoji_reactions.js +++ b/src/components/emoji_reactions/emoji_reactions.js @@ -2,9 +2,10 @@ 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' -import { useInstanceStore } from 'src/stores/instance.js' library.add(faPlus, faMinus, faCheck) diff --git a/src/components/settings_modal/tabs/general_tab.js b/src/components/settings_modal/tabs/general_tab.js index 4a5071647..d94191c9d 100644 --- a/src/components/settings_modal/tabs/general_tab.js +++ b/src/components/settings_modal/tabs/general_tab.js @@ -48,9 +48,6 @@ const GeneralTab = { }, ...SharedComputedObject(), ...mapState(useInstanceCapabilitiesStore, ['blockExpiration']), - ...mapState(useSyncConfigStore, { - theme3hacks: (store) => store.mergedConfig.theme3hacks, - }), }, methods: { updateProfile() { @@ -67,11 +64,8 @@ const GeneralTab = { this.$store.commit('setCurrentUser', user) }) }, - updateFont(key, value) { - useLocalConfigStore().set({ - path: `theme3hacks.fonts.${key}`, - value, - }) + updateFont(path, value) { + useLocalConfigStore().set({ path, value }) }, }, } diff --git a/src/components/settings_modal/tabs/general_tab.vue b/src/components/settings_modal/tabs/general_tab.vue index a3cb5be07..19800e0dd 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 467c2a4da..ab00e52e7 100644 --- a/src/components/settings_modal/tabs/posts_tab.js +++ b/src/components/settings_modal/tabs/posts_tab.js @@ -4,9 +4,10 @@ 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 GeneralTab = { +const PostsTab = { data() { return { conversationDisplayOptions: ['tree', 'linear'].map((mode) => ({ @@ -66,19 +67,10 @@ const GeneralTab = { ...SharedComputedObject(), }, methods: { - updateFont(key, value) { - useSyncConfigStore().setSimplePrefAndSave({ - path: 'theme3hacks', - value: { - ...this.mergedConfig.theme3hacks, - fonts: { - ...this.mergedConfig.theme3hacks.fonts, - [key]: value, - }, - }, - }) + updateFont(path, value) { + useLocalConfigStore().set({ path, value }) }, }, } -export default GeneralTab +export default PostsTab diff --git a/src/components/settings_modal/tabs/posts_tab.vue b/src/components/settings_modal/tabs/posts_tab.vue index 444f96392..1e684246d 100644 --- a/src/components/settings_modal/tabs/posts_tab.vue +++ b/src/components/settings_modal/tabs/posts_tab.vue @@ -56,22 +56,20 @@
  • diff --git a/src/lib/style.js b/src/lib/style.js index 50120b37b..343d24aea 100644 --- a/src/lib/style.js +++ b/src/lib/style.js @@ -1,3 +1,4 @@ +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' @@ -23,6 +24,15 @@ 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), @@ -36,6 +46,9 @@ 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 7823777a9..8634752bd 100644 --- a/src/modules/default_config_state.js +++ b/src/modules/default_config_state.js @@ -181,6 +181,13 @@ 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)) @@ -212,16 +219,4 @@ 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 dc15e1c24..935239d16 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 defaultConfigSync = { +export const oldDefaultConfigSync = { 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 e741877a6..d9e42ea76 100644 --- a/src/modules/users.js +++ b/src/modules/users.js @@ -702,13 +702,15 @@ 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 5840d6b34..b60eb6cf8 100644 --- a/src/stores/interface.js +++ b/src/stores/interface.js @@ -598,8 +598,9 @@ export const useInterfaceStore = defineStore('interface', { this.themeApplied = true }, async applyTheme({ recompile = false } = {}) { - const { forceThemeRecompilation, themeDebug, theme3hacks } = - useSyncConfigStore().mergedConfig + const { mergedConfig } = useSyncConfigStore() + const { forceThemeRecompilation, themeDebug } = mergedConfig + this.themeChangeInProgress = true // If we're not forced to recompile try using // cache (tryLoadCache return true if load successful) @@ -646,68 +647,41 @@ export const useInterfaceStore = defineStore('interface', { convertTheme2To3(normalizeThemeData(this.themeDataUsed)) const hacks = [] - 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 - } + const fontMap = { + Interface: 'Root', + Input: 'Input', + Posts: 'RichContent', + 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}"`, + }, + }) } }) + 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, @@ -724,6 +698,7 @@ export const useInterfaceStore = defineStore('interface', { themeDebug, ) } catch (e) { + console.error(e) window.splashError(e) } }, diff --git a/src/stores/sync_config.js b/src/stores/sync_config.js index e9a4a278e..ba4031e9a 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 { defaultConfigSync } from 'src/modules/old_default_config_state.js' +import { oldDefaultConfigSync } 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(defaultConfigSync).forEach(([key, value]) => { + Object.entries(oldDefaultConfigSync).forEach(([key, value]) => { const oldValue = vuexState.config[key] const defaultValue = value @@ -638,7 +638,30 @@ export const useSyncConfigStore = defineStore('sync_config', { if (present && !migrated && different) { console.debug(`Migrating config ${key}: ${oldValue}`) - this.setPreference({ path: `simple.${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 }) + } migratedEntries.add(key) needUpload = true } @@ -705,8 +728,7 @@ 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: { From c905219e8cd2a8b5749e089bc34134472573a568 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Wed, 18 Mar 2026 16:52:13 +0200 Subject: [PATCH 4/4] "fix" posts font --- src/stores/interface.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stores/interface.js b/src/stores/interface.js index b60eb6cf8..32a8226b4 100644 --- a/src/stores/interface.js +++ b/src/stores/interface.js @@ -650,7 +650,7 @@ export const useInterfaceStore = defineStore('interface', { const fontMap = { Interface: 'Root', Input: 'Input', - Posts: 'RichContent', + Posts: 'Post', Monospace: 'Root', }