Merge branch 'setttingssync' into shigusegubu-themes3

This commit is contained in:
Henry Jameson 2026-03-31 17:46:36 +03:00
commit 99eedadc6b
4 changed files with 122 additions and 102 deletions

View file

@ -1,6 +1,6 @@
import { throttle } from 'lodash' import { throttle } from 'lodash'
import { mapState } from 'pinia' import { mapState } from 'pinia'
import { defineAsyncComponent, toValue } from 'vue' import { defineAsyncComponent } from 'vue'
import DesktopNav from './components/desktop_nav/desktop_nav.vue' import DesktopNav from './components/desktop_nav/desktop_nav.vue'
import EditStatusModal from './components/edit_status_modal/edit_status_modal.vue' import EditStatusModal from './components/edit_status_modal/edit_status_modal.vue'
@ -33,7 +33,7 @@ import messages from 'src/i18n/messages'
import localeService from 'src/services/locale/locale.service.js' import localeService from 'src/services/locale/locale.service.js'
// Helper to unwrap reactive proxies // Helper to unwrap reactive proxies
window.toValue = toValue window.toValue = (x) => JSON.parse(JSON.stringify(x))
export default { export default {
name: 'app', name: 'app',

View file

@ -270,7 +270,7 @@ export const INSTANCE_DEFAULT_CONFIG_DEFINITIONS = {
}, },
interfaceLanguage: { interfaceLanguage: {
description: 'UI language', description: 'UI language',
default: browserLocale, default: [browserLocale],
}, },
hideScopeNotice: { hideScopeNotice: {
description: 'Hide scope notification', description: 'Hide scope notification',
@ -744,7 +744,7 @@ export const validateSetting = ({
throw new Error(string) throw new Error(string)
} else { } else {
console.error(string) console.error(string)
return value return undefined
} }
} }

View file

@ -290,87 +290,90 @@ export const _mergePrefs = (recent, stale) => {
*/ */
const resultOutput = { ...recentData } const resultOutput = { ...recentData }
const totalJournal = _mergeJournal(staleJournal, recentJournal) const totalJournal = _mergeJournal(staleJournal, recentJournal)
totalJournal.forEach(({ path, operation, args }) => { totalJournal
if (path.startsWith('_')) { .filter(({ path, operation, args }) => {
throw new Error( const definition = path.startsWith('simple.muteFilters')
`journal contains entry to edit internal (starts with _) field '${path}', something is incorrect here, ignoring.`, ? { default: {} }
) : ROOT_CONFIG_DEFINITIONS[path.split('.')[1]]
}
switch (operation) {
case 'set': {
if (path.startsWith('collections')) {
return console.error('Illegal operation "set" on a collection')
}
if (path.split(/\./g).length <= 1) {
return console.error(
`Calling set on depth <= 1 (path: ${path}) is not allowed`,
)
}
const definition = path.startsWith('simple.muteFilters') const finalValue = validateSetting({
? { default: {} } path: path.split('.')[1],
: ROOT_CONFIG_DEFINITIONS[path.split('.')[1]] value: args[0],
definition,
throwError: false,
defaultState: ROOT_CONFIG,
})
const finalValue = validateSetting({ return finalValue !== undefined
path: path.split('.')[1], })
value: args[0], .forEach(({ path, operation, args }) => {
definition, if (path.startsWith('_')) {
throwError: false, throw new Error(
defaultState: ROOT_CONFIG, `journal contains entry to edit internal (starts with _) field '${path}', something is incorrect here, ignoring.`,
})
set(resultOutput, path, finalValue)
break
}
case 'unset':
if (path.startsWith('collections')) {
return console.error('Illegal operation "unset" on a collection')
}
if (path.split(/\./g).length <= 2) {
return console.error(
`Calling unset on depth <= 2 (path: ${path}) is not allowed`,
)
}
unset(resultOutput, path)
break
case 'addToCollection':
if (!path.startsWith('collections')) {
return console.error(
'Illegal operation "addToCollection" on a non-collection',
)
}
set(
resultOutput,
path,
Array.from(new Set(get(resultOutput, path)).add(args[0])),
) )
break }
case 'removeFromCollection': { switch (operation) {
if (!path.startsWith('collections')) { case 'set': {
return console.error( if (path.startsWith('collections')) {
'Illegal operation "removeFromCollection" on a non-collection', return console.error('Illegal operation "set" on a collection')
) }
if (path.split(/\./g).length <= 1) {
return console.error(
`Calling set on depth <= 1 (path: ${path}) is not allowed`,
)
}
set(resultOutput, path, args[0])
break
} }
const newSet = new Set(get(resultOutput, path)) case 'unset':
newSet.delete(args[0]) if (path.startsWith('collections')) {
set(resultOutput, path, Array.from(newSet)) return console.error('Illegal operation "unset" on a collection')
break }
if (path.split(/\./g).length <= 2) {
return console.error(
`Calling unset on depth <= 2 (path: ${path}) is not allowed`,
)
}
unset(resultOutput, path)
break
case 'addToCollection':
if (!path.startsWith('collections')) {
return console.error(
'Illegal operation "addToCollection" on a non-collection',
)
}
set(
resultOutput,
path,
Array.from(new Set(get(resultOutput, path)).add(args[0])),
)
break
case 'removeFromCollection': {
if (!path.startsWith('collections')) {
return console.error(
'Illegal operation "removeFromCollection" on a non-collection',
)
}
const newSet = new Set(get(resultOutput, path))
newSet.delete(args[0])
set(resultOutput, path, Array.from(newSet))
break
}
case 'reorderCollection': {
const [value, movement] = args
set(
resultOutput,
path,
_moveItemInArray(get(resultOutput, path), value, movement),
)
break
}
default:
return console.error(
`Unknown journal operation: '${operation}', did we forget to run reverse migrations beforehand?`,
)
} }
case 'reorderCollection': { })
const [value, movement] = args
set(
resultOutput,
path,
_moveItemInArray(get(resultOutput, path), value, movement),
)
break
}
default:
return console.error(
`Unknown journal operation: '${operation}', did we forget to run reverse migrations beforehand?`,
)
}
})
return { ...resultOutput, _journal: totalJournal } return { ...resultOutput, _journal: totalJournal }
} }
@ -513,7 +516,7 @@ export const useSyncConfigStore = defineStore('sync_config', {
defaultState: ROOT_CONFIG, defaultState: ROOT_CONFIG,
}) })
set(this.prefsStorage, path, finalValue) if (finalValue !== undefined) set(this.prefsStorage, path, finalValue)
this.prefsStorage._journal = [ this.prefsStorage._journal = [
...this.prefsStorage._journal, ...this.prefsStorage._journal,
@ -754,7 +757,6 @@ export const useSyncConfigStore = defineStore('sync_config', {
this.flagStorage = this.cache.flagStorage this.flagStorage = this.cache.flagStorage
this.prefsStorage = this.cache.prefsStorage this.prefsStorage = this.cache.prefsStorage
this.pushSyncConfig() this.pushSyncConfig()
console.log('C', this.cache)
}, },
pushSyncConfig({ force = false } = {}) { pushSyncConfig({ force = false } = {}) {
const needPush = this.dirty || force const needPush = this.dirty || force
@ -766,7 +768,29 @@ export const useSyncConfigStore = defineStore('sync_config', {
}, },
persist: { persist: {
afterLoad(state) { afterLoad(state) {
return state console.log('Validating persisted state of SyncConfig')
const newState = { ...state }
const newEntries = Object.entries(newState.prefsStorage.simple).map(
([path, value]) => {
if (path === 'muteFilters') {
return value
}
const definition = ROOT_CONFIG_DEFINITIONS[path]
const finalValue = validateSetting({
path,
value,
definition,
throwError: false,
defaultState: ROOT_CONFIG,
})
return finalValue === undefined ? undefined : [path, finalValue]
},
)
newState.prefsStorage.simple = Object.fromEntries(
newEntries.filter((_) => _),
)
return newState
}, },
}, },
}) })

View file

@ -174,13 +174,11 @@ describe('The UserHighlight store', () => {
it('should prefer recent and apply journal to it', () => { it('should prefer recent and apply journal to it', () => {
expect( expect(
_mergeHighlights( _mergeHighlights(
// RECENT
{ {
highlight: { // RECENT
'a@test.xyz': 1, 'a@test.xyz': 1,
'b@test.xyz': 0, 'b@test.xyz': 0,
'c@test.xyz': true, 'c@test.xyz': true,
},
_journal: [ _journal: [
{ {
user: 'b@test.xyz', user: 'b@test.xyz',
@ -196,13 +194,11 @@ describe('The UserHighlight store', () => {
}, },
], ],
}, },
// STALE
{ {
highlight: { // STALE
'a@test.xyz': 1, 'a@test.xyz': 1,
'b@test.xyz': 1, 'b@test.xyz': 1,
'c@test.xyz': false, 'c@test.xyz': false,
},
_journal: [ _journal: [
{ {
user: 'a@test.xyz', user: 'a@test.xyz',
@ -220,7 +216,9 @@ describe('The UserHighlight store', () => {
}, },
), ),
).to.eql({ ).to.eql({
highlight: { 'a@test.xyz': 1, 'b@test.xyz': 1, 'c@test.xyz': true }, 'a@test.xyz': 1,
'b@test.xyz': 1,
'c@test.xyz': true,
_journal: [ _journal: [
{ user: 'a@test.xyz', operation: 'set', args: [1], timestamp: 1 }, { user: 'a@test.xyz', operation: 'set', args: [1], timestamp: 1 },
{ user: 'b@test.xyz', operation: 'set', args: [1], timestamp: 3 }, { user: 'b@test.xyz', operation: 'set', args: [1], timestamp: 3 },
@ -239,7 +237,7 @@ describe('The UserHighlight store', () => {
_mergeHighlights( _mergeHighlights(
// RECENT // RECENT
{ {
highlight: { 'a@test.xyz': { type: 'foo' } }, 'a@test.xyz': { type: 'foo' },
_journal: [ _journal: [
{ {
user: 'a@test.xyz', user: 'a@test.xyz',
@ -251,7 +249,7 @@ describe('The UserHighlight store', () => {
}, },
// STALE // STALE
{ {
highlight: { 'a@test.xyz': { type: 'bar' } }, 'a@test.xyz': { type: 'bar' },
_journal: [ _journal: [
{ {
user: 'a@test.xyz', user: 'a@test.xyz',
@ -263,7 +261,7 @@ describe('The UserHighlight store', () => {
}, },
), ),
).to.eql({ ).to.eql({
highlight: { 'a@test.xyz': { type: 'bar' } }, 'a@test.xyz': { type: 'bar' },
_journal: [ _journal: [
{ {
user: 'a@test.xyz', user: 'a@test.xyz',
@ -280,7 +278,7 @@ describe('The UserHighlight store', () => {
_mergeHighlights( _mergeHighlights(
// RECENT // RECENT
{ {
highlight: { 'a@test.xyz': { type: 'foo' } }, 'a@test.xyz': { type: 'foo' },
_journal: [ _journal: [
{ {
user: 'a@test.xyz', user: 'a@test.xyz',
@ -292,7 +290,6 @@ describe('The UserHighlight store', () => {
}, },
// STALE // STALE
{ {
highlight: {},
_journal: [ _journal: [
{ {
user: 'a@test.xyz', user: 'a@test.xyz',
@ -304,7 +301,6 @@ describe('The UserHighlight store', () => {
}, },
), ),
).to.eql({ ).to.eql({
highlight: {},
_journal: [ _journal: [
{ {
user: 'a@test.xyz', user: 'a@test.xyz',