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.
- package/dist/cjs/index.browser.cjs +176 -8
- package/dist/cjs/index.browser.cjs.map +3 -3
- package/dist/cjs/index.node.cjs +181 -8
- package/dist/cjs/index.node.cjs.map +3 -3
- package/dist/esm/index.js +176 -8
- package/dist/esm/index.js.map +3 -3
- package/dist/types/messageComposer/middleware/messageComposer/commandInjection.d.ts +4 -0
- package/dist/types/messageComposer/middleware/messageComposer/index.d.ts +1 -0
- package/dist/types/messageComposer/middleware/textComposer/activeCommandGuard.d.ts +4 -0
- package/dist/types/messageComposer/middleware/textComposer/commandStringExtraction.d.ts +5 -0
- package/dist/types/messageComposer/middleware/textComposer/index.d.ts +2 -0
- package/dist/types/messageComposer/middleware/textComposer/textMiddlewareUtils.d.ts +6 -0
- package/dist/types/messageComposer/middleware/textComposer/types.d.ts +1 -0
- package/dist/types/messageComposer/textComposer.d.ts +6 -3
- package/dist/types/pagination/BasePaginator.d.ts +1 -1
- package/dist/types/pagination/ReminderPaginator.d.ts +6 -2
- package/dist/types/reminders/ReminderManager.d.ts +3 -3
- package/dist/types/types.d.ts +1 -1
- package/package.json +1 -1
- package/src/messageComposer/middleware/messageComposer/commandInjection.ts +72 -0
- package/src/messageComposer/middleware/messageComposer/index.ts +1 -0
- package/src/messageComposer/middleware/textComposer/activeCommandGuard.ts +20 -0
- package/src/messageComposer/middleware/textComposer/commandStringExtraction.ts +56 -0
- package/src/messageComposer/middleware/textComposer/commands.ts +22 -4
- package/src/messageComposer/middleware/textComposer/index.ts +2 -0
- package/src/messageComposer/middleware/textComposer/textMiddlewareUtils.ts +14 -0
- package/src/messageComposer/middleware/textComposer/types.ts +1 -0
- package/src/messageComposer/textComposer.ts +23 -3
- package/src/pagination/BasePaginator.ts +1 -1
- package/src/pagination/ReminderPaginator.ts +20 -2
- package/src/reminders/ReminderManager.ts +16 -2
- 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;
|
|
@@ -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,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;
|
|
@@ -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
|
-
|
|
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
|
-
|
|
8
|
-
|
|
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
|
|
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
|
|
36
|
+
get stopTimerRefreshBoundaryMs(): number;
|
|
37
37
|
get scheduledOffsetsMs(): number[];
|
|
38
38
|
get reminders(): Map<string, Reminder>;
|
|
39
39
|
getFromState(messageId: MessageId): Reminder | undefined;
|
package/dist/types/types.d.ts
CHANGED
|
@@ -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
|
@@ -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
|
+
});
|
|
@@ -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 {
|
|
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:
|
|
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,
|
|
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
|
|
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,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,
|
|
@@ -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 = ({
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
13
|
-
|
|
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
|
|
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
|
|