@knocklabs/client 0.8.17 → 0.8.19
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/README.md +17 -0
- package/dist/api.d.ts +25 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +84 -0
- package/dist/cjs/api.js +2 -133
- package/dist/cjs/api.js.map +1 -1
- package/dist/cjs/clients/feed/feed.js +2 -937
- package/dist/cjs/clients/feed/feed.js.map +1 -1
- package/dist/cjs/clients/feed/index.js +2 -34
- package/dist/cjs/clients/feed/index.js.map +1 -1
- package/dist/cjs/clients/feed/store.js +2 -111
- package/dist/cjs/clients/feed/store.js.map +1 -1
- package/dist/cjs/clients/feed/utils.js +2 -26
- package/dist/cjs/clients/feed/utils.js.map +1 -1
- package/dist/cjs/clients/preferences/index.js +2 -373
- package/dist/cjs/clients/preferences/index.js.map +1 -1
- package/dist/cjs/clients/users/index.js +2 -185
- package/dist/cjs/clients/users/index.js.map +1 -1
- package/dist/cjs/index.js +2 -102
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/knock.js +6 -89
- package/dist/cjs/knock.js.map +1 -1
- package/dist/cjs/networkStatus.js +2 -18
- package/dist/cjs/networkStatus.js.map +1 -1
- package/dist/clients/feed/feed.d.ts +64 -0
- package/dist/clients/feed/feed.d.ts.map +1 -0
- package/dist/clients/feed/feed.js +572 -0
- package/dist/clients/feed/index.d.ts +15 -0
- package/dist/clients/feed/index.d.ts.map +1 -0
- package/dist/clients/feed/index.js +34 -0
- package/dist/clients/feed/interfaces.d.ts +60 -0
- package/dist/clients/feed/interfaces.d.ts.map +1 -0
- package/dist/clients/feed/interfaces.js +2 -0
- package/dist/clients/feed/store.d.ts +3 -0
- package/dist/clients/feed/store.d.ts.map +1 -0
- package/dist/clients/feed/store.js +72 -0
- package/dist/clients/feed/types.d.ts +34 -0
- package/dist/clients/feed/types.d.ts.map +1 -0
- package/dist/clients/feed/types.js +2 -0
- package/dist/clients/feed/utils.d.ts +4 -0
- package/dist/clients/feed/utils.d.ts.map +1 -0
- package/dist/clients/feed/utils.js +21 -0
- package/dist/clients/preferences/index.d.ts +46 -0
- package/dist/clients/preferences/index.d.ts.map +1 -0
- package/dist/clients/preferences/index.js +129 -0
- package/dist/clients/preferences/interfaces.d.ts +26 -0
- package/dist/clients/preferences/interfaces.d.ts.map +1 -0
- package/dist/clients/preferences/interfaces.js +2 -0
- package/dist/clients/users/index.d.ts +16 -0
- package/dist/clients/users/index.d.ts.map +1 -0
- package/dist/clients/users/index.js +56 -0
- package/dist/clients/users/interfaces.d.ts +8 -0
- package/dist/clients/users/interfaces.d.ts.map +1 -0
- package/dist/clients/users/interfaces.js +2 -0
- package/dist/esm/api.js +44 -84
- package/dist/esm/api.js.map +1 -1
- package/dist/esm/clients/feed/feed.js +296 -601
- package/dist/esm/clients/feed/feed.js.map +1 -1
- package/dist/esm/clients/feed/index.js +28 -12
- package/dist/esm/clients/feed/index.js.map +1 -1
- package/dist/esm/clients/feed/store.js +37 -71
- package/dist/esm/clients/feed/store.js.map +1 -1
- package/dist/esm/clients/feed/utils.js +10 -15
- package/dist/esm/clients/feed/utils.js.map +1 -1
- package/dist/esm/clients/preferences/index.js +79 -146
- package/dist/esm/clients/preferences/index.js.map +1 -1
- package/dist/esm/clients/users/index.js +52 -76
- package/dist/esm/clients/users/index.js.map +1 -1
- package/dist/esm/index.js +12 -11
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/knock.js +72 -51
- package/dist/esm/knock.js.map +1 -1
- package/dist/esm/networkStatus.js +14 -10
- package/dist/esm/networkStatus.js.map +1 -1
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +43 -0
- package/dist/interfaces.d.ts +41 -0
- package/dist/interfaces.d.ts.map +1 -0
- package/dist/interfaces.js +2 -0
- package/dist/knock.d.ts +30 -0
- package/dist/knock.d.ts.map +1 -0
- package/dist/knock.js +135 -0
- package/dist/networkStatus.d.ts +8 -0
- package/dist/networkStatus.d.ts.map +1 -0
- package/dist/networkStatus.js +18 -0
- package/dist/types/api.d.ts +0 -2
- package/dist/types/api.d.ts.map +1 -1
- package/dist/types/clients/feed/feed.d.ts +12 -4
- package/dist/types/clients/feed/feed.d.ts.map +1 -1
- package/dist/types/clients/feed/index.d.ts +4 -0
- package/dist/types/clients/feed/index.d.ts.map +1 -1
- package/dist/types/clients/feed/interfaces.d.ts +2 -1
- package/dist/types/clients/feed/interfaces.d.ts.map +1 -1
- package/dist/types/clients/feed/store.d.ts.map +1 -1
- package/dist/types/clients/feed/types.d.ts +1 -2
- package/dist/types/clients/feed/types.d.ts.map +1 -1
- package/dist/types/clients/feed/utils.d.ts +1 -1
- package/dist/types/clients/feed/utils.d.ts.map +1 -1
- package/dist/types/clients/preferences/index.d.ts +2 -1
- package/dist/types/clients/preferences/index.d.ts.map +1 -1
- package/dist/types/clients/preferences/interfaces.d.ts +1 -1
- package/dist/types/clients/preferences/interfaces.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/interfaces.d.ts +8 -8
- package/dist/types/interfaces.d.ts.map +1 -1
- package/dist/types/knock.d.ts +12 -4
- package/dist/types/knock.d.ts.map +1 -1
- package/package.json +15 -10
- package/dist/cjs/clients/feed/interfaces.js +0 -6
- package/dist/cjs/clients/feed/interfaces.js.map +0 -1
- package/dist/cjs/clients/feed/types.js +0 -6
- package/dist/cjs/clients/feed/types.js.map +0 -1
- package/dist/cjs/clients/preferences/interfaces.js +0 -6
- package/dist/cjs/clients/preferences/interfaces.js.map +0 -1
- package/dist/cjs/clients/users/interfaces.js +0 -6
- package/dist/cjs/clients/users/interfaces.js.map +0 -1
- package/dist/cjs/interfaces.js +0 -6
- package/dist/cjs/interfaces.js.map +0 -1
- package/dist/esm/clients/feed/interfaces.js +0 -2
- package/dist/esm/clients/feed/interfaces.js.map +0 -1
- package/dist/esm/clients/feed/types.js +0 -2
- package/dist/esm/clients/feed/types.js.map +0 -1
- package/dist/esm/clients/preferences/interfaces.js +0 -2
- package/dist/esm/clients/preferences/interfaces.js.map +0 -1
- package/dist/esm/clients/users/interfaces.js +0 -2
- package/dist/esm/clients/users/interfaces.js.map +0 -1
- package/dist/esm/interfaces.js +0 -2
- package/dist/esm/interfaces.js.map +0 -1
|
@@ -1,666 +1,361 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
7
|
-
|
|
8
|
-
// Default options to apply
|
|
9
|
-
var feedClientDefaults = {
|
|
1
|
+
var p = Object.defineProperty;
|
|
2
|
+
var _ = (m, e, t) => e in m ? p(m, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : m[e] = t;
|
|
3
|
+
var u = (m, e, t) => (_(m, typeof e != "symbol" ? e + "" : e, t), t);
|
|
4
|
+
import { EventEmitter2 as k } from "eventemitter2";
|
|
5
|
+
import { isRequestInFlight as S, NetworkStatus as f } from "../../networkStatus.js";
|
|
6
|
+
import g from "./store.js";
|
|
7
|
+
const v = {
|
|
10
8
|
archived: "exclude"
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
this
|
|
16
|
-
this
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
_defineProperty(this, "defaultOptions", void 0);
|
|
22
|
-
_defineProperty(this, "broadcastChannel", void 0);
|
|
23
|
-
_defineProperty(this, "disconnectTimer", null);
|
|
9
|
+
}, y = 2e3;
|
|
10
|
+
class A {
|
|
11
|
+
constructor(e, t, s) {
|
|
12
|
+
u(this, "userFeedId");
|
|
13
|
+
u(this, "channel");
|
|
14
|
+
u(this, "broadcaster");
|
|
15
|
+
u(this, "defaultOptions");
|
|
16
|
+
u(this, "broadcastChannel");
|
|
17
|
+
u(this, "disconnectTimer", null);
|
|
18
|
+
u(this, "hasSubscribedToRealTimeUpdates", !1);
|
|
24
19
|
// The raw store instance, used for binding in React and other environments
|
|
25
|
-
|
|
26
|
-
this.
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
});
|
|
34
|
-
this.defaultOptions = _objectSpread(_objectSpread({}, feedClientDefaults), options);
|
|
35
|
-
|
|
36
|
-
// In server environments we might not have a socket connection
|
|
37
|
-
if (this.apiClient.socket) {
|
|
38
|
-
this.channel = this.apiClient.socket.channel("feeds:".concat(this.userFeedId), this.defaultOptions);
|
|
39
|
-
this.channel.on("new-message", resp => this.onNewMessageReceived(resp));
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Attempt to bind to listen to other events from this feed in different tabs
|
|
43
|
-
// Note: here we ensure `self` is available (it's not in server rendered envs)
|
|
44
|
-
this.broadcastChannel = typeof self !== "undefined" && "BroadcastChannel" in self ? new BroadcastChannel("knock:feed:".concat(this.userFeedId)) : null;
|
|
45
|
-
if (options.auto_manage_socket_connection && this.apiClient.socket) {
|
|
46
|
-
this.setupAutoSocketManager(options.auto_manage_socket_connection_delay);
|
|
47
|
-
}
|
|
20
|
+
u(this, "store");
|
|
21
|
+
this.knock = e, this.feedId = t, this.feedId = t, this.userFeedId = this.buildUserFeedId(), this.store = g(), this.broadcaster = new k({ wildcard: !0, delimiter: "." }), this.defaultOptions = { ...v, ...s }, this.knock.log(`[Feed] Initialized a feed on channel ${t}`), this.initializeRealtimeConnection(), this.setupBroadcastChannel();
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Used to reinitialize a current feed instance, which is useful when reauthenticating users
|
|
25
|
+
*/
|
|
26
|
+
reinitialize() {
|
|
27
|
+
this.userFeedId = this.buildUserFeedId(), this.initializeRealtimeConnection(), this.setupBroadcastChannel();
|
|
48
28
|
}
|
|
49
|
-
|
|
50
29
|
/**
|
|
51
30
|
* Cleans up a feed instance by destroying the store and disconnecting
|
|
52
31
|
* an open socket connection.
|
|
53
32
|
*/
|
|
54
33
|
teardown() {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
this.broadcaster.removeAllListeners();
|
|
60
|
-
this.store.destroy();
|
|
61
|
-
if (this.broadcastChannel) {
|
|
62
|
-
this.broadcastChannel.close();
|
|
63
|
-
}
|
|
34
|
+
this.knock.log("[Feed] Tearing down feed instance"), this.channel && (this.channel.leave(), this.channel.off("new-message")), this.disconnectTimer && (clearTimeout(this.disconnectTimer), this.disconnectTimer = null), this.broadcastChannel && this.broadcastChannel.close();
|
|
35
|
+
}
|
|
36
|
+
/** Tears down an instance and removes it entirely from the feed manager */
|
|
37
|
+
dispose() {
|
|
38
|
+
this.knock.log("[Feed] Disposing of feed instance"), this.teardown(), this.broadcaster.removeAllListeners(), this.knock.feeds.removeInstance(this);
|
|
64
39
|
}
|
|
65
|
-
|
|
66
40
|
/*
|
|
67
41
|
Initializes a real-time connection to Knock, connecting the websocket for the
|
|
68
42
|
current ApiClient instance if the socket is not already connected.
|
|
69
43
|
*/
|
|
70
44
|
listenForUpdates() {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// Only join the channel if we're not already in a joining state
|
|
77
|
-
if (this.channel && ["closed", "errored"].includes(this.channel.state)) {
|
|
78
|
-
this.channel.join();
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// Opt into receiving updates from _other tabs for the same user / feed_ via the broadcast
|
|
82
|
-
// channel (iff it's enabled and exists)
|
|
83
|
-
if (this.broadcastChannel && this.defaultOptions.__experimentalCrossBrowserUpdates === true) {
|
|
84
|
-
this.broadcastChannel.onmessage = e => {
|
|
85
|
-
switch (e.data.type) {
|
|
86
|
-
case "items:archived":
|
|
87
|
-
case "items:unarchived":
|
|
88
|
-
case "items:seen":
|
|
89
|
-
case "items:unseen":
|
|
90
|
-
case "items:read":
|
|
91
|
-
case "items:unread":
|
|
92
|
-
case "items:all_read":
|
|
93
|
-
case "items:all_seen":
|
|
94
|
-
case "items:all_archived":
|
|
95
|
-
// When items are updated in any other tab, simply refetch to get the latest state
|
|
96
|
-
// to make sure that the state gets updated accordingly. In the future here we could
|
|
97
|
-
// maybe do this optimistically without the fetch.
|
|
98
|
-
return this.fetch();
|
|
99
|
-
break;
|
|
100
|
-
default:
|
|
101
|
-
return null;
|
|
102
|
-
}
|
|
103
|
-
};
|
|
104
|
-
}
|
|
45
|
+
this.knock.log("[Feed] Connecting to real-time service"), this.hasSubscribedToRealTimeUpdates = !0;
|
|
46
|
+
const e = this.knock.client().socket;
|
|
47
|
+
e && !e.isConnected() && e.connect(), this.channel && ["closed", "errored"].includes(this.channel.state) && this.channel.join();
|
|
105
48
|
}
|
|
106
|
-
|
|
107
49
|
/* Binds a handler to be invoked when event occurs */
|
|
108
|
-
on(
|
|
109
|
-
this.broadcaster.on(
|
|
50
|
+
on(e, t) {
|
|
51
|
+
this.broadcaster.on(e, t);
|
|
110
52
|
}
|
|
111
|
-
off(
|
|
112
|
-
this.broadcaster.off(
|
|
53
|
+
off(e, t) {
|
|
54
|
+
this.broadcaster.off(e, t);
|
|
113
55
|
}
|
|
114
56
|
getState() {
|
|
115
57
|
return this.store.getState();
|
|
116
58
|
}
|
|
117
|
-
markAsSeen(
|
|
118
|
-
|
|
119
|
-
return
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
})();
|
|
59
|
+
async markAsSeen(e) {
|
|
60
|
+
const t = (/* @__PURE__ */ new Date()).toISOString();
|
|
61
|
+
return this.optimisticallyPerformStatusUpdate(
|
|
62
|
+
e,
|
|
63
|
+
"seen",
|
|
64
|
+
{ seen_at: t },
|
|
65
|
+
"unseen_count"
|
|
66
|
+
), this.makeStatusUpdate(e, "seen");
|
|
126
67
|
}
|
|
127
|
-
markAllAsSeen() {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
// 3. We issue the API call to the endpoint
|
|
134
|
-
//
|
|
135
|
-
// Note: there is the potential for a race condition here because the bulk
|
|
136
|
-
// update is an async method, so if a new message comes in during this window before
|
|
137
|
-
// the update has been processed we'll effectively reset the `unseen_count` to be what it was.
|
|
138
|
-
//
|
|
139
|
-
// Note: here we optimistically handle the case whereby the feed is scoped to show only `unseen`
|
|
140
|
-
// items by removing everything from view.
|
|
141
|
-
var {
|
|
142
|
-
getState,
|
|
143
|
-
setState
|
|
144
|
-
} = _this2.store;
|
|
145
|
-
var {
|
|
146
|
-
metadata,
|
|
147
|
-
items
|
|
148
|
-
} = getState();
|
|
149
|
-
var isViewingOnlyUnseen = _this2.defaultOptions.status === "unseen";
|
|
150
|
-
|
|
151
|
-
// If we're looking at the unseen view, then we want to remove all of the items optimistically
|
|
152
|
-
// from the store given that nothing should be visible. We do this by resetting the store state
|
|
153
|
-
// and setting the current metadata counts to 0
|
|
154
|
-
if (isViewingOnlyUnseen) {
|
|
155
|
-
setState(store => store.resetStore(_objectSpread(_objectSpread({}, metadata), {}, {
|
|
68
|
+
async markAllAsSeen() {
|
|
69
|
+
const { getState: e, setState: t } = this.store, { metadata: s, items: a } = e();
|
|
70
|
+
if (this.defaultOptions.status === "unseen")
|
|
71
|
+
t(
|
|
72
|
+
(i) => i.resetStore({
|
|
73
|
+
...s,
|
|
156
74
|
total_count: 0,
|
|
157
75
|
unseen_count: 0
|
|
158
|
-
})
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
var itemIds = items.map(item => item.id);
|
|
168
|
-
setState(store => store.setItemAttrs(itemIds, attrs));
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
// Issue the API request to the bulk status change API
|
|
172
|
-
var result = yield _this2.makeBulkStatusUpdate("seen");
|
|
173
|
-
_this2.broadcaster.emit("items:all_seen", {
|
|
174
|
-
items
|
|
175
|
-
});
|
|
176
|
-
_this2.broadcastOverChannel("items:all_seen", {
|
|
177
|
-
items
|
|
178
|
-
});
|
|
179
|
-
return result;
|
|
180
|
-
})();
|
|
76
|
+
})
|
|
77
|
+
);
|
|
78
|
+
else {
|
|
79
|
+
t((o) => o.setMetadata({ ...s, unseen_count: 0 }));
|
|
80
|
+
const i = { seen_at: (/* @__PURE__ */ new Date()).toISOString() }, l = a.map((o) => o.id);
|
|
81
|
+
t((o) => o.setItemAttrs(l, i));
|
|
82
|
+
}
|
|
83
|
+
const n = await this.makeBulkStatusUpdate("seen");
|
|
84
|
+
return this.broadcaster.emit("items:all_seen", { items: a }), this.broadcastOverChannel("items:all_seen", { items: a }), n;
|
|
181
85
|
}
|
|
182
|
-
markAsUnseen(
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
})();
|
|
86
|
+
async markAsUnseen(e) {
|
|
87
|
+
return this.optimisticallyPerformStatusUpdate(
|
|
88
|
+
e,
|
|
89
|
+
"unseen",
|
|
90
|
+
{ seen_at: null },
|
|
91
|
+
"unseen_count"
|
|
92
|
+
), this.makeStatusUpdate(e, "unseen");
|
|
190
93
|
}
|
|
191
|
-
markAsRead(
|
|
192
|
-
|
|
193
|
-
return
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
})();
|
|
94
|
+
async markAsRead(e) {
|
|
95
|
+
const t = (/* @__PURE__ */ new Date()).toISOString();
|
|
96
|
+
return this.optimisticallyPerformStatusUpdate(
|
|
97
|
+
e,
|
|
98
|
+
"read",
|
|
99
|
+
{ read_at: t },
|
|
100
|
+
"unread_count"
|
|
101
|
+
), this.makeStatusUpdate(e, "read");
|
|
200
102
|
}
|
|
201
|
-
markAllAsRead() {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
// 3. We issue the API call to the endpoint
|
|
208
|
-
//
|
|
209
|
-
// Note: there is the potential for a race condition here because the bulk
|
|
210
|
-
// update is an async method, so if a new message comes in during this window before
|
|
211
|
-
// the update has been processed we'll effectively reset the `unread_count` to be what it was.
|
|
212
|
-
//
|
|
213
|
-
// Note: here we optimistically handle the case whereby the feed is scoped to show only `unread`
|
|
214
|
-
// items by removing everything from view.
|
|
215
|
-
var {
|
|
216
|
-
getState,
|
|
217
|
-
setState
|
|
218
|
-
} = _this5.store;
|
|
219
|
-
var {
|
|
220
|
-
metadata,
|
|
221
|
-
items
|
|
222
|
-
} = getState();
|
|
223
|
-
var isViewingOnlyUnread = _this5.defaultOptions.status === "unread";
|
|
224
|
-
|
|
225
|
-
// If we're looking at the unread view, then we want to remove all of the items optimistically
|
|
226
|
-
// from the store given that nothing should be visible. We do this by resetting the store state
|
|
227
|
-
// and setting the current metadata counts to 0
|
|
228
|
-
if (isViewingOnlyUnread) {
|
|
229
|
-
setState(store => store.resetStore(_objectSpread(_objectSpread({}, metadata), {}, {
|
|
103
|
+
async markAllAsRead() {
|
|
104
|
+
const { getState: e, setState: t } = this.store, { metadata: s, items: a } = e();
|
|
105
|
+
if (this.defaultOptions.status === "unread")
|
|
106
|
+
t(
|
|
107
|
+
(i) => i.resetStore({
|
|
108
|
+
...s,
|
|
230
109
|
total_count: 0,
|
|
231
110
|
unread_count: 0
|
|
232
|
-
})
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
var itemIds = items.map(item => item.id);
|
|
242
|
-
setState(store => store.setItemAttrs(itemIds, attrs));
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
// Issue the API request to the bulk status change API
|
|
246
|
-
var result = yield _this5.makeBulkStatusUpdate("read");
|
|
247
|
-
_this5.broadcaster.emit("items:all_read", {
|
|
248
|
-
items
|
|
249
|
-
});
|
|
250
|
-
_this5.broadcastOverChannel("items:all_read", {
|
|
251
|
-
items
|
|
252
|
-
});
|
|
253
|
-
return result;
|
|
254
|
-
})();
|
|
111
|
+
})
|
|
112
|
+
);
|
|
113
|
+
else {
|
|
114
|
+
t((o) => o.setMetadata({ ...s, unread_count: 0 }));
|
|
115
|
+
const i = { read_at: (/* @__PURE__ */ new Date()).toISOString() }, l = a.map((o) => o.id);
|
|
116
|
+
t((o) => o.setItemAttrs(l, i));
|
|
117
|
+
}
|
|
118
|
+
const n = await this.makeBulkStatusUpdate("read");
|
|
119
|
+
return this.broadcaster.emit("items:all_read", { items: a }), this.broadcastOverChannel("items:all_read", { items: a }), n;
|
|
255
120
|
}
|
|
256
|
-
markAsUnread(
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
})();
|
|
121
|
+
async markAsUnread(e) {
|
|
122
|
+
return this.optimisticallyPerformStatusUpdate(
|
|
123
|
+
e,
|
|
124
|
+
"unread",
|
|
125
|
+
{ read_at: null },
|
|
126
|
+
"unread_count"
|
|
127
|
+
), this.makeStatusUpdate(e, "unread");
|
|
264
128
|
}
|
|
265
|
-
markAsInteracted(
|
|
266
|
-
|
|
267
|
-
return
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
129
|
+
async markAsInteracted(e) {
|
|
130
|
+
const t = (/* @__PURE__ */ new Date()).toISOString();
|
|
131
|
+
return this.optimisticallyPerformStatusUpdate(
|
|
132
|
+
e,
|
|
133
|
+
"interacted",
|
|
134
|
+
{
|
|
135
|
+
read_at: t,
|
|
136
|
+
interacted_at: t
|
|
137
|
+
},
|
|
138
|
+
"unread_count"
|
|
139
|
+
), this.makeStatusUpdate(e, "interacted");
|
|
275
140
|
}
|
|
276
|
-
|
|
277
141
|
/*
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
## Feed scoped to exclude archived items (the default)
|
|
307
|
-
- Counts should be decremented
|
|
308
|
-
- Items should be removed
|
|
309
|
-
## Feed scoped to include archived items as well
|
|
310
|
-
- Counts should not be decremented
|
|
311
|
-
- Items should not be removed
|
|
312
|
-
*/
|
|
313
|
-
|
|
314
|
-
if (shouldOptimisticallyRemoveItems) {
|
|
315
|
-
// If any of the items are unseen or unread, then capture as we'll want to decrement
|
|
316
|
-
// the counts for these in the metadata we have
|
|
317
|
-
var unseenCount = normalizedItems.filter(i => !i.seen_at).length;
|
|
318
|
-
var unreadCount = normalizedItems.filter(i => !i.read_at).length;
|
|
319
|
-
|
|
320
|
-
// Build the new metadata
|
|
321
|
-
var updatedMetadata = _objectSpread(_objectSpread({}, state.metadata), {}, {
|
|
322
|
-
total_count: state.metadata.total_count - normalizedItems.length,
|
|
323
|
-
unseen_count: state.metadata.unseen_count - unseenCount,
|
|
324
|
-
unread_count: state.metadata.unread_count - unreadCount
|
|
325
|
-
});
|
|
326
|
-
|
|
327
|
-
// Remove the archiving entries
|
|
328
|
-
var entriesToSet = state.items.filter(item => !itemIds.includes(item.id));
|
|
329
|
-
setState(state => state.setResult({
|
|
330
|
-
entries: entriesToSet,
|
|
331
|
-
meta: updatedMetadata,
|
|
332
|
-
page_info: state.pageInfo
|
|
333
|
-
}));
|
|
334
|
-
} else {
|
|
335
|
-
// Mark all the entries being updated as archived either way so the state is correct
|
|
336
|
-
state.setItemAttrs(itemIds, {
|
|
337
|
-
archived_at: new Date().toISOString()
|
|
338
|
-
});
|
|
339
|
-
}
|
|
340
|
-
return _this8.makeStatusUpdate(itemOrItems, "archived");
|
|
341
|
-
})();
|
|
142
|
+
Marking one or more items as archived should:
|
|
143
|
+
|
|
144
|
+
- Decrement the badge count for any unread / unseen items
|
|
145
|
+
- Remove the item from the feed list when the `archived` flag is "exclude" (default)
|
|
146
|
+
|
|
147
|
+
TODO: how do we handle rollbacks?
|
|
148
|
+
*/
|
|
149
|
+
async markAsArchived(e) {
|
|
150
|
+
const { getState: t, setState: s } = this.store, a = t(), r = this.defaultOptions.archived === "exclude", n = Array.isArray(e) ? e : [e], i = n.map((l) => l.id);
|
|
151
|
+
if (r) {
|
|
152
|
+
const l = n.filter((c) => !c.seen_at).length, o = n.filter((c) => !c.read_at).length, d = {
|
|
153
|
+
...a.metadata,
|
|
154
|
+
total_count: a.metadata.total_count - n.length,
|
|
155
|
+
unseen_count: a.metadata.unseen_count - l,
|
|
156
|
+
unread_count: a.metadata.unread_count - o
|
|
157
|
+
}, h = a.items.filter(
|
|
158
|
+
(c) => !i.includes(c.id)
|
|
159
|
+
);
|
|
160
|
+
s(
|
|
161
|
+
(c) => c.setResult({
|
|
162
|
+
entries: h,
|
|
163
|
+
meta: d,
|
|
164
|
+
page_info: c.pageInfo
|
|
165
|
+
})
|
|
166
|
+
);
|
|
167
|
+
} else
|
|
168
|
+
a.setItemAttrs(i, { archived_at: (/* @__PURE__ */ new Date()).toISOString() });
|
|
169
|
+
return this.makeStatusUpdate(e, "archived");
|
|
342
170
|
}
|
|
343
|
-
markAllAsArchived() {
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
getState
|
|
352
|
-
} = _this9.store;
|
|
353
|
-
var {
|
|
354
|
-
items
|
|
355
|
-
} = getState();
|
|
356
|
-
|
|
357
|
-
// Here if we're looking at a feed that excludes all of the archived items by default then we
|
|
358
|
-
// will want to optimistically remove all of the items from the feed as they are now all excluded
|
|
359
|
-
var shouldOptimisticallyRemoveItems = _this9.defaultOptions.archived === "exclude";
|
|
360
|
-
if (shouldOptimisticallyRemoveItems) {
|
|
361
|
-
// Reset the store to clear out all of items and reset the badge count
|
|
362
|
-
setState(store => store.resetStore());
|
|
363
|
-
} else {
|
|
364
|
-
// Mark all the entries being updated as archived either way so the state is correct
|
|
365
|
-
setState(store => {
|
|
366
|
-
var itemIds = items.map(i => i.id);
|
|
367
|
-
store.setItemAttrs(itemIds, {
|
|
368
|
-
archived_at: new Date().toISOString()
|
|
369
|
-
});
|
|
370
|
-
});
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
// Issue the API request to the bulk status change API
|
|
374
|
-
var result = yield _this9.makeBulkStatusUpdate("archive");
|
|
375
|
-
_this9.broadcaster.emit("items:all_archived", {
|
|
376
|
-
items
|
|
377
|
-
});
|
|
378
|
-
_this9.broadcastOverChannel("items:all_archived", {
|
|
379
|
-
items
|
|
380
|
-
});
|
|
381
|
-
return result;
|
|
382
|
-
})();
|
|
171
|
+
async markAllAsArchived() {
|
|
172
|
+
const { setState: e, getState: t } = this.store, { items: s } = t(), a = this.defaultOptions.archived === "exclude";
|
|
173
|
+
e(a ? (n) => n.resetStore() : (n) => {
|
|
174
|
+
const i = s.map((l) => l.id);
|
|
175
|
+
n.setItemAttrs(i, { archived_at: (/* @__PURE__ */ new Date()).toISOString() });
|
|
176
|
+
});
|
|
177
|
+
const r = await this.makeBulkStatusUpdate("archive");
|
|
178
|
+
return this.broadcaster.emit("items:all_archived", { items: s }), this.broadcastOverChannel("items:all_archived", { items: s }), r;
|
|
383
179
|
}
|
|
384
|
-
markAsUnarchived(
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
archived_at: null
|
|
389
|
-
});
|
|
390
|
-
return _this10.makeStatusUpdate(itemOrItems, "unarchived");
|
|
391
|
-
})();
|
|
180
|
+
async markAsUnarchived(e) {
|
|
181
|
+
return this.optimisticallyPerformStatusUpdate(e, "unarchived", {
|
|
182
|
+
archived_at: null
|
|
183
|
+
}), this.makeStatusUpdate(e, "unarchived");
|
|
392
184
|
}
|
|
393
|
-
|
|
394
185
|
/* Fetches the feed content, appending it to the store */
|
|
395
|
-
fetch() {
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
var queryParams = _objectSpread(_objectSpread(_objectSpread({}, _this11.defaultOptions), options), {}, {
|
|
421
|
-
// Unset options that should not be sent to the API
|
|
422
|
-
__loadingType: undefined,
|
|
423
|
-
__fetchSource: undefined,
|
|
424
|
-
__experimentalCrossBrowserUpdates: undefined
|
|
425
|
-
});
|
|
426
|
-
var result = yield _this11.apiClient.makeRequest({
|
|
427
|
-
method: "GET",
|
|
428
|
-
url: "/v1/users/".concat(_this11.knock.userId, "/feeds/").concat(_this11.feedId),
|
|
429
|
-
params: queryParams
|
|
430
|
-
});
|
|
431
|
-
if (result.statusCode === "error" || !result.body) {
|
|
432
|
-
setState(store => store.setNetworkStatus(NetworkStatus.error));
|
|
433
|
-
return {
|
|
434
|
-
status: result.statusCode,
|
|
435
|
-
data: result.error || result.body
|
|
436
|
-
};
|
|
437
|
-
}
|
|
438
|
-
var response = {
|
|
439
|
-
entries: result.body.entries,
|
|
440
|
-
meta: result.body.meta,
|
|
441
|
-
page_info: result.body.page_info
|
|
442
|
-
};
|
|
443
|
-
if (options.before) {
|
|
444
|
-
var opts = {
|
|
445
|
-
shouldSetPage: false,
|
|
446
|
-
shouldAppend: true
|
|
447
|
-
};
|
|
448
|
-
setState(state => state.setResult(response, opts));
|
|
449
|
-
} else if (options.after) {
|
|
450
|
-
var _opts = {
|
|
451
|
-
shouldSetPage: true,
|
|
452
|
-
shouldAppend: true
|
|
453
|
-
};
|
|
454
|
-
setState(state => state.setResult(response, _opts));
|
|
455
|
-
} else {
|
|
456
|
-
setState(state => state.setResult(response));
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
// Legacy `messages.new` event, should be removed in a future version
|
|
460
|
-
_this11.broadcast("messages.new", response);
|
|
461
|
-
|
|
462
|
-
// Broadcast the appropriate event type depending on the fetch source
|
|
463
|
-
var feedEventType = options.__fetchSource === "socket" ? "items.received.realtime" : "items.received.page";
|
|
464
|
-
var eventPayload = {
|
|
465
|
-
items: response.entries,
|
|
466
|
-
metadata: response.meta,
|
|
467
|
-
event: feedEventType
|
|
468
|
-
};
|
|
469
|
-
_this11.broadcast(eventPayload.event, eventPayload);
|
|
470
|
-
return {
|
|
471
|
-
data: response,
|
|
472
|
-
status: result.statusCode
|
|
186
|
+
async fetch(e = {}) {
|
|
187
|
+
const { setState: t, getState: s } = this.store, { networkStatus: a } = s();
|
|
188
|
+
if (S(a))
|
|
189
|
+
return;
|
|
190
|
+
t(
|
|
191
|
+
(d) => d.setNetworkStatus(e.__loadingType ?? f.loading)
|
|
192
|
+
);
|
|
193
|
+
const r = {
|
|
194
|
+
...this.defaultOptions,
|
|
195
|
+
...e,
|
|
196
|
+
// Unset options that should not be sent to the API
|
|
197
|
+
__loadingType: void 0,
|
|
198
|
+
__fetchSource: void 0,
|
|
199
|
+
__experimentalCrossBrowserUpdates: void 0,
|
|
200
|
+
auto_manage_socket_connection: void 0,
|
|
201
|
+
auto_manage_socket_connection_delay: void 0
|
|
202
|
+
}, n = await this.knock.client().makeRequest({
|
|
203
|
+
method: "GET",
|
|
204
|
+
url: `/v1/users/${this.knock.userId}/feeds/${this.feedId}`,
|
|
205
|
+
params: r
|
|
206
|
+
});
|
|
207
|
+
if (n.statusCode === "error" || !n.body)
|
|
208
|
+
return t((d) => d.setNetworkStatus(f.error)), {
|
|
209
|
+
status: n.statusCode,
|
|
210
|
+
data: n.error || n.body
|
|
473
211
|
};
|
|
474
|
-
|
|
212
|
+
const i = {
|
|
213
|
+
entries: n.body.entries,
|
|
214
|
+
meta: n.body.meta,
|
|
215
|
+
page_info: n.body.page_info
|
|
216
|
+
};
|
|
217
|
+
if (e.before) {
|
|
218
|
+
const d = { shouldSetPage: !1, shouldAppend: !0 };
|
|
219
|
+
t((h) => h.setResult(i, d));
|
|
220
|
+
} else if (e.after) {
|
|
221
|
+
const d = { shouldSetPage: !0, shouldAppend: !0 };
|
|
222
|
+
t((h) => h.setResult(i, d));
|
|
223
|
+
} else
|
|
224
|
+
t((d) => d.setResult(i));
|
|
225
|
+
this.broadcast("messages.new", i);
|
|
226
|
+
const l = e.__fetchSource === "socket" ? "items.received.realtime" : "items.received.page", o = {
|
|
227
|
+
items: i.entries,
|
|
228
|
+
metadata: i.meta,
|
|
229
|
+
event: l
|
|
230
|
+
};
|
|
231
|
+
return this.broadcast(o.event, o), { data: i, status: n.statusCode };
|
|
475
232
|
}
|
|
476
|
-
fetchNextPage() {
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
} = _this12.store;
|
|
483
|
-
var {
|
|
484
|
-
pageInfo
|
|
485
|
-
} = getState();
|
|
486
|
-
if (!pageInfo.after) {
|
|
487
|
-
// Nothing more to fetch
|
|
488
|
-
return;
|
|
489
|
-
}
|
|
490
|
-
_this12.fetch({
|
|
491
|
-
after: pageInfo.after,
|
|
492
|
-
__loadingType: NetworkStatus.fetchMore
|
|
493
|
-
});
|
|
494
|
-
})();
|
|
233
|
+
async fetchNextPage() {
|
|
234
|
+
const { getState: e } = this.store, { pageInfo: t } = e();
|
|
235
|
+
t.after && this.fetch({
|
|
236
|
+
after: t.after,
|
|
237
|
+
__loadingType: f.fetchMore
|
|
238
|
+
});
|
|
495
239
|
}
|
|
496
|
-
broadcast(
|
|
497
|
-
this.broadcaster.emit(
|
|
240
|
+
broadcast(e, t) {
|
|
241
|
+
this.broadcaster.emit(e, t);
|
|
498
242
|
}
|
|
499
|
-
|
|
500
243
|
// Invoked when a new real-time message comes in from the socket
|
|
501
|
-
onNewMessageReceived(
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
// Handle the new message coming in
|
|
508
|
-
var {
|
|
509
|
-
getState,
|
|
510
|
-
setState
|
|
511
|
-
} = _this13.store;
|
|
512
|
-
var {
|
|
513
|
-
items
|
|
514
|
-
} = getState();
|
|
515
|
-
var currentHead = items[0];
|
|
516
|
-
// Optimistically set the badge counts
|
|
517
|
-
setState(state => state.setMetadata(metadata));
|
|
518
|
-
// Fetch the items before the current head (if it exists)
|
|
519
|
-
_this13.fetch({
|
|
520
|
-
before: currentHead === null || currentHead === void 0 ? void 0 : currentHead.__cursor,
|
|
521
|
-
__fetchSource: "socket"
|
|
522
|
-
});
|
|
523
|
-
})();
|
|
244
|
+
async onNewMessageReceived({
|
|
245
|
+
metadata: e
|
|
246
|
+
}) {
|
|
247
|
+
this.knock.log("[Feed] Received new real-time message");
|
|
248
|
+
const { getState: t, setState: s } = this.store, { items: a } = t(), r = a[0];
|
|
249
|
+
s((n) => n.setMetadata(e)), this.fetch({ before: r == null ? void 0 : r.__cursor, __fetchSource: "socket" });
|
|
524
250
|
}
|
|
525
251
|
buildUserFeedId() {
|
|
526
|
-
return
|
|
252
|
+
return `${this.feedId}:${this.knock.userId}`;
|
|
527
253
|
}
|
|
528
|
-
optimisticallyPerformStatusUpdate(
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
var normalizedItems = Array.isArray(itemOrItems) ? itemOrItems : [itemOrItems];
|
|
534
|
-
var itemIds = normalizedItems.map(item => item.id);
|
|
535
|
-
if (badgeCountAttr) {
|
|
536
|
-
var {
|
|
537
|
-
metadata
|
|
538
|
-
} = getState();
|
|
539
|
-
|
|
540
|
-
// We only want to update the counts of items that have not already been counted towards the
|
|
541
|
-
// badge count total to avoid updating the badge count unnecessarily.
|
|
542
|
-
var itemsToUpdate = normalizedItems.filter(item => {
|
|
543
|
-
switch (type) {
|
|
254
|
+
optimisticallyPerformStatusUpdate(e, t, s, a) {
|
|
255
|
+
const { getState: r, setState: n } = this.store, i = Array.isArray(e) ? e : [e], l = i.map((o) => o.id);
|
|
256
|
+
if (a) {
|
|
257
|
+
const { metadata: o } = r(), d = i.filter((c) => {
|
|
258
|
+
switch (t) {
|
|
544
259
|
case "seen":
|
|
545
|
-
return
|
|
260
|
+
return c.seen_at === null;
|
|
546
261
|
case "unseen":
|
|
547
|
-
return
|
|
262
|
+
return c.seen_at !== null;
|
|
548
263
|
case "read":
|
|
549
264
|
case "interacted":
|
|
550
|
-
return
|
|
265
|
+
return c.read_at === null;
|
|
551
266
|
case "unread":
|
|
552
|
-
return
|
|
267
|
+
return c.read_at !== null;
|
|
553
268
|
default:
|
|
554
|
-
return
|
|
269
|
+
return !0;
|
|
555
270
|
}
|
|
556
|
-
});
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
})));
|
|
271
|
+
}), h = t.startsWith("un") ? d.length : -d.length;
|
|
272
|
+
n(
|
|
273
|
+
(c) => c.setMetadata({
|
|
274
|
+
...o,
|
|
275
|
+
[a]: Math.max(0, o[a] + h)
|
|
276
|
+
})
|
|
277
|
+
);
|
|
564
278
|
}
|
|
565
|
-
|
|
566
|
-
// Update the items with the given attributes
|
|
567
|
-
setState(store => store.setItemAttrs(itemIds, attrs));
|
|
279
|
+
n((o) => o.setItemAttrs(l, s));
|
|
568
280
|
}
|
|
569
|
-
makeStatusUpdate(
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
method: "POST",
|
|
577
|
-
url: "/v1/messages/batch/".concat(type),
|
|
578
|
-
data: {
|
|
579
|
-
message_ids: itemIds
|
|
580
|
-
}
|
|
581
|
-
});
|
|
582
|
-
|
|
583
|
-
// Emit the event that these items had their statuses changed
|
|
584
|
-
// Note: we do this after the update to ensure that the server event actually completed
|
|
585
|
-
_this14.broadcaster.emit("items:".concat(type), {
|
|
586
|
-
items
|
|
587
|
-
});
|
|
588
|
-
_this14.broadcastOverChannel("items:".concat(type), {
|
|
589
|
-
items
|
|
590
|
-
});
|
|
591
|
-
return result;
|
|
592
|
-
})();
|
|
281
|
+
async makeStatusUpdate(e, t) {
|
|
282
|
+
const s = Array.isArray(e) ? e : [e], a = s.map((n) => n.id), r = await this.knock.client().makeRequest({
|
|
283
|
+
method: "POST",
|
|
284
|
+
url: `/v1/messages/batch/${t}`,
|
|
285
|
+
data: { message_ids: a }
|
|
286
|
+
});
|
|
287
|
+
return this.broadcaster.emit(`items:${t}`, { items: s }), this.broadcastOverChannel(`items:${t}`, { items: s }), r;
|
|
593
288
|
}
|
|
594
|
-
makeBulkStatusUpdate(
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
};
|
|
608
|
-
return yield _this15.apiClient.makeRequest({
|
|
609
|
-
method: "POST",
|
|
610
|
-
url: "/v1/channels/".concat(_this15.feedId, "/messages/bulk/").concat(type),
|
|
611
|
-
data: options
|
|
612
|
-
});
|
|
613
|
-
})();
|
|
289
|
+
async makeBulkStatusUpdate(e) {
|
|
290
|
+
const t = {
|
|
291
|
+
user_ids: [this.knock.userId],
|
|
292
|
+
engagement_status: this.defaultOptions.status !== "all" ? this.defaultOptions.status : void 0,
|
|
293
|
+
archived: this.defaultOptions.archived,
|
|
294
|
+
has_tenant: this.defaultOptions.has_tenant,
|
|
295
|
+
tenants: this.defaultOptions.tenant ? [this.defaultOptions.tenant] : void 0
|
|
296
|
+
};
|
|
297
|
+
return await this.knock.client().makeRequest({
|
|
298
|
+
method: "POST",
|
|
299
|
+
url: `/v1/channels/${this.feedId}/messages/bulk/${e}`,
|
|
300
|
+
data: t
|
|
301
|
+
});
|
|
614
302
|
}
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
}
|
|
303
|
+
setupBroadcastChannel() {
|
|
304
|
+
this.broadcastChannel = typeof self < "u" && "BroadcastChannel" in self ? new BroadcastChannel(`knock:feed:${this.userFeedId}`) : null, this.broadcastChannel && this.defaultOptions.__experimentalCrossBrowserUpdates === !0 && (this.broadcastChannel.onmessage = (e) => {
|
|
305
|
+
switch (e.data.type) {
|
|
306
|
+
case "items:archived":
|
|
307
|
+
case "items:unarchived":
|
|
308
|
+
case "items:seen":
|
|
309
|
+
case "items:unseen":
|
|
310
|
+
case "items:read":
|
|
311
|
+
case "items:unread":
|
|
312
|
+
case "items:all_read":
|
|
313
|
+
case "items:all_seen":
|
|
314
|
+
case "items:all_archived":
|
|
315
|
+
return this.fetch();
|
|
316
|
+
default:
|
|
317
|
+
return null;
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
broadcastOverChannel(e, t) {
|
|
322
|
+
if (this.broadcastChannel)
|
|
323
|
+
try {
|
|
324
|
+
const s = JSON.parse(JSON.stringify(t));
|
|
325
|
+
this.broadcastChannel.postMessage({
|
|
326
|
+
type: e,
|
|
327
|
+
payload: s
|
|
328
|
+
});
|
|
329
|
+
} catch (s) {
|
|
330
|
+
console.warn(`Could not broadcast ${e}, got error: ${s}`);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
initializeRealtimeConnection() {
|
|
334
|
+
const { socket: e } = this.knock.client();
|
|
335
|
+
e && (this.channel = e.channel(
|
|
336
|
+
`feeds:${this.userFeedId}`,
|
|
337
|
+
this.defaultOptions
|
|
338
|
+
), this.channel.on("new-message", (t) => this.onNewMessageReceived(t)), this.defaultOptions.auto_manage_socket_connection && this.setupAutoSocketManager(
|
|
339
|
+
this.defaultOptions.auto_manage_socket_connection_delay
|
|
340
|
+
), this.hasSubscribedToRealTimeUpdates && (e.isConnected() || e.connect(), this.channel.join()));
|
|
632
341
|
}
|
|
633
|
-
|
|
634
342
|
/**
|
|
635
343
|
* Listen for changes to document visibility and automatically disconnect
|
|
636
344
|
* or reconnect the socket after a delay
|
|
637
345
|
*/
|
|
638
|
-
setupAutoSocketManager(
|
|
639
|
-
|
|
346
|
+
setupAutoSocketManager(e) {
|
|
347
|
+
const t = e ?? y;
|
|
640
348
|
document.addEventListener("visibilitychange", () => {
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
} else if (document.visibilityState === "visible") {
|
|
648
|
-
var _this$apiClient$socke;
|
|
649
|
-
// When the tab is visible, clear the disconnect timer if active to cancel disconnecting
|
|
650
|
-
// This handles cases where the tab is only briefly hidden to avoid unnecessary disconnects
|
|
651
|
-
if (this.disconnectTimer) {
|
|
652
|
-
clearTimeout(this.disconnectTimer);
|
|
653
|
-
this.disconnectTimer = null;
|
|
654
|
-
}
|
|
655
|
-
|
|
656
|
-
// If the socket is not connected, try to reconnect
|
|
657
|
-
if (!((_this$apiClient$socke = this.apiClient.socket) !== null && _this$apiClient$socke !== void 0 && _this$apiClient$socke.isConnected())) {
|
|
658
|
-
this.apiClient.reconnectSocket();
|
|
659
|
-
this.fetch();
|
|
660
|
-
}
|
|
661
|
-
}
|
|
349
|
+
var a;
|
|
350
|
+
const s = this.knock.client();
|
|
351
|
+
document.visibilityState === "hidden" ? this.disconnectTimer = setTimeout(() => {
|
|
352
|
+
var r;
|
|
353
|
+
(r = s.socket) == null || r.disconnect(), this.disconnectTimer = null;
|
|
354
|
+
}, t) : document.visibilityState === "visible" && (this.disconnectTimer && (clearTimeout(this.disconnectTimer), this.disconnectTimer = null), (a = s.socket) != null && a.isConnected() || this.initializeRealtimeConnection());
|
|
662
355
|
});
|
|
663
356
|
}
|
|
664
357
|
}
|
|
665
|
-
export
|
|
666
|
-
|
|
358
|
+
export {
|
|
359
|
+
A as default
|
|
360
|
+
};
|
|
361
|
+
//# sourceMappingURL=feed.js.map
|