@subiz/widget-v4 4.1.123 → 4.1.125
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/compiled_src/chatbox/Events.js +1 -1
- package/compiled_src/plugin.js +1 -0
- package/compiled_src/store/api.js +0 -1
- package/compiled_src/store/api_fake.js +0 -1
- package/compiled_src/store/chain.js +228 -0
- package/compiled_src/store/inmem_localstorage.js +33 -0
- package/compiled_src/store/kv.js +86 -0
- package/compiled_src/store/lsdb.js +68 -0
- package/compiled_src/store/store.js +25 -17
- package/dist/132.js +6433 -2574
- package/dist/178.js +406 -0
- package/dist/18a02a9c54e.132.js +1 -0
- package/dist/18a02a9c54e.178.js +1 -0
- package/dist/18a02a9c54e.213.js +1 -0
- package/dist/18a02a9c54e.335.js +1 -0
- package/dist/18a02a9c54e.362.js +1 -0
- package/dist/18a02a9c54e.441.js +1 -0
- package/dist/18a02a9c54e.605.js +1 -0
- package/dist/18a02a9c54e.678.js +1 -0
- package/dist/18a02a9c54e.782.js +1 -0
- package/dist/18a02a9c54e.app.js +1 -0
- package/dist/{1964db39388.index.html → 18a02a9c54e.index.html} +4 -28
- package/dist/{1964db39388.library.html → 18a02a9c54e.library.html} +4 -28
- package/dist/18a02a9c54e.library.js +1 -0
- package/dist/{1964db39388.preview.html → 18a02a9c54e.preview.html} +1 -1
- package/dist/18a02a9c54e.preview.js +1 -0
- package/dist/18a02a9c54e.screenshoot.js +1 -0
- package/dist/18a02a9c54e.webview.js +1 -0
- package/dist/213.js +2780 -0
- package/dist/{74.js → 335.js} +35 -35
- package/dist/362.js +107 -0
- package/dist/441.js +2855 -0
- package/dist/{490.js → 605.js} +82 -82
- package/dist/{997.js → 678.js} +6 -6
- package/dist/782.js +107 -0
- package/dist/HASH +1 -1
- package/dist/assets/img/{subiz-mono.8fbc067.svg → subiz-mono.877e9f5.svg} +1 -1
- package/dist/malicious-app.js +4 -6
- package/dist/screenshoot.html +1 -1
- package/dist/screenshoot.js +4857 -9606
- package/package.json +1 -2
- package/src/chatbox/Events.js +1 -1
- package/src/chatbox/main.js +1 -0
- package/src/plugin.js +2 -0
- package/src/store/api.js +0 -1
- package/src/store/api_fake.js +0 -1
- package/src/store/chain.js +255 -0
- package/src/store/inmem_localstorage.js +40 -0
- package/src/store/kv.js +103 -0
- package/src/store/lsdb.js +74 -0
- package/src/store/store.js +22 -18
- package/dist/127.js +0 -273
- package/dist/185.js +0 -1885
- package/dist/1964db39388.127.js +0 -1
- package/dist/1964db39388.132.js +0 -1
- package/dist/1964db39388.185.js +0 -1
- package/dist/1964db39388.27.js +0 -1
- package/dist/1964db39388.278.js +0 -1
- package/dist/1964db39388.459.js +0 -1
- package/dist/1964db39388.490.js +0 -1
- package/dist/1964db39388.74.js +0 -1
- package/dist/1964db39388.997.js +0 -1
- package/dist/1964db39388.app.js +0 -1
- package/dist/1964db39388.library.js +0 -1
- package/dist/1964db39388.preview.js +0 -1
- package/dist/1964db39388.webview.js +0 -1
- package/dist/27.js +0 -107
- package/dist/278.js +0 -406
- package/dist/459.js +0 -107
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@subiz/widget-v4",
|
|
3
|
-
"version": "4.1.
|
|
3
|
+
"version": "4.1.125",
|
|
4
4
|
"main": "./compiled_src/lib.js",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"dev": "npx webpack serve --config webpack.dev.js",
|
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@subiz/ajax": "^3.0.19",
|
|
13
13
|
"@subiz/flow": "^1.1.0",
|
|
14
|
-
"@subiz/storage": "0.0.8",
|
|
15
14
|
"@subiz/wsclient": "^4.0.28",
|
|
16
15
|
"cookie_js": "1.4.2",
|
|
17
16
|
"core-js": "^3.41.0",
|
package/src/chatbox/Events.js
CHANGED
|
@@ -93,7 +93,7 @@ export default class Events extends Com {
|
|
|
93
93
|
if (this.state.error) return this.renderError()
|
|
94
94
|
let events = sb.map(this.props.store.listEvents(this.props.cid))
|
|
95
95
|
|
|
96
|
-
if (!this.state.loading && sb.size(events) === 0) {
|
|
96
|
+
if (!this.state.loading && sb.size(events) === 0 && !this.props.cid) {
|
|
97
97
|
return (
|
|
98
98
|
<div ref={(ref) => (this.refBody = ref)} class='widget-body--events-container'>
|
|
99
99
|
<div class='widget-body--empty'>
|
package/src/chatbox/main.js
CHANGED
|
@@ -70,6 +70,7 @@ export default class Main extends Com {
|
|
|
70
70
|
if (!this.state.cssready) return null
|
|
71
71
|
if (sb.isUserBanned(this.props.store.matchUser())) return null
|
|
72
72
|
if (!this.props.t) return null
|
|
73
|
+
|
|
73
74
|
return (
|
|
74
75
|
<div class={this.props.store.isMobile() ? 'mobile' : 'desktop'}>
|
|
75
76
|
<ChatButton
|
package/src/plugin.js
CHANGED
|
@@ -69,6 +69,8 @@ function Plugin(plugin, store, $container, lib) {
|
|
|
69
69
|
var _render = async () => {
|
|
70
70
|
if (_destroy) return
|
|
71
71
|
if (!$div) return
|
|
72
|
+
if (!this.t) return
|
|
73
|
+
|
|
72
74
|
if (plugin.type === 'chatbox') {
|
|
73
75
|
// if (!Chatbox) Chatbox = (await LoadChatbox()).default
|
|
74
76
|
render(<Chatbox destroy={_destroy} plugin={plugin} store={store} ref={_ref} t={this.t} />, $div)
|
package/src/store/api.js
CHANGED
|
@@ -290,7 +290,6 @@ export default class {
|
|
|
290
290
|
|
|
291
291
|
getUser = (_) => this.apireq.get(`/accounts/${this.accid}/users/${this.uid}`)
|
|
292
292
|
getAccountSetting = () => this.apireq.get(`/accounts/${this.accid}/settings`)
|
|
293
|
-
getIsOnline = () => this.apireq.get(`/accounts/${this.accid}/is_online`)
|
|
294
293
|
|
|
295
294
|
sendImpression = (impression) =>
|
|
296
295
|
this.apireq.post(`/accounts/${this.accid}/campaigns/${impression.campaign_id}/impressions`, impression)
|
package/src/store/api_fake.js
CHANGED
|
@@ -86,7 +86,6 @@ export default class {
|
|
|
86
86
|
},
|
|
87
87
|
})
|
|
88
88
|
getAccountSetting = () => this.apireq.get(`/accounts/${this.accid}/settings`)
|
|
89
|
-
getIsOnline = () => this.apireq.get(`/accounts/${this.accid}/is_online`)
|
|
90
89
|
|
|
91
90
|
sendImpression = (impression) => OK200
|
|
92
91
|
sendConversion = (conversion) => OK200
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
const ChainMaxSize = 50
|
|
2
|
+
// NOTE:
|
|
3
|
+
// index must be number and index must be positive
|
|
4
|
+
//
|
|
5
|
+
|
|
6
|
+
export default class Chain {
|
|
7
|
+
constructor(db, schema, inmem) {
|
|
8
|
+
this.schema = schema + '_chain'
|
|
9
|
+
this.dead = false
|
|
10
|
+
this.db = db
|
|
11
|
+
this.anchorCache = {}
|
|
12
|
+
this.cache = {} // note: cache must be continuously from start
|
|
13
|
+
|
|
14
|
+
this.init()
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
init() {
|
|
18
|
+
let inmemItemM = {}
|
|
19
|
+
|
|
20
|
+
let allitems = this.db.all('items')
|
|
21
|
+
allitems.map((item) => {
|
|
22
|
+
inmemItemM[item.chain] = inmemItemM[item.chain] || {}
|
|
23
|
+
inmemItemM[item.chain][item.id] = {
|
|
24
|
+
id: item.id,
|
|
25
|
+
chain: item.chain,
|
|
26
|
+
full_id: item.full_id,
|
|
27
|
+
index: item.index,
|
|
28
|
+
value: item.value,
|
|
29
|
+
}
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
map(inmemItemM, (itemM, chain) => {
|
|
33
|
+
if (size(itemM) < ChainMaxSize) return
|
|
34
|
+
let items = orderBy(map(itemM), ['index'], 'desc')
|
|
35
|
+
let removekeys = []
|
|
36
|
+
for (var i = ChainMaxSize; i < items.length; i++) {
|
|
37
|
+
removekeys.push(items[i].full_id)
|
|
38
|
+
delete itemM[items[i].id]
|
|
39
|
+
}
|
|
40
|
+
this.db.removes('items', removekeys)
|
|
41
|
+
inmemItemM[chain] = itemM
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
this.cache = inmemItemM
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
destroy() {
|
|
48
|
+
// clear all data
|
|
49
|
+
this.db.clear('items')
|
|
50
|
+
|
|
51
|
+
this.dead = true
|
|
52
|
+
this.cache = {}
|
|
53
|
+
this.anchorCache = {}
|
|
54
|
+
this.db = undefined
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// item: {id, index, value}
|
|
58
|
+
// note: should only call update when db is synced
|
|
59
|
+
put(chain, id, node_index, value) {
|
|
60
|
+
if (this.dead) return
|
|
61
|
+
|
|
62
|
+
let inmemItemM = this.cache[chain] || {}
|
|
63
|
+
let bottom = minIndex(inmemItemM) || {}
|
|
64
|
+
let bottomIndex = bottom.index || 'z'
|
|
65
|
+
if (size(inmemItemM) == 0) bottomIndex = ''
|
|
66
|
+
|
|
67
|
+
let item = {id, index: node_index, value, chain, full_id: chain + ':' + id}
|
|
68
|
+
delete inmemItemM[item.id]
|
|
69
|
+
|
|
70
|
+
if (bottomIndex > item.index + '') return
|
|
71
|
+
inmemItemM[item.id] = item
|
|
72
|
+
|
|
73
|
+
this.cache[chain] = inmemItemM
|
|
74
|
+
this.db.put('items', item.full_id, item)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
listM(chain) {
|
|
78
|
+
if (this.dead) return {}
|
|
79
|
+
let inmemItemM = this.cache[chain] || {}
|
|
80
|
+
let out = {}
|
|
81
|
+
map(inmemItemM, (item, id) => {
|
|
82
|
+
out[id] = item.value
|
|
83
|
+
})
|
|
84
|
+
return out
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
async fetchMore(chain, limit = 20, api) {
|
|
88
|
+
if (this.dead) return {error: 'dead'}
|
|
89
|
+
if (!api) return {error: 'no api'}
|
|
90
|
+
|
|
91
|
+
let anchor = this.anchorCache[chain] || ''
|
|
92
|
+
var [apiItems, newanchor, error] = await api(chain, anchor, limit)
|
|
93
|
+
|
|
94
|
+
if (error) return {error}
|
|
95
|
+
if (this.dead) return {error: 'dead'}
|
|
96
|
+
|
|
97
|
+
let inmemItemM = this.cache[chain] || {}
|
|
98
|
+
|
|
99
|
+
if (apiItems.length === 0) return {end: true}
|
|
100
|
+
|
|
101
|
+
apiItems.forEach((item) => {
|
|
102
|
+
item.chain = chain
|
|
103
|
+
item.full_id = chain + ':' + item.id
|
|
104
|
+
inmemItemM[item.id] = item
|
|
105
|
+
this.db.put('items', item.full_id, item)
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
// save items fetch from api to the db
|
|
109
|
+
this.anchorCache[chain] = newanchor
|
|
110
|
+
this.cache[chain] = inmemItemM
|
|
111
|
+
return {}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
del(chain, id) {
|
|
115
|
+
if (this.dead) return
|
|
116
|
+
let inmemItemM = this.cache[chain] || {}
|
|
117
|
+
let full_id = chain + ':' + id
|
|
118
|
+
|
|
119
|
+
delete inmemItemM[id]
|
|
120
|
+
this.db.removes('items', [full_id])
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
match(chain, id) {
|
|
124
|
+
return this.listM(chain)[id]
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
async reload(chain, api) {
|
|
128
|
+
if (this.dead) return
|
|
129
|
+
|
|
130
|
+
let top = maxIndex(this.listM(chain)) || {}
|
|
131
|
+
let topindex = top.index
|
|
132
|
+
if (!topindex) topindex = Date.now()
|
|
133
|
+
var lastanchor = ''
|
|
134
|
+
var fetchedItems = {}
|
|
135
|
+
for (;;) {
|
|
136
|
+
if (this.dead) return
|
|
137
|
+
let [newItems, newanchor, error] = await api(chain, lastanchor, 50)
|
|
138
|
+
if (error) return
|
|
139
|
+
if (this.dead) return
|
|
140
|
+
newItems.map((item) => {
|
|
141
|
+
fetchedItems[item.id] = Object.assign({}, item, {chain, full_id: chain + ':' + item.id})
|
|
142
|
+
})
|
|
143
|
+
if (newItems.length === 0 || newanchor === lastanchor) break // out of item
|
|
144
|
+
|
|
145
|
+
// still cannot join
|
|
146
|
+
if (fetchedItems.length >= 200) {
|
|
147
|
+
// fetch too much but still cannot merge with old data
|
|
148
|
+
// clear old data and write new data
|
|
149
|
+
|
|
150
|
+
let inmemItemM = this.cache[chain] || {}
|
|
151
|
+
let removeids = []
|
|
152
|
+
map(inmemItemM, (item) => {
|
|
153
|
+
if (item.chain !== chain) return
|
|
154
|
+
removeids.push(item.full_id)
|
|
155
|
+
})
|
|
156
|
+
this.db.removes('items', removeids)
|
|
157
|
+
this.cache[chain] = {}
|
|
158
|
+
break
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
let minindexitem = minIndex(fetchedItems) || {}
|
|
162
|
+
// try to join old data
|
|
163
|
+
if (minindexitem.index <= topindex) {
|
|
164
|
+
// successfully joined, reuse anchor
|
|
165
|
+
|
|
166
|
+
lastanchor = this.anchorCache[chain] || newanchor
|
|
167
|
+
break
|
|
168
|
+
}
|
|
169
|
+
lastanchor = newanchor
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
for (var i = 0; i < Object.keys(fetchedItems).length; i++) {
|
|
173
|
+
let item = fetchedItems[Object.keys(fetchedItems)[i]]
|
|
174
|
+
this.db.put('items', item.full_id, item)
|
|
175
|
+
this.cache[item.chain] = this.cache[item.chain] || {}
|
|
176
|
+
this.cache[item.chain][item.id] = item
|
|
177
|
+
}
|
|
178
|
+
this.anchorCache[chain] = lastanchor
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function minIndex(obj) {
|
|
183
|
+
if (!obj) return
|
|
184
|
+
let keys = Object.keys(obj)
|
|
185
|
+
if (!keys.length) return
|
|
186
|
+
let min = Infinity
|
|
187
|
+
let minKey = Object.keys(obj)[0]
|
|
188
|
+
for (var i = 0; i < keys.length; i++) {
|
|
189
|
+
let index = (obj[keys[i]] && obj[keys[i]].index) || Infinity
|
|
190
|
+
if (index < min) {
|
|
191
|
+
min = index
|
|
192
|
+
minKey = keys[i]
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return obj[minKey]
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function maxIndex(obj) {
|
|
200
|
+
if (!obj) return
|
|
201
|
+
let keys = Object.keys(obj)
|
|
202
|
+
if (!keys.length) return
|
|
203
|
+
let max = -Infinity
|
|
204
|
+
let maxKey = Object.keys(obj)[0]
|
|
205
|
+
for (var i = 0; i < keys.length; i++) {
|
|
206
|
+
let index = (obj[keys[i]] && obj[keys[i]].index) || -Infinity
|
|
207
|
+
if (index > max) {
|
|
208
|
+
max = index
|
|
209
|
+
maxKey = keys[i]
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return obj[keys[maxKey]]
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function map(collection, predicate) {
|
|
217
|
+
if (!collection) return []
|
|
218
|
+
if (!predicate) return collection
|
|
219
|
+
|
|
220
|
+
var out = []
|
|
221
|
+
if (Array.isArray(collection)) {
|
|
222
|
+
for (let i = 0; i < collection.length; i++) {
|
|
223
|
+
out.push(predicate(collection[i], i))
|
|
224
|
+
}
|
|
225
|
+
return out
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (typeof collection === 'object') {
|
|
229
|
+
var keys = Object.keys(collection)
|
|
230
|
+
for (let i = 0; i < keys.length; i++) {
|
|
231
|
+
var k = keys[i]
|
|
232
|
+
out.push(predicate(collection[k], k))
|
|
233
|
+
}
|
|
234
|
+
return out
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
return out
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
function size(o) {
|
|
241
|
+
if (!o) return 0
|
|
242
|
+
if (o.length !== undefined) return o.length
|
|
243
|
+
return Object.keys(o).length
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function orderBy(a, k, d) {
|
|
247
|
+
var clone = []
|
|
248
|
+
map(a, (v) => clone.push(v))
|
|
249
|
+
clone.sort((i, j) => {
|
|
250
|
+
if (i[k] === j[k]) return 0
|
|
251
|
+
var r = i[k] < j[k] ? -1 : 1
|
|
252
|
+
return d === 'desc' ? -r : r
|
|
253
|
+
})
|
|
254
|
+
return clone
|
|
255
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// this file implements localstorage in memory
|
|
2
|
+
var localStorageMemory = {}
|
|
3
|
+
var cache = {}
|
|
4
|
+
|
|
5
|
+
localStorageMemory.length = 0
|
|
6
|
+
|
|
7
|
+
localStorageMemory.getItem = function (key) {
|
|
8
|
+
if (key in cache) return cache[key]
|
|
9
|
+
return null
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
localStorageMemory.setItem = function (key, value) {
|
|
13
|
+
if (typeof value === 'undefined') {
|
|
14
|
+
localStorageMemory.removeItem(key)
|
|
15
|
+
} else {
|
|
16
|
+
if (!Object.prototype.hasOwnProperty.call(cache, key)) {
|
|
17
|
+
localStorageMemory.length++
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
cache[key] = value
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
localStorageMemory.removeItem = function (key) {
|
|
25
|
+
if (Object.prototype.hasOwnProperty.call(cache, key)) {
|
|
26
|
+
delete cache[key]
|
|
27
|
+
localStorageMemory.length--
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
localStorageMemory.key = function (index) {
|
|
32
|
+
return Object.keys(cache)[index] || null
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
localStorageMemory.clear = function () {
|
|
36
|
+
cache = {}
|
|
37
|
+
localStorageMemory.length = 0
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
module.exports = localStorageMemory
|
package/src/store/kv.js
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
let KvMaxSize = 500
|
|
2
|
+
// A key-value database with a cache layer
|
|
3
|
+
export default class {
|
|
4
|
+
constructor (db, schema) {
|
|
5
|
+
this.name = schema
|
|
6
|
+
schema += '_kv'
|
|
7
|
+
this.dead = false
|
|
8
|
+
this.db = db
|
|
9
|
+
this.cache = {}
|
|
10
|
+
|
|
11
|
+
this.initialized = false
|
|
12
|
+
this.init()
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
refreshCache () {
|
|
16
|
+
if (this.dead) return
|
|
17
|
+
let inmemItemM = {}
|
|
18
|
+
let allitems = this.db.all('items')
|
|
19
|
+
allitems.forEach(function(item) {
|
|
20
|
+
inmemItemM[item.key] = item.value
|
|
21
|
+
})
|
|
22
|
+
this.cache = inmemItemM
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
init () {
|
|
26
|
+
if (this.initialized) return
|
|
27
|
+
let inmemItemM = {}
|
|
28
|
+
|
|
29
|
+
console.time('KV' + this.name)
|
|
30
|
+
let allitems = this.db.all('items')
|
|
31
|
+
allitems.forEach(function(item) {
|
|
32
|
+
inmemItemM[item.key] = item.value
|
|
33
|
+
})
|
|
34
|
+
this.cache = inmemItemM
|
|
35
|
+
|
|
36
|
+
// If the cache is full. Randomly remove half of the cache. credit to thanos
|
|
37
|
+
// this is so simple since we don't need to keep track of last modified time
|
|
38
|
+
// for each key. Implementing a LRU cache won't add much value.
|
|
39
|
+
let allkeys = Object.keys(this.cache)
|
|
40
|
+
if (allkeys.length > KvMaxSize) {
|
|
41
|
+
let liveChance = KvMaxSize / 2 / allkeys.lenth
|
|
42
|
+
|
|
43
|
+
let removekeys = []
|
|
44
|
+
for (var i = 0; i < KvMaxSize; i++) {
|
|
45
|
+
let live = Math.random() <= liveChance
|
|
46
|
+
if (live) continue
|
|
47
|
+
|
|
48
|
+
let key = allkeys[i]
|
|
49
|
+
delete this.cache[key]
|
|
50
|
+
removekeys.push(key)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
this.db.removes('items', [removekeys])
|
|
54
|
+
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
this.initialized = true
|
|
58
|
+
console.timeEnd('KV' + this.name)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
all () {
|
|
62
|
+
if (this.dead) return []
|
|
63
|
+
if (!this.initialized) return []
|
|
64
|
+
return this.cache
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
match (key) {
|
|
68
|
+
if (this.dead || !this.initialized) return
|
|
69
|
+
if (!key) return
|
|
70
|
+
return this.cache[key]
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// keys could be a string or array
|
|
74
|
+
// put('1', {id: '1', name: 'thanh'})
|
|
75
|
+
// put({id: '1', name: 'thanh'}, 'id')
|
|
76
|
+
// put([{id: '1', name: 'thanh'},{id: '2', name: 'van'}], 'id')
|
|
77
|
+
put (key, value) {
|
|
78
|
+
if (!key) return
|
|
79
|
+
if (this.dead) return []
|
|
80
|
+
if (!this.initialized) throw new Error('uninitialized')
|
|
81
|
+
// if multiple key
|
|
82
|
+
this.cache[key] = value
|
|
83
|
+
this.db.put('items', key, { key, value })
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// delete an record in a schema
|
|
87
|
+
del (key) {
|
|
88
|
+
if (this.dead) return
|
|
89
|
+
if (!this.initialized) throw new Error('uninitialized')
|
|
90
|
+
delete this.cache[key]
|
|
91
|
+
this.db.removes('items', [key])
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
destroy () {
|
|
95
|
+
// clear all data
|
|
96
|
+
this.db.clear('items')
|
|
97
|
+
|
|
98
|
+
this.dead = true
|
|
99
|
+
this.db = undefined
|
|
100
|
+
this.cache = undefined
|
|
101
|
+
this.initialized = false
|
|
102
|
+
}
|
|
103
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// like db but implement using localstorage
|
|
2
|
+
let memlocalStorage = require('./inmem_localstorage.js')
|
|
3
|
+
import sb from '../util/index.js'
|
|
4
|
+
|
|
5
|
+
let requestIdleCallback = typeof window !== 'undefined' ? window.requestIdleCallback : null
|
|
6
|
+
if (!requestIdleCallback) requestIdleCallback = (cb) => cb()
|
|
7
|
+
|
|
8
|
+
const LIMIT = 80
|
|
9
|
+
|
|
10
|
+
export default class {
|
|
11
|
+
constructor(schema, inmem) {
|
|
12
|
+
this.localStorage = memlocalStorage
|
|
13
|
+
this.inmem = inmem
|
|
14
|
+
this.allkeys = {}
|
|
15
|
+
if (!inmem) {
|
|
16
|
+
try {
|
|
17
|
+
window.localStorage.setItem('sbzstore1029', '?')
|
|
18
|
+
window.localStorage.removeItem('sbzstore1029')
|
|
19
|
+
this.localStorage = window.localStorage
|
|
20
|
+
} catch (e) {}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
this.schema = schema
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
all(table) {
|
|
27
|
+
let items = []
|
|
28
|
+
for (var i = 0; i < this.localStorage.length; i++) {
|
|
29
|
+
let key = this.localStorage.key(i)
|
|
30
|
+
if (!key.startsWith(this.schema + '#' + table + '#')) continue
|
|
31
|
+
this.allkeys[key] = true
|
|
32
|
+
if (this.inmem)
|
|
33
|
+
items.push(this.localStorage.getItem(key)) // fast path
|
|
34
|
+
else items.push(sb.parseJSON(this.localStorage.getItem(key)))
|
|
35
|
+
}
|
|
36
|
+
return items
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
removes(table, keys) {
|
|
40
|
+
for (var i = 0; i < keys.length; i++) {
|
|
41
|
+
delete this.allkeys[this.schema + '#' + table + '#' + keys[i]]
|
|
42
|
+
this.localStorage.removeItem(this.schema + '#' + table + '#' + keys[i])
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
clear(table) {
|
|
47
|
+
for (var i = 0; i < this.localStorage.length; i++) {
|
|
48
|
+
let key = this.localStorage.key(i)
|
|
49
|
+
if (!key.startsWith(this.schema + '#' + table + '#')) continue
|
|
50
|
+
this.localStorage.removeItem(key)
|
|
51
|
+
}
|
|
52
|
+
this.allkeys = {}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// write a (key,value) pair to the table
|
|
56
|
+
// if the localstorage is already full, it would try to free by delete the whole table!
|
|
57
|
+
put(table, key, value) {
|
|
58
|
+
this.allkeys[this.schema + '#' + table + '#' + key] = true
|
|
59
|
+
if (this.inmem) return this.localStorage.setItem(this.schema + '#' + table + '#' + key, value) // fast path
|
|
60
|
+
if (Object.keys(this.allkeys).length > LIMIT) this.clear(table)
|
|
61
|
+
requestIdleCallback(() => {
|
|
62
|
+
try {
|
|
63
|
+
this.localStorage.setItem(this.schema + '#' + table + '#' + key, toString(value))
|
|
64
|
+
} catch (e) {
|
|
65
|
+
this.clear(table)
|
|
66
|
+
}
|
|
67
|
+
})
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function toString(obj) {
|
|
72
|
+
if (obj === undefined) return 'null'
|
|
73
|
+
return JSON.stringify(obj)
|
|
74
|
+
}
|
package/src/store/store.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import sb from '../util/index.js'
|
|
2
2
|
var flow = require('@subiz/flow')
|
|
3
|
-
import stor8 from '@subiz/storage'
|
|
4
3
|
import API from './api.js'
|
|
4
|
+
import LSDB from './lsdb.js'
|
|
5
|
+
import Chain from './chain.js'
|
|
6
|
+
import KV from './kv.js'
|
|
5
7
|
import APIFake from './api_fake.js'
|
|
6
8
|
import RealtimeFake from './realtime_fake.js'
|
|
7
9
|
var Realtime = require('@subiz/wsclient')
|
|
@@ -51,9 +53,9 @@ export default class Store {
|
|
|
51
53
|
|
|
52
54
|
cleanLocalStorage()
|
|
53
55
|
this.pubsub = new sb.Pubsub()
|
|
54
|
-
this.kv = new
|
|
55
|
-
this.cache = new
|
|
56
|
-
this.chain = new
|
|
56
|
+
this.kv = new KV(new LSDB('sbz2023', this.inmem), 'kv')
|
|
57
|
+
this.cache = new KV(new LSDB('sbz2023', true), 'kv')
|
|
58
|
+
this.chain = new Chain(new LSDB('cbz2023', true), 'ch')
|
|
57
59
|
this.getLocaleContent = this.api.getLocaleContent
|
|
58
60
|
|
|
59
61
|
// dont dupplicate seen
|
|
@@ -175,14 +177,12 @@ export default class Store {
|
|
|
175
177
|
async overrideAcc(acc) {
|
|
176
178
|
this.forceAcc = sb.cloneDeep(acc)
|
|
177
179
|
await this.readyGate.entry()
|
|
178
|
-
this.disconnect('account')
|
|
179
180
|
this.reconnect()
|
|
180
181
|
}
|
|
181
182
|
|
|
182
183
|
async overrideChatbox(chatbox) {
|
|
183
184
|
this.forceChatbox = chatbox
|
|
184
185
|
await this.readyGate.entry()
|
|
185
|
-
this.disconnect('account')
|
|
186
186
|
await this.reconnect()
|
|
187
187
|
sb.setTimeout(this.pubsub.publish('resetCSS'), 10)
|
|
188
188
|
}
|
|
@@ -492,10 +492,13 @@ export default class Store {
|
|
|
492
492
|
this.realtime = new Realtime(this.RealtimeURL, {account_id: accid, user_ref: userRef, user_mask: mask}, xhrsend)
|
|
493
493
|
|
|
494
494
|
this.realtime.onEvent(this.onWs.bind(this))
|
|
495
|
-
this.realtime.onInterrupted(() =>
|
|
495
|
+
this.realtime.onInterrupted(async () => {
|
|
496
|
+
await this.reconnectWs(accid, user.id)
|
|
497
|
+
this.reconnect()
|
|
498
|
+
})
|
|
496
499
|
|
|
497
500
|
this.seenLoop()
|
|
498
|
-
await this.reconnect()
|
|
501
|
+
await this.reconnect({user: user}) // already fetched
|
|
499
502
|
this.readyGate.open()
|
|
500
503
|
this.reconnectWs(accid, user.id)
|
|
501
504
|
return user
|
|
@@ -518,7 +521,10 @@ export default class Store {
|
|
|
518
521
|
else this.realtime = new Realtime(this.RealtimeURL, {getAccessToken: () => this.api.token_generator()})
|
|
519
522
|
|
|
520
523
|
this.realtime.onEvent(this.onWs.bind(this))
|
|
521
|
-
this.realtime.onInterrupted(() =>
|
|
524
|
+
this.realtime.onInterrupted(async () => {
|
|
525
|
+
await this.reconnectWs(accid, user.id)
|
|
526
|
+
this.reconnect()
|
|
527
|
+
})
|
|
522
528
|
|
|
523
529
|
this.seenLoop()
|
|
524
530
|
await this.reconnect()
|
|
@@ -599,25 +605,23 @@ export default class Store {
|
|
|
599
605
|
`conversation_rated.account.${accid}.user.${userid}`,
|
|
600
606
|
])
|
|
601
607
|
await this.readyGate.entry()
|
|
602
|
-
this.disconnect('account')
|
|
603
|
-
return this.reconnect()
|
|
604
608
|
}
|
|
605
609
|
|
|
606
|
-
async reconnect() {
|
|
610
|
+
async reconnect(p) {
|
|
607
611
|
if (this._die) return
|
|
608
612
|
// make sure we only run reconnect once in a time
|
|
609
|
-
|
|
610
613
|
await this.reconnectGate.entry(undefined, true)
|
|
611
614
|
// do nothing when account is synced
|
|
612
|
-
if (this.isInsync('account')) return this.reconnectGate.open()
|
|
615
|
+
// if (this.isInsync('account')) return this.reconnectGate.open()
|
|
613
616
|
this.markSync('account')
|
|
614
617
|
|
|
615
|
-
let
|
|
618
|
+
let fetchuser = p && p.user ? Promise.resolve({body: p.user}) : this.api.getUser()
|
|
619
|
+
let outs = await Promise.all([fetchuser, this.api.getAccountSetting()])
|
|
616
620
|
|
|
617
621
|
let error = sb.find(outs, (out) => out.error)
|
|
618
622
|
if (error) return console.error(error)
|
|
619
623
|
|
|
620
|
-
let set =
|
|
624
|
+
let set = outs[1].body
|
|
621
625
|
set.user = outs[0].body
|
|
622
626
|
await this._setSetting(set)
|
|
623
627
|
// refetch convo
|
|
@@ -1214,9 +1218,9 @@ export default class Store {
|
|
|
1214
1218
|
if ((k || '').startsWith('__sb')) this.cookie.remove(k)
|
|
1215
1219
|
})
|
|
1216
1220
|
this.kv.destroy()
|
|
1217
|
-
this.kv = new
|
|
1221
|
+
this.kv = new KV(new LSDB('sbz2023', this.inmem), 'kv')
|
|
1218
1222
|
this.chain.destroy()
|
|
1219
|
-
this.chain = new
|
|
1223
|
+
this.chain = new Chain(new LSDB('cbz2023', true), 'ch')
|
|
1220
1224
|
}
|
|
1221
1225
|
|
|
1222
1226
|
destroy() {
|