stream-chat 9.10.1 → 9.12.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.
Files changed (40) hide show
  1. package/dist/cjs/index.browser.cjs +400 -21
  2. package/dist/cjs/index.browser.cjs.map +4 -4
  3. package/dist/cjs/index.node.cjs +413 -28
  4. package/dist/cjs/index.node.cjs.map +4 -4
  5. package/dist/esm/index.js +400 -21
  6. package/dist/esm/index.js.map +4 -4
  7. package/dist/types/LiveLocationManager.d.ts +54 -0
  8. package/dist/types/channel.d.ts +5 -9
  9. package/dist/types/channel_manager.d.ts +5 -1
  10. package/dist/types/client.d.ts +7 -6
  11. package/dist/types/events.d.ts +2 -0
  12. package/dist/types/index.d.ts +1 -0
  13. package/dist/types/messageComposer/LocationComposer.d.ts +34 -0
  14. package/dist/types/messageComposer/attachmentIdentity.d.ts +2 -1
  15. package/dist/types/messageComposer/configuration/configuration.d.ts +2 -1
  16. package/dist/types/messageComposer/configuration/types.d.ts +11 -0
  17. package/dist/types/messageComposer/index.d.ts +1 -0
  18. package/dist/types/messageComposer/messageComposer.d.ts +7 -2
  19. package/dist/types/messageComposer/middleware/messageComposer/index.d.ts +1 -0
  20. package/dist/types/messageComposer/middleware/messageComposer/sharedLocation.d.ts +3 -0
  21. package/dist/types/types.d.ts +52 -5
  22. package/package.json +1 -1
  23. package/src/LiveLocationManager.ts +297 -0
  24. package/src/channel.ts +37 -2
  25. package/src/channel_manager.ts +15 -2
  26. package/src/client.ts +14 -5
  27. package/src/events.ts +2 -0
  28. package/src/index.ts +1 -0
  29. package/src/messageComposer/LocationComposer.ts +94 -0
  30. package/src/messageComposer/attachmentIdentity.ts +8 -1
  31. package/src/messageComposer/attachmentManager.ts +4 -0
  32. package/src/messageComposer/configuration/configuration.ts +8 -0
  33. package/src/messageComposer/configuration/types.ts +14 -0
  34. package/src/messageComposer/index.ts +1 -0
  35. package/src/messageComposer/messageComposer.ts +81 -9
  36. package/src/messageComposer/middleware/messageComposer/MessageComposerMiddlewareExecutor.ts +2 -0
  37. package/src/messageComposer/middleware/messageComposer/compositionValidation.ts +1 -5
  38. package/src/messageComposer/middleware/messageComposer/index.ts +1 -0
  39. package/src/messageComposer/middleware/messageComposer/sharedLocation.ts +42 -0
  40. package/src/types.ts +55 -5
@@ -8899,7 +8899,7 @@ var require_state = __commonJS({
8899
8899
  "node_modules/asynckit/lib/state.js"(exports2, module2) {
8900
8900
  module2.exports = state;
8901
8901
  function state(list, sortMethod) {
8902
- var isNamedList = !Array.isArray(list), initState6 = {
8902
+ var isNamedList = !Array.isArray(list), initState7 = {
8903
8903
  index: 0,
8904
8904
  keyedList: isNamedList || sortMethod ? Object.keys(list) : null,
8905
8905
  jobs: {},
@@ -8907,11 +8907,11 @@ var require_state = __commonJS({
8907
8907
  size: isNamedList ? Object.keys(list).length : list.length
8908
8908
  };
8909
8909
  if (sortMethod) {
8910
- initState6.keyedList.sort(isNamedList ? sortMethod : function(a, b) {
8910
+ initState7.keyedList.sort(isNamedList ? sortMethod : function(a, b) {
8911
8911
  return sortMethod(list[a], list[b]);
8912
8912
  });
8913
8913
  }
8914
- return initState6;
8914
+ return initState7;
8915
8915
  }
8916
8916
  }
8917
8917
  });
@@ -8937,11 +8937,11 @@ var require_terminator = __commonJS({
8937
8937
  var require_parallel = __commonJS({
8938
8938
  "node_modules/asynckit/parallel.js"(exports2, module2) {
8939
8939
  var iterate = require_iterate();
8940
- var initState6 = require_state();
8940
+ var initState7 = require_state();
8941
8941
  var terminator = require_terminator();
8942
8942
  module2.exports = parallel;
8943
8943
  function parallel(list, iterator, callback) {
8944
- var state = initState6(list);
8944
+ var state = initState7(list);
8945
8945
  while (state.index < (state["keyedList"] || list).length) {
8946
8946
  iterate(list, iterator, state, function(error, result) {
8947
8947
  if (error) {
@@ -8964,13 +8964,13 @@ var require_parallel = __commonJS({
8964
8964
  var require_serialOrdered = __commonJS({
8965
8965
  "node_modules/asynckit/serialOrdered.js"(exports2, module2) {
8966
8966
  var iterate = require_iterate();
8967
- var initState6 = require_state();
8967
+ var initState7 = require_state();
8968
8968
  var terminator = require_terminator();
8969
8969
  module2.exports = serialOrdered;
8970
8970
  module2.exports.ascending = ascending;
8971
8971
  module2.exports.descending = descending;
8972
8972
  function serialOrdered(list, iterator, sortMethod, callback) {
8973
- var state = initState6(list, sortMethod);
8973
+ var state = initState7(list, sortMethod);
8974
8974
  iterate(list, iterator, state, function iteratorHandler(error, result) {
8975
8975
  if (error) {
8976
8976
  callback(error, result);
@@ -10689,6 +10689,7 @@ __export(index_exports, {
10689
10689
  DEFAULT_CHANNEL_MANAGER_PAGINATION_OPTIONS: () => DEFAULT_CHANNEL_MANAGER_PAGINATION_OPTIONS,
10690
10690
  DEFAULT_COMPOSER_CONFIG: () => DEFAULT_COMPOSER_CONFIG,
10691
10691
  DEFAULT_LINK_PREVIEW_MANAGER_CONFIG: () => DEFAULT_LINK_PREVIEW_MANAGER_CONFIG,
10692
+ DEFAULT_LOCATION_COMPOSER_CONFIG: () => DEFAULT_LOCATION_COMPOSER_CONFIG,
10692
10693
  DEFAULT_PAGINATION_OPTIONS: () => DEFAULT_PAGINATION_OPTIONS,
10693
10694
  DEFAULT_REMINDER_MANAGER_CONFIG: () => DEFAULT_REMINDER_MANAGER_CONFIG,
10694
10695
  DEFAULT_STOP_REFRESH_BOUNDARY_MS: () => DEFAULT_STOP_REFRESH_BOUNDARY_MS,
@@ -10704,6 +10705,8 @@ __export(index_exports, {
10704
10705
  JWTUserToken: () => JWTUserToken,
10705
10706
  LinkPreviewStatus: () => LinkPreviewStatus,
10706
10707
  LinkPreviewsManager: () => LinkPreviewsManager,
10708
+ LiveLocationManager: () => LiveLocationManager,
10709
+ LocationComposer: () => LocationComposer,
10707
10710
  MAX_POLL_OPTIONS: () => MAX_POLL_OPTIONS,
10708
10711
  MODERATION_ENTITY_TYPES: () => MODERATION_ENTITY_TYPES,
10709
10712
  MaxPriority: () => MaxPriority,
@@ -10740,6 +10743,7 @@ __export(index_exports, {
10740
10743
  Thread: () => Thread,
10741
10744
  ThreadManager: () => ThreadManager,
10742
10745
  TokenManager: () => TokenManager,
10746
+ UPDATE_LIVE_LOCATION_REQUEST_MIN_THROTTLE_TIMEOUT: () => UPDATE_LIVE_LOCATION_REQUEST_MIN_THROTTLE_TIMEOUT,
10743
10747
  UserFromToken: () => UserFromToken,
10744
10748
  UserSearchSource: () => UserSearchSource,
10745
10749
  VALID_MAX_VOTES_VALUE_REGEX: () => VALID_MAX_VOTES_VALUE_REGEX,
@@ -10770,6 +10774,7 @@ __export(index_exports, {
10770
10774
  createMentionsMiddleware: () => createMentionsMiddleware,
10771
10775
  createMessageComposerStateCompositionMiddleware: () => createMessageComposerStateCompositionMiddleware,
10772
10776
  createPollComposerStateMiddleware: () => createPollComposerStateMiddleware,
10777
+ createSharedLocationCompositionMiddleware: () => createSharedLocationCompositionMiddleware,
10773
10778
  createTextComposerCompositionMiddleware: () => createTextComposerCompositionMiddleware,
10774
10779
  createTextComposerPreValidationMiddleware: () => createTextComposerPreValidationMiddleware,
10775
10780
  decodeBase64: () => decodeBase64,
@@ -10806,6 +10811,7 @@ __export(index_exports, {
10806
10811
  isOwnUser: () => isOwnUser,
10807
10812
  isPatch: () => isPatch,
10808
10813
  isScrapedContent: () => isScrapedContent,
10814
+ isSharedLocationResponse: () => isSharedLocationResponse,
10809
10815
  isTargetedOptionTextUpdate: () => isTargetedOptionTextUpdate,
10810
10816
  isUploadedAttachment: () => isUploadedAttachment,
10811
10817
  isVideoAttachment: () => isVideoAttachment,
@@ -15362,6 +15368,7 @@ var isLocalVoiceRecordingAttachment = (attachment) => isVoiceRecordingAttachment
15362
15368
  var isVideoAttachment = (attachment, supportedVideoFormat = []) => attachment.type === "video" || !!(attachment.mime_type && supportedVideoFormat.indexOf(attachment.mime_type) !== -1);
15363
15369
  var isLocalVideoAttachment = (attachment) => isVideoAttachment(attachment) && isLocalAttachment(attachment);
15364
15370
  var isUploadedAttachment = (attachment) => isAudioAttachment(attachment) || isFileAttachment(attachment) || isImageAttachment(attachment) || isVideoAttachment(attachment) || isVoiceRecordingAttachment(attachment);
15371
+ var isSharedLocationResponse = (location) => !!location.latitude && !!location.longitude && !!location.channel_cid;
15365
15372
 
15366
15373
  // src/messageComposer/fileUtils.ts
15367
15374
  var isFile2 = (fileLike) => !!fileLike.lastModified && !("uri" in fileLike);
@@ -16150,6 +16157,9 @@ var AttachmentManager = class {
16150
16157
  if (isFileReference(fileLike) && fileLike.thumb_url) {
16151
16158
  localAttachment.thumb_url = fileLike.thumb_url;
16152
16159
  }
16160
+ if (isFileReference(fileLike) && fileLike.duration) {
16161
+ localAttachment.duration = fileLike.duration;
16162
+ }
16153
16163
  return localAttachment;
16154
16164
  };
16155
16165
  this.ensureLocalUploadAttachment = async (attachment) => {
@@ -16401,10 +16411,15 @@ var DEFAULT_TEXT_COMPOSER_CONFIG = {
16401
16411
  enabled: true,
16402
16412
  publishTypingEvents: true
16403
16413
  };
16414
+ var DEFAULT_LOCATION_COMPOSER_CONFIG = {
16415
+ enabled: true,
16416
+ getDeviceId: () => generateUUIDv4()
16417
+ };
16404
16418
  var DEFAULT_COMPOSER_CONFIG = {
16405
16419
  attachments: DEFAULT_ATTACHMENT_MANAGER_CONFIG,
16406
16420
  drafts: { enabled: false },
16407
16421
  linkPreviews: DEFAULT_LINK_PREVIEW_MANAGER_CONFIG,
16422
+ location: DEFAULT_LOCATION_COMPOSER_CONFIG,
16408
16423
  text: DEFAULT_TEXT_COMPOSER_CONFIG
16409
16424
  };
16410
16425
 
@@ -16660,6 +16675,54 @@ _LinkPreviewsManager.getPreviewData = (preview) => {
16660
16675
  };
16661
16676
  var LinkPreviewsManager = _LinkPreviewsManager;
16662
16677
 
16678
+ // src/messageComposer/LocationComposer.ts
16679
+ var MIN_LIVE_LOCATION_SHARE_DURATION = 60 * 1e3;
16680
+ var initState4 = ({
16681
+ message
16682
+ }) => ({
16683
+ location: message?.shared_location ?? null
16684
+ });
16685
+ var LocationComposer = class {
16686
+ constructor({ composer, message }) {
16687
+ this.initState = ({ message } = {}) => {
16688
+ this.state.next(initState4({ message }));
16689
+ };
16690
+ this.setData = (data) => {
16691
+ if (!this.config.enabled) return;
16692
+ if (!data.latitude || !data.longitude) return;
16693
+ this.state.partialNext({
16694
+ location: {
16695
+ ...data,
16696
+ message_id: this.composer.id,
16697
+ created_by_device_id: this.deviceId
16698
+ }
16699
+ });
16700
+ };
16701
+ this.composer = composer;
16702
+ this.state = new StateStore(initState4({ message }));
16703
+ this._deviceId = this.config.getDeviceId();
16704
+ }
16705
+ get config() {
16706
+ return this.composer.config.location;
16707
+ }
16708
+ get deviceId() {
16709
+ return this._deviceId;
16710
+ }
16711
+ get location() {
16712
+ return this.state.getLatestValue().location;
16713
+ }
16714
+ get validLocation() {
16715
+ const { durationMs, ...location } = this.location ?? {};
16716
+ if (!!location?.created_by_device_id && location.message_id && location.latitude && location.longitude && (typeof durationMs === "undefined" || durationMs >= MIN_LIVE_LOCATION_SHARE_DURATION)) {
16717
+ return {
16718
+ ...location,
16719
+ end_at: durationMs && new Date(Date.now() + durationMs).toISOString()
16720
+ };
16721
+ }
16722
+ return null;
16723
+ }
16724
+ };
16725
+
16663
16726
  // src/utils/concurrency.ts
16664
16727
  var withoutConcurrency = createRunner(wrapWithContinuationTracking);
16665
16728
  var withCancellation = createRunner(wrapWithCancellation);
@@ -17343,9 +17406,8 @@ var createCompositionValidationMiddleware = (composer) => ({
17343
17406
  }) => {
17344
17407
  const { maxLengthOnSend } = composer.config.text ?? {};
17345
17408
  const inputText = state.message.text ?? "";
17346
- const isEmptyMessage = textIsEmpty(inputText) && !state.message.attachments?.length && !state.message.poll_id;
17347
17409
  const hasExceededMaxLength = typeof maxLengthOnSend === "number" && inputText.length > maxLengthOnSend;
17348
- if (isEmptyMessage || hasExceededMaxLength) {
17410
+ if (composer.compositionIsEmpty || hasExceededMaxLength) {
17349
17411
  return await discard();
17350
17412
  }
17351
17413
  return await forward();
@@ -17625,6 +17687,40 @@ var createPollOnlyCompositionMiddleware = (composer) => ({
17625
17687
  }
17626
17688
  });
17627
17689
 
17690
+ // src/messageComposer/middleware/messageComposer/sharedLocation.ts
17691
+ var createSharedLocationCompositionMiddleware = (composer) => ({
17692
+ id: "stream-io/message-composer-middleware/shared-location",
17693
+ handlers: {
17694
+ compose: ({
17695
+ state,
17696
+ next,
17697
+ forward
17698
+ }) => {
17699
+ const { locationComposer } = composer;
17700
+ const location = locationComposer.validLocation;
17701
+ if (!locationComposer || !location || !composer.client.user) return forward();
17702
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
17703
+ return next({
17704
+ ...state,
17705
+ localMessage: {
17706
+ ...state.localMessage,
17707
+ shared_location: {
17708
+ ...location,
17709
+ channel_cid: composer.channel.cid,
17710
+ created_at: timestamp,
17711
+ updated_at: timestamp,
17712
+ user_id: composer.client.user.id
17713
+ }
17714
+ },
17715
+ message: {
17716
+ ...state.message,
17717
+ shared_location: location
17718
+ }
17719
+ });
17720
+ }
17721
+ }
17722
+ });
17723
+
17628
17724
  // src/messageComposer/middleware/messageComposer/MessageComposerMiddlewareExecutor.ts
17629
17725
  var MessageComposerMiddlewareExecutor = class extends MiddlewareExecutor {
17630
17726
  constructor({ composer }) {
@@ -17635,6 +17731,7 @@ var MessageComposerMiddlewareExecutor = class extends MiddlewareExecutor {
17635
17731
  createTextComposerCompositionMiddleware(composer),
17636
17732
  createAttachmentsCompositionMiddleware(composer),
17637
17733
  createLinkPreviewsCompositionMiddleware(composer),
17734
+ createSharedLocationCompositionMiddleware(composer),
17638
17735
  createMessageComposerStateCompositionMiddleware(composer),
17639
17736
  createCustomDataCompositionMiddleware(composer),
17640
17737
  createCompositionValidationMiddleware(composer),
@@ -18676,7 +18773,7 @@ var textIsEmpty = (text) => {
18676
18773
  const trimmedText = text.trim();
18677
18774
  return trimmedText === "" || trimmedText === ">" || trimmedText === "``````" || trimmedText === "``" || trimmedText === "**" || trimmedText === "____" || trimmedText === "__" || trimmedText === "****";
18678
18775
  };
18679
- var initState4 = ({
18776
+ var initState5 = ({
18680
18777
  composer,
18681
18778
  message
18682
18779
  }) => {
@@ -18701,7 +18798,7 @@ var initState4 = ({
18701
18798
  var TextComposer = class {
18702
18799
  constructor({ composer, message }) {
18703
18800
  this.initState = ({ message } = {}) => {
18704
- this.state.next(initState4({ composer: this.composer, message }));
18801
+ this.state.next(initState5({ composer: this.composer, message }));
18705
18802
  };
18706
18803
  this.upsertMentionedUser = (user) => {
18707
18804
  const mentionedUsers = [...this.mentionedUsers];
@@ -18829,7 +18926,7 @@ var TextComposer = class {
18829
18926
  this.state.next(output.state);
18830
18927
  };
18831
18928
  this.composer = composer;
18832
- this.state = new StateStore(initState4({ composer, message }));
18929
+ this.state = new StateStore(initState5({ composer, message }));
18833
18930
  this.middlewareExecutor = new TextComposerMiddlewareExecutor({ composer });
18834
18931
  }
18835
18932
  get channel() {
@@ -19402,7 +19499,7 @@ var initEditingAuditState = (composition) => {
19402
19499
  }
19403
19500
  };
19404
19501
  };
19405
- var initState5 = (composition) => {
19502
+ var initState6 = (composition) => {
19406
19503
  if (!composition) {
19407
19504
  return {
19408
19505
  draftId: null,
@@ -19440,6 +19537,9 @@ var _MessageComposer = class _MessageComposer extends WithSubscriptions {
19440
19537
  client
19441
19538
  }) {
19442
19539
  super();
19540
+ this.refreshId = () => {
19541
+ this.state.partialNext({ id: _MessageComposer.generateId() });
19542
+ };
19443
19543
  this.initState = ({
19444
19544
  composition
19445
19545
  } = {}) => {
@@ -19447,10 +19547,11 @@ var _MessageComposer = class _MessageComposer extends WithSubscriptions {
19447
19547
  const message = typeof composition === "undefined" ? composition : compositionIsDraftResponse(composition) ? composition.message : formatMessage(composition);
19448
19548
  this.attachmentManager.initState({ message });
19449
19549
  this.linkPreviewsManager.initState({ message });
19550
+ this.locationComposer.initState({ message });
19450
19551
  this.textComposer.initState({ message });
19451
19552
  this.pollComposer.initState();
19452
19553
  this.customDataManager.initState({ message });
19453
- this.state.next(initState5(composition));
19554
+ this.state.next(initState6(composition));
19454
19555
  if (composition && !compositionIsDraftResponse(composition) && message && isLocalMessage(message)) {
19455
19556
  this.editedMessage = message;
19456
19557
  }
@@ -19490,6 +19591,7 @@ var _MessageComposer = class _MessageComposer extends WithSubscriptions {
19490
19591
  this.addUnsubscribeFunction(this.subscribeTextComposerStateChanged());
19491
19592
  this.addUnsubscribeFunction(this.subscribeAttachmentManagerStateChanged());
19492
19593
  this.addUnsubscribeFunction(this.subscribeLinkPreviewsManagerStateChanged());
19594
+ this.addUnsubscribeFunction(this.subscribeLocationComposerStateChanged());
19493
19595
  this.addUnsubscribeFunction(this.subscribePollComposerStateChanged());
19494
19596
  this.addUnsubscribeFunction(this.subscribeCustomDataManagerStateChanged());
19495
19597
  this.addUnsubscribeFunction(this.subscribeMessageComposerStateChanged());
@@ -19586,6 +19688,14 @@ var _MessageComposer = class _MessageComposer extends WithSubscriptions {
19586
19688
  return;
19587
19689
  }
19588
19690
  });
19691
+ this.subscribeLocationComposerStateChanged = () => this.locationComposer.state.subscribe((_, previousValue) => {
19692
+ if (typeof previousValue === "undefined") return;
19693
+ this.logStateUpdateTimestamp();
19694
+ if (this.compositionIsEmpty) {
19695
+ this.deleteDraft();
19696
+ return;
19697
+ }
19698
+ });
19589
19699
  this.subscribeLinkPreviewsManagerStateChanged = () => this.linkPreviewsManager.state.subscribe((_, previousValue) => {
19590
19700
  if (typeof previousValue === "undefined") return;
19591
19701
  this.logStateUpdateTimestamp();
@@ -19806,10 +19916,32 @@ var _MessageComposer = class _MessageComposer extends WithSubscriptions {
19806
19916
  throw error;
19807
19917
  }
19808
19918
  };
19919
+ this.sendLocation = async () => {
19920
+ const location = this.locationComposer.validLocation;
19921
+ if (this.threadId || !location) return;
19922
+ try {
19923
+ await this.channel.sendSharedLocation(location);
19924
+ this.refreshId();
19925
+ this.locationComposer.initState();
19926
+ } catch (error) {
19927
+ this.client.notifications.addError({
19928
+ message: "Failed to share the location",
19929
+ origin: {
19930
+ emitter: "MessageComposer",
19931
+ context: { composer: this }
19932
+ },
19933
+ options: {
19934
+ type: "api:location:create:failed",
19935
+ metadata: {
19936
+ reason: error.message
19937
+ },
19938
+ originalError: error instanceof Error ? error : void 0
19939
+ }
19940
+ });
19941
+ throw error;
19942
+ }
19943
+ };
19809
19944
  this.compositionContext = compositionContext;
19810
- this.configState = new StateStore(
19811
- mergeWith(DEFAULT_COMPOSER_CONFIG, config ?? {})
19812
- );
19813
19945
  if (compositionContext instanceof Channel) {
19814
19946
  this.channel = compositionContext;
19815
19947
  } else if (compositionContext instanceof Thread) {
@@ -19822,6 +19954,21 @@ var _MessageComposer = class _MessageComposer extends WithSubscriptions {
19822
19954
  "MessageComposer requires composition context pointing to channel (channel or context.cid)"
19823
19955
  );
19824
19956
  }
19957
+ const mergeChannelConfigCustomizer = (originalVal, channelConfigVal, key) => typeof originalVal === "object" ? void 0 : originalVal === false && key === "enabled" ? false : ["string", "number", "bigint", "boolean", "symbol"].includes(
19958
+ // prevent enabling features that are disabled server-side
19959
+ typeof channelConfigVal
19960
+ ) ? channelConfigVal : originalVal;
19961
+ this.configState = new StateStore(
19962
+ mergeWith(
19963
+ mergeWith(DEFAULT_COMPOSER_CONFIG, config ?? {}),
19964
+ {
19965
+ location: {
19966
+ enabled: this.channel.getConfig()?.shared_locations
19967
+ }
19968
+ },
19969
+ mergeChannelConfigCustomizer
19970
+ )
19971
+ );
19825
19972
  let message = void 0;
19826
19973
  if (compositionIsDraftResponse(composition)) {
19827
19974
  message = composition.message;
@@ -19831,13 +19978,14 @@ var _MessageComposer = class _MessageComposer extends WithSubscriptions {
19831
19978
  }
19832
19979
  this.attachmentManager = new AttachmentManager({ composer: this, message });
19833
19980
  this.linkPreviewsManager = new LinkPreviewsManager({ composer: this, message });
19981
+ this.locationComposer = new LocationComposer({ composer: this, message });
19834
19982
  this.textComposer = new TextComposer({ composer: this, message });
19835
19983
  this.pollComposer = new PollComposer({ composer: this });
19836
19984
  this.customDataManager = new CustomDataManager({ composer: this, message });
19837
19985
  this.editingAuditState = new StateStore(
19838
19986
  this.initEditingAuditState(composition)
19839
19987
  );
19840
- this.state = new StateStore(initState5(composition));
19988
+ this.state = new StateStore(initState6(composition));
19841
19989
  this.compositionMiddlewareExecutor = new MessageComposerMiddlewareExecutor({
19842
19990
  composer: this
19843
19991
  });
@@ -19912,10 +20060,10 @@ var _MessageComposer = class _MessageComposer extends WithSubscriptions {
19912
20060
  if (this.client.offlineDb) {
19913
20061
  return !this.compositionIsEmpty;
19914
20062
  }
19915
- return !!(!this.attachmentManager.uploadsInProgressCount && (!this.textComposer.textIsEmpty || this.attachmentManager.successfulUploadsCount > 0) || this.pollId);
20063
+ return !!(!this.attachmentManager.uploadsInProgressCount && (!this.textComposer.textIsEmpty || this.attachmentManager.successfulUploadsCount > 0) || this.pollId || !!this.locationComposer.validLocation);
19916
20064
  }
19917
20065
  get compositionIsEmpty() {
19918
- return !this.quotedMessage && this.textComposer.textIsEmpty && !this.attachmentManager.attachments.length && !this.pollId;
20066
+ return !this.quotedMessage && this.textComposer.textIsEmpty && !this.attachmentManager.attachments.length && !this.pollId && !this.locationComposer.validLocation;
19919
20067
  }
19920
20068
  get lastChangeOriginIsLocal() {
19921
20069
  const initiatedWithoutDraft = this.lastChange.draftUpdate === null;
@@ -20442,6 +20590,30 @@ var Channel = class {
20442
20590
  this.data = data.channel;
20443
20591
  return data;
20444
20592
  }
20593
+ async sendSharedLocation(location, userId) {
20594
+ const result = await this.sendMessage({
20595
+ id: location.message_id,
20596
+ shared_location: location,
20597
+ user: userId ? { id: userId } : void 0
20598
+ });
20599
+ if (location.end_at) {
20600
+ this.getClient().dispatchEvent({
20601
+ message: result.message,
20602
+ type: "live_location_sharing.started"
20603
+ });
20604
+ }
20605
+ return result;
20606
+ }
20607
+ async stopLiveLocationSharing(payload) {
20608
+ const location = await this.getClient().updateLocation({
20609
+ ...payload,
20610
+ end_at: (/* @__PURE__ */ new Date()).toISOString()
20611
+ });
20612
+ this.getClient().dispatchEvent({
20613
+ live_location: location,
20614
+ type: "live_location_sharing.stopped"
20615
+ });
20616
+ }
20445
20617
  /**
20446
20618
  * delete - Delete the channel. Messages are permanently removed.
20447
20619
  *
@@ -23676,7 +23848,8 @@ var ChannelManager = class extends WithSubscriptions {
23676
23848
  constructor({
23677
23849
  client,
23678
23850
  eventHandlerOverrides = {},
23679
- options = {}
23851
+ options = {},
23852
+ queryChannelsOverride
23680
23853
  }) {
23681
23854
  super();
23682
23855
  this.eventHandlers = /* @__PURE__ */ new Map();
@@ -23716,6 +23889,9 @@ var ChannelManager = class extends WithSubscriptions {
23716
23889
  Object.entries(truthyEventHandlerOverrides)
23717
23890
  );
23718
23891
  };
23892
+ this.setQueryChannelsRequest = (queryChannelsRequest) => {
23893
+ this.queryChannelsRequest = queryChannelsRequest;
23894
+ };
23719
23895
  this.setOptions = (options = {}) => {
23720
23896
  this.options = { ...DEFAULT_CHANNEL_MANAGER_OPTIONS, ...options };
23721
23897
  };
@@ -23726,7 +23902,7 @@ var ChannelManager = class extends WithSubscriptions {
23726
23902
  ...options
23727
23903
  };
23728
23904
  try {
23729
- const channels = await this.client.queryChannels(
23905
+ const channels = await this.queryChannelsRequest(
23730
23906
  filters,
23731
23907
  sort,
23732
23908
  options,
@@ -23842,7 +24018,7 @@ var ChannelManager = class extends WithSubscriptions {
23842
24018
  this.state.partialNext({
23843
24019
  pagination: { ...pagination, isLoading: false, isLoadingNext: true }
23844
24020
  });
23845
- const nextChannels = await this.client.queryChannels(
24021
+ const nextChannels = await this.queryChannelsRequest(
23846
24022
  filters,
23847
24023
  sort,
23848
24024
  options,
@@ -24085,6 +24261,7 @@ var ChannelManager = class extends WithSubscriptions {
24085
24261
  });
24086
24262
  this.setEventHandlerOverrides(eventHandlerOverrides);
24087
24263
  this.setOptions(options);
24264
+ this.queryChannelsRequest = queryChannelsOverride ?? ((...params) => this.client.queryChannels(...params));
24088
24265
  this.eventHandlers = new Map(
24089
24266
  Object.entries({
24090
24267
  channelDeletedHandler: this.channelDeletedHandler,
@@ -24786,8 +24963,14 @@ var StreamChat = class _StreamChat {
24786
24963
  */
24787
24964
  this.createChannelManager = ({
24788
24965
  eventHandlerOverrides = {},
24789
- options = {}
24790
- }) => new ChannelManager({ client: this, eventHandlerOverrides, options });
24966
+ options = {},
24967
+ queryChannelsOverride
24968
+ }) => new ChannelManager({
24969
+ client: this,
24970
+ eventHandlerOverrides,
24971
+ options,
24972
+ queryChannelsOverride
24973
+ });
24791
24974
  /**
24792
24975
  * Creates a new WebSocket connection with the current user. Returns empty promise, if there is an active connection
24793
24976
  */
@@ -26891,7 +27074,7 @@ var StreamChat = class _StreamChat {
26891
27074
  if (this.userAgent) {
26892
27075
  return this.userAgent;
26893
27076
  }
26894
- const version = "9.10.1";
27077
+ const version = "9.12.0";
26895
27078
  const clientBundle = "node-cjs";
26896
27079
  let userAgentString = "";
26897
27080
  if (this.sdkIdentifier) {
@@ -27983,9 +28166,9 @@ var StreamChat = class _StreamChat {
27983
28166
  /**
27984
28167
  * updateLocation - Updates a location
27985
28168
  *
27986
- * @param location UserLocation the location data to update
28169
+ * @param location SharedLocationRequest the location data to update
27987
28170
  *
27988
- * @returns {Promise<APIResponse>} The server response
28171
+ * @returns {Promise<SharedLocationResponse>} The server response
27989
28172
  */
27990
28173
  async updateLocation(location) {
27991
28174
  return await this.put(
@@ -28106,6 +28289,8 @@ var EVENT_MAP = {
28106
28289
  "connection.recovered": true,
28107
28290
  "transport.changed": true,
28108
28291
  "capabilities.changed": true,
28292
+ "live_location_sharing.started": true,
28293
+ "live_location_sharing.stopped": true,
28109
28294
  // Reminder events
28110
28295
  "reminder.created": true,
28111
28296
  "reminder.updated": true,
@@ -28961,6 +29146,200 @@ var AbstractOfflineDB = class {
28961
29146
  }
28962
29147
  };
28963
29148
 
29149
+ // src/LiveLocationManager.ts
29150
+ var isExpiredLocation = (location) => {
29151
+ const endTimeTimestamp = new Date(location.end_at).getTime();
29152
+ return endTimeTimestamp < Date.now();
29153
+ };
29154
+ function isValidLiveLocationMessage(message) {
29155
+ if (!message || message.type === "deleted" || !message.shared_location?.end_at)
29156
+ return false;
29157
+ return !isExpiredLocation(message.shared_location);
29158
+ }
29159
+ var UPDATE_LIVE_LOCATION_REQUEST_MIN_THROTTLE_TIMEOUT = 3e3;
29160
+ var _LiveLocationManager = class _LiveLocationManager extends WithSubscriptions {
29161
+ constructor({
29162
+ client,
29163
+ getDeviceId,
29164
+ watchLocation
29165
+ }) {
29166
+ if (!client.userID) {
29167
+ throw new Error("Live-location sharing is reserved for client-side use only");
29168
+ }
29169
+ super();
29170
+ this.registerSubscriptions = () => {
29171
+ this.incrementRefCount();
29172
+ if (this.hasSubscriptions) return;
29173
+ this.addUnsubscribeFunction(this.subscribeLiveLocationSharingUpdates());
29174
+ this.addUnsubscribeFunction(this.subscribeTargetMessagesChange());
29175
+ };
29176
+ this.unregisterSubscriptions = () => super.unregisterSubscriptions();
29177
+ this.client = client;
29178
+ this.state = new StateStore({
29179
+ messages: /* @__PURE__ */ new Map(),
29180
+ ready: false
29181
+ });
29182
+ this._deviceId = getDeviceId();
29183
+ this.getDeviceId = getDeviceId;
29184
+ this.watchLocation = watchLocation;
29185
+ }
29186
+ async init() {
29187
+ await this.assureStateInit();
29188
+ this.registerSubscriptions();
29189
+ }
29190
+ get messages() {
29191
+ return this.state.getLatestValue().messages;
29192
+ }
29193
+ get stateIsReady() {
29194
+ return this.state.getLatestValue().ready;
29195
+ }
29196
+ get deviceId() {
29197
+ if (!this._deviceId) {
29198
+ this._deviceId = this.getDeviceId();
29199
+ }
29200
+ return this._deviceId;
29201
+ }
29202
+ async assureStateInit() {
29203
+ if (this.stateIsReady) return;
29204
+ const { active_live_locations } = await this.client.getSharedLocations();
29205
+ this.state.next({
29206
+ messages: new Map(
29207
+ active_live_locations.filter((location) => !isExpiredLocation(location)).map((location) => [
29208
+ location.message_id,
29209
+ {
29210
+ ...location,
29211
+ stopSharingTimeout: setTimeout(
29212
+ () => {
29213
+ this.unregisterMessages([location.message_id]);
29214
+ },
29215
+ new Date(location.end_at).getTime() - Date.now()
29216
+ )
29217
+ }
29218
+ ])
29219
+ ),
29220
+ ready: true
29221
+ });
29222
+ }
29223
+ subscribeTargetMessagesChange() {
29224
+ let unsubscribeWatchLocation = null;
29225
+ const unsubscribe = this.state.subscribeWithSelector(
29226
+ ({ messages }) => ({ messages }),
29227
+ ({ messages }) => {
29228
+ if (!messages.size) {
29229
+ unsubscribeWatchLocation?.();
29230
+ unsubscribeWatchLocation = null;
29231
+ } else if (messages.size && !unsubscribeWatchLocation) {
29232
+ unsubscribeWatchLocation = this.subscribeWatchLocation();
29233
+ }
29234
+ }
29235
+ );
29236
+ return () => {
29237
+ unsubscribe();
29238
+ unsubscribeWatchLocation?.();
29239
+ };
29240
+ }
29241
+ subscribeWatchLocation() {
29242
+ let nextAllowedUpdateCallTimestamp = Date.now();
29243
+ const unsubscribe = this.watchLocation(({ latitude, longitude }) => {
29244
+ if (Date.now() < nextAllowedUpdateCallTimestamp) return;
29245
+ nextAllowedUpdateCallTimestamp = Date.now() + UPDATE_LIVE_LOCATION_REQUEST_MIN_THROTTLE_TIMEOUT;
29246
+ withCancellation(_LiveLocationManager.symbol, async () => {
29247
+ const promises = [];
29248
+ await this.assureStateInit();
29249
+ const expiredLocations = [];
29250
+ for (const [messageId, location] of this.messages) {
29251
+ if (isExpiredLocation(location)) {
29252
+ expiredLocations.push(location.message_id);
29253
+ continue;
29254
+ }
29255
+ if (location.latitude === latitude && location.longitude === longitude)
29256
+ continue;
29257
+ const promise = this.client.updateLocation({
29258
+ created_by_device_id: location.created_by_device_id,
29259
+ message_id: messageId,
29260
+ latitude,
29261
+ longitude
29262
+ });
29263
+ promises.push(promise);
29264
+ }
29265
+ this.unregisterMessages(expiredLocations);
29266
+ if (promises.length > 0) {
29267
+ await Promise.allSettled(promises);
29268
+ }
29269
+ });
29270
+ });
29271
+ return unsubscribe;
29272
+ }
29273
+ subscribeLiveLocationSharingUpdates() {
29274
+ const subscriptions = [
29275
+ ...[
29276
+ "live_location_sharing.started",
29277
+ "message.updated",
29278
+ "message.deleted"
29279
+ ].map(
29280
+ (eventType) => this.client.on(eventType, (event) => {
29281
+ if (!event.message) return;
29282
+ if (event.type === "live_location_sharing.started") {
29283
+ this.registerMessage(event.message);
29284
+ } else if (event.type === "message.updated") {
29285
+ const isRegistered = this.messages.has(event.message.id);
29286
+ if (isRegistered && !isValidLiveLocationMessage(event.message)) {
29287
+ this.unregisterMessages([event.message.id]);
29288
+ }
29289
+ this.registerMessage(event.message);
29290
+ } else {
29291
+ this.unregisterMessages([event.message.id]);
29292
+ }
29293
+ })
29294
+ ),
29295
+ this.client.on("live_location_sharing.stopped", (event) => {
29296
+ if (!event.live_location) return;
29297
+ this.unregisterMessages([event.live_location?.message_id]);
29298
+ })
29299
+ ];
29300
+ return () => subscriptions.forEach((subscription) => subscription.unsubscribe());
29301
+ }
29302
+ registerMessage(message) {
29303
+ if (!this.client.userID || message?.user?.id !== this.client.userID || !isValidLiveLocationMessage(message))
29304
+ return;
29305
+ this.state.next((currentValue) => {
29306
+ const messages = new Map(currentValue.messages);
29307
+ messages.set(message.id, {
29308
+ ...message.shared_location,
29309
+ stopSharingTimeout: setTimeout(
29310
+ () => {
29311
+ this.unregisterMessages([message.id]);
29312
+ },
29313
+ new Date(message.shared_location.end_at).getTime() - Date.now()
29314
+ )
29315
+ });
29316
+ return {
29317
+ ...currentValue,
29318
+ messages
29319
+ };
29320
+ });
29321
+ }
29322
+ unregisterMessages(messageIds) {
29323
+ const messages = this.messages;
29324
+ const removedMessages = new Set(messageIds);
29325
+ const newMessages = new Map(
29326
+ Array.from(messages).filter(([messageId, location]) => {
29327
+ if (removedMessages.has(messageId) && location.stopSharingTimeout) {
29328
+ clearTimeout(location.stopSharingTimeout);
29329
+ location.stopSharingTimeout = null;
29330
+ }
29331
+ return !removedMessages.has(messageId);
29332
+ })
29333
+ );
29334
+ if (newMessages.size === messages.size) return;
29335
+ this.state.partialNext({
29336
+ messages: newMessages
29337
+ });
29338
+ }
29339
+ };
29340
+ _LiveLocationManager.symbol = Symbol(_LiveLocationManager.name);
29341
+ var LiveLocationManager = _LiveLocationManager;
29342
+
28964
29343
  // src/utils/FixedSizeQueueCache.ts
28965
29344
  var FixedSizeQueueCache = class {
28966
29345
  constructor(size, options) {
@@ -29040,6 +29419,7 @@ var FixedSizeQueueCache = class {
29040
29419
  DEFAULT_CHANNEL_MANAGER_PAGINATION_OPTIONS,
29041
29420
  DEFAULT_COMPOSER_CONFIG,
29042
29421
  DEFAULT_LINK_PREVIEW_MANAGER_CONFIG,
29422
+ DEFAULT_LOCATION_COMPOSER_CONFIG,
29043
29423
  DEFAULT_PAGINATION_OPTIONS,
29044
29424
  DEFAULT_REMINDER_MANAGER_CONFIG,
29045
29425
  DEFAULT_STOP_REFRESH_BOUNDARY_MS,
@@ -29055,6 +29435,8 @@ var FixedSizeQueueCache = class {
29055
29435
  JWTUserToken,
29056
29436
  LinkPreviewStatus,
29057
29437
  LinkPreviewsManager,
29438
+ LiveLocationManager,
29439
+ LocationComposer,
29058
29440
  MAX_POLL_OPTIONS,
29059
29441
  MODERATION_ENTITY_TYPES,
29060
29442
  MaxPriority,
@@ -29091,6 +29473,7 @@ var FixedSizeQueueCache = class {
29091
29473
  Thread,
29092
29474
  ThreadManager,
29093
29475
  TokenManager,
29476
+ UPDATE_LIVE_LOCATION_REQUEST_MIN_THROTTLE_TIMEOUT,
29094
29477
  UserFromToken,
29095
29478
  UserSearchSource,
29096
29479
  VALID_MAX_VOTES_VALUE_REGEX,
@@ -29121,6 +29504,7 @@ var FixedSizeQueueCache = class {
29121
29504
  createMentionsMiddleware,
29122
29505
  createMessageComposerStateCompositionMiddleware,
29123
29506
  createPollComposerStateMiddleware,
29507
+ createSharedLocationCompositionMiddleware,
29124
29508
  createTextComposerCompositionMiddleware,
29125
29509
  createTextComposerPreValidationMiddleware,
29126
29510
  decodeBase64,
@@ -29157,6 +29541,7 @@ var FixedSizeQueueCache = class {
29157
29541
  isOwnUser,
29158
29542
  isPatch,
29159
29543
  isScrapedContent,
29544
+ isSharedLocationResponse,
29160
29545
  isTargetedOptionTextUpdate,
29161
29546
  isUploadedAttachment,
29162
29547
  isVideoAttachment,