theme/style/palette seem to be working

This commit is contained in:
Henry Jameson 2026-01-23 14:11:48 +02:00
commit 1f57fab6ae
10 changed files with 122 additions and 63 deletions

View file

@ -25,6 +25,7 @@ import { useInterfaceStore } from 'src/stores/interface.js'
import { useShoutStore } from 'src/stores/shout.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { applyStyleConfig } from 'src/services/style_setter/style_setter.js'
import { getOrCreateServiceWorker } from 'src/services/sw/sw'
import {
windowHeight,
@ -76,7 +77,9 @@ export default {
},
created() {
document.getElementById('modal').classList = ['-' + this.layoutType]
useI18nStore().setLanguage()
applyStyleConfig(useSyncConfigStore().mergedConfig)
// Create bound handlers
this.updateScrollState = throttle(this.scrollHandler, 200)

View file

@ -18,7 +18,7 @@ config.autoAddCss = false
import App from '../App.vue'
import backendInteractorService from '../services/backend_interactor_service/backend_interactor_service.js'
import FaviconService from '../services/favicon_service/favicon_service.js'
import { applyConfig } from '../services/style_setter/style_setter.js'
import { applyStyleConfig } from '../services/style_setter/style_setter.js'
import { initServiceWorker, updateFocus } from '../services/sw/sw.js'
import {
windowHeight,
@ -26,12 +26,13 @@ import {
} from '../services/window_utils/window_utils'
import routes from './routes'
import { useAnnouncementsStore } from 'src/stores/announcements'
import { useAuthFlowStore } from 'src/stores/auth_flow'
import { useI18nStore } from 'src/stores/i18n'
import { useInstanceStore } from 'src/stores/instance'
import { useInterfaceStore } from 'src/stores/interface'
import { useOAuthStore } from 'src/stores/oauth'
import { useAnnouncementsStore } from 'src/stores/announcements.js'
import { useAuthFlowStore } from 'src/stores/auth_flow.js'
import { useI18nStore } from 'src/stores/i18n.js'
import { useInstanceStore } from 'src/stores/instance.js'
import { useInterfaceStore } from 'src/stores/interface.js'
import { useOAuthStore } from 'src/stores/oauth.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import VBodyScrollLock from 'src/directives/body_scroll_lock'
import {
@ -164,7 +165,6 @@ const setSettings = async ({ apiConfig, staticConfig, store }) => {
} else {
config = { ...staticConfig, ...apiConfig }
}
console.trace(config)
const copyInstanceIdentityOption = (path) => {
if (get(config, path) !== undefined) {
@ -567,7 +567,7 @@ const afterStoreSetup = async ({ pinia, store, storageError, i18n }) => {
return Promise.reject(e)
}
applyConfig(store.state.config, i18n.global)
applyStyleConfig(useSyncConfigStore().mergedConfig)
// Now we can try getting the server settings and logging in
// Most of these are preloaded into the index.html so blocking is minimized

View file

@ -281,7 +281,7 @@ const AppearanceTab = {
},
instanceWallpaperUsed() {
return (
useInstanceStore().background &&
this.instanceWallpaper &&
!this.$store.state.users.currentUser.background_image
)
},
@ -312,9 +312,9 @@ const AppearanceTab = {
},
onImport(parsed, filename) {
if (filename.endsWith('.json')) {
useInterfaceStore().setThemeCustom(parsed.source || parsed.theme)
this.setThemeCustom(parsed.source || parsed.theme)
} else if (filename.endsWith('.iss')) {
useInterfaceStore().setStyleCustom(parsed)
this.setStyleCustom(parsed)
}
},
onImportFailure(result) {
@ -336,25 +336,42 @@ const AppearanceTab = {
}
},
isThemeActive(key) {
return key === (this.mergedConfig.theme || useInstanceStore().theme)
return (
key ===
(useSyncConfigStore().mergedConfig.theme)
)
},
isStyleActive(key) {
return key === (this.mergedConfig.style || useInstanceStore().style)
return (
key ===
(useSyncConfigStore().mergedConfig.style)
)
},
isPaletteActive(key) {
return key === (this.mergedConfig.palette || useInstanceStore().palette)
return (
key ===
(useSyncConfigStore().mergedConfig.palette ||
useInstanceStore().palette)
)
},
...mapActions(useInterfaceStore, ['setStyle', 'setTheme']),
setPalette(name, data) {
useInterfaceStore().setPalette(name)
...mapActions(useInterfaceStore, [
'setStyle',
'setStyleCustom',
'setPalette',
'setPaletteCustom',
'setTheme',
'setThemeCustom',
]),
setLocalPalette(name, data) {
this.setPalette(name)
this.userPalette = data
},
setPaletteCustom(data) {
useInterfaceStore().setPaletteCustom(data)
setLocalPaletteCustom(data) {
this.setPaletteCustom(data)
this.userPalette = data
},
resetTheming() {
useInterfaceStore().setStyle('stock')
this.setStyle('stock')
},
previewTheme(key, version, input) {
let theme3

View file

@ -54,7 +54,7 @@
:key="style.key"
:data-theme-key="style.key"
class="button-default theme-preview"
:class="{ toggled: isThemeActive(style.key), disabled: switchInProgress }"
:class="{ toggled: isStyleActive(style.key), disabled: switchInProgress }"
:disabled="switchInProgress"
@click="style.version === 'v2' ? setTheme(style.key) : setStyle(style.key)"
>
@ -90,7 +90,7 @@
class="btn button-default palette-entry"
:class="{ toggled: isPaletteActive(p.key), disabled: switchInProgress }"
:disabled="switchInProgress"
@click="() => setPalette(p.key, p)"
@click="() => setLocalPalette(p.key, p)"
>
<div class="palette-label">
<label>
@ -113,7 +113,7 @@
class="btn button-default palette-entry"
:class="{ toggled: isPaletteActive(p.key), disabled: switchInProgress }"
:disabled="switchInProgress"
@click="() => setPalette(p.key, p)"
@click="() => setLocalPalette(p.key, p)"
>
<div class="palette-label">
<label>
@ -143,7 +143,7 @@
:compact="true"
:apply="true"
:disabled="switchInProgress"
@apply-palette="data => setPaletteCustom(data)"
@apply-palette="data => setLocalPaletteCustom(data)"
/>
</template>
<template v-else-if="customThemeVersion === 'v2'">

29
src/lib/style.js Normal file
View file

@ -0,0 +1,29 @@
import { applyStyleConfig } from 'src/services/style_setter/style_setter.js'
const APPEARANCE_SETTINGS_KEYS = new Set(
[
'sidebarColumnWidth',
'contentColumnWidth',
'notifsColumnWidth',
'themeEditorMinWidth',
'textSize',
'navbarSize',
'panelHeaderSize',
'forcedRoundness',
'emojiSize',
'emojiReactionsScale',
].map((x) => 'simple.' + x),
)
export const piniaStylePlugin = ({ store, options }) => {
if (store.$id === 'sync_config') {
store.$onAction(({ name, args }) => {
if (name === 'setPreference') {
const { path, value } = args[0]
if (APPEARANCE_SETTINGS_KEYS.has(path)) {
applyStyleConfig(store.mergedConfig)
}
}
})
}
}

View file

@ -27,6 +27,7 @@ import {
import vuexModules from './modules/index.js'
import { piniaLanguagePlugin } from 'src/lib/language.js'
import { piniaStylePlugin } from 'src/lib/style.js'
const currentLocale = (window.navigator.language || 'en').split('-')[0]
@ -75,6 +76,7 @@ const persistedStateOptions = {
const pinia = createPinia()
pinia.use(piniaPersistPlugin())
pinia.use(piniaLanguagePlugin)
pinia.use(piniaStylePlugin)
pinia.use(piniaPushNotificationsPlugin)
try {

View file

@ -1,27 +1,15 @@
import Cookies from 'js-cookie'
import { set } from 'lodash'
import messages from '../i18n/messages'
import localeService from '../services/locale/locale.service.js'
import { applyConfig } from '../services/style_setter/style_setter.js'
import { defaultState, instanceDefaultConfig } from './default_config_state.js'
import { useI18nStore } from 'src/stores/i18n.js'
import { useInterfaceStore } from 'src/stores/interface.js'
import messages from 'src/i18n/messages'
import localeService from 'src/services/locale/locale.service.js'
const BACKEND_LANGUAGE_COOKIE_NAME = 'userLanguage'
const APPEARANCE_SETTINGS_KEYS = new Set([
'sidebarColumnWidth',
'contentColumnWidth',
'notifsColumnWidth',
'themeEditorMinWidth',
'textSize',
'navbarSize',
'panelHeaderSize',
'forcedRoundness',
'emojiSize',
'emojiReactionsScale',
])
/* TODO this is a bit messy.
* We need to declare settings with their types and also deal with
@ -46,7 +34,6 @@ const config = {
mutations: {
setOptionTemporarily(state, { name, value }) {
set(state, name, value)
applyConfig(state)
},
setOption(state, { name, value }) {
set(state, name, value)
@ -95,9 +82,6 @@ const config = {
}
} else {
commit('setOption', { name, value })
if (APPEARANCE_SETTINGS_KEYS.has(name)) {
applyConfig(state)
}
if (name.startsWith('theme3hacks')) {
dispatch('applyTheme', { recompile: true })
}

View file

@ -255,7 +255,7 @@ const extractStyleConfig = ({
const defaultStyleConfig = extractStyleConfig(defaultState)
export const applyConfig = (input) => {
export const applyStyleConfig = (input) => {
const config = extractStyleConfig(input)
if (config === defaultStyleConfig) {

View file

@ -209,7 +209,6 @@ export const useEmojiStore = defineStore('emoji', {
)
}
console.log('EMOJI', useInstanceStore().server)
const emoji = Object.entries(values)
.map(([key, value]) => {
const imageUrl = value.image_url

View file

@ -243,7 +243,8 @@ export const useInterfaceStore = defineStore('interface', {
this.resetThemeV3Palette()
this.resetThemeV2()
useSyncConfigStore().setPreference({ path: 'palette', value })
useSyncConfigStore().setPreference({ path: 'simple.palette', value })
useSyncConfigStore().pushSyncConfig()
this.applyTheme({ recompile: true })
},
@ -251,7 +252,11 @@ export const useInterfaceStore = defineStore('interface', {
this.resetThemeV3Palette()
this.resetThemeV2()
useSyncConfigStore().setPreference({ path: 'paletteCustomData', value })
useSyncConfigStore().setPreference({
path: 'simple.paletteCustomData',
value,
})
useSyncConfigStore().pushSyncConfig()
this.applyTheme({ recompile: true })
},
@ -277,7 +282,8 @@ export const useInterfaceStore = defineStore('interface', {
this.resetThemeV2()
this.resetThemeV3Palette()
useSyncConfigStore().setPreference({ path: 'style', value })
useSyncConfigStore().setPreference({ path: 'simple.style', value })
useSyncConfigStore().pushSyncConfig()
this.useStylePalette = true
this.applyTheme({ recompile: true }).then(() => {
@ -289,7 +295,11 @@ export const useInterfaceStore = defineStore('interface', {
this.resetThemeV2()
this.resetThemeV3Palette()
useSyncConfigStore().setPreference({ path: 'styleCustomData', value })
useSyncConfigStore().setPreference({
path: 'simple.styleCustomData',
value,
})
useSyncConfigStore().pushSyncConfig()
this.useStylePalette = true
this.applyTheme({ recompile: true }).then(() => {
@ -315,7 +325,8 @@ export const useInterfaceStore = defineStore('interface', {
this.resetThemeV3Palette()
this.resetThemeV2()
useSyncConfigStore().setPreference({ name: 'theme', value })
useSyncConfigStore().setPreference({ path: 'simple.theme', value })
useSyncConfigStore().pushSyncConfig()
this.applyTheme({ recompile: true })
},
@ -324,32 +335,45 @@ export const useInterfaceStore = defineStore('interface', {
this.resetThemeV3Palette()
this.resetThemeV2()
useSyncConfigStore().setPreference({ path: 'customTheme', value })
useSyncConfigStore().setPreference({ path: 'customThemeSource', value })
useSyncConfigStore().setPreference({ path: 'simple.customTheme', value })
useSyncConfigStore().setPreference({
path: 'simple.customThemeSource',
value,
})
useSyncConfigStore().pushSyncConfig()
this.applyTheme({ recompile: true })
},
resetThemeV3() {
useSyncConfigStore().setPreference({ path: 'style', value: null })
useSyncConfigStore().setPreference({ path: 'simple.style', value: null })
useSyncConfigStore().setPreference({
path: 'styleCustomData',
path: 'simple.styleCustomData',
value: null,
})
useSyncConfigStore().pushSyncConfig()
},
resetThemeV3Palette() {
useSyncConfigStore().setPreference({ path: 'palette', value: null })
useSyncConfigStore().setPreference({
name: 'paletteCustomData',
path: 'simple.palette',
value: null,
})
useSyncConfigStore().setPreference({
path: 'simple.paletteCustomData',
value: null,
})
useSyncConfigStore().pushSyncConfig()
},
resetThemeV2() {
useSyncConfigStore().setPreference({ path: 'theme', value: null })
useSyncConfigStore().setPreference({ path: 'customTheme', value: null })
useSyncConfigStore().setPreference({ path: 'simple.theme', value: null })
useSyncConfigStore().setPreference({
path: 'customThemeSource',
path: 'simple.customTheme',
value: null,
})
useSyncConfigStore().setPreference({
path: 'simple.customThemeSource',
value: null,
})
useSyncConfigStore().pushSyncConfig()
},
async getThemeData() {
const getData = async (resource, index, customData, name) => {
@ -406,13 +430,13 @@ export const useInterfaceStore = defineStore('interface', {
styleCustomData: userStyleCustomData,
palette: userPaletteName,
paletteCustomData: userPaletteCustomData,
} = window.vuex.state.config
} = useSyncConfigStore().mergedConfig
let {
theme: userThemeV2Name,
customTheme: userThemeV2Snapshot,
customThemeSource: userThemeV2Source,
} = window.vuex.state.config
} = useSyncConfigStore().mergedConfig
let majorVersionUsed
@ -516,9 +540,10 @@ export const useInterfaceStore = defineStore('interface', {
if (this.useStylePalette) {
useSyncConfigStore().setPreference({
path: 'palette',
path: 'path.palette',
value: firstStylePaletteName,
})
useSyncConfigStore().pushSyncConfig()
}
this.paletteNameUsed = palette.nameUsed