@knocklabs/client 0.18.0 → 0.18.2
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/CHANGELOG.md +12 -0
- package/dist/cjs/api.js +1 -1
- package/dist/cjs/clients/feed/feed.js +1 -1
- package/dist/cjs/clients/feed/feed.js.map +1 -1
- package/dist/cjs/clients/guide/client.js +1 -1
- package/dist/cjs/clients/guide/client.js.map +1 -1
- package/dist/cjs/clients/guide/helpers.js +1 -1
- package/dist/cjs/clients/guide/helpers.js.map +1 -1
- package/dist/esm/api.mjs +1 -1
- package/dist/esm/clients/feed/feed.mjs +196 -177
- package/dist/esm/clients/feed/feed.mjs.map +1 -1
- package/dist/esm/clients/guide/client.mjs +150 -130
- package/dist/esm/clients/guide/client.mjs.map +1 -1
- package/dist/esm/clients/guide/helpers.mjs +35 -33
- package/dist/esm/clients/guide/helpers.mjs.map +1 -1
- package/dist/types/clients/feed/feed.d.ts.map +1 -1
- package/dist/types/clients/guide/client.d.ts.map +1 -1
- package/dist/types/clients/guide/helpers.d.ts +3 -1
- package/dist/types/clients/guide/helpers.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/clients/feed/feed.ts +40 -3
- package/src/clients/guide/client.ts +57 -22
- package/src/clients/guide/helpers.ts +10 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
var p = Object.defineProperty;
|
|
2
|
-
var g = (u,
|
|
3
|
-
var
|
|
2
|
+
var g = (u, t, e) => t in u ? p(u, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : u[t] = e;
|
|
3
|
+
var c = (u, t, e) => g(u, typeof t != "symbol" ? t + "" : t, e);
|
|
4
4
|
import k from "eventemitter2";
|
|
5
5
|
import { nanoid as _ } from "nanoid";
|
|
6
6
|
import { isValidUuid as v } from "../../helpers.mjs";
|
|
@@ -8,46 +8,46 @@ import { isRequestInFlight as S, NetworkStatus as m } from "../../networkStatus.
|
|
|
8
8
|
import { SocketEventType as y } from "./socket-manager.mjs";
|
|
9
9
|
import b from "./store.mjs";
|
|
10
10
|
import { mergeDateRangeParams as f, getFormattedTriggerData as I } from "./utils.mjs";
|
|
11
|
-
const
|
|
11
|
+
const C = {
|
|
12
12
|
archived: "exclude"
|
|
13
|
-
},
|
|
13
|
+
}, U = 2e3, w = "client_";
|
|
14
14
|
class P {
|
|
15
|
-
constructor(
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
15
|
+
constructor(t, e, s, n) {
|
|
16
|
+
c(this, "defaultOptions");
|
|
17
|
+
c(this, "referenceId");
|
|
18
|
+
c(this, "unsubscribeFromSocketEvents");
|
|
19
|
+
c(this, "socketManager");
|
|
20
|
+
c(this, "userFeedId");
|
|
21
|
+
c(this, "broadcaster");
|
|
22
|
+
c(this, "broadcastChannel");
|
|
23
|
+
c(this, "disconnectTimer", null);
|
|
24
|
+
c(this, "hasSubscribedToRealTimeUpdates", !1);
|
|
25
|
+
c(this, "visibilityChangeHandler", () => {
|
|
26
26
|
});
|
|
27
|
-
|
|
27
|
+
c(this, "visibilityChangeListenerConnected", !1);
|
|
28
28
|
// The raw store instance, used for binding in React and other environments
|
|
29
|
-
|
|
30
|
-
this.knock =
|
|
29
|
+
c(this, "store");
|
|
30
|
+
this.knock = t, this.feedId = e, (!e || !v(e)) && this.knock.log(
|
|
31
31
|
"[Feed] Invalid or missing feedId provided to the Feed constructor. The feed should be a UUID of an in-app feed channel (`in_app_feed`) found in the Knock dashboard. Please provide a valid feedId to the Feed constructor.",
|
|
32
32
|
!0
|
|
33
|
-
), this.feedId =
|
|
34
|
-
...
|
|
33
|
+
), this.feedId = e, this.userFeedId = this.buildUserFeedId(), this.referenceId = w + _(), this.socketManager = n, this.store = b(), this.broadcaster = new k({ wildcard: !0, delimiter: "." }), this.defaultOptions = {
|
|
34
|
+
...C,
|
|
35
35
|
...f(s)
|
|
36
|
-
}, this.knock.log(`[Feed] Initialized a feed on channel ${
|
|
36
|
+
}, this.knock.log(`[Feed] Initialized a feed on channel ${e}`), this.initializeRealtimeConnection(), this.setupBroadcastChannel();
|
|
37
37
|
}
|
|
38
38
|
/**
|
|
39
39
|
* Used to reinitialize a current feed instance, which is useful when reauthenticating users
|
|
40
40
|
*/
|
|
41
|
-
reinitialize(
|
|
42
|
-
this.socketManager =
|
|
41
|
+
reinitialize(t) {
|
|
42
|
+
this.socketManager = t, this.userFeedId = this.buildUserFeedId(), this.initializeRealtimeConnection(), this.setupBroadcastChannel();
|
|
43
43
|
}
|
|
44
44
|
/**
|
|
45
45
|
* Cleans up a feed instance by destroying the store and disconnecting
|
|
46
46
|
* an open socket connection.
|
|
47
47
|
*/
|
|
48
48
|
teardown() {
|
|
49
|
-
var
|
|
50
|
-
this.knock.log("[Feed] Tearing down feed instance"), (
|
|
49
|
+
var t;
|
|
50
|
+
this.knock.log("[Feed] Tearing down feed instance"), (t = this.socketManager) == null || t.leave(this), this.tearDownVisibilityListeners(), this.disconnectTimer && (clearTimeout(this.disconnectTimer), this.disconnectTimer = null), this.broadcastChannel && this.broadcastChannel.close();
|
|
51
51
|
}
|
|
52
52
|
/** Tears down an instance and removes it entirely from the feed manager */
|
|
53
53
|
dispose() {
|
|
@@ -58,102 +58,102 @@ class P {
|
|
|
58
58
|
current ApiClient instance if the socket is not already connected.
|
|
59
59
|
*/
|
|
60
60
|
listenForUpdates() {
|
|
61
|
-
var
|
|
61
|
+
var t;
|
|
62
62
|
if (this.knock.log("[Feed] Connecting to real-time service"), this.hasSubscribedToRealTimeUpdates = !0, !this.knock.isAuthenticated()) {
|
|
63
63
|
this.knock.log(
|
|
64
64
|
"[Feed] User is not authenticated, skipping listening for updates"
|
|
65
65
|
);
|
|
66
66
|
return;
|
|
67
67
|
}
|
|
68
|
-
this.unsubscribeFromSocketEvents = (
|
|
68
|
+
this.unsubscribeFromSocketEvents = (t = this.socketManager) == null ? void 0 : t.join(this);
|
|
69
69
|
}
|
|
70
70
|
/* Binds a handler to be invoked when event occurs */
|
|
71
|
-
on(
|
|
72
|
-
this.broadcaster.on(
|
|
71
|
+
on(t, e) {
|
|
72
|
+
this.broadcaster.on(t, e);
|
|
73
73
|
}
|
|
74
|
-
off(
|
|
75
|
-
this.broadcaster.off(
|
|
74
|
+
off(t, e) {
|
|
75
|
+
this.broadcaster.off(t, e);
|
|
76
76
|
}
|
|
77
77
|
getState() {
|
|
78
78
|
return this.store.getState();
|
|
79
79
|
}
|
|
80
|
-
async markAsSeen(
|
|
81
|
-
const
|
|
80
|
+
async markAsSeen(t) {
|
|
81
|
+
const e = (/* @__PURE__ */ new Date()).toISOString();
|
|
82
82
|
return this.optimisticallyPerformStatusUpdate(
|
|
83
|
-
|
|
83
|
+
t,
|
|
84
84
|
"seen",
|
|
85
|
-
{ seen_at:
|
|
85
|
+
{ seen_at: e },
|
|
86
86
|
"unseen_count"
|
|
87
|
-
), this.makeStatusUpdate(
|
|
87
|
+
), this.makeStatusUpdate(t, "seen");
|
|
88
88
|
}
|
|
89
89
|
async markAllAsSeen() {
|
|
90
|
-
const { metadata:
|
|
90
|
+
const { metadata: t, items: e, ...s } = this.store.getState();
|
|
91
91
|
if (this.defaultOptions.status === "unseen")
|
|
92
92
|
s.resetStore({
|
|
93
|
-
...
|
|
93
|
+
...t,
|
|
94
94
|
total_count: 0,
|
|
95
95
|
unseen_count: 0
|
|
96
96
|
});
|
|
97
97
|
else {
|
|
98
|
-
s.setMetadata({ ...
|
|
99
|
-
const
|
|
100
|
-
s.setItemAttrs(
|
|
98
|
+
s.setMetadata({ ...t, unseen_count: 0 });
|
|
99
|
+
const a = { seen_at: (/* @__PURE__ */ new Date()).toISOString() }, i = e.map((d) => d.id);
|
|
100
|
+
s.setItemAttrs(i, a);
|
|
101
101
|
}
|
|
102
|
-
const
|
|
103
|
-
return this.emitEvent("all_seen",
|
|
102
|
+
const o = await this.makeBulkStatusUpdate("seen");
|
|
103
|
+
return this.emitEvent("all_seen", e), o;
|
|
104
104
|
}
|
|
105
|
-
async markAsUnseen(
|
|
105
|
+
async markAsUnseen(t) {
|
|
106
106
|
return this.optimisticallyPerformStatusUpdate(
|
|
107
|
-
|
|
107
|
+
t,
|
|
108
108
|
"unseen",
|
|
109
109
|
{ seen_at: null },
|
|
110
110
|
"unseen_count"
|
|
111
|
-
), this.makeStatusUpdate(
|
|
111
|
+
), this.makeStatusUpdate(t, "unseen");
|
|
112
112
|
}
|
|
113
|
-
async markAsRead(
|
|
114
|
-
const
|
|
113
|
+
async markAsRead(t) {
|
|
114
|
+
const e = (/* @__PURE__ */ new Date()).toISOString();
|
|
115
115
|
return this.optimisticallyPerformStatusUpdate(
|
|
116
|
-
|
|
116
|
+
t,
|
|
117
117
|
"read",
|
|
118
|
-
{ read_at:
|
|
118
|
+
{ read_at: e },
|
|
119
119
|
"unread_count"
|
|
120
|
-
), this.makeStatusUpdate(
|
|
120
|
+
), this.makeStatusUpdate(t, "read");
|
|
121
121
|
}
|
|
122
122
|
async markAllAsRead() {
|
|
123
|
-
const { metadata:
|
|
123
|
+
const { metadata: t, items: e, ...s } = this.store.getState();
|
|
124
124
|
if (this.defaultOptions.status === "unread")
|
|
125
125
|
s.resetStore({
|
|
126
|
-
...
|
|
126
|
+
...t,
|
|
127
127
|
total_count: 0,
|
|
128
128
|
unread_count: 0
|
|
129
129
|
});
|
|
130
130
|
else {
|
|
131
|
-
s.setMetadata({ ...
|
|
132
|
-
const
|
|
133
|
-
s.setItemAttrs(
|
|
131
|
+
s.setMetadata({ ...t, unread_count: 0 });
|
|
132
|
+
const a = { read_at: (/* @__PURE__ */ new Date()).toISOString() }, i = e.map((d) => d.id);
|
|
133
|
+
s.setItemAttrs(i, a);
|
|
134
134
|
}
|
|
135
|
-
const
|
|
136
|
-
return this.emitEvent("all_read",
|
|
135
|
+
const o = await this.makeBulkStatusUpdate("read");
|
|
136
|
+
return this.emitEvent("all_read", e), o;
|
|
137
137
|
}
|
|
138
|
-
async markAsUnread(
|
|
138
|
+
async markAsUnread(t) {
|
|
139
139
|
return this.optimisticallyPerformStatusUpdate(
|
|
140
|
-
|
|
140
|
+
t,
|
|
141
141
|
"unread",
|
|
142
142
|
{ read_at: null },
|
|
143
143
|
"unread_count"
|
|
144
|
-
), this.makeStatusUpdate(
|
|
144
|
+
), this.makeStatusUpdate(t, "unread");
|
|
145
145
|
}
|
|
146
|
-
async markAsInteracted(
|
|
146
|
+
async markAsInteracted(t, e) {
|
|
147
147
|
const s = (/* @__PURE__ */ new Date()).toISOString();
|
|
148
148
|
return this.optimisticallyPerformStatusUpdate(
|
|
149
|
-
|
|
149
|
+
t,
|
|
150
150
|
"interacted",
|
|
151
151
|
{
|
|
152
152
|
read_at: s,
|
|
153
153
|
interacted_at: s
|
|
154
154
|
},
|
|
155
155
|
"unread_count"
|
|
156
|
-
), this.makeStatusUpdate(
|
|
156
|
+
), this.makeStatusUpdate(t, "interacted", e);
|
|
157
157
|
}
|
|
158
158
|
/*
|
|
159
159
|
Marking one or more items as archived should:
|
|
@@ -163,147 +163,166 @@ class P {
|
|
|
163
163
|
|
|
164
164
|
TODO: how do we handle rollbacks?
|
|
165
165
|
*/
|
|
166
|
-
async markAsArchived(
|
|
167
|
-
const
|
|
166
|
+
async markAsArchived(t) {
|
|
167
|
+
const e = this.store.getState(), s = this.defaultOptions.archived === "exclude", n = Array.isArray(t) ? t : [t], o = n.map((a) => a.id);
|
|
168
168
|
if (s) {
|
|
169
|
-
const
|
|
170
|
-
...
|
|
169
|
+
const a = n.filter((r) => !r.seen_at).length, i = n.filter((r) => !r.read_at).length, d = {
|
|
170
|
+
...e.metadata,
|
|
171
171
|
// Ensure that the counts don't ever go below 0 on archiving where the client state
|
|
172
172
|
// gets out of sync with the server state
|
|
173
|
-
total_count: Math.max(0,
|
|
174
|
-
unseen_count: Math.max(0,
|
|
175
|
-
unread_count: Math.max(0,
|
|
176
|
-
}, l =
|
|
177
|
-
(
|
|
173
|
+
total_count: Math.max(0, e.metadata.total_count - n.length),
|
|
174
|
+
unseen_count: Math.max(0, e.metadata.unseen_count - a),
|
|
175
|
+
unread_count: Math.max(0, e.metadata.unread_count - i)
|
|
176
|
+
}, l = e.items.filter(
|
|
177
|
+
(r) => !o.includes(r.id)
|
|
178
178
|
);
|
|
179
|
-
|
|
179
|
+
e.setResult({
|
|
180
180
|
entries: l,
|
|
181
|
-
meta:
|
|
182
|
-
page_info:
|
|
181
|
+
meta: d,
|
|
182
|
+
page_info: e.pageInfo
|
|
183
183
|
});
|
|
184
184
|
} else
|
|
185
|
-
|
|
186
|
-
return this.makeStatusUpdate(
|
|
185
|
+
e.setItemAttrs(o, { archived_at: (/* @__PURE__ */ new Date()).toISOString() });
|
|
186
|
+
return this.makeStatusUpdate(t, "archived");
|
|
187
187
|
}
|
|
188
188
|
async markAllAsArchived() {
|
|
189
|
-
const { items:
|
|
189
|
+
const { items: t, ...e } = this.store.getState();
|
|
190
190
|
if (this.defaultOptions.archived === "exclude")
|
|
191
|
-
|
|
191
|
+
e.resetStore();
|
|
192
192
|
else {
|
|
193
|
-
const
|
|
194
|
-
|
|
193
|
+
const o = t.map((a) => a.id);
|
|
194
|
+
e.setItemAttrs(o, { archived_at: (/* @__PURE__ */ new Date()).toISOString() });
|
|
195
195
|
}
|
|
196
|
-
const
|
|
197
|
-
return this.emitEvent("all_archived",
|
|
196
|
+
const n = await this.makeBulkStatusUpdate("archive");
|
|
197
|
+
return this.emitEvent("all_archived", t), n;
|
|
198
198
|
}
|
|
199
199
|
async markAllReadAsArchived() {
|
|
200
|
-
const { items:
|
|
201
|
-
if (
|
|
200
|
+
const { items: t, ...e } = this.store.getState(), n = t.filter((i) => i.read_at === null).map((i) => i.id);
|
|
201
|
+
if (e.setItemAttrs(n, {
|
|
202
202
|
archived_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
203
203
|
}), this.defaultOptions.archived === "exclude") {
|
|
204
|
-
const
|
|
205
|
-
...
|
|
206
|
-
total_count:
|
|
204
|
+
const i = t.filter((l) => !n.includes(l.id)), d = {
|
|
205
|
+
...e.metadata,
|
|
206
|
+
total_count: i.length,
|
|
207
207
|
unread_count: 0
|
|
208
208
|
};
|
|
209
|
-
|
|
210
|
-
entries:
|
|
211
|
-
meta:
|
|
212
|
-
page_info:
|
|
209
|
+
e.setResult({
|
|
210
|
+
entries: i,
|
|
211
|
+
meta: d,
|
|
212
|
+
page_info: e.pageInfo
|
|
213
213
|
});
|
|
214
214
|
}
|
|
215
215
|
return await this.makeBulkStatusUpdate("archive");
|
|
216
216
|
}
|
|
217
|
-
async markAsUnarchived(
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
217
|
+
async markAsUnarchived(t) {
|
|
218
|
+
const e = this.store.getState(), s = Array.isArray(t) ? t : [t], n = s.map((a) => a.id);
|
|
219
|
+
if (this.defaultOptions.archived === "only") {
|
|
220
|
+
const a = s.filter((r) => !r.seen_at).length, i = s.filter((r) => !r.read_at).length, d = {
|
|
221
|
+
...e.metadata,
|
|
222
|
+
// Ensure that the counts don't ever go below 0 on unarchiving where the client state
|
|
223
|
+
// gets out of sync with the server state
|
|
224
|
+
total_count: Math.max(0, e.metadata.total_count - s.length),
|
|
225
|
+
unseen_count: Math.max(0, e.metadata.unseen_count - a),
|
|
226
|
+
unread_count: Math.max(0, e.metadata.unread_count - i)
|
|
227
|
+
}, l = e.items.filter(
|
|
228
|
+
(r) => !n.includes(r.id)
|
|
229
|
+
);
|
|
230
|
+
e.setResult({
|
|
231
|
+
entries: l,
|
|
232
|
+
meta: d,
|
|
233
|
+
page_info: e.pageInfo
|
|
234
|
+
});
|
|
235
|
+
} else
|
|
236
|
+
this.optimisticallyPerformStatusUpdate(t, "unarchived", {
|
|
237
|
+
archived_at: null
|
|
238
|
+
});
|
|
239
|
+
return this.makeStatusUpdate(t, "unarchived");
|
|
221
240
|
}
|
|
222
241
|
/* Fetches the feed content, appending it to the store */
|
|
223
|
-
async fetch(
|
|
224
|
-
const { networkStatus:
|
|
242
|
+
async fetch(t = {}) {
|
|
243
|
+
const { networkStatus: e, ...s } = this.store.getState();
|
|
225
244
|
if (!this.knock.isAuthenticated()) {
|
|
226
245
|
this.knock.log("[Feed] User is not authenticated, skipping fetch");
|
|
227
246
|
return;
|
|
228
247
|
}
|
|
229
|
-
if (S(
|
|
248
|
+
if (S(e)) {
|
|
230
249
|
this.knock.log("[Feed] Request is in flight, skipping fetch");
|
|
231
250
|
return;
|
|
232
251
|
}
|
|
233
|
-
s.setNetworkStatus(
|
|
234
|
-
const
|
|
252
|
+
s.setNetworkStatus(t.__loadingType ?? m.loading);
|
|
253
|
+
const n = I({
|
|
235
254
|
...this.defaultOptions,
|
|
236
|
-
...
|
|
237
|
-
}),
|
|
255
|
+
...t
|
|
256
|
+
}), o = {
|
|
238
257
|
...this.defaultOptions,
|
|
239
|
-
...f(
|
|
240
|
-
trigger_data:
|
|
258
|
+
...f(t),
|
|
259
|
+
trigger_data: n,
|
|
241
260
|
// Unset options that should not be sent to the API
|
|
242
261
|
__loadingType: void 0,
|
|
243
262
|
__fetchSource: void 0,
|
|
244
263
|
__experimentalCrossBrowserUpdates: void 0,
|
|
245
264
|
auto_manage_socket_connection: void 0,
|
|
246
265
|
auto_manage_socket_connection_delay: void 0
|
|
247
|
-
},
|
|
266
|
+
}, a = await this.knock.client().makeRequest({
|
|
248
267
|
method: "GET",
|
|
249
268
|
url: `/v1/users/${this.knock.userId}/feeds/${this.feedId}`,
|
|
250
|
-
params:
|
|
269
|
+
params: o
|
|
251
270
|
});
|
|
252
|
-
if (
|
|
271
|
+
if (a.statusCode === "error" || !a.body)
|
|
253
272
|
return s.setNetworkStatus(m.error), {
|
|
254
|
-
status:
|
|
255
|
-
data:
|
|
273
|
+
status: a.statusCode,
|
|
274
|
+
data: a.error || a.body
|
|
256
275
|
};
|
|
257
|
-
const
|
|
258
|
-
entries:
|
|
259
|
-
meta:
|
|
260
|
-
page_info:
|
|
276
|
+
const i = {
|
|
277
|
+
entries: a.body.entries,
|
|
278
|
+
meta: a.body.meta,
|
|
279
|
+
page_info: a.body.page_info
|
|
261
280
|
};
|
|
262
|
-
if (
|
|
263
|
-
const
|
|
264
|
-
s.setResult(
|
|
265
|
-
} else if (
|
|
266
|
-
const
|
|
267
|
-
s.setResult(
|
|
281
|
+
if (t.before) {
|
|
282
|
+
const r = { shouldSetPage: !1, shouldAppend: !0 };
|
|
283
|
+
s.setResult(i, r);
|
|
284
|
+
} else if (t.after) {
|
|
285
|
+
const r = { shouldSetPage: !0, shouldAppend: !0 };
|
|
286
|
+
s.setResult(i, r);
|
|
268
287
|
} else
|
|
269
|
-
s.setResult(
|
|
270
|
-
this.broadcast("messages.new",
|
|
271
|
-
const
|
|
272
|
-
items:
|
|
273
|
-
metadata:
|
|
274
|
-
event:
|
|
288
|
+
s.setResult(i);
|
|
289
|
+
this.broadcast("messages.new", i);
|
|
290
|
+
const d = t.__fetchSource === "socket" ? "items.received.realtime" : "items.received.page", l = {
|
|
291
|
+
items: i.entries,
|
|
292
|
+
metadata: i.meta,
|
|
293
|
+
event: d
|
|
275
294
|
};
|
|
276
|
-
return this.broadcast(l.event, l), { data:
|
|
295
|
+
return this.broadcast(l.event, l), { data: i, status: a.statusCode };
|
|
277
296
|
}
|
|
278
|
-
async fetchNextPage(
|
|
279
|
-
const { pageInfo:
|
|
280
|
-
|
|
281
|
-
...
|
|
282
|
-
after:
|
|
297
|
+
async fetchNextPage(t = {}) {
|
|
298
|
+
const { pageInfo: e } = this.store.getState();
|
|
299
|
+
e.after && this.fetch({
|
|
300
|
+
...t,
|
|
301
|
+
after: e.after,
|
|
283
302
|
__loadingType: m.fetchMore
|
|
284
303
|
});
|
|
285
304
|
}
|
|
286
305
|
get socketChannelTopic() {
|
|
287
306
|
return `feeds:${this.userFeedId}`;
|
|
288
307
|
}
|
|
289
|
-
broadcast(
|
|
290
|
-
this.broadcaster.emit(
|
|
308
|
+
broadcast(t, e) {
|
|
309
|
+
this.broadcaster.emit(t, e);
|
|
291
310
|
}
|
|
292
311
|
// Invoked when a new real-time message comes in from the socket
|
|
293
|
-
async onNewMessageReceived({ data:
|
|
294
|
-
var
|
|
312
|
+
async onNewMessageReceived({ data: t }) {
|
|
313
|
+
var a;
|
|
295
314
|
this.knock.log("[Feed] Received new real-time message");
|
|
296
|
-
const { items:
|
|
297
|
-
|
|
315
|
+
const { items: e, ...s } = this.store.getState(), n = e[0], o = (a = t[this.referenceId]) == null ? void 0 : a.metadata;
|
|
316
|
+
o && s.setMetadata(o), this.fetch({ before: n == null ? void 0 : n.__cursor, __fetchSource: "socket" });
|
|
298
317
|
}
|
|
299
318
|
buildUserFeedId() {
|
|
300
319
|
return `${this.feedId}:${this.knock.userId}`;
|
|
301
320
|
}
|
|
302
|
-
optimisticallyPerformStatusUpdate(
|
|
303
|
-
const
|
|
304
|
-
if (
|
|
305
|
-
const { metadata:
|
|
306
|
-
switch (
|
|
321
|
+
optimisticallyPerformStatusUpdate(t, e, s, n) {
|
|
322
|
+
const o = this.store.getState(), a = Array.isArray(t) ? t : [t], i = a.map((d) => d.id);
|
|
323
|
+
if (n) {
|
|
324
|
+
const { metadata: d } = o, l = a.filter((h) => {
|
|
325
|
+
switch (e) {
|
|
307
326
|
case "seen":
|
|
308
327
|
return h.seen_at === null;
|
|
309
328
|
case "unseen":
|
|
@@ -316,24 +335,24 @@ class P {
|
|
|
316
335
|
default:
|
|
317
336
|
return !0;
|
|
318
337
|
}
|
|
319
|
-
}),
|
|
320
|
-
|
|
321
|
-
...
|
|
322
|
-
[
|
|
338
|
+
}), r = e.startsWith("un") ? l.length : -l.length;
|
|
339
|
+
o.setMetadata({
|
|
340
|
+
...d,
|
|
341
|
+
[n]: Math.max(0, d[n] + r)
|
|
323
342
|
});
|
|
324
343
|
}
|
|
325
|
-
|
|
344
|
+
o.setItemAttrs(i, s);
|
|
326
345
|
}
|
|
327
|
-
async makeStatusUpdate(
|
|
328
|
-
const
|
|
329
|
-
|
|
330
|
-
|
|
346
|
+
async makeStatusUpdate(t, e, s) {
|
|
347
|
+
const n = Array.isArray(t) ? t : [t], o = n.map((i) => i.id), a = await this.knock.messages.batchUpdateStatuses(
|
|
348
|
+
o,
|
|
349
|
+
e,
|
|
331
350
|
{ metadata: s }
|
|
332
351
|
);
|
|
333
|
-
return this.emitEvent(
|
|
352
|
+
return this.emitEvent(e, n), a;
|
|
334
353
|
}
|
|
335
|
-
async makeBulkStatusUpdate(
|
|
336
|
-
const
|
|
354
|
+
async makeBulkStatusUpdate(t) {
|
|
355
|
+
const e = {
|
|
337
356
|
user_ids: [this.knock.userId],
|
|
338
357
|
engagement_status: this.defaultOptions.status !== "all" ? this.defaultOptions.status : void 0,
|
|
339
358
|
archived: this.defaultOptions.archived,
|
|
@@ -342,13 +361,13 @@ class P {
|
|
|
342
361
|
};
|
|
343
362
|
return await this.knock.messages.bulkUpdateAllStatusesInChannel({
|
|
344
363
|
channelId: this.feedId,
|
|
345
|
-
status:
|
|
346
|
-
options:
|
|
364
|
+
status: t,
|
|
365
|
+
options: e
|
|
347
366
|
});
|
|
348
367
|
}
|
|
349
368
|
setupBroadcastChannel() {
|
|
350
|
-
this.broadcastChannel = typeof self < "u" && "BroadcastChannel" in self ? new BroadcastChannel(`knock:feed:${this.userFeedId}`) : null, this.broadcastChannel && this.defaultOptions.__experimentalCrossBrowserUpdates === !0 && (this.broadcastChannel.onmessage = (
|
|
351
|
-
switch (
|
|
369
|
+
this.broadcastChannel = typeof self < "u" && "BroadcastChannel" in self ? new BroadcastChannel(`knock:feed:${this.userFeedId}`) : null, this.broadcastChannel && this.defaultOptions.__experimentalCrossBrowserUpdates === !0 && (this.broadcastChannel.onmessage = (t) => {
|
|
370
|
+
switch (t.data.type) {
|
|
352
371
|
case "items:archived":
|
|
353
372
|
case "items:unarchived":
|
|
354
373
|
case "items:seen":
|
|
@@ -364,29 +383,29 @@ class P {
|
|
|
364
383
|
}
|
|
365
384
|
});
|
|
366
385
|
}
|
|
367
|
-
broadcastOverChannel(
|
|
386
|
+
broadcastOverChannel(t, e) {
|
|
368
387
|
if (this.broadcastChannel)
|
|
369
388
|
try {
|
|
370
|
-
const s = JSON.parse(JSON.stringify(
|
|
389
|
+
const s = JSON.parse(JSON.stringify(e));
|
|
371
390
|
this.broadcastChannel.postMessage({
|
|
372
|
-
type:
|
|
391
|
+
type: t,
|
|
373
392
|
payload: s
|
|
374
393
|
});
|
|
375
394
|
} catch (s) {
|
|
376
|
-
console.warn(`Could not broadcast ${
|
|
395
|
+
console.warn(`Could not broadcast ${t}, got error: ${s}`);
|
|
377
396
|
}
|
|
378
397
|
}
|
|
379
398
|
initializeRealtimeConnection() {
|
|
380
|
-
var
|
|
381
|
-
this.socketManager && (this.defaultOptions.auto_manage_socket_connection && this.setUpVisibilityListeners(), this.hasSubscribedToRealTimeUpdates && this.knock.isAuthenticated() && (this.unsubscribeFromSocketEvents = (
|
|
399
|
+
var t;
|
|
400
|
+
this.socketManager && (this.defaultOptions.auto_manage_socket_connection && this.setUpVisibilityListeners(), this.hasSubscribedToRealTimeUpdates && this.knock.isAuthenticated() && (this.unsubscribeFromSocketEvents = (t = this.socketManager) == null ? void 0 : t.join(this)));
|
|
382
401
|
}
|
|
383
|
-
async handleSocketEvent(
|
|
384
|
-
switch (
|
|
402
|
+
async handleSocketEvent(t) {
|
|
403
|
+
switch (t.event) {
|
|
385
404
|
case y.NewMessage:
|
|
386
|
-
this.onNewMessageReceived(
|
|
405
|
+
this.onNewMessageReceived(t);
|
|
387
406
|
return;
|
|
388
407
|
default: {
|
|
389
|
-
|
|
408
|
+
t.event;
|
|
390
409
|
return;
|
|
391
410
|
}
|
|
392
411
|
}
|
|
@@ -404,16 +423,16 @@ class P {
|
|
|
404
423
|
this.visibilityChangeHandler
|
|
405
424
|
), this.visibilityChangeListenerConnected = !1);
|
|
406
425
|
}
|
|
407
|
-
emitEvent(
|
|
408
|
-
this.broadcaster.emit(`items.${
|
|
426
|
+
emitEvent(t, e) {
|
|
427
|
+
this.broadcaster.emit(`items.${t}`, { items: e }), this.broadcaster.emit(`items:${t}`, { items: e }), this.broadcastOverChannel(`items:${t}`, { items: e });
|
|
409
428
|
}
|
|
410
429
|
handleVisibilityChange() {
|
|
411
|
-
var s,
|
|
412
|
-
const
|
|
430
|
+
var s, n;
|
|
431
|
+
const t = this.defaultOptions.auto_manage_socket_connection_delay ?? U, e = this.knock.client();
|
|
413
432
|
document.visibilityState === "hidden" ? this.disconnectTimer = setTimeout(() => {
|
|
414
|
-
var
|
|
415
|
-
(
|
|
416
|
-
},
|
|
433
|
+
var o;
|
|
434
|
+
(o = e.socket) == null || o.disconnect(), this.disconnectTimer = null;
|
|
435
|
+
}, t) : document.visibilityState === "visible" && (this.disconnectTimer && (clearTimeout(this.disconnectTimer), this.disconnectTimer = null), (s = e.socket) != null && s.isConnected() || (n = e.socket) == null || n.connect());
|
|
417
436
|
}
|
|
418
437
|
}
|
|
419
438
|
export {
|