initial prefs storage work
This commit is contained in:
parent
750696643f
commit
aa41cedd93
|
@ -1,5 +1,5 @@
|
|||
import { toRaw } from 'vue'
|
||||
import { isEqual, cloneDeep } from 'lodash'
|
||||
import { isEqual, uniqBy, cloneDeep, set } from 'lodash'
|
||||
import { CURRENT_UPDATE_COUNTER } from 'src/components/update_notification/update_notification.js'
|
||||
|
||||
export const VERSION = 1
|
||||
|
@ -22,6 +22,10 @@ export const defaultState = {
|
|||
// 1000: trim keys to those known by currently running FE
|
||||
// 1001: same as above + reset everything to 0
|
||||
},
|
||||
prefsStorage: {
|
||||
_journal: [],
|
||||
simple: {}
|
||||
},
|
||||
// raw data
|
||||
raw: null,
|
||||
// local cache
|
||||
|
@ -93,6 +97,42 @@ export const _mergeFlags = (recent, stale, allFlagKeys) => {
|
|||
}))
|
||||
}
|
||||
|
||||
export const _mergePrefs = (recent, stale, allFlagKeys) => {
|
||||
if (!stale) return recent
|
||||
if (!recent) return stale
|
||||
const { _journal: recentJournal, ...recentData } = recent
|
||||
const { _journal: staleJournal } = stale
|
||||
/** Journal entry format:
|
||||
* path: path to entry in prefsStorage
|
||||
* timestamp: timestamp of the change
|
||||
* operation: operation type
|
||||
* arguments: array of arguments, depends on operation type
|
||||
*
|
||||
* currently only supported operation type is "set" which just sets the value
|
||||
* to requested one. Intended only to be used with simple preferences (boolean, number)
|
||||
* shouldn't be used with collections!
|
||||
*/
|
||||
const resultOutput = { ...recentData }
|
||||
const totalJournal = uniqBy(
|
||||
[...recentJournal, ...staleJournal].sort((a, b) => a.timestamp > b.timestamp ? -1 : 1),
|
||||
'path'
|
||||
).reverse()
|
||||
totalJournal.forEach(({ path, timestamp, operation, args }) => {
|
||||
if (path.startsWith('_')) {
|
||||
console.error(`journal contains entry to edit internal (starts with _) field '${path}', something is incorrect here, ignoring.`)
|
||||
return
|
||||
}
|
||||
switch (operation) {
|
||||
case 'set':
|
||||
set(resultOutput, path, args[0])
|
||||
break
|
||||
default:
|
||||
console.error(`Unknown journal operation: '${operation}', did we forget to run reverse migrations beforehand?`)
|
||||
}
|
||||
})
|
||||
return { ...resultOutput, _journal: totalJournal }
|
||||
}
|
||||
|
||||
export const _resetFlags = (totalFlags, knownKeys = defaultState.flagStorage) => {
|
||||
let result = { ...totalFlags }
|
||||
const allFlagKeys = Object.keys(totalFlags)
|
||||
|
@ -165,7 +205,8 @@ export const mutations = {
|
|||
if (recent === null) {
|
||||
console.debug(`Data is empty, initializing for ${userNew ? 'new' : 'existing'} user`)
|
||||
recent = _wrapData({
|
||||
flagStorage: { ...flagsTemplate }
|
||||
flagStorage: { ...flagsTemplate },
|
||||
prefsStorage: { ...defaultState.prefsStorage }
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -180,17 +221,21 @@ export const mutations = {
|
|||
|
||||
const allFlagKeys = _getAllFlags(recent, stale)
|
||||
let totalFlags
|
||||
let totalPrefs
|
||||
if (dirty) {
|
||||
// Merge the flags
|
||||
console.debug('Merging the flags...')
|
||||
console.debug('Merging the data...')
|
||||
totalFlags = _mergeFlags(recent, stale, allFlagKeys)
|
||||
totalPrefs = _mergePrefs(recent.prefsStorage, stale.prefsStorage)
|
||||
} else {
|
||||
totalFlags = recent.flagStorage
|
||||
totalPrefs = recent.prefsStorage
|
||||
}
|
||||
|
||||
totalFlags = _resetFlags(totalFlags)
|
||||
|
||||
recent.flagStorage = totalFlags
|
||||
recent.prefsStorage = totalPrefs
|
||||
|
||||
state.dirty = dirty || needsUpload
|
||||
state.cache = recent
|
||||
|
@ -216,7 +261,8 @@ const serverSideStorage = {
|
|||
const needPush = state.dirty || force
|
||||
if (!needPush) return
|
||||
state.cache = _wrapData({
|
||||
flagStorage: toRaw(state.flagStorage)
|
||||
flagStorage: toRaw(state.flagStorage),
|
||||
prefsStorage: toRaw(state.flagStorage)
|
||||
})
|
||||
const params = { pleroma_settings_store: { 'pleroma-fe': state.cache } }
|
||||
rootState.api.backendInteractor
|
||||
|
|
|
@ -7,6 +7,7 @@ import {
|
|||
_getRecentData,
|
||||
_getAllFlags,
|
||||
_mergeFlags,
|
||||
_mergePrefs,
|
||||
_resetFlags,
|
||||
mutations,
|
||||
defaultState,
|
||||
|
@ -28,6 +29,7 @@ describe('The serverSideStorage module', () => {
|
|||
expect(state.cache._version).to.eql(VERSION)
|
||||
expect(state.cache._timestamp).to.be.a('number')
|
||||
expect(state.cache.flagStorage).to.eql(defaultState.flagStorage)
|
||||
expect(state.cache.prefsStorage).to.eql(defaultState.prefsStorage)
|
||||
})
|
||||
|
||||
it('should initialize storage with proper flags for new users if none present', () => {
|
||||
|
@ -36,6 +38,7 @@ describe('The serverSideStorage module', () => {
|
|||
expect(state.cache._version).to.eql(VERSION)
|
||||
expect(state.cache._timestamp).to.be.a('number')
|
||||
expect(state.cache.flagStorage).to.eql(newUserFlags)
|
||||
expect(state.cache.prefsStorage).to.eql(defaultState.prefsStorage)
|
||||
})
|
||||
|
||||
it('should merge flags even if remote timestamp is older', () => {
|
||||
|
@ -57,6 +60,9 @@ describe('The serverSideStorage module', () => {
|
|||
flagStorage: {
|
||||
...defaultState.flagStorage,
|
||||
updateCounter: 1
|
||||
},
|
||||
prefsStorage: {
|
||||
...defaultState.flagStorage,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -157,6 +163,94 @@ describe('The serverSideStorage module', () => {
|
|||
})
|
||||
})
|
||||
|
||||
describe('_mergePrefs', () => {
|
||||
it('should prefer recent and apply journal to it', () => {
|
||||
expect(
|
||||
_mergePrefs(
|
||||
// RECENT
|
||||
{
|
||||
simple: { a: 1, b: 0, c: true },
|
||||
_journal: [
|
||||
{ path: 'simple.b', operation: 'set', args: [0], timestamp: 2 },
|
||||
{ path: 'simple.c', operation: 'set', args: [true], timestamp: 4 }
|
||||
]
|
||||
},
|
||||
// STALE
|
||||
{
|
||||
simple: { a: 1, b: 1, c: false },
|
||||
_journal: [
|
||||
{ path: 'simple.a', operation: 'set', args: [1], timestamp: 1 },
|
||||
{ path: 'simple.b', operation: 'set', args: [1], timestamp: 3 }
|
||||
]
|
||||
}
|
||||
)
|
||||
).to.eql({
|
||||
simple: { a: 1, b: 1, c: true },
|
||||
_journal: [
|
||||
{ path: 'simple.a', operation: 'set', args: [1], timestamp: 1 },
|
||||
{ path: 'simple.b', operation: 'set', args: [1], timestamp: 3 },
|
||||
{ path: 'simple.c', operation: 'set', args: [true], timestamp: 4 }
|
||||
]
|
||||
})
|
||||
})
|
||||
|
||||
it('should allow setting falsy values', () => {
|
||||
expect(
|
||||
_mergePrefs(
|
||||
// RECENT
|
||||
{
|
||||
simple: { a: 1, b: 0, c: false },
|
||||
_journal: [
|
||||
{ path: 'simple.b', operation: 'set', args: [0], timestamp: 2 },
|
||||
{ path: 'simple.c', operation: 'set', args: [false], timestamp: 4 }
|
||||
]
|
||||
},
|
||||
// STALE
|
||||
{
|
||||
simple: { a: 0, b: 0, c: true },
|
||||
_journal: [
|
||||
{ path: 'simple.a', operation: 'set', args: [0], timestamp: 1 },
|
||||
{ path: 'simple.b', operation: 'set', args: [0], timestamp: 3 }
|
||||
]
|
||||
}
|
||||
)
|
||||
).to.eql({
|
||||
simple: { a: 0, b: 0, c: false },
|
||||
_journal: [
|
||||
{ path: 'simple.a', operation: 'set', args: [0], timestamp: 1 },
|
||||
{ path: 'simple.b', operation: 'set', args: [0], timestamp: 3 },
|
||||
{ path: 'simple.c', operation: 'set', args: [false], timestamp: 4 }
|
||||
]
|
||||
})
|
||||
})
|
||||
|
||||
it('should work with strings', () => {
|
||||
expect(
|
||||
_mergePrefs(
|
||||
// RECENT
|
||||
{
|
||||
simple: { a: 'foo' },
|
||||
_journal: [
|
||||
{ path: 'simple.a', operation: 'set', args: ['foo'], timestamp: 2 }
|
||||
]
|
||||
},
|
||||
// STALE
|
||||
{
|
||||
simple: { a: 'bar' },
|
||||
_journal: [
|
||||
{ path: 'simple.a', operation: 'set', args: ['bar'], timestamp: 4 }
|
||||
]
|
||||
}
|
||||
)
|
||||
).to.eql({
|
||||
simple: { a: 'bar' },
|
||||
_journal: [
|
||||
{ path: 'simple.a', operation: 'set', args: ['bar'], timestamp: 4 }
|
||||
]
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('_resetFlags', () => {
|
||||
it('should reset all known flags to 0 when reset flag is set to > 0 and < 9000', () => {
|
||||
const totalFlags = { a: 0, b: 3, reset: 1 }
|
||||
|
|
Loading…
Reference in New Issue