stream-chat 9.5.0 → 9.6.0

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.
@@ -204,6 +204,7 @@ __export(index_exports, {
204
204
  MiddlewareExecutor: () => MiddlewareExecutor,
205
205
  MinPriority: () => MinPriority,
206
206
  Moderation: () => Moderation,
207
+ NotificationManager: () => NotificationManager,
207
208
  OfflineDBSyncManager: () => OfflineDBSyncManager,
208
209
  OfflineError: () => OfflineError,
209
210
  Permission: () => Permission,
@@ -4789,7 +4790,8 @@ var AttachmentManager = class {
4789
4790
  if (!attachment.localMetadata?.file || !attachment.localMetadata.id) {
4790
4791
  this.client.notifications.addError({
4791
4792
  message: "File is required for upload attachment",
4792
- origin: { emitter: "AttachmentManager", context: { attachment } }
4793
+ origin: { emitter: "AttachmentManager", context: { attachment } },
4794
+ options: { type: "validation:attachment:file:missing" }
4793
4795
  });
4794
4796
  return;
4795
4797
  }
@@ -4839,8 +4841,17 @@ var AttachmentManager = class {
4839
4841
  if (localAttachment.localMetadata.uploadState === "blocked") {
4840
4842
  this.upsertAttachments([localAttachment]);
4841
4843
  this.client.notifications.addError({
4842
- message: "Error uploading attachment",
4843
- origin: { emitter: "AttachmentManager", context: { attachment } }
4844
+ message: `The attachment upload was blocked`,
4845
+ origin: {
4846
+ emitter: "AttachmentManager",
4847
+ context: { attachment, blockedAttachment: localAttachment }
4848
+ },
4849
+ options: {
4850
+ type: "validation:attachment:upload:blocked",
4851
+ metadata: {
4852
+ reason: localAttachment.localMetadata.uploadPermissionCheck?.reason
4853
+ }
4854
+ }
4844
4855
  });
4845
4856
  return localAttachment;
4846
4857
  }
@@ -4857,19 +4868,7 @@ var AttachmentManager = class {
4857
4868
  try {
4858
4869
  response = await this.doUploadRequest(localAttachment.localMetadata.file);
4859
4870
  } catch (error) {
4860
- let finalError = {
4861
- message: "Error uploading attachment",
4862
- name: "Error"
4863
- };
4864
- if (typeof error.message === "string") {
4865
- finalError = error;
4866
- } else if (typeof error === "object") {
4867
- finalError = Object.assign(finalError, error);
4868
- }
4869
- this.client.notifications.addError({
4870
- message: finalError.message,
4871
- origin: { emitter: "AttachmentManager", context: { attachment } }
4872
- });
4871
+ const reason = error instanceof Error ? error.message : "unknown error";
4873
4872
  const failedAttachment = {
4874
4873
  ...attachment,
4875
4874
  localMetadata: {
@@ -4877,6 +4876,18 @@ var AttachmentManager = class {
4877
4876
  uploadState: "failed"
4878
4877
  }
4879
4878
  };
4879
+ this.client.notifications.addError({
4880
+ message: "Error uploading attachment",
4881
+ origin: {
4882
+ emitter: "AttachmentManager",
4883
+ context: { attachment, failedAttachment }
4884
+ },
4885
+ options: {
4886
+ type: "api:attachment:upload:failed",
4887
+ metadata: { reason },
4888
+ originalError: error instanceof Error ? error : void 0
4889
+ }
4890
+ });
4880
4891
  this.updateAttachment(failedAttachment);
4881
4892
  return failedAttachment;
4882
4893
  }
@@ -5440,15 +5451,14 @@ var pollStateChangeValidators = {
5440
5451
  return { max_votes_allowed: "Type a number from 2 to 10" };
5441
5452
  return { max_votes_allowed: void 0 };
5442
5453
  },
5443
- options: ({ value }) => {
5454
+ options: ({ value: options }) => {
5444
5455
  const errors = {};
5445
5456
  const seenOptions = /* @__PURE__ */ new Set();
5446
- value.forEach((option) => {
5447
- const trimmedText = option.text.trim();
5448
- if (seenOptions.has(trimmedText)) {
5457
+ options.forEach((option) => {
5458
+ if (seenOptions.has(option.text) && option.text.length) {
5449
5459
  errors[option.id] = "Option already exists";
5450
5460
  } else {
5451
- seenOptions.add(trimmedText);
5461
+ seenOptions.add(option.text);
5452
5462
  }
5453
5463
  });
5454
5464
  return Object.keys(errors).length > 0 ? { options: errors } : { options: void 0 };
@@ -5801,13 +5811,13 @@ var PollComposer = class {
5801
5811
  }
5802
5812
  get canCreatePoll() {
5803
5813
  const { data, errors } = this.state.getLatestValue();
5804
- const hasAtLeastOneOption = data.options.filter((o) => !!o.text).length > 0;
5814
+ const hasAtLeastOneNonEmptyOption = data.options.filter((o) => !!o.text.trim()).length > 0;
5805
5815
  const hasName = !!data.name;
5806
5816
  const maxVotesAllowedNumber = parseInt(
5807
5817
  data.max_votes_allowed?.match(VALID_MAX_VOTES_VALUE_REGEX)?.[0] || ""
5808
5818
  );
5809
5819
  const validMaxVotesAllowed = data.max_votes_allowed === "" || !!maxVotesAllowedNumber && (2 <= maxVotesAllowedNumber || maxVotesAllowedNumber <= 10);
5810
- return hasAtLeastOneOption && hasName && validMaxVotesAllowed && Object.values(errors).filter((errorText) => !!errorText).length === 0;
5820
+ return hasAtLeastOneNonEmptyOption && hasName && validMaxVotesAllowed && Object.values(errors).filter((errorText) => !!errorText).length === 0;
5811
5821
  }
5812
5822
  };
5813
5823
 
@@ -5897,8 +5907,7 @@ var createCompositionDataCleanupMiddleware = (composer) => ({
5897
5907
  localMessage: formatMessage({
5898
5908
  ...composer.editedMessage,
5899
5909
  ...state.localMessage,
5900
- ...common,
5901
- user: composer.client.user
5910
+ ...common
5902
5911
  }),
5903
5912
  message: {
5904
5913
  ...editedMessagePayloadToBeSent,
@@ -6144,6 +6153,9 @@ var createMessageComposerStateCompositionMiddleware = (composer) => ({
6144
6153
  if (composer.pollId) {
6145
6154
  payload.poll_id = composer.pollId;
6146
6155
  }
6156
+ if (composer.showReplyInChannel) {
6157
+ payload.show_in_channel = true;
6158
+ }
6147
6159
  return next({
6148
6160
  ...state,
6149
6161
  localMessage: {
@@ -6173,6 +6185,9 @@ var createDraftMessageComposerStateCompositionMiddleware = (composer) => ({
6173
6185
  if (composer.pollId) {
6174
6186
  payload.poll_id = composer.pollId;
6175
6187
  }
6188
+ if (composer.showReplyInChannel) {
6189
+ payload.show_in_channel = true;
6190
+ }
6176
6191
  return next({
6177
6192
  ...state,
6178
6193
  draft: {
@@ -6184,6 +6199,31 @@ var createDraftMessageComposerStateCompositionMiddleware = (composer) => ({
6184
6199
  }
6185
6200
  });
6186
6201
 
6202
+ // src/messageComposer/middleware/messageComposer/userDataInjection.ts
6203
+ var createUserDataInjectionMiddleware = (composer) => ({
6204
+ id: "stream-io/message-composer-middleware/user-data-injection",
6205
+ handlers: {
6206
+ compose: ({
6207
+ state,
6208
+ next,
6209
+ forward
6210
+ }) => {
6211
+ if (!composer.client.user) {
6212
+ return forward();
6213
+ }
6214
+ const { channel_mutes, devices, mutes, ...messageUser } = composer.client.user;
6215
+ return next({
6216
+ ...state,
6217
+ localMessage: {
6218
+ ...state.localMessage,
6219
+ user: messageUser,
6220
+ user_id: messageUser.id
6221
+ }
6222
+ });
6223
+ }
6224
+ }
6225
+ });
6226
+
6187
6227
  // src/messageComposer/middleware/messageComposer/pollOnly.ts
6188
6228
  var pollLocalMessageNullifiedFields = {
6189
6229
  attachments: [],
@@ -6225,6 +6265,7 @@ var MessageComposerMiddlewareExecutor = class extends MiddlewareExecutor {
6225
6265
  constructor({ composer }) {
6226
6266
  super();
6227
6267
  this.use([
6268
+ createUserDataInjectionMiddleware(composer),
6228
6269
  createPollOnlyCompositionMiddleware(composer),
6229
6270
  createTextComposerCompositionMiddleware(composer),
6230
6271
  createAttachmentsCompositionMiddleware(composer),
@@ -7799,10 +7840,11 @@ var initEditingAuditState = (composition) => {
7799
7840
  var initState5 = (composition) => {
7800
7841
  if (!composition) {
7801
7842
  return {
7843
+ draftId: null,
7802
7844
  id: MessageComposer.generateId(),
7803
- quotedMessage: null,
7804
7845
  pollId: null,
7805
- draftId: null
7846
+ quotedMessage: null,
7847
+ showReplyInChannel: false
7806
7848
  };
7807
7849
  }
7808
7850
  const quotedMessage = composition.quoted_message;
@@ -7819,8 +7861,9 @@ var initState5 = (composition) => {
7819
7861
  return {
7820
7862
  draftId,
7821
7863
  id,
7864
+ pollId: message.poll_id ?? null,
7822
7865
  quotedMessage: quotedMessage ? formatMessage(quotedMessage) : null,
7823
- pollId: message.poll_id ?? null
7866
+ showReplyInChannel: false
7824
7867
  };
7825
7868
  };
7826
7869
  var noop3 = () => void 0;
@@ -8015,6 +8058,9 @@ var _MessageComposer = class _MessageComposer extends WithSubscriptions {
8015
8058
  this.setQuotedMessage = (quotedMessage) => {
8016
8059
  this.state.partialNext({ quotedMessage });
8017
8060
  };
8061
+ this.toggleShowReplyInChannel = () => {
8062
+ this.state.partialNext({ showReplyInChannel: !this.showReplyInChannel });
8063
+ };
8018
8064
  this.clear = () => {
8019
8065
  this.initState();
8020
8066
  };
@@ -8088,15 +8134,21 @@ var _MessageComposer = class _MessageComposer extends WithSubscriptions {
8088
8134
  const composition = await this.pollComposer.compose();
8089
8135
  if (!composition || !composition.data.id) return;
8090
8136
  try {
8091
- const { poll } = await this.client.createPoll(composition.data);
8092
- this.state.partialNext({ pollId: poll.id });
8093
- this.pollComposer.initState();
8137
+ const poll = await this.client.polls.createPoll(composition.data);
8138
+ this.state.partialNext({ pollId: poll?.id });
8094
8139
  } catch (error) {
8095
- this.client.notifications.add({
8140
+ this.client.notifications.addError({
8096
8141
  message: "Failed to create the poll",
8097
8142
  origin: {
8098
8143
  emitter: "MessageComposer",
8099
8144
  context: { composer: this }
8145
+ },
8146
+ options: {
8147
+ type: "api:poll:create:failed",
8148
+ metadata: {
8149
+ reason: error.message
8150
+ },
8151
+ originalError: error instanceof Error ? error : void 0
8100
8152
  }
8101
8153
  });
8102
8154
  throw error;
@@ -8201,6 +8253,9 @@ var _MessageComposer = class _MessageComposer extends WithSubscriptions {
8201
8253
  get pollId() {
8202
8254
  return this.state.getLatestValue().pollId;
8203
8255
  }
8256
+ get showReplyInChannel() {
8257
+ return this.state.getLatestValue().showReplyInChannel;
8258
+ }
8204
8259
  get hasSendableData() {
8205
8260
  return !!(!this.attachmentManager.uploadsInProgressCount && (!this.textComposer.textIsEmpty || this.attachmentManager.successfulUploadsCount > 0) || this.pollId);
8206
8261
  }
@@ -11789,7 +11844,11 @@ var PollManager = class extends WithSubscriptions {
11789
11844
  };
11790
11845
  this.createPoll = async (poll) => {
11791
11846
  const { poll: createdPoll } = await this.client.createPoll(poll);
11792
- return new Poll({ client: this.client, poll: createdPoll });
11847
+ if (!createdPoll.vote_counts_by_option) {
11848
+ createdPoll.vote_counts_by_option = {};
11849
+ }
11850
+ this.setOrOverwriteInCache(createdPoll);
11851
+ return this.fromState(createdPoll.id);
11793
11852
  };
11794
11853
  this.getPoll = async (id) => {
11795
11854
  const cachedPoll = this.fromState(id);
@@ -12327,21 +12386,23 @@ var ChannelManager = class extends WithSubscriptions {
12327
12386
  }
12328
12387
  };
12329
12388
 
12330
- // src/notifications/NotificationManager.ts
12331
- var DURATIONS = {
12332
- error: 1e4,
12333
- warning: 5e3,
12334
- info: 3e3,
12335
- success: 3e3
12389
+ // src/notifications/configuration.ts
12390
+ var DURATION_MS = 3e3;
12391
+ var DEFAULT_NOTIFICATION_MANAGER_CONFIG = {
12392
+ durations: {
12393
+ error: DURATION_MS,
12394
+ info: DURATION_MS,
12395
+ success: DURATION_MS,
12396
+ warning: DURATION_MS
12397
+ }
12336
12398
  };
12399
+
12400
+ // src/notifications/NotificationManager.ts
12337
12401
  var NotificationManager = class {
12338
12402
  constructor(config = {}) {
12339
12403
  this.timeouts = /* @__PURE__ */ new Map();
12340
12404
  this.store = new StateStore({ notifications: [] });
12341
- this.config = {
12342
- ...config,
12343
- durations: config.durations || DURATIONS
12344
- };
12405
+ this.config = mergeWith(DEFAULT_NOTIFICATION_MANAGER_CONFIG, config);
12345
12406
  }
12346
12407
  get notifications() {
12347
12408
  return this.store.getLatestValue().notifications;
@@ -12361,21 +12422,24 @@ var NotificationManager = class {
12361
12422
  add({ message, origin, options = {} }) {
12362
12423
  const id = generateUUIDv4();
12363
12424
  const now = Date.now();
12425
+ const severity = options.severity || "info";
12426
+ const duration = options.duration ?? this.config.durations[severity];
12364
12427
  const notification = {
12365
12428
  id,
12366
12429
  message,
12367
12430
  origin,
12368
- severity: options.severity || "info",
12431
+ type: options?.type,
12432
+ severity,
12369
12433
  createdAt: now,
12370
- expiresAt: options.duration ? now + options.duration : void 0,
12371
- autoClose: options.autoClose ?? true,
12434
+ expiresAt: now + duration,
12372
12435
  actions: options.actions,
12373
- metadata: options.metadata
12436
+ metadata: options.metadata,
12437
+ originalError: options.originalError
12374
12438
  };
12375
12439
  this.store.partialNext({
12376
12440
  notifications: [...this.store.getLatestValue().notifications, notification]
12377
12441
  });
12378
- if (notification.autoClose && notification.expiresAt) {
12442
+ if (notification.expiresAt) {
12379
12443
  const timeout = setTimeout(() => {
12380
12444
  this.remove(id);
12381
12445
  }, options.duration || this.config.durations[notification.severity]);
@@ -14741,7 +14805,7 @@ var StreamChat = class _StreamChat {
14741
14805
  data
14742
14806
  );
14743
14807
  }
14744
- DBDeleteChannelType(channelType) {
14808
+ deleteChannelType(channelType) {
14745
14809
  return this.delete(
14746
14810
  this.baseURL + `/channeltypes/${encodeURIComponent(channelType)}`
14747
14811
  );
@@ -15084,7 +15148,7 @@ var StreamChat = class _StreamChat {
15084
15148
  if (this.userAgent) {
15085
15149
  return this.userAgent;
15086
15150
  }
15087
- const version = "9.5.0";
15151
+ const version = "9.6.0";
15088
15152
  const clientBundle = "browser-cjs";
15089
15153
  let userAgentString = "";
15090
15154
  if (this.sdkIdentifier) {