pleroma-fe/src/modules/serverSideStorage.js
2022-08-04 01:56:52 +03:00

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