Merge branch 'develop' into setttingssync

This commit is contained in:
Henry Jameson 2026-02-12 17:16:18 +02:00
commit 3530830b07
134 changed files with 1411 additions and 1299 deletions

View file

@ -107,6 +107,12 @@ const adminSettingsStorage = {
if (Array.isArray(value) && value.length > 0 && value[0].tuple) {
if (!preserveTuples) {
return value.reduce((acc, c) => {
if (c.tuple == null) {
return {
...acc,
[c]: c,
}
}
return {
...acc,
[c.tuple[0]]: convert(c.tuple[1], preserveTuplesLv2),

View file

@ -5,6 +5,7 @@ import backendInteractorService from '../services/backend_interactor_service/bac
import { maybeShowChatNotification } from '../services/chat_utils/chat_utils.js'
import { useInstanceStore } from 'src/stores/instance.js'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useInterfaceStore } from 'src/stores/interface.js'
import { useShoutStore } from 'src/stores/shout.js'
@ -239,7 +240,7 @@ const api = {
) {
if (
timeline === 'favourites' &&
!store.rootState.instance.pleromaPublicFavouritesAvailable
!useInstanceCapabilitiesStore().pleromaPublicFavouritesAvailable
)
return
if (store.state.fetchers[timeline]) return
@ -324,7 +325,8 @@ const api = {
// Bookmark folders
startFetchingBookmarkFolders(store) {
if (store.state.fetchers.bookmarkFolders) return
if (!useInstanceStore().featureSet.pleromaBookmarkFoldersAvailable) return
if (!useInstanceCapabilitiesStore().pleromaBookmarkFoldersAvailable)
return
const fetcher =
store.state.backendInteractor.startFetchingBookmarkFolders({ store })
store.commit('addFetcher', { fetcherName: 'bookmarkFolders', fetcher })
@ -343,7 +345,7 @@ const api = {
// Set up websocket connection
const token = state.wsToken
if (
useInstanceStore().featureSet.shoutAvailable &&
useInstanceStore().shoutAvailable &&
typeof token !== 'undefined' &&
state.socket === null
) {

View file

@ -1,15 +1,29 @@
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 { useEmojiStore } from 'src/stores/emoji.js'
import { useI18nStore } from 'src/stores/i18n.js'
import { useInstanceStore } from 'src/stores/instance.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
@ -31,9 +45,33 @@ export const instanceDefaultProperties = Object.keys(instanceDefaultConfig)
const config = {
state: { ...defaultState },
getters: {
defaultConfig() {
return {
...defaultState,
...Object.fromEntries(
instanceDefaultProperties.map((key) => [
key,
useInstanceStore().prefsStorage[key],
]),
),
}
},
mergedConfig(state) {
const instancePrefs = useInstanceStore().prefsStorage
const result = Object.fromEntries(
Object.keys(defaultState).map((key) => [
key,
state[key] ?? instancePrefs[key],
]),
)
return result
},
},
mutations: {
setOptionTemporarily(state, { name, value }) {
set(state, name, value)
applyConfig(state)
},
setOption(state, { name, value }) {
set(state, name, value)
@ -51,6 +89,47 @@ const config = {
},
},
actions: {
loadSettings({ dispatch }, data) {
const knownKeys = new Set(Object.keys(defaultState))
const presentKeys = new Set(Object.keys(data))
const intersection = new Set()
for (const elem of presentKeys) {
if (knownKeys.has(elem)) {
intersection.add(elem)
}
}
intersection.forEach((name) =>
dispatch('setOption', { name, value: data[name] }),
)
},
setHighlight({ commit }, { user, color, type }) {
commit('setHighlight', { user, color, type })
},
setOptionTemporarily({ commit, dispatch, state }, { name, value }) {
if (useInterfaceStore().temporaryChangesTimeoutId !== null) {
console.warn("Can't track more than one temporary change")
return
}
const oldValue = state[name]
commit('setOptionTemporarily', { name, value })
const confirm = () => {
dispatch('setOption', { name, value })
useInterfaceStore().clearTemporaryChanges()
}
const revert = () => {
commit('setOptionTemporarily', { name, value: oldValue })
useInterfaceStore().clearTemporaryChanges()
}
useInterfaceStore().setTemporaryChanges({
confirm,
revert,
})
},
setThemeV2({ commit, dispatch }, { customTheme, customThemeSource }) {
commit('setOption', { name: 'theme', value: 'custom' })
commit('setOption', { name: 'customTheme', value: customTheme })
@ -82,6 +161,9 @@ const config = {
}
} else {
commit('setOption', { name, value })
if (APPEARANCE_SETTINGS_KEYS.has(name)) {
applyConfig(state)
}
if (name.startsWith('theme3hacks')) {
dispatch('applyTheme', { recompile: true })
}
@ -100,7 +182,7 @@ const config = {
}
case 'interfaceLanguage':
messages.setLanguage(useI18nStore().i18n, value)
dispatch('loadUnicodeEmojiData', value)
useEmojiStore().loadUnicodeEmojiData(value)
Cookies.set(
BACKEND_LANGUAGE_COOKIE_NAME,
localeService.internalToBackendLocaleMulti(value),

View file

@ -22,6 +22,10 @@ export const staticOrApiConfigDefault = {
nsfwCensorImage: null,
showFeaturesPanel: true,
showInstanceSpecificPanel: false,
// Html stuff
instanceSpecificPanelContent: '',
tos: '',
}
/// This object contains setting entries that makes sense

View file

@ -10,7 +10,7 @@ import {
} from '../services/notification_utils/notification_utils.js'
import { useReportsStore } from 'src/stores/reports.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { useServerSideStorageStore } from 'src/stores/serverSideStorage.js'
const emptyNotifications = () => ({
desktopNotificationSilence: true,
@ -119,7 +119,9 @@ export const notifications = {
maybeShowNotification(
store,
Object.values(useSyncConfigStore().prefsStorage.simple.muteFilters),
Object.values(
useServerSideStorageStore().prefsStorage.simple.muteFilters,
),
notification,
)
} else if (notification.seen) {

View file

@ -15,7 +15,8 @@ import {
import apiService from '../services/api/api.service.js'
import { useInterfaceStore } from 'src/stores/interface'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useInterfaceStore } from 'src/stores/interface.js'
const emptyTl = (userId = 0) => ({
statuses: [],
@ -41,7 +42,6 @@ export const defaultState = () => ({
conversationsObject: {},
maxId: 0,
favorites: new Set(),
pleromaScrobblesAvailable: true, // not reported in nodeinfo
timelines: {
mentions: emptyTl(),
public: emptyTl(),
@ -115,7 +115,8 @@ const sortTimeline = (timeline) => {
}
const getLatestScrobble = (state, user) => {
const scrobblesSupport = state.pleromaScrobblesAvailable
const scrobblesSupport =
useInstanceCapabilitiesStore().pleromaScrobblesAvailable
if (!scrobblesSupport || !user.name || user.id === 'undefined') {
return
@ -134,7 +135,7 @@ const getLatestScrobble = (state, user) => {
.fetchScrobbles({ accountId: user.id })
.then((scrobbles) => {
if (scrobbles?.error) {
state.pleromaScrobblesAvailable = false
useInstanceCapabilitiesStore().set('pleromaScrobblesAvailable', false)
return
}

View file

@ -23,9 +23,10 @@ import {
import { useEmojiStore } from 'src/stores/emoji.js'
import { useInstanceStore } from 'src/stores/instance.js'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useInterfaceStore } from 'src/stores/interface.js'
import { useOAuthStore } from 'src/stores/oauth.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { useServerSideStorageStore } from 'src/stores/serverSideStorage'
import { declarations } from 'src/modules/config_declaration'
@ -681,14 +682,13 @@ const users = {
useInterfaceStore().setLastTimeline('public-timeline')
useInterfaceStore().setLayoutWidth(windowWidth())
useInterfaceStore().setLayoutHeight(windowHeight())
store.commit('clearSyncConfig')
store.commit('clearServerSideStorage')
})
},
loginUser(store, accessToken) {
return new Promise((resolve, reject) => {
const commit = store.commit
const dispatch = store.dispatch
commit('beginLogin')
store.rootState.api.backendInteractor
.verifyCredentials(accessToken)
@ -702,7 +702,7 @@ const users = {
user.domainMutes = []
commit('setCurrentUser', user)
useSyncConfigStore().setSyncConfig(user)
useServerSideStorageStore().setServerSideStorage(user)
commit('addNewUsers', [user])
useEmojiStore().fetchEmoji()
@ -723,16 +723,17 @@ const users = {
/*
// Reset wordfilter
Object.keys(
useSyncConfigStore().prefsStorage.simple.muteFilters
useServerSideStorageStore().prefsStorage.simple.muteFilters
).forEach(key => {
useSyncConfigStore().unsetPreference({ path: 'simple.muteFilters.' + key, value: null })
useServerSideStorageStore().unsetPreference({ path: 'simple.muteFilters.' + key, value: null })
})
// Reset flag to 0 to re-run migrations
useSyncConfigStore().setFlag({ flag: 'configMigration', value: 0 })
useServerSideStorageStore().setFlag({ flag: 'configMigration', value: 0 })
/**/
const { configMigration } = useSyncConfigStore().flagStorage
const { configMigration } =
useServerSideStorageStore().flagStorage
declarations
.filter((x) => {
return (
@ -743,12 +744,12 @@ const users = {
})
.toSorted((a, b) => a.configMigration - b.configMigration)
.forEach((value) => {
value.migration(useSyncConfigStore(), store.rootState)
useSyncConfigStore().setFlag({
value.migration(useServerSideStorageStore(), store.rootState)
useServerSideStorageStore().setFlag({
flag: 'configMigration',
value: value.migrationNum,
})
useSyncConfigStore().pushSyncConfig()
useServerSideStorageStore().pushServerSideStorage()
})
if (user.token) {
@ -766,7 +767,7 @@ const users = {
dispatch('startFetchingNotifications')
if (
useInstanceStore().featureSet.pleromaChatMessagesAvailable
useInstanceCapabilitiesStore().pleromaChatMessagesAvailable
) {
// Start fetching chats
dispatch('startFetchingChats')
@ -780,7 +781,7 @@ const users = {
dispatch('startFetchingFollowRequests')
}
if (useSyncConfigStore().mergedConfig.useStreamingApi) {
if (store.getters.mergedConfig.useStreamingApi) {
dispatch('fetchTimeline', { timeline: 'friends', since: null })
dispatch('fetchNotifications', { since: null })
dispatch('enableMastoSockets', true)