stream-chat 9.42.3 → 9.43.1

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 (45) hide show
  1. package/dist/cjs/index.browser.js +1457 -1178
  2. package/dist/cjs/index.browser.js.map +3 -3
  3. package/dist/cjs/index.node.js +1458 -1180
  4. package/dist/cjs/index.node.js.map +3 -3
  5. package/dist/esm/index.mjs +1457 -1178
  6. package/dist/esm/index.mjs.map +3 -3
  7. package/dist/types/client.d.ts +4 -2
  8. package/dist/types/messageComposer/CustomDataManager.d.ts +3 -0
  9. package/dist/types/messageComposer/LocationComposer.d.ts +3 -0
  10. package/dist/types/messageComposer/MessageComposerEffectHandlers.d.ts +17 -0
  11. package/dist/types/messageComposer/attachmentManager.d.ts +7 -0
  12. package/dist/types/messageComposer/linkPreviewsManager.d.ts +4 -1
  13. package/dist/types/messageComposer/messageComposer.d.ts +39 -1
  14. package/dist/types/messageComposer/middleware/textComposer/TextComposerMiddlewareExecutor.d.ts +2 -1
  15. package/dist/types/messageComposer/middleware/textComposer/commandEffects.d.ts +5 -0
  16. package/dist/types/messageComposer/middleware/textComposer/commandUtils.d.ts +7 -0
  17. package/dist/types/messageComposer/middleware/textComposer/commands.d.ts +2 -0
  18. package/dist/types/messageComposer/middleware/textComposer/index.d.ts +1 -0
  19. package/dist/types/messageComposer/middleware/textComposer/textMiddlewareUtils.d.ts +0 -34
  20. package/dist/types/messageComposer/middleware/textComposer/types.d.ts +13 -0
  21. package/dist/types/messageComposer/pollComposer.d.ts +3 -0
  22. package/dist/types/messageComposer/textComposer.d.ts +5 -1
  23. package/dist/types/types.d.ts +19 -4
  24. package/dist/types/utils.d.ts +4 -2
  25. package/package.json +1 -1
  26. package/src/client.ts +0 -8
  27. package/src/connection.ts +5 -4
  28. package/src/messageComposer/CustomDataManager.ts +8 -0
  29. package/src/messageComposer/LocationComposer.ts +8 -0
  30. package/src/messageComposer/MessageComposerEffectHandlers.ts +89 -0
  31. package/src/messageComposer/attachmentManager.ts +54 -0
  32. package/src/messageComposer/linkPreviewsManager.ts +12 -3
  33. package/src/messageComposer/messageComposer.ts +107 -0
  34. package/src/messageComposer/middleware/messageComposer/compositionValidation.ts +58 -18
  35. package/src/messageComposer/middleware/textComposer/TextComposerMiddlewareExecutor.ts +7 -1
  36. package/src/messageComposer/middleware/textComposer/commandEffects.ts +51 -0
  37. package/src/messageComposer/middleware/textComposer/commandStringExtraction.ts +1 -4
  38. package/src/messageComposer/middleware/textComposer/commandUtils.ts +48 -0
  39. package/src/messageComposer/middleware/textComposer/commands.ts +15 -7
  40. package/src/messageComposer/middleware/textComposer/index.ts +1 -0
  41. package/src/messageComposer/middleware/textComposer/textMiddlewareUtils.ts +3 -46
  42. package/src/messageComposer/middleware/textComposer/types.ts +20 -0
  43. package/src/messageComposer/pollComposer.ts +8 -0
  44. package/src/messageComposer/textComposer.ts +54 -6
  45. package/src/types.ts +27 -4
@@ -1,5 +1,4 @@
1
1
  import type { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
2
- import type WebSocket from 'isomorphic-ws';
3
2
  import { Channel } from './channel';
4
3
  import { ClientState } from './client_state';
5
4
  import { StableWSConnection } from './connection';
@@ -409,7 +408,6 @@ export declare class StreamChat {
409
408
  errorFromResponse(response: AxiosResponse<APIErrorResponse>): ErrorFromResponse<APIErrorResponse>;
410
409
  handleResponse<T>(response: AxiosResponse<T>): T;
411
410
  dispatchEvent: (event: Event) => void;
412
- handleEvent: (messageEvent: WebSocket.MessageEvent) => void;
413
411
  /**
414
412
  * Updates the members, watchers and read references of the currently active channels that contain this user
415
413
  *
@@ -1033,6 +1031,8 @@ export declare class StreamChat {
1033
1031
  member?: import("./types").ChannelMemberResponse;
1034
1032
  mentioned_users?: UserResponse[];
1035
1033
  mentioned_channel?: boolean;
1034
+ mentioned_here?: boolean;
1035
+ mentioned_roles?: string[];
1036
1036
  message_text_updated_at?: string;
1037
1037
  moderation?: import("./types").ModerationResponse;
1038
1038
  moderation_details?: import("./types").ModerationDetailsResponse;
@@ -1730,6 +1730,8 @@ export declare class StreamChat {
1730
1730
  member?: import("./types").ChannelMemberResponse;
1731
1731
  mentioned_users?: UserResponse[];
1732
1732
  mentioned_channel?: boolean;
1733
+ mentioned_here?: boolean;
1734
+ mentioned_roles?: string[];
1733
1735
  message_text_updated_at?: string;
1734
1736
  moderation?: import("./types").ModerationResponse;
1735
1737
  moderation_details?: import("./types").ModerationDetailsResponse;
@@ -6,6 +6,7 @@ export type CustomDataManagerState = {
6
6
  message: CustomMessageData;
7
7
  custom: CustomMessageComposerData;
8
8
  };
9
+ export type CustomDataManagerSnapshot = CustomDataManagerState;
9
10
  export type CustomDataManagerOptions = {
10
11
  composer: MessageComposer;
11
12
  message?: DraftMessage | LocalMessage;
@@ -20,6 +21,8 @@ export declare class CustomDataManager {
20
21
  initState: ({ message }?: {
21
22
  message?: DraftMessage | LocalMessage;
22
23
  }) => void;
24
+ getSnapshot: () => CustomDataManagerSnapshot;
25
+ restoreSnapshot: (snapshot: CustomDataManagerSnapshot) => void;
23
26
  setMessageData(data: DeepPartial<CustomMessageData>): void;
24
27
  setCustomData(data: DeepPartial<CustomMessageComposerData>): void;
25
28
  }
@@ -16,6 +16,7 @@ export type LiveLocationPreview = Omit<LiveLocationPayload, 'end_at'> & {
16
16
  export type LocationComposerState = {
17
17
  location: StaticLocationPreview | LiveLocationPreview | null;
18
18
  };
19
+ export type LocationComposerSnapshot = LocationComposerState;
19
20
  export declare class LocationComposer {
20
21
  readonly state: StateStore<LocationComposerState>;
21
22
  readonly composer: MessageComposer;
@@ -28,6 +29,8 @@ export declare class LocationComposer {
28
29
  initState: ({ message }?: {
29
30
  message?: DraftMessage | LocalMessage;
30
31
  }) => void;
32
+ getSnapshot: () => LocationComposerSnapshot;
33
+ restoreSnapshot: (snapshot: LocationComposerSnapshot) => void;
31
34
  setData: (data: {
32
35
  durationMs?: number;
33
36
  } & Coords) => void;
@@ -0,0 +1,17 @@
1
+ import type { MessageComposer, MessageComposerEffectHandler } from './messageComposer';
2
+ export type MessageComposerEffectHandlersOptions = {
3
+ composer: MessageComposer;
4
+ };
5
+ export declare class MessageComposerEffectHandlers {
6
+ private options;
7
+ private handlers;
8
+ constructor(options: MessageComposerEffectHandlersOptions);
9
+ private registerDefaultHandlers;
10
+ registerEffectHandler: <T extends {
11
+ type: string;
12
+ }>(type: T["type"], handler: MessageComposerEffectHandler<T>) => void;
13
+ applyEffects: <T extends {
14
+ type: string;
15
+ }>(effects?: T[]) => void;
16
+ private applyEffect;
17
+ }
@@ -8,6 +8,7 @@ export type FileUploadFilter = (file: Partial<LocalUploadAttachment>) => boolean
8
8
  export type AttachmentManagerState = {
9
9
  attachments: LocalAttachment[];
10
10
  };
11
+ export type AttachmentManagerSnapshot = AttachmentManagerState;
11
12
  export type AttachmentManagerOptions = {
12
13
  composer: MessageComposer;
13
14
  message?: DraftMessage | LocalMessage;
@@ -41,9 +42,15 @@ export declare class AttachmentManager {
41
42
  get pendingUploadsCount(): number;
42
43
  get availableUploadSlots(): number;
43
44
  getUploadsByState(state: AttachmentLoadingState): LocalAttachment[];
45
+ cancelAttachmentUploads: (attachments?: LocalAttachment[]) => void;
46
+ private normalizeSnapshotAttachment;
44
47
  initState: ({ message }?: {
45
48
  message?: DraftMessage | LocalMessage;
46
49
  }) => void;
50
+ getSnapshot: () => AttachmentManagerSnapshot;
51
+ restoreSnapshot: (snapshot: AttachmentManagerSnapshot) => void;
52
+ setAttachments: (attachments: LocalAttachment[]) => void;
53
+ clearAttachments: () => void;
47
54
  getAttachmentIndex: (localId: string) => number;
48
55
  private prepareAttachmentUpdate;
49
56
  updateAttachment: (attachmentToUpdate: LocalAttachment) => void;
@@ -7,7 +7,7 @@ export type LinkPreview = OGAttachment & {
7
7
  status: LinkPreviewStatus;
8
8
  };
9
9
  export interface ILinkPreviewsManager {
10
- /** Function cancels all the scheduled or in-progress URL enrichment queries and resets the state. */
10
+ /** Function cancels all scheduled or in-progress URL enrichment queries. */
11
11
  cancelURLEnrichment: () => void;
12
12
  /** Function that triggers the search for URLs and their enrichment. */
13
13
  findAndEnrichUrls?: DebouncedFunc<(text: string) => void>;
@@ -29,6 +29,7 @@ export type LinkPreviewMap = Map<LinkURL, LinkPreview>;
29
29
  export type LinkPreviewsManagerState = {
30
30
  previews: LinkPreviewMap;
31
31
  };
32
+ export type LinkPreviewsManagerSnapshot = LinkPreviewsManagerState;
32
33
  export type LinkPreviewsManagerOptions = {
33
34
  composer: MessageComposer;
34
35
  message?: DraftMessage | LocalMessage;
@@ -59,6 +60,8 @@ export declare class LinkPreviewsManager implements ILinkPreviewsManager {
59
60
  initState: ({ message }?: {
60
61
  message?: DraftMessage | LocalMessage;
61
62
  }) => void;
63
+ getSnapshot: () => LinkPreviewsManagerSnapshot;
64
+ restoreSnapshot: (snapshot: LinkPreviewsManagerSnapshot) => void;
62
65
  private _findAndEnrichUrls;
63
66
  cancelURLEnrichment: () => void;
64
67
  /**
@@ -11,10 +11,17 @@ import { StateStore } from '../store';
11
11
  import { generateUUIDv4 } from '../utils';
12
12
  import { Channel } from '../channel';
13
13
  import { Thread } from '../thread';
14
- import type { ChannelAPIResponse, DraftResponse, LocalMessage, LocalMessageBase, MessageResponse } from '../types';
14
+ import type { ChannelAPIResponse, CommandResponse, DraftResponse, LocalMessage, LocalMessageBase, MessageResponse } from '../types';
15
15
  import { WithSubscriptions } from '../utils/WithSubscriptions';
16
16
  import type { StreamChat } from '../client';
17
17
  import type { MessageComposerConfig } from './configuration/types';
18
+ import type { CommandSuggestionDisabledReason, TextComposerCommandActivationEffect, TextComposerCommandClearEffect } from './middleware/textComposer/types';
19
+ import type { AttachmentManagerSnapshot } from './attachmentManager';
20
+ import type { CustomDataManagerSnapshot } from './CustomDataManager';
21
+ import type { LinkPreviewsManagerSnapshot } from './linkPreviewsManager';
22
+ import type { LocationComposerSnapshot } from './LocationComposer';
23
+ import type { PollComposerSnapshot } from './pollComposer';
24
+ import type { TextComposerSnapshot } from './textComposer';
18
25
  import type { DeepPartial } from '../types.utility';
19
26
  type UnregisterSubscriptions = Unsubscribe;
20
27
  export type LastComposerChange = {
@@ -24,6 +31,22 @@ export type LastComposerChange = {
24
31
  export type EditingAuditState = {
25
32
  lastChange: LastComposerChange;
26
33
  };
34
+ export type BuiltInMessageComposerEffect = TextComposerCommandActivationEffect | TextComposerCommandClearEffect;
35
+ export type CustomMessageComposerEffect = {
36
+ type: string & {};
37
+ } & Record<string, unknown>;
38
+ export type MessageComposerEffect = BuiltInMessageComposerEffect | CustomMessageComposerEffect;
39
+ export type MessageComposerEffectHandler<T extends {
40
+ type: string;
41
+ } = MessageComposerEffect> = (effect: T, composer: MessageComposer) => void;
42
+ export type MessageComposerSnapshot = {
43
+ attachmentManager: AttachmentManagerSnapshot;
44
+ customDataManager: CustomDataManagerSnapshot;
45
+ linkPreviewsManager: LinkPreviewsManagerSnapshot;
46
+ locationComposer: LocationComposerSnapshot;
47
+ pollComposer: PollComposerSnapshot;
48
+ textComposer: TextComposerSnapshot;
49
+ };
27
50
  export type LocalMessageWithLegacyThreadId = LocalMessage & {
28
51
  legacyThreadId?: string;
29
52
  };
@@ -60,6 +83,8 @@ export declare class MessageComposer extends WithSubscriptions {
60
83
  pollComposer: PollComposer;
61
84
  locationComposer: LocationComposer;
62
85
  customDataManager: CustomDataManager;
86
+ private snapshots;
87
+ private effectHandlers;
63
88
  constructor({ composition, config, compositionContext, client, }: MessageComposerOptions);
64
89
  static evaluateContextType(compositionContext: CompositionContext): "message" | "channel" | "thread" | "legacy_thread";
65
90
  static constructTag(compositionContext: CompositionContext): `${ReturnType<typeof MessageComposer.evaluateContextType>}_${string}`;
@@ -76,6 +101,8 @@ export declare class MessageComposer extends WithSubscriptions {
76
101
  get draftId(): string | null;
77
102
  get lastChange(): LastComposerChange;
78
103
  get quotedMessage(): LocalMessageBase | null;
104
+ getCommandDisabledReason: (command: CommandResponse) => CommandSuggestionDisabledReason | undefined;
105
+ isCommandDisabled: (command: CommandResponse) => boolean;
79
106
  get pollId(): string | null;
80
107
  get showReplyInChannel(): boolean;
81
108
  get hasSendableData(): boolean;
@@ -89,6 +116,17 @@ export declare class MessageComposer extends WithSubscriptions {
89
116
  }) => void;
90
117
  initStateFromChannelResponse: (channelApiResponse: ChannelAPIResponse) => void;
91
118
  initEditingAuditState: (composition?: DraftResponse | MessageResponse | LocalMessage) => EditingAuditState;
119
+ clearSnapshots: () => void;
120
+ getSnapshot: () => MessageComposerSnapshot;
121
+ restoreSnapshot: (snapshot: MessageComposerSnapshot) => void;
122
+ captureSnapshot: (snapshot?: MessageComposerSnapshot) => void;
123
+ popSnapshot: () => MessageComposerSnapshot | undefined;
124
+ registerEffectHandler: <T extends {
125
+ type: string;
126
+ }>(type: T["type"], handler: MessageComposerEffectHandler<T>) => void;
127
+ applyEffects: <T extends {
128
+ type: string;
129
+ }>(effects?: T[]) => void;
92
130
  private logStateUpdateTimestamp;
93
131
  private logDraftUpdateTimestamp;
94
132
  registerDraftEventSubscriptions: () => () => void;
@@ -1,10 +1,11 @@
1
1
  import { MiddlewareExecutor } from '../../../middleware';
2
2
  import type { ExecuteParams, MiddlewareExecutionResult, MiddlewareHandler } from '../../../middleware';
3
- import type { Suggestion, TextComposerMiddlewareExecutorOptions, TextComposerState } from './types';
3
+ import type { Suggestion, TextComposerEffect, TextComposerMiddlewareExecutorOptions, TextComposerState } from './types';
4
4
  export type TextComposerMiddlewareExecutorState<T extends Suggestion = Suggestion> = TextComposerState<T> & {
5
5
  change?: {
6
6
  selectedSuggestion?: T;
7
7
  };
8
+ effects?: TextComposerEffect[];
8
9
  };
9
10
  export type TextComposerHandlerNames = 'onChange' | 'onSuggestionItemSelect';
10
11
  export type TextComposerMiddleware<T extends Suggestion = Suggestion> = {
@@ -0,0 +1,5 @@
1
+ import type { Middleware } from '../../../middleware';
2
+ import type { CommandSuggestion } from './types';
3
+ import type { TextComposerMiddlewareExecutorState } from './TextComposerMiddlewareExecutor';
4
+ export type CommandEffectsMiddleware = Middleware<TextComposerMiddlewareExecutorState<CommandSuggestion>, 'onChange' | 'onSuggestionItemSelect'>;
5
+ export declare const createCommandEffectsMiddleware: () => CommandEffectsMiddleware;
@@ -0,0 +1,7 @@
1
+ import type { MessageComposer } from '../../messageComposer';
2
+ import type { CommandResponse } from '../../../types';
3
+ export declare function escapeCommandRegExp(text: string): string;
4
+ export declare const getRawCommandName: (text?: string) => string | undefined;
5
+ export declare const getCompleteCommandInString: (text: string) => string | null;
6
+ export declare const stripCommandFromText: (text: string, commandName: string) => string;
7
+ export declare const notifyCommandDisabled: (composer: MessageComposer, command: CommandResponse) => true | undefined;
@@ -2,6 +2,7 @@ import type { Channel } from '../../../channel';
2
2
  import type { Middleware } from '../../../middleware';
3
3
  import type { SearchSourceOptions } from '../../../search';
4
4
  import { BaseSearchSourceSync } from '../../../search';
5
+ import type { MessageComposer } from '../../messageComposer';
5
6
  import type { CommandSuggestion, TextComposerMiddlewareOptions } from './types';
6
7
  import type { TextComposerMiddlewareExecutorState } from './TextComposerMiddlewareExecutor';
7
8
  export declare class CommandSearchSource extends BaseSearchSourceSync<CommandSuggestion> {
@@ -35,5 +36,6 @@ export declare class CommandSearchSource extends BaseSearchSourceSync<CommandSug
35
36
  }
36
37
  export type CommandsMiddleware = Middleware<TextComposerMiddlewareExecutorState<CommandSuggestion>, 'onChange' | 'onSuggestionItemSelect'>;
37
38
  export declare const createCommandsMiddleware: (channel: Channel, options?: Partial<TextComposerMiddlewareOptions> & {
39
+ composer?: MessageComposer;
38
40
  searchSource?: CommandSearchSource;
39
41
  }) => CommandsMiddleware;
@@ -1,5 +1,6 @@
1
1
  export * from './activeCommandGuard';
2
2
  export * from './commands';
3
+ export * from './commandEffects';
3
4
  export * from './commandStringExtraction';
4
5
  export * from './mentions';
5
6
  export * from './validation';
@@ -10,7 +10,6 @@ export declare const getTriggerCharWithToken: ({ trigger, text, isCommand, accep
10
10
  isCommand?: boolean;
11
11
  acceptTrailingSpaces?: boolean;
12
12
  }) => string | null;
13
- export declare const getCompleteCommandInString: (text: string) => string | null;
14
13
  export declare const insertItemWithTrigger: ({ insertText, selection, text, trigger, }: {
15
14
  insertText: string;
16
15
  selection: TextSelection;
@@ -28,39 +27,6 @@ export declare const replaceWordWithEntity: ({ caretPosition, getEntityString, t
28
27
  getEntityString: (word: string) => Promise<string | null> | string | null;
29
28
  text: string;
30
29
  }) => Promise<string>;
31
- /**
32
- * Escapes a string for use in a regular expression
33
- * @param text - The string to escape
34
- * @returns The escaped string
35
- * What does this regex do?
36
-
37
- The regex escapes special regex characters by adding a backslash before them. Here's what it matches:
38
- - dash
39
- [ ] square brackets
40
- { } curly braces
41
- ( ) parentheses
42
- * asterisk
43
- + plus
44
- ? question mark
45
- . period
46
- , comma
47
- / forward slash
48
- \ backslash
49
- ^ caret
50
- $ dollar sign
51
- | pipe
52
- # hash
53
-
54
- The \\$& replacement adds a backslash before any matched character.
55
- This is needed when you want to use these characters literally
56
- in a regex pattern instead of their special regex meanings.
57
- For example:
58
- escapeRegExp("hello.world") // Returns: "hello\.world"
59
- escapeRegExp("[test]") // Returns: "\[test\]"
60
-
61
- This is commonly used when building dynamic regex patterns from user input to prevent special characters from being interpreted as regex syntax.
62
- */
63
- export declare function escapeRegExp(text: string): string;
64
30
  export type TokenizationPayload = {
65
31
  tokenizedDisplayName: {
66
32
  token: string;
@@ -1,4 +1,5 @@
1
1
  import type { MessageComposer } from '../../messageComposer';
2
+ import type { MessageComposerEffect } from '../../messageComposer';
2
3
  import type { CommandResponse, UserResponse } from '../../../types';
3
4
  import type { TokenizationPayload } from './textMiddlewareUtils';
4
5
  import type { SearchSource, SearchSourceSync } from '../../../search';
@@ -9,10 +10,22 @@ export type TextComposerSuggestion<T = unknown> = T & {
9
10
  export type BaseSuggestion = {
10
11
  id: string;
11
12
  };
13
+ export type CommandSuggestionDisabledReason = 'editing' | 'quoted_message';
12
14
  export type CommandSuggestion = BaseSuggestion & CommandResponse;
13
15
  export type UserSuggestion = BaseSuggestion & UserResponse & TokenizationPayload;
14
16
  export type CustomValidSuggestion = BaseSuggestion & CustomTextComposerSuggestion;
15
17
  export type Suggestion = CommandSuggestion | UserSuggestion | CustomValidSuggestion;
18
+ export type TextComposerStateSnapshot = TextComposerState;
19
+ export type TextComposerCommandActivationStateToRestore = Partial<TextComposerStateSnapshot>;
20
+ export type TextComposerCommandActivationEffect = {
21
+ command: CommandResponse;
22
+ stateToRestore?: TextComposerCommandActivationStateToRestore;
23
+ type: 'command.activate';
24
+ };
25
+ export type TextComposerCommandClearEffect = {
26
+ type: 'command.clear';
27
+ };
28
+ export type TextComposerEffect = MessageComposerEffect;
16
29
  export type TextComposerMiddlewareOptions = {
17
30
  minChars: number;
18
31
  trigger: string;
@@ -3,6 +3,7 @@ import { StateStore } from '../store';
3
3
  import { VotingVisibility } from '../types';
4
4
  import type { MessageComposer } from './messageComposer';
5
5
  import type { PollComposerFieldErrors, PollComposerState, UpdateFieldsData } from './middleware/pollComposer';
6
+ export type PollComposerSnapshot = PollComposerState;
6
7
  export type PollComposerOptions = {
7
8
  composer: MessageComposer;
8
9
  };
@@ -25,6 +26,8 @@ export declare class PollComposer {
25
26
  get voting_visibility(): VotingVisibility | undefined;
26
27
  get canCreatePoll(): boolean;
27
28
  initState: () => void;
29
+ getSnapshot: () => PollComposerSnapshot;
30
+ restoreSnapshot: (snapshot: PollComposerSnapshot) => void;
28
31
  /**
29
32
  * Updates specified fields and generates relevant errors
30
33
  * @param data
@@ -2,7 +2,7 @@ import { TextComposerMiddlewareExecutor } from './middleware';
2
2
  import { StateStore } from '../store';
3
3
  import type { TextComposerSuggestion } from './middleware/textComposer/types';
4
4
  import type { TextSelection } from './middleware/textComposer/types';
5
- import type { TextComposerState } from './middleware/textComposer/types';
5
+ import type { TextComposerState, TextComposerStateSnapshot } from './middleware/textComposer/types';
6
6
  import type { Suggestions } from './middleware/textComposer/types';
7
7
  import type { MessageComposer } from './messageComposer';
8
8
  import type { CommandResponse, DraftMessage, LocalMessage, UserResponse } from '../types';
@@ -10,6 +10,7 @@ export type TextComposerOptions = {
10
10
  composer: MessageComposer;
11
11
  message?: DraftMessage | LocalMessage;
12
12
  };
13
+ export type TextComposerSnapshot = TextComposerStateSnapshot;
13
14
  export declare const textIsEmpty: (text: string) => boolean;
14
15
  export declare class TextComposer {
15
16
  readonly composer: MessageComposer;
@@ -37,6 +38,8 @@ export declare class TextComposer {
37
38
  initState: ({ message }?: {
38
39
  message?: DraftMessage | LocalMessage;
39
40
  }) => void;
41
+ getSnapshot: (state?: TextComposerState) => TextComposerSnapshot;
42
+ restoreSnapshot: (snapshot: TextComposerSnapshot) => void;
40
43
  setMentionedUsers(users: UserResponse[]): void;
41
44
  clearCommand(): void;
42
45
  upsertMentionedUser: (user: UserResponse) => void;
@@ -56,6 +59,7 @@ export declare class TextComposer {
56
59
  }) => void;
57
60
  setSuggestions: (suggestions: Suggestions) => void;
58
61
  closeSuggestions: () => void;
62
+ private commitState;
59
63
  handleChange: ({ text, selection, }: {
60
64
  selection: TextSelection;
61
65
  text: string;
@@ -81,6 +81,7 @@ export type AppSettingsAPIResponse = APIResponse & {
81
81
  uploads?: boolean;
82
82
  url_enrichment?: boolean;
83
83
  user_message_reminders?: boolean;
84
+ push_level?: 'all' | 'all_mentions' | 'direct_mentions' | 'mentions' | 'none' | '';
84
85
  }>;
85
86
  reminders_interval: number;
86
87
  async_moderation_config?: AsyncModerationOptions;
@@ -115,9 +116,11 @@ export type AppSettingsAPIResponse = APIResponse & {
115
116
  max_aggregated_activities_length?: number;
116
117
  moderation_bulk_submit_action_enabled?: boolean;
117
118
  moderation_dashboard_preferences?: Record<string, unknown> | null;
119
+ moderation_audio_call_moderation_enabled?: boolean;
118
120
  moderation_enabled?: boolean;
119
121
  moderation_llm_configurability_enabled?: boolean;
120
122
  moderation_multitenant_blocklist_enabled?: boolean;
123
+ moderation_video_call_moderation_enabled?: boolean;
121
124
  moderation_webhook_url?: string;
122
125
  multi_tenant_enabled?: boolean;
123
126
  name?: string;
@@ -450,8 +453,8 @@ export type LocalMessageBase = Omit<MessageResponseBase, 'created_at' | 'deleted
450
453
  updated_at: Date;
451
454
  };
452
455
  export type LocalMessage = LocalMessageBase & {
453
- error?: ErrorFromResponse<APIErrorResponse>;
454
- quoted_message?: LocalMessageBase;
456
+ error?: ErrorFromResponse<APIErrorResponse> | null;
457
+ quoted_message?: LocalMessageBase | null;
455
458
  };
456
459
  /**
457
460
  * @deprecated in favor of LocalMessage
@@ -627,6 +630,8 @@ export type MessageResponseBase = MessageBase & {
627
630
  member?: ChannelMemberResponse;
628
631
  mentioned_users?: UserResponse[];
629
632
  mentioned_channel?: boolean;
633
+ mentioned_here?: boolean;
634
+ mentioned_roles?: string[];
630
635
  message_text_updated_at?: string;
631
636
  moderation?: ModerationResponse;
632
637
  moderation_details?: ModerationDetailsResponse;
@@ -658,6 +663,12 @@ export type ReactionGroupResponse = {
658
663
  sum_scores: number;
659
664
  first_reaction_at?: string;
660
665
  last_reaction_at?: string;
666
+ latest_reactions_by?: ReactionGroupUserResponse[];
667
+ };
668
+ export type ReactionGroupUserResponse = {
669
+ created_at: string;
670
+ user_id: string;
671
+ user?: UserResponse;
661
672
  };
662
673
  export type ModerationDetailsResponse = {
663
674
  action: 'MESSAGE_RESPONSE_ACTION_BOUNCE' | (string & {});
@@ -1964,6 +1975,7 @@ export type ChannelConfigFields = {
1964
1975
  uploads?: boolean;
1965
1976
  url_enrichment?: boolean;
1966
1977
  user_message_reminders?: boolean;
1978
+ push_level?: 'all' | 'all_mentions' | 'direct_mentions' | 'mentions' | 'none' | '';
1967
1979
  };
1968
1980
  export type ChannelConfigWithInfo = ChannelConfigFields & CreatedAtUpdatedAt & {
1969
1981
  commands?: CommandResponse[];
@@ -2184,9 +2196,12 @@ export type Mute = {
2184
2196
  updated_at: string;
2185
2197
  user: UserResponse;
2186
2198
  };
2199
+ export type PartialUpdateChannelFields = Partial<ChannelResponse> & {
2200
+ config_overrides?: Partial<ChannelConfigFields>;
2201
+ };
2187
2202
  export type PartialUpdateChannel = {
2188
- set?: Partial<ChannelResponse>;
2189
- unset?: Array<keyof ChannelResponse>;
2203
+ set?: PartialUpdateChannelFields;
2204
+ unset?: Array<keyof PartialUpdateChannelFields>;
2190
2205
  };
2191
2206
  export type PartialUpdateMember = {
2192
2207
  set?: ChannelMemberUpdates;
@@ -122,6 +122,8 @@ export declare const toDeletedMessage: ({ message, deletedAt, hardDelete, }: {
122
122
  deleted_reply_count?: number | undefined;
123
123
  member?: import("./types").ChannelMemberResponse | undefined;
124
124
  mentioned_channel?: boolean | undefined;
125
+ mentioned_here?: boolean | undefined;
126
+ mentioned_roles?: string[] | undefined;
125
127
  message_text_updated_at?: string | undefined;
126
128
  moderation?: import("./types").ModerationResponse | undefined;
127
129
  moderation_details?: import("./types").ModerationDetailsResponse | undefined;
@@ -142,8 +144,8 @@ export declare const toDeletedMessage: ({ message, deletedAt, hardDelete, }: {
142
144
  pinned_at: Date | null;
143
145
  status: string;
144
146
  updated_at: Date;
145
- error?: import("./types").ErrorFromResponse<import("./types").APIErrorResponse>;
146
- quoted_message?: LocalMessageBase;
147
+ error?: import("./types").ErrorFromResponse<import("./types").APIErrorResponse> | null;
148
+ quoted_message?: LocalMessageBase | null;
147
149
  };
148
150
  export declare const deleteUserMessages: ({ messages, user, hardDelete, deletedAt, }: {
149
151
  messages: Array<LocalMessage>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stream-chat",
3
- "version": "9.42.3",
3
+ "version": "9.43.1",
4
4
  "description": "JS SDK for the Stream Chat API",
5
5
  "homepage": "https://getstream.io/chat/",
6
6
  "author": {
package/src/client.ts CHANGED
@@ -4,7 +4,6 @@
4
4
  import type { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
5
5
  import axios from 'axios';
6
6
  import https from 'https';
7
- import type WebSocket from 'isomorphic-ws';
8
7
 
9
8
  import { Channel } from './channel';
10
9
  import { ClientState } from './client_state';
@@ -1381,13 +1380,6 @@ export class StreamChat {
1381
1380
  });
1382
1381
  };
1383
1382
 
1384
- handleEvent = (messageEvent: WebSocket.MessageEvent) => {
1385
- // dispatch the event to the channel listeners
1386
- const jsonString = messageEvent.data as string;
1387
- const event = JSON.parse(jsonString) as Event;
1388
- this.dispatchEvent(event);
1389
- };
1390
-
1391
1383
  /**
1392
1384
  * Updates the members, watchers and read references of the currently active channels that contain this user
1393
1385
  *
package/src/connection.ts CHANGED
@@ -477,12 +477,13 @@ export class StableWSConnection {
477
477
  if (this.wsID !== wsID) return;
478
478
 
479
479
  this._log('onmessage() - onmessage callback', { event, wsID });
480
- const data = typeof event.data === 'string' ? JSON.parse(event.data) : null;
480
+ if (typeof event.data !== 'string') return;
481
+ const data = JSON.parse(event.data);
481
482
 
482
483
  // we wait till the first message before we consider the connection open..
483
484
  // the reason for this is that auth errors and similar errors trigger a ws.onopen and immediately
484
485
  // after that a ws.onclose..
485
- if (!this.isResolved && data) {
486
+ if (!this.isResolved) {
486
487
  this.isResolved = true;
487
488
  if (data.error) {
488
489
  this.rejectPromise?.(this._errorFromWSEvent(data, false));
@@ -496,11 +497,11 @@ export class StableWSConnection {
496
497
  // trigger the event..
497
498
  this.lastEvent = new Date();
498
499
 
499
- if (data && data.type === 'health.check') {
500
+ if (data.type === 'health.check') {
500
501
  this.scheduleNextPing();
501
502
  }
502
503
 
503
- this.client.handleEvent(event);
504
+ this.client.dispatchEvent(data);
504
505
  this.scheduleConnectionCheck();
505
506
  };
506
507
 
@@ -13,6 +13,8 @@ export type CustomDataManagerState = {
13
13
  custom: CustomMessageComposerData;
14
14
  };
15
15
 
16
+ export type CustomDataManagerSnapshot = CustomDataManagerState;
17
+
16
18
  export type CustomDataManagerOptions = {
17
19
  composer: MessageComposer;
18
20
  message?: DraftMessage | LocalMessage;
@@ -50,6 +52,12 @@ export class CustomDataManager {
50
52
  this.state.next(initState({ composer: this.composer, message }));
51
53
  };
52
54
 
55
+ getSnapshot = (): CustomDataManagerSnapshot => this.state.getLatestValue();
56
+
57
+ restoreSnapshot = (snapshot: CustomDataManagerSnapshot) => {
58
+ this.state.next(snapshot);
59
+ };
60
+
53
61
  setMessageData(data: DeepPartial<CustomMessageData>) {
54
62
  this.state.partialNext({
55
63
  message: {
@@ -24,6 +24,8 @@ export type LocationComposerState = {
24
24
  location: StaticLocationPreview | LiveLocationPreview | null;
25
25
  };
26
26
 
27
+ export type LocationComposerSnapshot = LocationComposerState;
28
+
27
29
  const MIN_LIVE_LOCATION_SHARE_DURATION = 60 * 1000; // 1 minute;
28
30
 
29
31
  const initState = ({
@@ -79,6 +81,12 @@ export class LocationComposer {
79
81
  this.state.next(initState({ message }));
80
82
  };
81
83
 
84
+ getSnapshot = (): LocationComposerSnapshot => this.state.getLatestValue();
85
+
86
+ restoreSnapshot = (snapshot: LocationComposerSnapshot) => {
87
+ this.state.next(snapshot);
88
+ };
89
+
82
90
  setData = (data: { durationMs?: number } & Coords) => {
83
91
  if (!this.config.enabled) return;
84
92
  if (!data.latitude || !data.longitude) return;