stream-chat 9.7.0 → 9.8.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 (32) hide show
  1. package/dist/cjs/index.browser.cjs +176 -8
  2. package/dist/cjs/index.browser.cjs.map +3 -3
  3. package/dist/cjs/index.node.cjs +181 -8
  4. package/dist/cjs/index.node.cjs.map +3 -3
  5. package/dist/esm/index.js +176 -8
  6. package/dist/esm/index.js.map +3 -3
  7. package/dist/types/messageComposer/middleware/messageComposer/commandInjection.d.ts +4 -0
  8. package/dist/types/messageComposer/middleware/messageComposer/index.d.ts +1 -0
  9. package/dist/types/messageComposer/middleware/textComposer/activeCommandGuard.d.ts +4 -0
  10. package/dist/types/messageComposer/middleware/textComposer/commandStringExtraction.d.ts +5 -0
  11. package/dist/types/messageComposer/middleware/textComposer/index.d.ts +2 -0
  12. package/dist/types/messageComposer/middleware/textComposer/textMiddlewareUtils.d.ts +6 -0
  13. package/dist/types/messageComposer/middleware/textComposer/types.d.ts +1 -0
  14. package/dist/types/messageComposer/textComposer.d.ts +6 -3
  15. package/dist/types/pagination/BasePaginator.d.ts +1 -1
  16. package/dist/types/pagination/ReminderPaginator.d.ts +6 -2
  17. package/dist/types/reminders/ReminderManager.d.ts +3 -3
  18. package/dist/types/types.d.ts +1 -1
  19. package/package.json +1 -1
  20. package/src/messageComposer/middleware/messageComposer/commandInjection.ts +72 -0
  21. package/src/messageComposer/middleware/messageComposer/index.ts +1 -0
  22. package/src/messageComposer/middleware/textComposer/activeCommandGuard.ts +20 -0
  23. package/src/messageComposer/middleware/textComposer/commandStringExtraction.ts +56 -0
  24. package/src/messageComposer/middleware/textComposer/commands.ts +22 -4
  25. package/src/messageComposer/middleware/textComposer/index.ts +2 -0
  26. package/src/messageComposer/middleware/textComposer/textMiddlewareUtils.ts +14 -0
  27. package/src/messageComposer/middleware/textComposer/types.ts +1 -0
  28. package/src/messageComposer/textComposer.ts +23 -3
  29. package/src/pagination/BasePaginator.ts +1 -1
  30. package/src/pagination/ReminderPaginator.ts +20 -2
  31. package/src/reminders/ReminderManager.ts +16 -2
  32. package/src/types.ts +1 -1
@@ -0,0 +1,4 @@
1
+ import type { MessageComposer } from '../../messageComposer';
2
+ import type { MessageCompositionMiddleware, MessageDraftCompositionMiddleware } from '../messageComposer/types';
3
+ export declare const createCommandInjectionMiddleware: (composer: MessageComposer) => MessageCompositionMiddleware;
4
+ export declare const createDraftCommandInjectionMiddleware: (composer: MessageComposer) => MessageDraftCompositionMiddleware;
@@ -7,3 +7,4 @@ export * from './MessageComposerMiddlewareExecutor';
7
7
  export * from './messageComposerState';
8
8
  export * from './textComposer';
9
9
  export * from './types';
10
+ export * from './commandInjection';
@@ -0,0 +1,4 @@
1
+ import type { Middleware } from '../../../middleware';
2
+ import type { TextComposerMiddlewareExecutorState } from './TextComposerMiddlewareExecutor';
3
+ export type PreCommandMiddleware = Middleware<TextComposerMiddlewareExecutorState, 'onChange' | 'onSuggestionItemSelect'>;
4
+ export declare const createActiveCommandGuardMiddleware: () => PreCommandMiddleware;
@@ -0,0 +1,5 @@
1
+ import type { TextComposerMiddlewareExecutorState } from './TextComposerMiddlewareExecutor';
2
+ import type { CommandSuggestion } from './types';
3
+ import type { Middleware } from '../../../middleware';
4
+ export type CommandStringExtractionMiddleware = Middleware<TextComposerMiddlewareExecutorState<CommandSuggestion>, 'onChange' | 'onSuggestionItemSelect'>;
5
+ export declare const createCommandStringExtractionMiddleware: () => CommandStringExtractionMiddleware;
@@ -1,4 +1,6 @@
1
+ export * from './activeCommandGuard';
1
2
  export * from './commands';
3
+ export * from './commandStringExtraction';
2
4
  export * from './mentions';
3
5
  export * from './validation';
4
6
  export * from './TextComposerMiddlewareExecutor';
@@ -1,10 +1,16 @@
1
1
  import type { TextSelection } from './types';
2
+ /**
3
+ * For commands, we want to match all patterns except:
4
+ * 1. Text not starting with trigger
5
+ * 2. Trigger in middle of text
6
+ */
2
7
  export declare const getTriggerCharWithToken: ({ trigger, text, isCommand, acceptTrailingSpaces, }: {
3
8
  trigger: string;
4
9
  text: string;
5
10
  isCommand?: boolean;
6
11
  acceptTrailingSpaces?: boolean;
7
12
  }) => string | null;
13
+ export declare const getCompleteCommandInString: (text: string) => string | null;
8
14
  export declare const insertItemWithTrigger: ({ insertText, selection, text, trigger, }: {
9
15
  insertText: string;
10
16
  selection: TextSelection;
@@ -33,5 +33,6 @@ export type TextComposerState<T extends Suggestion = Suggestion> = {
33
33
  mentionedUsers: UserResponse[];
34
34
  selection: TextSelection;
35
35
  text: string;
36
+ command?: CommandResponse | null;
36
37
  suggestions?: Suggestions<T>;
37
38
  };
@@ -5,7 +5,7 @@ import type { TextSelection } from './middleware/textComposer/types';
5
5
  import type { TextComposerState } from './middleware/textComposer/types';
6
6
  import type { Suggestions } from './middleware/textComposer/types';
7
7
  import type { MessageComposer } from './messageComposer';
8
- import type { DraftMessage, LocalMessage, UserResponse } from '../types';
8
+ import type { CommandResponse, DraftMessage, LocalMessage, UserResponse } from '../types';
9
9
  export type TextComposerOptions = {
10
10
  composer: MessageComposer;
11
11
  message?: DraftMessage | LocalMessage;
@@ -28,6 +28,7 @@ export declare class TextComposer {
28
28
  set maxLengthOnSend(maxLengthOnSend: number | undefined);
29
29
  get publishTypingEvents(): boolean;
30
30
  set publishTypingEvents(publishTypingEvents: boolean);
31
+ get command(): CommandResponse | null | undefined;
31
32
  get mentionedUsers(): UserResponse[];
32
33
  get selection(): TextSelection;
33
34
  get suggestions(): Suggestions<import("..").Suggestion> | undefined;
@@ -37,15 +38,17 @@ export declare class TextComposer {
37
38
  message?: DraftMessage | LocalMessage;
38
39
  }) => void;
39
40
  setMentionedUsers(users: UserResponse[]): void;
41
+ clearCommand(): void;
40
42
  upsertMentionedUser: (user: UserResponse) => void;
41
43
  getMentionedUser: (userId: string) => UserResponse | undefined;
42
44
  removeMentionedUser: (userId: string) => void;
45
+ setCommand: (command: CommandResponse | null) => void;
43
46
  setText: (text: string) => void;
44
47
  setSelection: (selection: TextSelection) => void;
45
- insertText: ({ text, selection }: {
48
+ insertText: ({ text, selection, }: {
46
49
  text: string;
47
50
  selection?: TextSelection;
48
- }) => void;
51
+ }) => Promise<void>;
49
52
  wrapSelection: ({ head, selection, tail, }: {
50
53
  head?: string;
51
54
  selection?: TextSelection;
@@ -37,7 +37,7 @@ export type PaginatorOptions = {
37
37
  export declare const DEFAULT_PAGINATION_OPTIONS: Required<PaginatorOptions>;
38
38
  export declare abstract class BasePaginator<T> {
39
39
  state: StateStore<PaginatorState<T>>;
40
- protected pageSize: number;
40
+ pageSize: number;
41
41
  protected _executeQueryDebounced: DebouncedExecQueryFunction;
42
42
  protected _isCursorPagination: boolean;
43
43
  protected constructor(options?: PaginatorOptions);
@@ -4,8 +4,12 @@ import type { ReminderFilters, ReminderResponse, ReminderSort } from '../types';
4
4
  import type { StreamChat } from '../client';
5
5
  export declare class ReminderPaginator extends BasePaginator<ReminderResponse> {
6
6
  private client;
7
- filters: ReminderFilters | undefined;
8
- sort: ReminderSort | undefined;
7
+ protected _filters: ReminderFilters | undefined;
8
+ protected _sort: ReminderSort | undefined;
9
+ get filters(): ReminderFilters | undefined;
10
+ get sort(): ReminderSort | undefined;
11
+ set filters(filters: ReminderFilters | undefined);
12
+ set sort(sort: ReminderSort | undefined);
9
13
  constructor(client: StreamChat, options?: PaginatorOptions);
10
14
  query: ({ direction, }: PaginationQueryParams) => Promise<PaginationQueryReturnValue<ReminderResponse>>;
11
15
  filterQueryResults: (items: ReminderResponse[]) => ReminderResponse[];
@@ -20,11 +20,11 @@ export type ReminderManagerState = {
20
20
  };
21
21
  export type ReminderManagerConfig = {
22
22
  scheduledOffsetsMs: number[];
23
- stopTimerRefreshBoundaryMs?: number;
23
+ stopTimerRefreshBoundaryMs: number;
24
24
  };
25
25
  export type ReminderManagerOptions = {
26
26
  client: StreamChat;
27
- config?: ReminderManagerConfig;
27
+ config?: Partial<ReminderManagerConfig>;
28
28
  };
29
29
  export declare class ReminderManager extends WithSubscriptions {
30
30
  private client;
@@ -33,7 +33,7 @@ export declare class ReminderManager extends WithSubscriptions {
33
33
  paginator: ReminderPaginator;
34
34
  constructor({ client, config }: ReminderManagerOptions);
35
35
  updateConfig(config: Partial<ReminderManagerConfig>): void;
36
- get stopTimerRefreshBoundaryMs(): number | undefined;
36
+ get stopTimerRefreshBoundaryMs(): number;
37
37
  get scheduledOffsetsMs(): number[];
38
38
  get reminders(): Map<string, Reminder>;
39
39
  getFromState(messageId: MessageId): Reminder | undefined;
@@ -2931,7 +2931,7 @@ export type ReminderAPIResponse = APIResponse & {
2931
2931
  };
2932
2932
  export type CreateReminderOptions = {
2933
2933
  messageId: string;
2934
- remind_at?: string;
2934
+ remind_at?: string | null;
2935
2935
  user_id?: string;
2936
2936
  };
2937
2937
  export type UpdateReminderOptions = CreateReminderOptions;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stream-chat",
3
- "version": "9.7.0",
3
+ "version": "9.8.0",
4
4
  "description": "JS SDK for the Stream Chat API",
5
5
  "homepage": "https://getstream.io/chat/",
6
6
  "author": {
@@ -0,0 +1,72 @@
1
+ import type { MessageComposer } from '../../messageComposer';
2
+ import type {
3
+ MessageComposerMiddlewareState,
4
+ MessageCompositionMiddleware,
5
+ MessageDraftComposerMiddlewareValueState,
6
+ MessageDraftCompositionMiddleware,
7
+ } from '../messageComposer/types';
8
+ import type { MiddlewareHandlerParams } from '../../../middleware';
9
+
10
+ export const createCommandInjectionMiddleware = (
11
+ composer: MessageComposer,
12
+ ): MessageCompositionMiddleware => ({
13
+ handlers: {
14
+ compose: ({
15
+ forward,
16
+ next,
17
+ state,
18
+ }: MiddlewareHandlerParams<MessageComposerMiddlewareState>) => {
19
+ const command = composer.textComposer.command;
20
+ if (!command) {
21
+ return forward();
22
+ }
23
+ const { text } = state.localMessage;
24
+
25
+ const injection = `/${command?.name}`;
26
+ const enrichedText = `${injection} ${text}`;
27
+
28
+ return next({
29
+ ...state,
30
+ localMessage: {
31
+ ...state.localMessage,
32
+ text: enrichedText,
33
+ },
34
+ message: {
35
+ ...state.message,
36
+ text: enrichedText,
37
+ },
38
+ });
39
+ },
40
+ },
41
+ id: 'stream-io/message-composer-middleware/command-string-injection',
42
+ });
43
+
44
+ export const createDraftCommandInjectionMiddleware = (
45
+ composer: MessageComposer,
46
+ ): MessageDraftCompositionMiddleware => ({
47
+ handlers: {
48
+ compose: ({
49
+ forward,
50
+ next,
51
+ state,
52
+ }: MiddlewareHandlerParams<MessageDraftComposerMiddlewareValueState>) => {
53
+ const command = composer.textComposer.command;
54
+ if (!command) {
55
+ return forward();
56
+ }
57
+ const { text } = state.draft;
58
+
59
+ const injection = `/${command?.name}`;
60
+ const enrichedText = `${injection} ${text}`;
61
+
62
+ return next({
63
+ ...state,
64
+ draft: {
65
+ ...state.draft,
66
+ text: enrichedText,
67
+ },
68
+ });
69
+ },
70
+ },
71
+ id: 'stream-io/message-composer-middleware/draft-command-string-injection',
72
+ });
@@ -7,3 +7,4 @@ export * from './MessageComposerMiddlewareExecutor';
7
7
  export * from './messageComposerState';
8
8
  export * from './textComposer';
9
9
  export * from './types';
10
+ export * from './commandInjection';
@@ -0,0 +1,20 @@
1
+ import type { Middleware } from '../../../middleware';
2
+ import type { TextComposerMiddlewareExecutorState } from './TextComposerMiddlewareExecutor';
3
+
4
+ export type PreCommandMiddleware = Middleware<
5
+ TextComposerMiddlewareExecutorState,
6
+ 'onChange' | 'onSuggestionItemSelect'
7
+ >;
8
+
9
+ export const createActiveCommandGuardMiddleware = (): PreCommandMiddleware => ({
10
+ handlers: {
11
+ onChange: ({ complete, forward, state }) => {
12
+ if (state.command) {
13
+ return complete(state);
14
+ }
15
+ return forward();
16
+ },
17
+ onSuggestionItemSelect: ({ forward }) => forward(),
18
+ },
19
+ id: 'stream-io/text-composer/active-command-guard',
20
+ });
@@ -0,0 +1,56 @@
1
+ import type { TextComposerMiddlewareExecutorState } from './TextComposerMiddlewareExecutor';
2
+ import type { CommandSuggestion } from './types';
3
+ import type { Middleware } from '../../../middleware';
4
+ import { escapeRegExp } from './textMiddlewareUtils';
5
+
6
+ export type CommandStringExtractionMiddleware = Middleware<
7
+ TextComposerMiddlewareExecutorState<CommandSuggestion>,
8
+ 'onChange' | 'onSuggestionItemSelect'
9
+ >;
10
+
11
+ const stripCommandFromText = (text: string, commandName: string) =>
12
+ text.replace(new RegExp(`^${escapeRegExp(`/${commandName}`)}\\s*`), '');
13
+
14
+ export const createCommandStringExtractionMiddleware =
15
+ (): CommandStringExtractionMiddleware => ({
16
+ handlers: {
17
+ onChange: ({ complete, forward, state }) => {
18
+ const { command } = state;
19
+
20
+ if (!command?.name) {
21
+ return forward();
22
+ }
23
+
24
+ const newText = stripCommandFromText(state.text, command.name);
25
+
26
+ return complete({
27
+ ...state,
28
+ selection: {
29
+ end: newText.length,
30
+ start: newText.length,
31
+ },
32
+ text: newText,
33
+ });
34
+ },
35
+ onSuggestionItemSelect: ({ next, forward, state }) => {
36
+ const { command } = state;
37
+
38
+ if (!command) {
39
+ return forward();
40
+ }
41
+
42
+ const triggerWithCommand = `/${command?.name} `;
43
+
44
+ const newText = state.text.slice(triggerWithCommand.length);
45
+ return next({
46
+ ...state,
47
+ selection: {
48
+ end: newText.length,
49
+ start: newText.length,
50
+ },
51
+ text: newText,
52
+ });
53
+ },
54
+ },
55
+ id: 'stream-io/text-composer/command-string-extraction',
56
+ });
@@ -5,7 +5,11 @@ import { BaseSearchSourceSync } from '../../../search';
5
5
  import type { CommandResponse } from '../../../types';
6
6
  import { mergeWith } from '../../../utils/mergeWith';
7
7
  import type { CommandSuggestion, TextComposerMiddlewareOptions } from './types';
8
- import { getTriggerCharWithToken, insertItemWithTrigger } from './textMiddlewareUtils';
8
+ import {
9
+ getCompleteCommandInString,
10
+ getTriggerCharWithToken,
11
+ insertItemWithTrigger,
12
+ } from './textMiddlewareUtils';
9
13
  import type { TextComposerMiddlewareExecutorState } from './TextComposerMiddlewareExecutor';
10
14
 
11
15
  export class CommandSearchSource extends BaseSearchSourceSync<CommandSuggestion> {
@@ -115,10 +119,22 @@ export const createCommandsMiddleware = (
115
119
  handlers: {
116
120
  onChange: ({ state, next, complete, forward }) => {
117
121
  if (!state.selection) return forward();
122
+ const finalText = state.text.slice(0, state.selection.end);
123
+ const commandName = getCompleteCommandInString(finalText);
124
+ if (commandName) {
125
+ const command = searchSource?.query(commandName).items[0];
126
+ if (command) {
127
+ return next({
128
+ ...state,
129
+ command,
130
+ suggestions: undefined,
131
+ });
132
+ }
133
+ }
118
134
 
119
135
  const triggerWithToken = getTriggerCharWithToken({
120
136
  trigger: finalOptions.trigger,
121
- text: state.text.slice(0, state.selection.end),
137
+ text: finalText,
122
138
  acceptTrailingSpaces: false,
123
139
  isCommand: true,
124
140
  });
@@ -144,6 +160,7 @@ export const createCommandsMiddleware = (
144
160
 
145
161
  return complete({
146
162
  ...state,
163
+ command: null,
147
164
  suggestions: {
148
165
  query: triggerWithToken.slice(1),
149
166
  searchSource,
@@ -151,13 +168,13 @@ export const createCommandsMiddleware = (
151
168
  },
152
169
  });
153
170
  },
154
- onSuggestionItemSelect: ({ state, complete, forward }) => {
171
+ onSuggestionItemSelect: ({ state, next, forward }) => {
155
172
  const { selectedSuggestion } = state.change ?? {};
156
173
  if (!selectedSuggestion || state.suggestions?.trigger !== finalOptions.trigger)
157
174
  return forward();
158
175
 
159
176
  searchSource.resetStateAndActivate();
160
- return complete({
177
+ return next({
161
178
  ...state,
162
179
  ...insertItemWithTrigger({
163
180
  insertText: `/${selectedSuggestion.name} `,
@@ -165,6 +182,7 @@ export const createCommandsMiddleware = (
165
182
  text: state.text,
166
183
  trigger: finalOptions.trigger,
167
184
  }),
185
+ command: selectedSuggestion,
168
186
  suggestions: undefined,
169
187
  });
170
188
  },
@@ -1,4 +1,6 @@
1
+ export * from './activeCommandGuard';
1
2
  export * from './commands';
3
+ export * from './commandStringExtraction';
2
4
  export * from './mentions';
3
5
  export * from './validation';
4
6
  export * from './TextComposerMiddlewareExecutor';
@@ -1,5 +1,10 @@
1
1
  import type { TextSelection } from './types';
2
2
 
3
+ /**
4
+ * For commands, we want to match all patterns except:
5
+ * 1. Text not starting with trigger
6
+ * 2. Trigger in middle of text
7
+ */
3
8
  export const getTriggerCharWithToken = ({
4
9
  trigger,
5
10
  text,
@@ -12,6 +17,7 @@ export const getTriggerCharWithToken = ({
12
17
  acceptTrailingSpaces?: boolean;
13
18
  }) => {
14
19
  const triggerNorWhitespace = `[^\\s${trigger}]*`;
20
+
15
21
  const match = text.match(
16
22
  new RegExp(
17
23
  isCommand
@@ -26,6 +32,14 @@ export const getTriggerCharWithToken = ({
26
32
  return match && match[match.length - 1].trim();
27
33
  };
28
34
 
35
+ export const getCompleteCommandInString = (text: string) => {
36
+ // starts with "/" followed by 1+ non-whitespace chars followed by 1+ white-space chars
37
+ // the comand name is extracted into a separate group
38
+ const match = text.match(/^\/(\S+)\s+.*/);
39
+ const commandName = match && match[1];
40
+ return commandName;
41
+ };
42
+
29
43
  export const insertItemWithTrigger = ({
30
44
  insertText,
31
45
  selection,
@@ -38,5 +38,6 @@ export type TextComposerState<T extends Suggestion = Suggestion> = {
38
38
  mentionedUsers: UserResponse[];
39
39
  selection: TextSelection;
40
40
  text: string;
41
+ command?: CommandResponse | null;
41
42
  suggestions?: Suggestions<T>;
42
43
  };
@@ -6,7 +6,7 @@ import type { TextSelection } from './middleware/textComposer/types';
6
6
  import type { TextComposerState } from './middleware/textComposer/types';
7
7
  import type { Suggestions } from './middleware/textComposer/types';
8
8
  import type { MessageComposer } from './messageComposer';
9
- import type { DraftMessage, LocalMessage, UserResponse } from '../types';
9
+ import type { CommandResponse, DraftMessage, LocalMessage, UserResponse } from '../types';
10
10
 
11
11
  export type TextComposerOptions = {
12
12
  composer: MessageComposer;
@@ -37,6 +37,7 @@ const initState = ({
37
37
  if (!message) {
38
38
  const text = composer.config.text.defaultValue ?? '';
39
39
  return {
40
+ command: null,
40
41
  mentionedUsers: [],
41
42
  text,
42
43
  selection: { start: text.length, end: text.length },
@@ -118,6 +119,10 @@ export class TextComposer {
118
119
 
119
120
  // --- START STATE API ---
120
121
 
122
+ get command() {
123
+ return this.state.getLatestValue().command;
124
+ }
125
+
121
126
  get mentionedUsers() {
122
127
  return this.state.getLatestValue().mentionedUsers;
123
128
  }
@@ -146,6 +151,10 @@ export class TextComposer {
146
151
  this.state.partialNext({ mentionedUsers: users });
147
152
  }
148
153
 
154
+ clearCommand() {
155
+ this.state.partialNext({ command: null });
156
+ }
157
+
149
158
  upsertMentionedUser = (user: UserResponse) => {
150
159
  const mentionedUsers = [...this.mentionedUsers];
151
160
  const existingUserIndex = mentionedUsers.findIndex((u) => u.id === user.id);
@@ -169,6 +178,11 @@ export class TextComposer {
169
178
  this.state.partialNext({ mentionedUsers });
170
179
  };
171
180
 
181
+ setCommand = (command: CommandResponse | null) => {
182
+ if (command?.name === this.command?.name) return;
183
+ this.state.partialNext({ command });
184
+ };
185
+
172
186
  setText = (text: string) => {
173
187
  if (!this.enabled || text === this.text) return;
174
188
  this.state.partialNext({ text });
@@ -181,7 +195,13 @@ export class TextComposer {
181
195
  this.state.partialNext({ selection });
182
196
  };
183
197
 
184
- insertText = ({ text, selection }: { text: string; selection?: TextSelection }) => {
198
+ insertText = async ({
199
+ text,
200
+ selection,
201
+ }: {
202
+ text: string;
203
+ selection?: TextSelection;
204
+ }) => {
185
205
  if (!this.enabled) return;
186
206
 
187
207
  const finalSelection: TextSelection = selection ?? this.selection;
@@ -203,7 +223,7 @@ export class TextComposer {
203
223
  ? finalText.length
204
224
  : currentText.slice(0, expectedCursorPosition).length;
205
225
 
206
- this.state.partialNext({
226
+ await this.handleChange({
207
227
  text: finalText,
208
228
  selection: {
209
229
  start: cursorPosition,
@@ -38,7 +38,7 @@ export const DEFAULT_PAGINATION_OPTIONS: Required<PaginatorOptions> = {
38
38
 
39
39
  export abstract class BasePaginator<T> {
40
40
  state: StateStore<PaginatorState<T>>;
41
- protected pageSize: number;
41
+ pageSize: number;
42
42
  protected _executeQueryDebounced!: DebouncedExecQueryFunction;
43
43
  protected _isCursorPagination = false;
44
44
 
@@ -9,8 +9,26 @@ import type { StreamChat } from '../client';
9
9
 
10
10
  export class ReminderPaginator extends BasePaginator<ReminderResponse> {
11
11
  private client: StreamChat;
12
- filters: ReminderFilters | undefined;
13
- sort: ReminderSort | undefined;
12
+ protected _filters: ReminderFilters | undefined;
13
+ protected _sort: ReminderSort | undefined;
14
+
15
+ get filters(): ReminderFilters | undefined {
16
+ return this._filters;
17
+ }
18
+
19
+ get sort(): ReminderSort | undefined {
20
+ return this._sort;
21
+ }
22
+
23
+ set filters(filters: ReminderFilters | undefined) {
24
+ this._filters = filters;
25
+ this.resetState();
26
+ }
27
+
28
+ set sort(sort: ReminderSort | undefined) {
29
+ this._sort = sort;
30
+ this.resetState();
31
+ }
14
32
 
15
33
  constructor(client: StreamChat, options?: PaginatorOptions) {
16
34
  super(options);
@@ -1,4 +1,5 @@
1
1
  import { Reminder } from './Reminder';
2
+ import { DEFAULT_STOP_REFRESH_BOUNDARY_MS } from './ReminderTimer';
2
3
  import { StateStore } from '../store';
3
4
  import { ReminderPaginator } from '../pagination';
4
5
  import { WithSubscriptions } from '../utils/WithSubscriptions';
@@ -26,6 +27,7 @@ export const DEFAULT_REMINDER_MANAGER_CONFIG: ReminderManagerConfig = {
26
27
  8 * oneHour,
27
28
  oneDay,
28
29
  ],
30
+ stopTimerRefreshBoundaryMs: DEFAULT_STOP_REFRESH_BOUNDARY_MS,
29
31
  };
30
32
 
31
33
  const isReminderExistsError = (error: Error) =>
@@ -51,12 +53,12 @@ export type ReminderManagerState = {
51
53
 
52
54
  export type ReminderManagerConfig = {
53
55
  scheduledOffsetsMs: number[];
54
- stopTimerRefreshBoundaryMs?: number;
56
+ stopTimerRefreshBoundaryMs: number;
55
57
  };
56
58
 
57
59
  export type ReminderManagerOptions = {
58
60
  client: StreamChat;
59
- config?: ReminderManagerConfig;
61
+ config?: Partial<ReminderManagerConfig>;
60
62
  };
61
63
 
62
64
  export class ReminderManager extends WithSubscriptions {
@@ -71,6 +73,9 @@ export class ReminderManager extends WithSubscriptions {
71
73
  this.configState = new StateStore({
72
74
  scheduledOffsetsMs:
73
75
  config?.scheduledOffsetsMs ?? DEFAULT_REMINDER_MANAGER_CONFIG.scheduledOffsetsMs,
76
+ stopTimerRefreshBoundaryMs:
77
+ config?.stopTimerRefreshBoundaryMs ??
78
+ DEFAULT_REMINDER_MANAGER_CONFIG.stopTimerRefreshBoundaryMs,
74
79
  });
75
80
  this.state = new StateStore({ reminders: new Map<MessageId, Reminder>() });
76
81
  this.paginator = new ReminderPaginator(client);
@@ -78,6 +83,15 @@ export class ReminderManager extends WithSubscriptions {
78
83
 
79
84
  // Config API START //
80
85
  updateConfig(config: Partial<ReminderManagerConfig>) {
86
+ if (
87
+ typeof config.stopTimerRefreshBoundaryMs === 'number' &&
88
+ config.stopTimerRefreshBoundaryMs !== this.stopTimerRefreshBoundaryMs
89
+ ) {
90
+ this.reminders.forEach((reminder) => {
91
+ reminder.timer.stopRefreshBoundaryMs =
92
+ config?.stopTimerRefreshBoundaryMs as number;
93
+ });
94
+ }
81
95
  this.configState.partialNext(config);
82
96
  }
83
97
 
package/src/types.ts CHANGED
@@ -4036,7 +4036,7 @@ export type ReminderAPIResponse = APIResponse & {
4036
4036
 
4037
4037
  export type CreateReminderOptions = {
4038
4038
  messageId: string;
4039
- remind_at?: string;
4039
+ remind_at?: string | null;
4040
4040
  user_id?: string;
4041
4041
  };
4042
4042