@twilio/conversations 2.1.0-rc.8 → 3.0.0-canary.5
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 +7 -3
- package/builds/browser.js +2350 -1627
- package/builds/browser.js.map +1 -1
- package/builds/lib.d.ts +512 -304
- package/builds/lib.js +2350 -1627
- package/builds/lib.js.map +1 -1
- package/builds/twilio-conversations.js +3448 -3403
- package/builds/twilio-conversations.min.js +2 -2
- package/dist/client.js +402 -281
- package/dist/client.js.map +1 -1
- package/dist/command-executor.js.map +1 -1
- package/dist/configuration.js +2 -2
- package/dist/configuration.js.map +1 -1
- package/dist/conversation.js +408 -373
- package/dist/conversation.js.map +1 -1
- package/dist/data/conversations.js +9 -10
- package/dist/data/conversations.js.map +1 -1
- package/dist/data/messages.js +46 -26
- package/dist/data/messages.js.map +1 -1
- package/dist/data/participants.js +19 -10
- package/dist/data/participants.js.map +1 -1
- package/dist/data/users.js +2 -2
- package/dist/data/users.js.map +1 -1
- package/dist/media.js +36 -25
- package/dist/media.js.map +1 -1
- package/dist/message-builder.js +24 -18
- package/dist/message-builder.js.map +1 -1
- package/dist/message.js +46 -19
- package/dist/message.js.map +1 -1
- package/dist/packages/conversations/package.json.js +1 -1
- package/dist/participant.js.map +1 -1
- package/dist/push-notification.js.map +1 -1
- package/dist/services/typing-indicator.js +1 -1
- package/dist/services/typing-indicator.js.map +1 -1
- package/dist/unsent-message.js +13 -3
- package/dist/unsent-message.js.map +1 -1
- package/package.json +12 -10
- package/CHANGELOG.md +0 -404
- package/docs/assets/css/main.css +0 -2660
- package/docs/assets/images/icons.png +0 -0
- package/docs/assets/images/icons@2x.png +0 -0
- package/docs/assets/images/widgets.png +0 -0
- package/docs/assets/images/widgets@2x.png +0 -0
- package/docs/assets/js/main.js +0 -248
- package/docs/assets/js/search.js +0 -1
- package/docs/classes/AggregatedDeliveryReceipt.html +0 -3184
- package/docs/classes/Client.html +0 -4073
- package/docs/classes/Conversation.html +0 -4302
- package/docs/classes/DetailedDeliveryReceipt.html +0 -3163
- package/docs/classes/Media.html +0 -3193
- package/docs/classes/Message.html +0 -3677
- package/docs/classes/MessageBuilder.html +0 -3254
- package/docs/classes/Participant.html +0 -3444
- package/docs/classes/PushNotification.html +0 -3130
- package/docs/classes/RestPaginator.html +0 -3160
- package/docs/classes/UnsentMessage.html +0 -3042
- package/docs/classes/User.html +0 -3349
- package/docs/index.html +0 -3512
- package/docs/interfaces/ClientOptions.html +0 -3034
- package/docs/interfaces/ConversationBindings.html +0 -3001
- package/docs/interfaces/ConversationEmailBinding.html +0 -3001
- package/docs/interfaces/ConversationLimits.html +0 -3098
- package/docs/interfaces/ConversationState.html +0 -3050
- package/docs/interfaces/CreateConversationOptions.html +0 -3066
- package/docs/interfaces/LastMessage.html +0 -3050
- package/docs/interfaces/Paginator.html +0 -3141
- package/docs/interfaces/ParticipantBindings.html +0 -3001
- package/docs/interfaces/ParticipantEmailBinding.html +0 -3001
- package/docs/interfaces/PushNotificationData.html +0 -3066
- package/docs/interfaces/SendEmailOptions.html +0 -3034
- package/docs/interfaces/SendMediaOptions.html +0 -3068
- package/docs/modules.html +0 -3513
package/dist/conversation.js
CHANGED
@@ -146,7 +146,9 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau
|
|
146
146
|
|
147
147
|
var isEqual__default = /*#__PURE__*/_interopDefaultLegacy(isEqual);
|
148
148
|
|
149
|
-
|
149
|
+
/**
|
150
|
+
* Map of the fields that will be processed with update messages.
|
151
|
+
*/
|
150
152
|
const fieldMappings = {
|
151
153
|
lastMessage: "lastMessage",
|
152
154
|
attributes: "attributes",
|
@@ -162,252 +164,150 @@ const fieldMappings = {
|
|
162
164
|
state: "state",
|
163
165
|
bindings: "bindings",
|
164
166
|
};
|
165
|
-
function parseTime(timeString) {
|
166
|
-
try {
|
167
|
-
return new Date(timeString);
|
168
|
-
}
|
169
|
-
catch (e) {
|
170
|
-
return null;
|
171
|
-
}
|
172
|
-
}
|
173
167
|
/**
|
174
|
-
* A conversation represents communication between multiple Conversations
|
168
|
+
* A conversation represents communication between multiple Conversations
|
169
|
+
* clients.
|
175
170
|
*/
|
176
171
|
class Conversation extends replayEventEmitter.ReplayEventEmitter {
|
177
172
|
/**
|
173
|
+
* @param descriptor Conversation descriptor.
|
174
|
+
* @param sid Conversation SID.
|
175
|
+
* @param links Conversation links for REST requests.
|
176
|
+
* @param configuration Client configuration.
|
177
|
+
* @param services Conversation services.
|
178
178
|
* @internal
|
179
179
|
*/
|
180
180
|
constructor(descriptor, sid, links, configuration, services) {
|
181
|
-
var _a;
|
181
|
+
var _a, _b;
|
182
182
|
super();
|
183
183
|
this.sid = sid;
|
184
|
-
this.
|
185
|
-
this.
|
186
|
-
this.
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
const dateUpdated = parseTime(descriptor.dateUpdated);
|
191
|
-
const friendlyName = descriptor.friendlyName || null;
|
192
|
-
const lastReadMessageIndex = Number.isInteger(descriptor.lastConsumedMessageIndex)
|
193
|
-
? descriptor.lastConsumedMessageIndex
|
194
|
-
: null;
|
195
|
-
const uniqueName = descriptor.uniqueName || null;
|
196
|
-
try {
|
197
|
-
JSON.stringify(attributes);
|
198
|
-
}
|
199
|
-
catch (e) {
|
200
|
-
throw new Error("Attributes must be a valid JSON object.");
|
201
|
-
}
|
202
|
-
this.entityName = descriptor.channel;
|
203
|
-
this.channelState = {
|
204
|
-
uniqueName,
|
184
|
+
this._links = links;
|
185
|
+
this._configuration = configuration;
|
186
|
+
this._services = services;
|
187
|
+
this._entityName = descriptor.channel;
|
188
|
+
this._internalState = {
|
189
|
+
uniqueName: descriptor.uniqueName || null,
|
205
190
|
status: "notParticipating",
|
206
|
-
attributes,
|
207
|
-
createdBy,
|
208
|
-
dateCreated,
|
209
|
-
dateUpdated,
|
210
|
-
friendlyName,
|
211
|
-
lastReadMessageIndex
|
212
|
-
|
191
|
+
attributes: (_a = descriptor.attributes) !== null && _a !== void 0 ? _a : {},
|
192
|
+
createdBy: descriptor.createdBy,
|
193
|
+
dateCreated: index.parseTime(descriptor.dateCreated),
|
194
|
+
dateUpdated: index.parseTime(descriptor.dateUpdated),
|
195
|
+
friendlyName: descriptor.friendlyName || null,
|
196
|
+
lastReadMessageIndex: Number.isInteger(descriptor.lastConsumedMessageIndex)
|
197
|
+
? descriptor.lastConsumedMessageIndex
|
198
|
+
: null,
|
199
|
+
bindings: (_b = descriptor.bindings) !== null && _b !== void 0 ? _b : {},
|
213
200
|
};
|
214
201
|
if (descriptor.notificationLevel) {
|
215
|
-
this.
|
202
|
+
this._internalState.notificationLevel = descriptor.notificationLevel;
|
216
203
|
}
|
217
204
|
const participantsLinks = {
|
218
|
-
participants: this.
|
205
|
+
participants: this._links.participants,
|
219
206
|
};
|
220
|
-
this.
|
221
|
-
this.
|
222
|
-
this.
|
223
|
-
this.
|
224
|
-
this.
|
225
|
-
this.
|
226
|
-
this.
|
227
|
-
this.
|
228
|
-
this.
|
207
|
+
this._participants = new Map();
|
208
|
+
this._participantsEntity = new participants.Participants(this, this._participants, participantsLinks, this._configuration, this._services);
|
209
|
+
this._participantsEntity.on("participantJoined", (participant) => this.emit("participantJoined", participant));
|
210
|
+
this._participantsEntity.on("participantLeft", (participant) => this.emit("participantLeft", participant));
|
211
|
+
this._participantsEntity.on("participantUpdated", (args) => this.emit("participantUpdated", args));
|
212
|
+
this._messagesEntity = new messages.Messages(this, configuration, services);
|
213
|
+
this._messagesEntity.on("messageAdded", (message) => this._onMessageAdded(message));
|
214
|
+
this._messagesEntity.on("messageUpdated", (args) => this.emit("messageUpdated", args));
|
215
|
+
this._messagesEntity.on("messageRemoved", (message) => this.emit("messageRemoved", message));
|
229
216
|
}
|
230
217
|
/**
|
231
218
|
* Unique name of the conversation.
|
232
219
|
*/
|
233
220
|
get uniqueName() {
|
234
|
-
return this.
|
221
|
+
return this._internalState.uniqueName;
|
235
222
|
}
|
236
223
|
/**
|
237
224
|
* Status of the conversation.
|
238
225
|
*/
|
239
226
|
get status() {
|
240
|
-
return this.
|
227
|
+
return this._internalState.status;
|
241
228
|
}
|
242
229
|
/**
|
243
230
|
* Name of the conversation.
|
244
231
|
*/
|
245
232
|
get friendlyName() {
|
246
|
-
return this.
|
233
|
+
return this._internalState.friendlyName;
|
247
234
|
}
|
248
235
|
/**
|
249
236
|
* Date this conversation was last updated on.
|
250
237
|
*/
|
251
238
|
get dateUpdated() {
|
252
|
-
return this.
|
239
|
+
return this._internalState.dateUpdated;
|
253
240
|
}
|
254
241
|
/**
|
255
242
|
* Date this conversation was created on.
|
256
243
|
*/
|
257
244
|
get dateCreated() {
|
258
|
-
return this.
|
245
|
+
return this._internalState.dateCreated;
|
259
246
|
}
|
260
247
|
/**
|
261
248
|
* Identity of the user that created this conversation.
|
262
249
|
*/
|
263
250
|
get createdBy() {
|
264
251
|
var _a;
|
265
|
-
return (_a = this.
|
252
|
+
return (_a = this._internalState.createdBy) !== null && _a !== void 0 ? _a : "";
|
266
253
|
}
|
267
254
|
/**
|
268
255
|
* Custom attributes of the conversation.
|
269
256
|
*/
|
270
257
|
get attributes() {
|
271
|
-
return this.
|
258
|
+
return this._internalState.attributes;
|
272
259
|
}
|
273
260
|
/**
|
274
261
|
* Index of the last message the user has read in this conversation.
|
275
262
|
*/
|
276
263
|
get lastReadMessageIndex() {
|
277
|
-
return this.
|
264
|
+
return this._internalState.lastReadMessageIndex;
|
278
265
|
}
|
279
266
|
/**
|
280
267
|
* Last message sent to this conversation.
|
281
268
|
*/
|
282
269
|
get lastMessage() {
|
283
270
|
var _a;
|
284
|
-
return (_a = this.
|
271
|
+
return (_a = this._internalState.lastMessage) !== null && _a !== void 0 ? _a : undefined;
|
285
272
|
}
|
286
273
|
/**
|
287
274
|
* User notification level for this conversation.
|
288
275
|
*/
|
289
276
|
get notificationLevel() {
|
290
277
|
var _a;
|
291
|
-
return (_a = this.
|
292
|
-
}
|
293
|
-
get bindings() {
|
294
|
-
return this.channelState.bindings;
|
295
|
-
}
|
296
|
-
get limits() {
|
297
|
-
return this.configuration.limits;
|
298
|
-
}
|
299
|
-
/**
|
300
|
-
* State of the conversation.
|
301
|
-
*/
|
302
|
-
get state() {
|
303
|
-
return this.channelState.state;
|
278
|
+
return (_a = this._internalState.notificationLevel) !== null && _a !== void 0 ? _a : "default";
|
304
279
|
}
|
305
280
|
/**
|
306
|
-
*
|
307
|
-
* This or _subscribeStreams will need to be called before any events on conversation will fire.
|
281
|
+
* Conversation bindings. Undocumented feature (for now).
|
308
282
|
* @internal
|
309
283
|
*/
|
310
|
-
|
311
|
-
|
312
|
-
return (this.entityPromise =
|
313
|
-
(_a = this.entityPromise) !== null && _a !== void 0 ? _a : this.services.syncClient
|
314
|
-
.document({ id: this.entityName, mode: "open_existing" })
|
315
|
-
.then((entity) => {
|
316
|
-
this.entity = entity;
|
317
|
-
this.entity.on("updated", (args) => {
|
318
|
-
this._update(args.data);
|
319
|
-
});
|
320
|
-
this.entity.on("removed", () => this.emit("removed", this));
|
321
|
-
this._update(this.entity.data);
|
322
|
-
return entity;
|
323
|
-
})
|
324
|
-
.catch((err) => {
|
325
|
-
this.entity = null;
|
326
|
-
this.entityPromise = null;
|
327
|
-
if (this.services.syncClient.connectionState != "disconnected") {
|
328
|
-
log.error("Failed to get conversation object", err);
|
329
|
-
}
|
330
|
-
log.debug("ERROR: Failed to get conversation object", err);
|
331
|
-
throw err;
|
332
|
-
}));
|
284
|
+
get bindings() {
|
285
|
+
return this._internalState.bindings;
|
333
286
|
}
|
334
287
|
/**
|
335
|
-
*
|
336
|
-
* This or _subscribe will need to be called before any events on the conversation will fire.
|
337
|
-
* This will need to be called before any events on participants or messages will fire
|
338
|
-
* @internal
|
288
|
+
* Current conversation limits.
|
339
289
|
*/
|
340
|
-
|
341
|
-
|
342
|
-
try {
|
343
|
-
await this._subscribe();
|
344
|
-
log.trace("_subscribeStreams, this.entity.data=", (_a = this.entity) === null || _a === void 0 ? void 0 : _a.data);
|
345
|
-
const messagesObjectName = ((_b = this.entity) === null || _b === void 0 ? void 0 : _b.data)
|
346
|
-
.messages;
|
347
|
-
const rosterObjectName = ((_c = this.entity) === null || _c === void 0 ? void 0 : _c.data)
|
348
|
-
.roster;
|
349
|
-
await Promise.all([
|
350
|
-
this.messagesEntity.subscribe(messagesObjectName),
|
351
|
-
this.participantsEntity.subscribe(rosterObjectName),
|
352
|
-
]);
|
353
|
-
}
|
354
|
-
catch (err) {
|
355
|
-
if (this.services.syncClient.connectionState !== "disconnected") {
|
356
|
-
log.error("Failed to subscribe on conversation objects", this.sid, err);
|
357
|
-
}
|
358
|
-
log.debug("ERROR: Failed to subscribe on conversation objects", this.sid, err);
|
359
|
-
throw err;
|
360
|
-
}
|
290
|
+
get limits() {
|
291
|
+
return this._configuration.limits;
|
361
292
|
}
|
362
293
|
/**
|
363
|
-
*
|
364
|
-
* @internal
|
294
|
+
* State of the conversation.
|
365
295
|
*/
|
366
|
-
|
367
|
-
|
368
|
-
await this.entity.close();
|
369
|
-
this.entity = null;
|
370
|
-
this.entityPromise = null;
|
371
|
-
}
|
372
|
-
return Promise.all([
|
373
|
-
this.participantsEntity.unsubscribe(),
|
374
|
-
this.messagesEntity.unsubscribe(),
|
375
|
-
]);
|
296
|
+
get state() {
|
297
|
+
return this._internalState.state;
|
376
298
|
}
|
377
299
|
/**
|
378
|
-
*
|
300
|
+
* Source of the conversation update.
|
379
301
|
* @internal
|
380
302
|
*/
|
381
|
-
|
382
|
-
this.
|
383
|
-
if (this.channelState.status === status) {
|
384
|
-
return;
|
385
|
-
}
|
386
|
-
this.channelState.status = status;
|
387
|
-
if (status === "joined") {
|
388
|
-
this._subscribeStreams().catch((err) => {
|
389
|
-
log.debug("ERROR while setting conversation status " + status, err);
|
390
|
-
if (this.services.syncClient.connectionState !== "disconnected") {
|
391
|
-
throw err;
|
392
|
-
}
|
393
|
-
});
|
394
|
-
}
|
395
|
-
else if (this.entityPromise) {
|
396
|
-
this._unsubscribe().catch((err) => {
|
397
|
-
log.debug("ERROR while setting conversation status " + status, err);
|
398
|
-
if (this.services.syncClient.connectionState !== "disconnected") {
|
399
|
-
throw err;
|
400
|
-
}
|
401
|
-
});
|
402
|
-
}
|
303
|
+
get _statusSource() {
|
304
|
+
return this._dataSource;
|
403
305
|
}
|
404
306
|
/**
|
405
|
-
*
|
406
|
-
* @
|
307
|
+
* Preprocess the update object.
|
308
|
+
* @param update The update object received from Sync.
|
309
|
+
* @param conversationSid The SID of the conversation in question.
|
407
310
|
*/
|
408
|
-
_statusSource() {
|
409
|
-
return this.statusSource;
|
410
|
-
}
|
411
311
|
static preprocessUpdate(update, conversationSid) {
|
412
312
|
try {
|
413
313
|
if (typeof update.attributes === "string") {
|
@@ -418,27 +318,23 @@ class Conversation extends replayEventEmitter.ReplayEventEmitter {
|
|
418
318
|
}
|
419
319
|
}
|
420
320
|
catch (e) {
|
421
|
-
|
321
|
+
Conversation._logger.warn("Retrieved malformed attributes from the server for conversation: " +
|
422
322
|
conversationSid);
|
423
323
|
update.attributes = {};
|
424
324
|
}
|
425
325
|
try {
|
426
|
-
|
427
|
-
update.dateCreated = new Date(update.dateCreated);
|
428
|
-
}
|
326
|
+
update.dateCreated && (update.dateCreated = new Date(update.dateCreated));
|
429
327
|
}
|
430
328
|
catch (e) {
|
431
|
-
|
329
|
+
Conversation._logger.warn("Retrieved malformed dateCreated from the server for conversation: " +
|
432
330
|
conversationSid);
|
433
331
|
delete update.dateCreated;
|
434
332
|
}
|
435
333
|
try {
|
436
|
-
|
437
|
-
update.dateUpdated = new Date(update.dateUpdated);
|
438
|
-
}
|
334
|
+
update.dateUpdated && (update.dateUpdated = new Date(update.dateUpdated));
|
439
335
|
}
|
440
336
|
catch (e) {
|
441
|
-
|
337
|
+
Conversation._logger.warn("Retrieved malformed dateUpdated from the server for conversation: " +
|
442
338
|
conversationSid);
|
443
339
|
delete update.dateUpdated;
|
444
340
|
}
|
@@ -448,158 +344,44 @@ class Conversation extends replayEventEmitter.ReplayEventEmitter {
|
|
448
344
|
}
|
449
345
|
}
|
450
346
|
catch (e) {
|
451
|
-
|
347
|
+
Conversation._logger.warn("Retrieved malformed lastMessage.timestamp from the server for conversation: " +
|
452
348
|
conversationSid);
|
453
349
|
delete update.lastMessage.timestamp;
|
454
350
|
}
|
455
351
|
}
|
456
|
-
/**
|
457
|
-
* Update the local conversation object with new values.
|
458
|
-
* @internal
|
459
|
-
*/
|
460
|
-
_update(update) {
|
461
|
-
var _a, _b, _c, _d, _e;
|
462
|
-
log.trace("_update", update);
|
463
|
-
Conversation.preprocessUpdate(update, this.sid);
|
464
|
-
const updateReasons = new Set();
|
465
|
-
for (const key of Object.keys(update)) {
|
466
|
-
const localKey = fieldMappings[key];
|
467
|
-
if (!localKey) {
|
468
|
-
continue;
|
469
|
-
}
|
470
|
-
switch (localKey) {
|
471
|
-
case fieldMappings.status:
|
472
|
-
if (!update.status ||
|
473
|
-
update.status === "unknown" ||
|
474
|
-
this.channelState.status === update.status) {
|
475
|
-
break;
|
476
|
-
}
|
477
|
-
this.channelState.status = update.status;
|
478
|
-
updateReasons.add(localKey);
|
479
|
-
break;
|
480
|
-
case fieldMappings.attributes:
|
481
|
-
if (isEqual__default['default'](this.channelState.attributes, update.attributes)) {
|
482
|
-
break;
|
483
|
-
}
|
484
|
-
this.channelState.attributes = update.attributes;
|
485
|
-
updateReasons.add(localKey);
|
486
|
-
break;
|
487
|
-
case fieldMappings.lastConsumedMessageIndex:
|
488
|
-
if (update.lastConsumedMessageIndex === undefined ||
|
489
|
-
update.lastConsumedMessageIndex ===
|
490
|
-
this.channelState.lastReadMessageIndex) {
|
491
|
-
break;
|
492
|
-
}
|
493
|
-
this.channelState.lastReadMessageIndex =
|
494
|
-
update.lastConsumedMessageIndex;
|
495
|
-
updateReasons.add("lastReadMessageIndex");
|
496
|
-
break;
|
497
|
-
case fieldMappings.lastMessage:
|
498
|
-
if (this.channelState.lastMessage && !update.lastMessage) {
|
499
|
-
delete this.channelState.lastMessage;
|
500
|
-
updateReasons.add(localKey);
|
501
|
-
break;
|
502
|
-
}
|
503
|
-
this.channelState.lastMessage = this.channelState.lastMessage || {};
|
504
|
-
if (((_a = update.lastMessage) === null || _a === void 0 ? void 0 : _a.index) !== undefined &&
|
505
|
-
update.lastMessage.index !== this.channelState.lastMessage.index) {
|
506
|
-
this.channelState.lastMessage.index = update.lastMessage.index;
|
507
|
-
updateReasons.add(localKey);
|
508
|
-
}
|
509
|
-
if (((_b = update.lastMessage) === null || _b === void 0 ? void 0 : _b.timestamp) !== undefined &&
|
510
|
-
((_d = (_c = this.channelState.lastMessage) === null || _c === void 0 ? void 0 : _c.dateCreated) === null || _d === void 0 ? void 0 : _d.getTime()) !==
|
511
|
-
update.lastMessage.timestamp.getTime()) {
|
512
|
-
this.channelState.lastMessage.dateCreated =
|
513
|
-
update.lastMessage.timestamp;
|
514
|
-
updateReasons.add(localKey);
|
515
|
-
}
|
516
|
-
if (isEqual__default['default'](this.channelState.lastMessage, {})) {
|
517
|
-
delete this.channelState.lastMessage;
|
518
|
-
}
|
519
|
-
break;
|
520
|
-
case fieldMappings.state:
|
521
|
-
const state = update.state || undefined;
|
522
|
-
if (state !== undefined) {
|
523
|
-
state.dateUpdated = new Date(state.dateUpdated);
|
524
|
-
}
|
525
|
-
if (isEqual__default['default'](this.channelState.state, state)) {
|
526
|
-
break;
|
527
|
-
}
|
528
|
-
this.channelState.state = state;
|
529
|
-
updateReasons.add(localKey);
|
530
|
-
break;
|
531
|
-
case fieldMappings.bindings:
|
532
|
-
if (isEqual__default['default'](this.channelState.bindings, update.bindings)) {
|
533
|
-
break;
|
534
|
-
}
|
535
|
-
this.channelState.bindings = update.bindings;
|
536
|
-
updateReasons.add(localKey);
|
537
|
-
break;
|
538
|
-
default:
|
539
|
-
const isDate = update[key] instanceof Date;
|
540
|
-
const keysMatchAsDates = isDate &&
|
541
|
-
((_e = this.channelState[localKey]) === null || _e === void 0 ? void 0 : _e.getTime()) === update[key].getTime();
|
542
|
-
const keysMatchAsNonDates = !isDate && this[localKey] === update[key];
|
543
|
-
if (keysMatchAsDates || keysMatchAsNonDates) {
|
544
|
-
break;
|
545
|
-
}
|
546
|
-
this.channelState[localKey] = update[key];
|
547
|
-
updateReasons.add(localKey);
|
548
|
-
}
|
549
|
-
}
|
550
|
-
if (updateReasons.size > 0) {
|
551
|
-
this.emit("updated", {
|
552
|
-
conversation: this,
|
553
|
-
updateReasons: [...updateReasons],
|
554
|
-
});
|
555
|
-
}
|
556
|
-
}
|
557
|
-
/**
|
558
|
-
* @internal
|
559
|
-
*/
|
560
|
-
_onMessageAdded(message) {
|
561
|
-
for (const participant of this.participants.values()) {
|
562
|
-
if (participant.identity === message.author) {
|
563
|
-
participant._endTyping();
|
564
|
-
break;
|
565
|
-
}
|
566
|
-
}
|
567
|
-
this.emit("messageAdded", message);
|
568
|
-
}
|
569
|
-
async _setLastReadMessageIndex(index) {
|
570
|
-
const result = await this.services.commandExecutor.mutateResource("post", `${this.configuration.links.myConversations}/${this.sid}`, {
|
571
|
-
last_read_message_index: index,
|
572
|
-
});
|
573
|
-
return result.unread_messages_count;
|
574
|
-
}
|
575
352
|
/**
|
576
353
|
* Add a participant to the conversation by its identity.
|
577
354
|
* @param identity Identity of the Client to add.
|
578
355
|
* @param attributes Attributes to be attached to the participant.
|
356
|
+
* @returns The added participant.
|
579
357
|
*/
|
580
358
|
async add(identity, attributes) {
|
581
|
-
return this.
|
359
|
+
return this._participantsEntity.add(identity, attributes !== null && attributes !== void 0 ? attributes : {});
|
582
360
|
}
|
583
361
|
/**
|
584
362
|
* Add a non-chat participant to the conversation.
|
585
363
|
* @param proxyAddress Proxy (Twilio) address of the participant.
|
586
364
|
* @param address User address of the participant.
|
587
365
|
* @param attributes Attributes to be attached to the participant.
|
588
|
-
* @param bindingOptions Options for adding email participants - name and
|
366
|
+
* @param bindingOptions Options for adding email participants - name and
|
367
|
+
* CC/To level.
|
368
|
+
* @returns The added participant.
|
589
369
|
*/
|
590
370
|
async addNonChatParticipant(proxyAddress, address, attributes = {}, bindingOptions = {}) {
|
591
|
-
return this.
|
371
|
+
return this._participantsEntity.addNonChatParticipant(proxyAddress, address, attributes !== null && attributes !== void 0 ? attributes : {}, bindingOptions !== null && bindingOptions !== void 0 ? bindingOptions : {});
|
592
372
|
}
|
593
373
|
/**
|
594
|
-
* Advance the conversation's last read message index to the current read
|
595
|
-
* Rejects if the user is not a participant of the conversation.
|
596
|
-
*
|
374
|
+
* Advance the conversation's last read message index to the current read
|
375
|
+
* horizon. Rejects if the user is not a participant of the conversation. Last
|
376
|
+
* read message index is updated only if the new index value is higher than
|
377
|
+
* the previous.
|
597
378
|
* @param index Message index to advance to.
|
598
379
|
* @return Resulting unread messages count in the conversation.
|
599
380
|
*/
|
600
381
|
async advanceLastReadMessageIndex(index) {
|
382
|
+
var _a;
|
601
383
|
await this._subscribeStreams();
|
602
|
-
if (index < (this.lastReadMessageIndex
|
384
|
+
if (index < ((_a = this.lastReadMessageIndex) !== null && _a !== void 0 ? _a : 0)) {
|
603
385
|
return await this._setLastReadMessageIndex(this.lastReadMessageIndex);
|
604
386
|
}
|
605
387
|
return await this._setLastReadMessageIndex(index);
|
@@ -608,7 +390,7 @@ class Conversation extends replayEventEmitter.ReplayEventEmitter {
|
|
608
390
|
* Delete the conversation and unsubscribe from its events.
|
609
391
|
*/
|
610
392
|
async delete() {
|
611
|
-
await this.
|
393
|
+
await this._services.commandExecutor.mutateResource("delete", this._links.self);
|
612
394
|
return this;
|
613
395
|
}
|
614
396
|
/**
|
@@ -620,39 +402,43 @@ class Conversation extends replayEventEmitter.ReplayEventEmitter {
|
|
620
402
|
}
|
621
403
|
/**
|
622
404
|
* Returns messages from the conversation using the paginator interface.
|
623
|
-
* @param pageSize Number of messages to return in a single chunk. Default is
|
624
|
-
*
|
625
|
-
* @param
|
626
|
-
*
|
405
|
+
* @param pageSize Number of messages to return in a single chunk. Default is
|
406
|
+
* 30.
|
407
|
+
* @param anchor Index of the newest message to fetch. Default is from the
|
408
|
+
* end.
|
409
|
+
* @param direction Query direction. By default, it queries backwards
|
410
|
+
* from newer to older. The `"forward"` value will query in the opposite
|
411
|
+
* direction.
|
627
412
|
* @return A page of messages.
|
628
413
|
*/
|
629
414
|
async getMessages(pageSize, anchor, direction) {
|
630
415
|
await this._subscribeStreams();
|
631
|
-
return this.
|
416
|
+
return this._messagesEntity.getMessages(pageSize, anchor, direction);
|
632
417
|
}
|
633
418
|
/**
|
634
419
|
* Get a list of all the participants who are joined to this conversation.
|
635
420
|
*/
|
636
421
|
async getParticipants() {
|
637
422
|
await this._subscribeStreams();
|
638
|
-
return this.
|
423
|
+
return this._participantsEntity.getParticipants();
|
639
424
|
}
|
640
425
|
/**
|
641
426
|
* Get conversation participants count.
|
642
427
|
*
|
643
|
-
* This method is semi-realtime. This means that this data will be eventually
|
644
|
-
* but will also be possibly incorrect for a few seconds. The
|
645
|
-
* provide real time events for counter values
|
428
|
+
* This method is semi-realtime. This means that this data will be eventually
|
429
|
+
* correct, but will also be possibly incorrect for a few seconds. The
|
430
|
+
* Conversations system does not provide real time events for counter values
|
431
|
+
* changes.
|
646
432
|
*
|
647
|
-
* This is useful for any UI badges, but it is not recommended to build any
|
648
|
-
* logic based on these counters being accurate in real time.
|
433
|
+
* This is useful for any UI badges, but it is not recommended to build any
|
434
|
+
* core application logic based on these counters being accurate in real time.
|
649
435
|
*/
|
650
436
|
async getParticipantsCount() {
|
651
437
|
var _a;
|
652
|
-
const url = new index.UriBuilder(this.
|
438
|
+
const url = new index.UriBuilder(this._configuration.links.conversations)
|
653
439
|
.path(this.sid)
|
654
440
|
.build();
|
655
|
-
const response = await this.
|
441
|
+
const response = await this._services.network.get(url);
|
656
442
|
return (_a = response.body.participants_count) !== null && _a !== void 0 ? _a : 0;
|
657
443
|
}
|
658
444
|
/**
|
@@ -660,53 +446,55 @@ class Conversation extends replayEventEmitter.ReplayEventEmitter {
|
|
660
446
|
* @param participantSid Participant SID.
|
661
447
|
*/
|
662
448
|
async getParticipantBySid(participantSid) {
|
663
|
-
return this.
|
449
|
+
return this._participantsEntity.getParticipantBySid(participantSid);
|
664
450
|
}
|
665
451
|
/**
|
666
452
|
* Get a participant by its identity.
|
667
453
|
* @param identity Participant identity.
|
668
454
|
*/
|
669
455
|
async getParticipantByIdentity(identity = "") {
|
670
|
-
return this.
|
456
|
+
return this._participantsEntity.getParticipantByIdentity(identity !== null && identity !== void 0 ? identity : "");
|
671
457
|
}
|
672
458
|
/**
|
673
459
|
* Get the total message count in the conversation.
|
674
460
|
*
|
675
|
-
* This method is semi-realtime. This means that this data will be eventually
|
676
|
-
* but will also be possibly incorrect for a few seconds. The
|
677
|
-
* provide real time events for counter values
|
461
|
+
* This method is semi-realtime. This means that this data will be eventually
|
462
|
+
* correct, but will also be possibly incorrect for a few seconds. The
|
463
|
+
* Conversations system does not provide real time events for counter values
|
464
|
+
* changes.
|
678
465
|
*
|
679
|
-
* This is useful for any UI badges, but it is not recommended to build any
|
680
|
-
* logic based on these counters being accurate in real time.
|
466
|
+
* This is useful for any UI badges, but it is not recommended to build any
|
467
|
+
* core application logic based on these counters being accurate in real time.
|
681
468
|
*/
|
682
469
|
async getMessagesCount() {
|
683
470
|
var _a;
|
684
|
-
const url = new index.UriBuilder(this.
|
471
|
+
const url = new index.UriBuilder(this._configuration.links.conversations)
|
685
472
|
.path(this.sid)
|
686
473
|
.build();
|
687
|
-
const response = await this.
|
474
|
+
const response = await this._services.network.get(url);
|
688
475
|
return (_a = response.body.messages_count) !== null && _a !== void 0 ? _a : 0;
|
689
476
|
}
|
690
477
|
/**
|
691
|
-
* Get unread messages count for the user if they are a participant of this
|
692
|
-
* Rejects if the user is not a participant of the conversation.
|
478
|
+
* Get unread messages count for the user if they are a participant of this
|
479
|
+
* conversation. Rejects if the user is not a participant of the conversation.
|
693
480
|
*
|
694
481
|
* Use this method to obtain the number of unread messages together with
|
695
482
|
* {@link Conversation.updateLastReadMessageIndex} instead of relying on the
|
696
483
|
* message indices which may have gaps. See {@link Message.index} for details.
|
697
484
|
*
|
698
|
-
* This method is semi-realtime. This means that this data will be eventually
|
699
|
-
* but will also be possibly incorrect for a few seconds. The
|
700
|
-
* provide real time events for counter values
|
485
|
+
* This method is semi-realtime. This means that this data will be eventually
|
486
|
+
* correct, but will also be possibly incorrect for a few seconds. The
|
487
|
+
* Conversations system does not provide real time events for counter values
|
488
|
+
* changes.
|
701
489
|
*
|
702
|
-
* This is useful for any UI badges, but it is not recommended to build any
|
703
|
-
* logic based on these counters being accurate in real time.
|
490
|
+
* This is useful for any UI badges, but it is not recommended to build any
|
491
|
+
* core application logic based on these counters being accurate in real time.
|
704
492
|
*/
|
705
493
|
async getUnreadMessagesCount() {
|
706
|
-
const url = new index.UriBuilder(this.
|
494
|
+
const url = new index.UriBuilder(this._configuration.links.myConversations)
|
707
495
|
.path(this.sid)
|
708
496
|
.build();
|
709
|
-
const response = await this.
|
497
|
+
const response = await this._services.network.get(url);
|
710
498
|
if (response.body.conversation_sid !== this.sid) {
|
711
499
|
throw new Error("Conversation was not found in the user conversations list");
|
712
500
|
}
|
@@ -720,8 +508,8 @@ class Conversation extends replayEventEmitter.ReplayEventEmitter {
|
|
720
508
|
* Join the conversation and subscribe to its events.
|
721
509
|
*/
|
722
510
|
async join() {
|
723
|
-
await this.
|
724
|
-
identity: this.
|
511
|
+
await this._services.commandExecutor.mutateResource("post", this._links.participants, {
|
512
|
+
identity: this._configuration.userIdentity,
|
725
513
|
});
|
726
514
|
return this;
|
727
515
|
}
|
@@ -729,8 +517,8 @@ class Conversation extends replayEventEmitter.ReplayEventEmitter {
|
|
729
517
|
* Leave the conversation.
|
730
518
|
*/
|
731
519
|
async leave() {
|
732
|
-
if (this.
|
733
|
-
await this.
|
520
|
+
if (this._internalState.status === "joined") {
|
521
|
+
await this._services.commandExecutor.mutateResource("delete", `${this._links.participants}/${this._configuration.userIdentity}`);
|
734
522
|
}
|
735
523
|
return this;
|
736
524
|
}
|
@@ -742,12 +530,13 @@ class Conversation extends replayEventEmitter.ReplayEventEmitter {
|
|
742
530
|
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
743
531
|
// @ts-ignore TODO: fix validateTypesAsync typing
|
744
532
|
async removeParticipant(participant) {
|
745
|
-
await this.
|
533
|
+
await this._participantsEntity.remove(typeof participant === "string" ? participant : participant.sid);
|
746
534
|
}
|
747
535
|
/**
|
748
536
|
* Send a message to the conversation.
|
749
537
|
* @param message Message body for the text message,
|
750
|
-
* `FormData` or {@link SendMediaOptions} for media content. Sending FormData
|
538
|
+
* `FormData` or {@link SendMediaOptions} for media content. Sending FormData
|
539
|
+
* is supported only with the browser engine.
|
751
540
|
* @param messageAttributes Attributes for the message.
|
752
541
|
* @param emailOptions Email options for the message.
|
753
542
|
* @return Index of the new message.
|
@@ -755,22 +544,23 @@ class Conversation extends replayEventEmitter.ReplayEventEmitter {
|
|
755
544
|
async sendMessage(message, messageAttributes, emailOptions) {
|
756
545
|
var _a, _b;
|
757
546
|
if (typeof message === "string" || message === null) {
|
758
|
-
const response = await this.
|
547
|
+
const response = await this._messagesEntity.send(message, messageAttributes, emailOptions);
|
759
548
|
return (_a = index.parseToNumber(response.index)) !== null && _a !== void 0 ? _a : 0;
|
760
549
|
}
|
761
|
-
const response = await this.
|
550
|
+
const response = await this._messagesEntity.sendMedia(message, messageAttributes, emailOptions);
|
762
551
|
return (_b = index.parseToNumber(response.index)) !== null && _b !== void 0 ? _b : 0;
|
763
552
|
}
|
764
553
|
/**
|
765
554
|
* New interface to prepare for sending a message.
|
766
|
-
* Use instead of
|
555
|
+
* Use this instead of {@link Message.sendMessage}.
|
767
556
|
* @return A MessageBuilder to help set all message sending options.
|
768
557
|
*/
|
769
558
|
prepareMessage() {
|
770
|
-
return new messageBuilder.MessageBuilder(this.limits, this.
|
559
|
+
return new messageBuilder.MessageBuilder(this.limits, this._messagesEntity);
|
771
560
|
}
|
772
561
|
/**
|
773
|
-
* Set last read message index of the conversation to the index of the last
|
562
|
+
* Set last read message index of the conversation to the index of the last
|
563
|
+
* known message.
|
774
564
|
* @return Resulting unread messages count in the conversation.
|
775
565
|
*/
|
776
566
|
async setAllMessagesRead() {
|
@@ -779,7 +569,7 @@ class Conversation extends replayEventEmitter.ReplayEventEmitter {
|
|
779
569
|
if (messagesPage.items.length > 0) {
|
780
570
|
return this.advanceLastReadMessageIndex(messagesPage.items[0].index);
|
781
571
|
}
|
782
|
-
return
|
572
|
+
return 0;
|
783
573
|
}
|
784
574
|
/**
|
785
575
|
* Set all messages in the conversation unread.
|
@@ -794,23 +584,25 @@ class Conversation extends replayEventEmitter.ReplayEventEmitter {
|
|
794
584
|
* @param notificationLevel New user notification level.
|
795
585
|
*/
|
796
586
|
async setUserNotificationLevel(notificationLevel) {
|
797
|
-
await this.
|
587
|
+
await this._services.commandExecutor.mutateResource("post", `${this._configuration.links.myConversations}/${this.sid}`, {
|
798
588
|
notification_level: notificationLevel,
|
799
589
|
});
|
800
590
|
}
|
801
591
|
/**
|
802
|
-
* Send a notification to the server indicating that this client is currently
|
803
|
-
* Typing ended notification is sent after a
|
592
|
+
* Send a notification to the server indicating that this client is currently
|
593
|
+
* typing in this conversation. Typing ended notification is sent after a
|
594
|
+
* while automatically, but by calling this method again you ensure that
|
595
|
+
* typing ended is not received.
|
804
596
|
*/
|
805
597
|
typing() {
|
806
|
-
return this.
|
598
|
+
return this._services.typingIndicator.send(this.sid);
|
807
599
|
}
|
808
600
|
/**
|
809
601
|
* Update the attributes of the conversation.
|
810
602
|
* @param attributes New attributes.
|
811
603
|
*/
|
812
604
|
async updateAttributes(attributes) {
|
813
|
-
await this.
|
605
|
+
await this._services.commandExecutor.mutateResource("post", this._links.self, {
|
814
606
|
attributes: attributes !== undefined ? JSON.stringify(attributes) : undefined,
|
815
607
|
});
|
816
608
|
return this;
|
@@ -820,15 +612,15 @@ class Conversation extends replayEventEmitter.ReplayEventEmitter {
|
|
820
612
|
* @param friendlyName New friendly name.
|
821
613
|
*/
|
822
614
|
async updateFriendlyName(friendlyName) {
|
823
|
-
if (this.
|
824
|
-
await this.
|
615
|
+
if (this._internalState.friendlyName !== friendlyName) {
|
616
|
+
await this._services.commandExecutor.mutateResource("post", this._links.self, { friendly_name: friendlyName });
|
825
617
|
}
|
826
618
|
return this;
|
827
619
|
}
|
828
620
|
/**
|
829
621
|
* Set the last read message index to the current read horizon.
|
830
|
-
* @param index Message index to set as last read.
|
831
|
-
*
|
622
|
+
* @param index Message index to set as last read. If null is provided, then
|
623
|
+
* the behavior is identical to {@link Conversation.setAllMessagesUnread}.
|
832
624
|
* @returns Resulting unread messages count in the conversation.
|
833
625
|
*/
|
834
626
|
async updateLastReadMessageIndex(index) {
|
@@ -837,25 +629,251 @@ class Conversation extends replayEventEmitter.ReplayEventEmitter {
|
|
837
629
|
}
|
838
630
|
/**
|
839
631
|
* Update the unique name of the conversation.
|
840
|
-
* @param uniqueName New unique name for the conversation. Setting unique name
|
632
|
+
* @param uniqueName New unique name for the conversation. Setting unique name
|
633
|
+
* to null removes it.
|
841
634
|
*/
|
842
635
|
async updateUniqueName(uniqueName) {
|
843
|
-
if (this.
|
844
|
-
|
845
|
-
|
846
|
-
}
|
847
|
-
await this.services.commandExecutor.mutateResource("post", this.links.self, {
|
636
|
+
if (this._internalState.uniqueName !== uniqueName) {
|
637
|
+
uniqueName || (uniqueName = "");
|
638
|
+
await this._services.commandExecutor.mutateResource("post", this._links.self, {
|
848
639
|
unique_name: uniqueName,
|
849
640
|
});
|
850
641
|
}
|
851
642
|
return this;
|
852
643
|
}
|
644
|
+
/**
|
645
|
+
* Load and subscribe to this conversation and do not subscribe to its
|
646
|
+
* participants and messages. This or _subscribeStreams will need to be called
|
647
|
+
* before any events on conversation will fire.
|
648
|
+
* @internal
|
649
|
+
*/
|
650
|
+
async _subscribe() {
|
651
|
+
if (this._entityPromise) {
|
652
|
+
return this._entityPromise;
|
653
|
+
}
|
654
|
+
this._entityPromise = this._services.syncClient.document({
|
655
|
+
id: this._entityName,
|
656
|
+
mode: "open_existing",
|
657
|
+
});
|
658
|
+
try {
|
659
|
+
this._entity = await this._entityPromise;
|
660
|
+
this._entity.on("updated", (args) => this._update(args.data));
|
661
|
+
this._entity.on("removed", () => this.emit("removed", this));
|
662
|
+
this._update(this._entity.data);
|
663
|
+
return this._entity;
|
664
|
+
}
|
665
|
+
catch (err) {
|
666
|
+
this._entity = null;
|
667
|
+
this._entityPromise = null;
|
668
|
+
if (this._services.syncClient.connectionState != "disconnected") {
|
669
|
+
Conversation._logger.error("Failed to get conversation object", err);
|
670
|
+
}
|
671
|
+
Conversation._logger.debug("ERROR: Failed to get conversation object", err);
|
672
|
+
throw err;
|
673
|
+
}
|
674
|
+
}
|
675
|
+
/**
|
676
|
+
* Load the attributes of this conversation and instantiate its participants
|
677
|
+
* and messages. This or _subscribe will need to be called before any events
|
678
|
+
* on the conversation will fire. This will need to be called before any
|
679
|
+
* events on participants or messages will fire
|
680
|
+
* @internal
|
681
|
+
*/
|
682
|
+
async _subscribeStreams() {
|
683
|
+
var _a, _b;
|
684
|
+
try {
|
685
|
+
await this._subscribe();
|
686
|
+
Conversation._logger.trace("_subscribeStreams, this.entity.data=", (_a = this._entity) === null || _a === void 0 ? void 0 : _a.data);
|
687
|
+
const data = (_b = this._entity) === null || _b === void 0 ? void 0 : _b.data;
|
688
|
+
const messagesObjectName = data.messages;
|
689
|
+
const rosterObjectName = data.roster;
|
690
|
+
await Promise.all([
|
691
|
+
this._messagesEntity.subscribe(messagesObjectName),
|
692
|
+
this._participantsEntity.subscribe(rosterObjectName),
|
693
|
+
]);
|
694
|
+
}
|
695
|
+
catch (err) {
|
696
|
+
if (this._services.syncClient.connectionState !== "disconnected") {
|
697
|
+
Conversation._logger.error("Failed to subscribe on conversation objects", this.sid, err);
|
698
|
+
}
|
699
|
+
Conversation._logger.debug("ERROR: Failed to subscribe on conversation objects", this.sid, err);
|
700
|
+
throw err;
|
701
|
+
}
|
702
|
+
}
|
703
|
+
/**
|
704
|
+
* Stop listening for and firing events on this conversation.
|
705
|
+
* @internal
|
706
|
+
*/
|
707
|
+
async _unsubscribe() {
|
708
|
+
if (this._entity) {
|
709
|
+
await this._entity.close();
|
710
|
+
this._entity = null;
|
711
|
+
this._entityPromise = null;
|
712
|
+
}
|
713
|
+
return Promise.all([
|
714
|
+
this._participantsEntity.unsubscribe(),
|
715
|
+
this._messagesEntity.unsubscribe(),
|
716
|
+
]);
|
717
|
+
}
|
718
|
+
/**
|
719
|
+
* Set conversation status.
|
720
|
+
* @internal
|
721
|
+
*/
|
722
|
+
_setStatus(status, source) {
|
723
|
+
this._dataSource = source;
|
724
|
+
if (this._internalState.status === status) {
|
725
|
+
return;
|
726
|
+
}
|
727
|
+
this._internalState.status = status;
|
728
|
+
if (status === "joined") {
|
729
|
+
this._subscribeStreams().catch((err) => {
|
730
|
+
Conversation._logger.debug("ERROR while setting conversation status " + status, err);
|
731
|
+
if (this._services.syncClient.connectionState !== "disconnected") {
|
732
|
+
throw err;
|
733
|
+
}
|
734
|
+
});
|
735
|
+
return;
|
736
|
+
}
|
737
|
+
if (this._entityPromise) {
|
738
|
+
this._unsubscribe().catch((err) => {
|
739
|
+
Conversation._logger.debug("ERROR while setting conversation status " + status, err);
|
740
|
+
if (this._services.syncClient.connectionState !== "disconnected") {
|
741
|
+
throw err;
|
742
|
+
}
|
743
|
+
});
|
744
|
+
}
|
745
|
+
}
|
746
|
+
/**
|
747
|
+
* Update the local conversation object with new values.
|
748
|
+
* @internal
|
749
|
+
*/
|
750
|
+
_update(update) {
|
751
|
+
var _a, _b, _c, _d, _e;
|
752
|
+
Conversation._logger.trace("_update", update);
|
753
|
+
Conversation.preprocessUpdate(update, this.sid);
|
754
|
+
const updateReasons = new Set();
|
755
|
+
for (const key of Object.keys(update)) {
|
756
|
+
const localKey = fieldMappings[key];
|
757
|
+
if (!localKey) {
|
758
|
+
continue;
|
759
|
+
}
|
760
|
+
switch (localKey) {
|
761
|
+
case fieldMappings.status:
|
762
|
+
if (!update.status ||
|
763
|
+
update.status === "unknown" ||
|
764
|
+
this._internalState.status === update.status) {
|
765
|
+
break;
|
766
|
+
}
|
767
|
+
this._internalState.status = update.status;
|
768
|
+
updateReasons.add(localKey);
|
769
|
+
break;
|
770
|
+
case fieldMappings.attributes:
|
771
|
+
if (isEqual__default['default'](this._internalState.attributes, update.attributes)) {
|
772
|
+
break;
|
773
|
+
}
|
774
|
+
this._internalState.attributes = update.attributes;
|
775
|
+
updateReasons.add(localKey);
|
776
|
+
break;
|
777
|
+
case fieldMappings.lastConsumedMessageIndex:
|
778
|
+
if (update.lastConsumedMessageIndex === undefined ||
|
779
|
+
update.lastConsumedMessageIndex ===
|
780
|
+
this._internalState.lastReadMessageIndex) {
|
781
|
+
break;
|
782
|
+
}
|
783
|
+
this._internalState.lastReadMessageIndex =
|
784
|
+
update.lastConsumedMessageIndex;
|
785
|
+
updateReasons.add("lastReadMessageIndex");
|
786
|
+
break;
|
787
|
+
case fieldMappings.lastMessage:
|
788
|
+
if (this._internalState.lastMessage && !update.lastMessage) {
|
789
|
+
delete this._internalState.lastMessage;
|
790
|
+
updateReasons.add(localKey);
|
791
|
+
break;
|
792
|
+
}
|
793
|
+
this._internalState.lastMessage =
|
794
|
+
this._internalState.lastMessage || {};
|
795
|
+
if (((_a = update.lastMessage) === null || _a === void 0 ? void 0 : _a.index) !== undefined &&
|
796
|
+
update.lastMessage.index !== this._internalState.lastMessage.index) {
|
797
|
+
this._internalState.lastMessage.index = update.lastMessage.index;
|
798
|
+
updateReasons.add(localKey);
|
799
|
+
}
|
800
|
+
if (((_b = update.lastMessage) === null || _b === void 0 ? void 0 : _b.timestamp) !== undefined &&
|
801
|
+
((_d = (_c = this._internalState.lastMessage) === null || _c === void 0 ? void 0 : _c.dateCreated) === null || _d === void 0 ? void 0 : _d.getTime()) !==
|
802
|
+
update.lastMessage.timestamp.getTime()) {
|
803
|
+
this._internalState.lastMessage.dateCreated =
|
804
|
+
update.lastMessage.timestamp;
|
805
|
+
updateReasons.add(localKey);
|
806
|
+
}
|
807
|
+
if (isEqual__default['default'](this._internalState.lastMessage, {})) {
|
808
|
+
delete this._internalState.lastMessage;
|
809
|
+
}
|
810
|
+
break;
|
811
|
+
case fieldMappings.state:
|
812
|
+
const state = update.state || undefined;
|
813
|
+
if (state !== undefined) {
|
814
|
+
state.dateUpdated = new Date(state.dateUpdated);
|
815
|
+
}
|
816
|
+
if (isEqual__default['default'](this._internalState.state, state)) {
|
817
|
+
break;
|
818
|
+
}
|
819
|
+
this._internalState.state = state;
|
820
|
+
updateReasons.add(localKey);
|
821
|
+
break;
|
822
|
+
case fieldMappings.bindings:
|
823
|
+
if (isEqual__default['default'](this._internalState.bindings, update.bindings)) {
|
824
|
+
break;
|
825
|
+
}
|
826
|
+
this._internalState.bindings = update.bindings;
|
827
|
+
updateReasons.add(localKey);
|
828
|
+
break;
|
829
|
+
default:
|
830
|
+
const isDate = update[key] instanceof Date;
|
831
|
+
const keysMatchAsDates = isDate &&
|
832
|
+
((_e = this._internalState[localKey]) === null || _e === void 0 ? void 0 : _e.getTime()) === update[key].getTime();
|
833
|
+
const keysMatchAsNonDates = !isDate && this[localKey] === update[key];
|
834
|
+
if (keysMatchAsDates || keysMatchAsNonDates) {
|
835
|
+
break;
|
836
|
+
}
|
837
|
+
this._internalState[localKey] = update[key];
|
838
|
+
updateReasons.add(localKey);
|
839
|
+
}
|
840
|
+
}
|
841
|
+
if (updateReasons.size > 0) {
|
842
|
+
this.emit("updated", {
|
843
|
+
conversation: this,
|
844
|
+
updateReasons: [...updateReasons],
|
845
|
+
});
|
846
|
+
}
|
847
|
+
}
|
848
|
+
/**
|
849
|
+
* Handle onMessageAdded event.
|
850
|
+
*/
|
851
|
+
_onMessageAdded(message) {
|
852
|
+
for (const participant of this._participants.values()) {
|
853
|
+
if (participant.identity === message.author) {
|
854
|
+
participant._endTyping();
|
855
|
+
break;
|
856
|
+
}
|
857
|
+
}
|
858
|
+
this.emit("messageAdded", message);
|
859
|
+
}
|
860
|
+
/**
|
861
|
+
* Set last read message index.
|
862
|
+
* @param index New index to set.
|
863
|
+
*/
|
864
|
+
async _setLastReadMessageIndex(index) {
|
865
|
+
const result = await this._services.commandExecutor.mutateResource("post", `${this._configuration.links.myConversations}/${this.sid}`, {
|
866
|
+
last_read_message_index: index,
|
867
|
+
});
|
868
|
+
return result.unread_messages_count;
|
869
|
+
}
|
853
870
|
}
|
854
871
|
/**
|
855
872
|
* Fired when a participant has joined the conversation.
|
856
873
|
*
|
857
874
|
* Parameters:
|
858
|
-
* 1. {@link Participant} `participant` - participant that joined the
|
875
|
+
* 1. {@link Participant} `participant` - participant that joined the
|
876
|
+
* conversation
|
859
877
|
* @event
|
860
878
|
*/
|
861
879
|
Conversation.participantJoined = "participantJoined";
|
@@ -863,7 +881,8 @@ Conversation.participantJoined = "participantJoined";
|
|
863
881
|
* Fired when a participant has left the conversation.
|
864
882
|
*
|
865
883
|
* Parameters:
|
866
|
-
* 1. {@link Participant} `participant` - participant that left the
|
884
|
+
* 1. {@link Participant} `participant` - participant that left the
|
885
|
+
* conversation
|
867
886
|
* @event
|
868
887
|
*/
|
869
888
|
Conversation.participantLeft = "participantLeft";
|
@@ -871,9 +890,12 @@ Conversation.participantLeft = "participantLeft";
|
|
871
890
|
* Fired when data of a participant has been updated.
|
872
891
|
*
|
873
892
|
* Parameters:
|
874
|
-
* 1. object `data` - info object provided with the event. It has the
|
875
|
-
*
|
876
|
-
* * {@link
|
893
|
+
* 1. object `data` - info object provided with the event. It has the
|
894
|
+
* following properties:
|
895
|
+
* * {@link Participant} `participant` - participant that has received the
|
896
|
+
* update
|
897
|
+
* * {@link ParticipantUpdateReason}[] `updateReasons` - array of reasons
|
898
|
+
* for the update
|
877
899
|
* @event
|
878
900
|
*/
|
879
901
|
Conversation.participantUpdated = "participantUpdated";
|
@@ -897,9 +919,11 @@ Conversation.messageRemoved = "messageRemoved";
|
|
897
919
|
* Fired when data of a message has been updated.
|
898
920
|
*
|
899
921
|
* Parameters:
|
900
|
-
* 1. object `data` - info object provided with the event. It has the
|
922
|
+
* 1. object `data` - info object provided with the event. It has the
|
923
|
+
* following properties:
|
901
924
|
* * {@link Message} `message` - message that has received the update
|
902
|
-
* * {@link MessageUpdateReason}[] `updateReasons` - array of reasons for
|
925
|
+
* * {@link MessageUpdateReason}[] `updateReasons` - array of reasons for
|
926
|
+
* the update
|
903
927
|
* @event
|
904
928
|
*/
|
905
929
|
Conversation.messageUpdated = "messageUpdated";
|
@@ -907,7 +931,8 @@ Conversation.messageUpdated = "messageUpdated";
|
|
907
931
|
* Fired when a participant has stopped typing.
|
908
932
|
*
|
909
933
|
* Parameters:
|
910
|
-
* 1. {@link Participant} `participant` - the participant that has stopped
|
934
|
+
* 1. {@link Participant} `participant` - the participant that has stopped
|
935
|
+
* typing
|
911
936
|
* @event
|
912
937
|
*/
|
913
938
|
Conversation.typingEnded = "typingEnded";
|
@@ -915,7 +940,8 @@ Conversation.typingEnded = "typingEnded";
|
|
915
940
|
* Fired when a participant has started typing.
|
916
941
|
*
|
917
942
|
* Parameters:
|
918
|
-
* 1. {@link Participant} `participant` - the participant that has started
|
943
|
+
* 1. {@link Participant} `participant` - the participant that has started
|
944
|
+
* typing
|
919
945
|
* @event
|
920
946
|
*/
|
921
947
|
Conversation.typingStarted = "typingStarted";
|
@@ -923,20 +949,28 @@ Conversation.typingStarted = "typingStarted";
|
|
923
949
|
* Fired when the data of the conversation has been updated.
|
924
950
|
*
|
925
951
|
* Parameters:
|
926
|
-
* 1. object `data` - info object provided with the event. It has the
|
927
|
-
*
|
928
|
-
* * {@link
|
952
|
+
* 1. object `data` - info object provided with the event. It has the
|
953
|
+
* following properties:
|
954
|
+
* * {@link Conversation} `conversation` - conversation that has received
|
955
|
+
* the update
|
956
|
+
* * {@link ConversationUpdateReason}[] `updateReasons` - array of reasons
|
957
|
+
* for the update
|
929
958
|
* @event
|
930
959
|
*/
|
931
960
|
Conversation.updated = "updated";
|
932
961
|
/**
|
933
|
-
* Fired when the conversation was destroyed or the currently-logged-in user
|
962
|
+
* Fired when the conversation was destroyed or the currently-logged-in user
|
963
|
+
* has left private conversation.
|
934
964
|
*
|
935
965
|
* Parameters:
|
936
966
|
* 1. {@link Conversation} `conversation` - conversation that has been removed
|
937
967
|
* @event
|
938
968
|
*/
|
939
969
|
Conversation.removed = "removed";
|
970
|
+
/**
|
971
|
+
* Logger instance.
|
972
|
+
*/
|
973
|
+
Conversation._logger = logger.Logger.scope("Conversation");
|
940
974
|
tslib_es6.__decorate([
|
941
975
|
declarativeTypeValidator.validateTypesAsync(declarativeTypeValidator.nonEmptyString, attributes.optionalAttributesValidator),
|
942
976
|
tslib_es6.__metadata("design:type", Function),
|
@@ -982,9 +1016,10 @@ tslib_es6.__decorate([
|
|
982
1016
|
tslib_es6.__decorate([
|
983
1017
|
declarativeTypeValidator.validateTypesAsync([
|
984
1018
|
"string",
|
1019
|
+
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
1020
|
+
// @ts-ignore TODO: fix validateTypesAsync typing
|
1021
|
+
FormData,
|
985
1022
|
declarativeTypeValidator.literal(null),
|
986
|
-
// Wrapping it into a custom rule is necessary because the FormData class is not available on initialization.
|
987
|
-
declarativeTypeValidator.custom((value) => [value instanceof FormData, "an instance of FormData"]),
|
988
1023
|
declarativeTypeValidator.objectSchema("media options", {
|
989
1024
|
contentType: declarativeTypeValidator.nonEmptyString,
|
990
1025
|
media: declarativeTypeValidator.custom((value) => {
|
@@ -1024,7 +1059,7 @@ tslib_es6.__decorate([
|
|
1024
1059
|
tslib_es6.__metadata("design:returntype", Promise)
|
1025
1060
|
], Conversation.prototype, "updateAttributes", null);
|
1026
1061
|
tslib_es6.__decorate([
|
1027
|
-
declarativeTypeValidator.validateTypesAsync(
|
1062
|
+
declarativeTypeValidator.validateTypesAsync("string"),
|
1028
1063
|
tslib_es6.__metadata("design:type", Function),
|
1029
1064
|
tslib_es6.__metadata("design:paramtypes", [String]),
|
1030
1065
|
tslib_es6.__metadata("design:returntype", Promise)
|