1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
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
|