aboutsummaryrefslogtreecommitdiff
path: root/src/modules
diff options
context:
space:
mode:
authorHenry Jameson <me@hjkos.com>2022-08-04 01:56:52 +0300
committerHenry Jameson <me@hjkos.com>2022-08-04 01:56:52 +0300
commitdbfca224d812c2ba80a48852ba047bb65c4c6dd9 (patch)
treeb764284bf0bfe1348482cb4097c1b63c06118a7f /src/modules
parent5b7c6538745083dfd48771392ab22de557a7a344 (diff)
server-side storage for flags
Diffstat (limited to 'src/modules')
-rw-r--r--src/modules/serverSideStorage.js158
-rw-r--r--src/modules/users.js2
2 files changed, 160 insertions, 0 deletions
diff --git a/src/modules/serverSideStorage.js b/src/modules/serverSideStorage.js
new file mode 100644
index 00000000..5ebe17fd
--- /dev/null
+++ b/src/modules/serverSideStorage.js
@@ -0,0 +1,158 @@
+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
diff --git a/src/modules/users.js b/src/modules/users.js
index 13d4e318..b6fb9746 100644
--- a/src/modules/users.js
+++ b/src/modules/users.js
@@ -525,6 +525,7 @@ const users = {
user.muteIds = []
user.domainMutes = []
commit('setCurrentUser', user)
+ commit('setServerSideStorage', user)
commit('addNewUsers', [user])
store.dispatch('fetchEmoji')
@@ -534,6 +535,7 @@ const users = {
// Set our new backend interactor
commit('setBackendInteractor', backendInteractorService(accessToken))
+ store.dispatch('pushServerSideStorage')
if (user.token) {
store.dispatch('setWsToken', user.token)