159 lines
5.6 KiB
JavaScript
159 lines
5.6 KiB
JavaScript
|
import { toRaw } from 'vue'
|
||
|
|
||
|
const VERSION = 1
|
||
|
const NEW_USER_DATE = new Date('04-08-2022') // date of writing this, basically
|
||
|
|
||
|
const COMMAND_TRIM_FLAGS = 1000
|
||
|
const COMMAND_TRIM_FLAGS_AND_RESET = 1001
|
||
|
|
||
|
const defaultState = {
|
||
|
// last timestamp
|
||
|
timestamp: 0,
|
||
|
// need to update server
|
||
|
dirty: false,
|
||
|
// storage of flags - stuff that can only be set and incremented
|
||
|
flagStorage: {
|
||
|
updateCounter: 0, // Counter for most recent update notification seen
|
||
|
// TODO move to prefsStorage when that becomes a thing since only way
|
||
|
// this can be reset is by complete reset of all flags
|
||
|
dontShowUpdateNotifs: 0, // if user chose to not show update notifications ever again
|
||
|
reset: 0 // special flag that can be used to force-reset all flags, debug purposes only
|
||
|
// special reset codes:
|
||
|
// 1000: trim keys to those known by currently running FE
|
||
|
// 1001: same as above + reset everything to 0
|
||
|
},
|
||
|
// raw data
|
||
|
raw: null,
|
||
|
// local cache
|
||
|
cache: null
|
||
|
}
|
||
|
|
||
|
const newUserFlags = {
|
||
|
...defaultState.flagStorage,
|
||
|
updateCounter: 1 // new users don't need to see update notification
|
||
|
}
|
||
|
|
||
|
const serverSideStorage = {
|
||
|
state: {
|
||
|
...defaultState
|
||
|
},
|
||
|
mutations: {
|
||
|
setServerSideStorage (state, userData) {
|
||
|
const live = userData.storage
|
||
|
const userNew = userData.created_at > NEW_USER_DATE
|
||
|
const flagsTemplate = userNew ? newUserFlags : defaultState.defaultState
|
||
|
state.raw = live
|
||
|
console.log(1111, live._timestamp)
|
||
|
let recent = null
|
||
|
const cache = state.cache || {}
|
||
|
const cacheValid = cache._timestamp > 0 && cache._version > 0
|
||
|
const liveValid = live._timestamp > 0 && live._version > 0
|
||
|
if (!liveValid) {
|
||
|
state.dirty = true
|
||
|
console.debug('Nothing valid stored on server, assuming cache to be source of truth')
|
||
|
if (cacheValid) {
|
||
|
recent = cache
|
||
|
} else {
|
||
|
console.debug(`Local cache is empty, initializing for ${userNew ? 'new' : 'existing'} user`)
|
||
|
|
||
|
recent = {
|
||
|
_timestamp: Date.now(),
|
||
|
_version: VERSION,
|
||
|
flagStorage: { ...flagsTemplate }
|
||
|
}
|
||
|
}
|
||
|
} else if (!cacheValid) {
|
||
|
console.debug('Valid storage on server found, no local cache found, using live as source of truth')
|
||
|
recent = live
|
||
|
} else {
|
||
|
console.debug('Both sources have valid data, figuring things out...')
|
||
|
console.log(live._timestamp, cache._timestamp)
|
||
|
if (live._timestamp === cache._timestamp && live._version === cache._version) {
|
||
|
console.debug('Same version/timestamp on both source, source of truth irrelevant')
|
||
|
recent = cache
|
||
|
} else {
|
||
|
state.dirty = true
|
||
|
console.debug('Different timestamp, figuring out which one is more recent')
|
||
|
let stale
|
||
|
if (live._timestamp < cache._timestamp) {
|
||
|
recent = cache
|
||
|
stale = live
|
||
|
} else {
|
||
|
recent = live
|
||
|
stale = cache
|
||
|
}
|
||
|
|
||
|
// Merge the flags
|
||
|
console.debug('Merging the flags...')
|
||
|
recent.flagStorage = recent.flagStorage || { ...flagsTemplate }
|
||
|
stale.flagStorage = stale.flagStorage || { ...flagsTemplate }
|
||
|
const allFlags = Array.from(new Set([
|
||
|
...Object.keys(toRaw(recent.flagStorage)),
|
||
|
...Object.keys(toRaw(stale.flagStorage))
|
||
|
]))
|
||
|
|
||
|
const totalFlags = Object.fromEntries(allFlags.map(flag => {
|
||
|
const recentFlag = recent.flagStorage[flag]
|
||
|
const staleFlag = stale.flagStorage[flag]
|
||
|
// use flag that is of higher value
|
||
|
return [flag, recentFlag > staleFlag ? recentFlag : staleFlag]
|
||
|
}))
|
||
|
|
||
|
console.debug('AAA', totalFlags)
|
||
|
// flag reset functionality
|
||
|
if (totalFlags.reset >= COMMAND_TRIM_FLAGS && totalFlags.reset <= COMMAND_TRIM_FLAGS_AND_RESET) {
|
||
|
console.debug('Received command to trim the flags')
|
||
|
const knownKeys = new Set(Object.keys(defaultState.flagStorage))
|
||
|
allFlags.forEach(flag => {
|
||
|
if (!knownKeys.has(flag)) {
|
||
|
delete totalFlags[flag]
|
||
|
}
|
||
|
})
|
||
|
if (totalFlags.reset === COMMAND_TRIM_FLAGS_AND_RESET) {
|
||
|
// 1001 - and reset everything to 0
|
||
|
console.debug('Received command to reset the flags')
|
||
|
allFlags.forEach(flag => { totalFlags[flag] = 0 })
|
||
|
} else {
|
||
|
// reset the reset 0
|
||
|
totalFlags.reset = 0
|
||
|
}
|
||
|
} else if (totalFlags.reset > 0 && totalFlags.reset < 9000) {
|
||
|
console.debug('Received command to reset the flags')
|
||
|
allFlags.forEach(flag => { totalFlags[flag] = 0 })
|
||
|
// for good luck
|
||
|
totalFlags.reset = 0
|
||
|
}
|
||
|
console.log('AAAA', totalFlags)
|
||
|
state.cache.flagStorage = totalFlags
|
||
|
}
|
||
|
}
|
||
|
state.cache = recent
|
||
|
state.flagStorage = state.cache.flagStorage
|
||
|
},
|
||
|
setFlag (state, { flag, value }) {
|
||
|
state.flagStorage[flag] = value
|
||
|
state.dirty = true
|
||
|
}
|
||
|
},
|
||
|
actions: {
|
||
|
pushServerSideStorage ({ state, rootState, commit }, { force = false } = {}) {
|
||
|
console.log('PUSH')
|
||
|
const needPush = state.dirty || force
|
||
|
if (!needPush) return
|
||
|
state.cache = {
|
||
|
_timestamp: Date.now(),
|
||
|
_version: VERSION,
|
||
|
flagStorage: toRaw(state.flagStorage)
|
||
|
}
|
||
|
console.log('YES')
|
||
|
const params = { pleroma_settings_store: { 'pleroma-fe': state.cache } }
|
||
|
rootState.api.backendInteractor
|
||
|
.updateProfile({ params })
|
||
|
.then((user) => commit('setServerSideStorage', user))
|
||
|
state.dirty = false
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
export default serverSideStorage
|