stream-chat 9.6.1 → 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 +532 -57
- package/dist/cjs/index.browser.cjs.map +4 -4
- package/dist/cjs/index.node.cjs +538 -57
- package/dist/cjs/index.node.cjs.map +4 -4
- package/dist/esm/index.js +532 -57
- package/dist/esm/index.js.map +4 -4
- package/dist/types/channel.d.ts +36 -4
- package/dist/types/client.d.ts +38 -0
- package/dist/types/messageComposer/messageComposer.d.ts +4 -1
- 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/commands.d.ts +5 -5
- package/dist/types/messageComposer/middleware/textComposer/index.d.ts +2 -0
- package/dist/types/messageComposer/middleware/textComposer/mentions.d.ts +1 -2
- package/dist/types/messageComposer/middleware/textComposer/textMiddlewareUtils.d.ts +6 -0
- package/dist/types/messageComposer/middleware/textComposer/types.d.ts +3 -2
- package/dist/types/messageComposer/textComposer.d.ts +6 -3
- package/dist/types/offline-support/offline_support_api.d.ts +39 -0
- package/dist/types/offline-support/types.d.ts +36 -2
- 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/search/BaseSearchSource.d.ts +37 -31
- package/dist/types/search/ChannelSearchSource.d.ts +1 -1
- package/dist/types/search/MessageSearchSource.d.ts +1 -1
- package/dist/types/search/UserSearchSource.d.ts +1 -1
- package/dist/types/search/index.d.ts +1 -0
- package/dist/types/search/types.d.ts +20 -0
- package/dist/types/types.d.ts +6 -2
- package/dist/types/utils.d.ts +11 -2
- package/package.json +1 -1
- package/src/channel.ts +85 -10
- package/src/client.ts +61 -3
- package/src/messageComposer/messageComposer.ts +120 -14
- 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 +28 -11
- package/src/messageComposer/middleware/textComposer/index.ts +2 -0
- package/src/messageComposer/middleware/textComposer/mentions.ts +1 -2
- package/src/messageComposer/middleware/textComposer/textMiddlewareUtils.ts +14 -0
- package/src/messageComposer/middleware/textComposer/types.ts +3 -2
- package/src/messageComposer/textComposer.ts +23 -3
- package/src/offline-support/offline_support_api.ts +79 -0
- package/src/offline-support/types.ts +41 -1
- package/src/pagination/BasePaginator.ts +1 -1
- package/src/pagination/ReminderPaginator.ts +20 -2
- package/src/reminders/ReminderManager.ts +16 -2
- package/src/search/BaseSearchSource.ts +123 -52
- package/src/search/ChannelSearchSource.ts +1 -1
- package/src/search/MessageSearchSource.ts +1 -1
- package/src/search/UserSearchSource.ts +1 -1
- package/src/search/index.ts +1 -0
- package/src/search/types.ts +20 -0
- package/src/types.ts +9 -2
- package/src/utils.ts +31 -2
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
import { StateStore } from '../store';
|
|
2
2
|
import { debounce, type DebouncedFunc } from '../utils';
|
|
3
|
+
import type {
|
|
4
|
+
QueryReturnValue,
|
|
5
|
+
SearchSourceOptions,
|
|
6
|
+
SearchSourceState,
|
|
7
|
+
SearchSourceType,
|
|
8
|
+
} from './types';
|
|
3
9
|
|
|
4
|
-
export type SearchSourceType = 'channels' | 'users' | 'messages' | (string & {});
|
|
5
|
-
export type QueryReturnValue<T> = { items: T[]; next?: string | null };
|
|
6
10
|
export type DebounceOptions = {
|
|
7
11
|
debounceMs: number;
|
|
8
12
|
};
|
|
9
13
|
type DebouncedExecQueryFunction = DebouncedFunc<(searchString?: string) => Promise<void>>;
|
|
10
14
|
|
|
11
15
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
12
|
-
|
|
16
|
+
interface ISearchSource<T = any> {
|
|
13
17
|
activate(): void;
|
|
14
18
|
|
|
15
|
-
cancelScheduledQuery(): void;
|
|
16
|
-
|
|
17
19
|
canExecuteQuery(newSearchString?: string): boolean;
|
|
18
20
|
|
|
19
21
|
deactivate(): void;
|
|
@@ -30,48 +32,40 @@ export interface SearchSource<T = any> {
|
|
|
30
32
|
|
|
31
33
|
resetState(): void;
|
|
32
34
|
|
|
33
|
-
search(text?: string): Promise<void> | undefined;
|
|
34
|
-
|
|
35
35
|
readonly searchQuery: string;
|
|
36
36
|
|
|
37
|
-
setDebounceOptions(options: DebounceOptions): void;
|
|
38
|
-
|
|
39
37
|
readonly state: StateStore<SearchSourceState<T>>;
|
|
40
38
|
readonly type: SearchSourceType;
|
|
41
39
|
}
|
|
42
40
|
|
|
43
41
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
44
|
-
export
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
pageSize?: number;
|
|
58
|
-
};
|
|
42
|
+
export interface SearchSource<T = any> extends ISearchSource<T> {
|
|
43
|
+
cancelScheduledQuery(): void;
|
|
44
|
+
setDebounceOptions(options: DebounceOptions): void;
|
|
45
|
+
search(text?: string): Promise<void> | undefined;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
49
|
+
export interface SearchSourceSync<T = any> extends ISearchSource<T> {
|
|
50
|
+
cancelScheduledQuery(): void;
|
|
51
|
+
setDebounceOptions(options: DebounceOptions): void;
|
|
52
|
+
search(text?: string): void;
|
|
53
|
+
}
|
|
54
|
+
|
|
59
55
|
const DEFAULT_SEARCH_SOURCE_OPTIONS: Required<SearchSourceOptions> = {
|
|
60
56
|
debounceMs: 300,
|
|
61
57
|
pageSize: 10,
|
|
62
58
|
} as const;
|
|
63
59
|
|
|
64
|
-
|
|
60
|
+
abstract class BaseSearchSourceBase<T> implements ISearchSource<T> {
|
|
65
61
|
state: StateStore<SearchSourceState<T>>;
|
|
66
62
|
protected pageSize: number;
|
|
67
63
|
abstract readonly type: SearchSourceType;
|
|
68
|
-
protected searchDebounced!: DebouncedExecQueryFunction;
|
|
69
64
|
|
|
70
65
|
protected constructor(options?: SearchSourceOptions) {
|
|
71
|
-
const {
|
|
66
|
+
const { pageSize } = { ...DEFAULT_SEARCH_SOURCE_OPTIONS, ...options };
|
|
72
67
|
this.pageSize = pageSize;
|
|
73
68
|
this.state = new StateStore<SearchSourceState<T>>(this.initialState);
|
|
74
|
-
this.setDebounceOptions({ debounceMs });
|
|
75
69
|
}
|
|
76
70
|
|
|
77
71
|
get lastQueryError() {
|
|
@@ -123,14 +117,6 @@ export abstract class BaseSearchSource<T> implements SearchSource<T> {
|
|
|
123
117
|
return this.state.getLatestValue().searchQuery;
|
|
124
118
|
}
|
|
125
119
|
|
|
126
|
-
protected abstract query(searchQuery: string): Promise<QueryReturnValue<T>>;
|
|
127
|
-
|
|
128
|
-
protected abstract filterQueryResults(items: T[]): T[] | Promise<T[]>;
|
|
129
|
-
|
|
130
|
-
setDebounceOptions = ({ debounceMs }: DebounceOptions) => {
|
|
131
|
-
this.searchDebounced = debounce(this.executeQuery.bind(this), debounceMs);
|
|
132
|
-
};
|
|
133
|
-
|
|
134
120
|
activate = () => {
|
|
135
121
|
if (this.isActive) return;
|
|
136
122
|
this.state.partialNext({ isActive: true });
|
|
@@ -177,8 +163,7 @@ export abstract class BaseSearchSource<T> implements SearchSource<T> {
|
|
|
177
163
|
};
|
|
178
164
|
}
|
|
179
165
|
|
|
180
|
-
|
|
181
|
-
if (!this.canExecuteQuery(newSearchString)) return;
|
|
166
|
+
protected prepareStateForQuery(newSearchString?: string) {
|
|
182
167
|
const hasNewSearchQuery = typeof newSearchString !== 'undefined';
|
|
183
168
|
const searchString = newSearchString ?? this.searchQuery;
|
|
184
169
|
|
|
@@ -188,20 +173,67 @@ export abstract class BaseSearchSource<T> implements SearchSource<T> {
|
|
|
188
173
|
this.state.partialNext({ isLoading: true });
|
|
189
174
|
}
|
|
190
175
|
|
|
176
|
+
return { searchString, hasNewSearchQuery };
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
protected updatePaginationStateFromQuery(result: QueryReturnValue<T>) {
|
|
180
|
+
const { items, next } = result;
|
|
181
|
+
|
|
191
182
|
const stateUpdate: Partial<SearchSourceState<T>> = {};
|
|
183
|
+
if (next || next === null) {
|
|
184
|
+
stateUpdate.next = next;
|
|
185
|
+
stateUpdate.hasNext = !!next;
|
|
186
|
+
} else {
|
|
187
|
+
stateUpdate.offset = (this.offset ?? 0) + items.length;
|
|
188
|
+
stateUpdate.hasNext = items.length === this.pageSize;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return stateUpdate;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
resetState() {
|
|
195
|
+
this.state.next(this.initialState);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
resetStateAndActivate() {
|
|
199
|
+
this.resetState();
|
|
200
|
+
this.activate();
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export abstract class BaseSearchSource<T>
|
|
205
|
+
extends BaseSearchSourceBase<T>
|
|
206
|
+
implements SearchSource<T>
|
|
207
|
+
{
|
|
208
|
+
protected searchDebounced!: DebouncedExecQueryFunction;
|
|
209
|
+
|
|
210
|
+
constructor(options?: SearchSourceOptions) {
|
|
211
|
+
const { debounceMs } = { ...DEFAULT_SEARCH_SOURCE_OPTIONS, ...options };
|
|
212
|
+
super(options);
|
|
213
|
+
this.setDebounceOptions({ debounceMs });
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
protected abstract query(searchQuery: string): Promise<QueryReturnValue<T>>;
|
|
217
|
+
|
|
218
|
+
protected abstract filterQueryResults(items: T[]): T[] | Promise<T[]>;
|
|
219
|
+
|
|
220
|
+
setDebounceOptions = ({ debounceMs }: DebounceOptions) => {
|
|
221
|
+
this.searchDebounced = debounce(this.executeQuery.bind(this), debounceMs);
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
async executeQuery(newSearchString?: string) {
|
|
225
|
+
if (!this.canExecuteQuery(newSearchString)) return;
|
|
226
|
+
|
|
227
|
+
const { hasNewSearchQuery, searchString } =
|
|
228
|
+
this.prepareStateForQuery(newSearchString);
|
|
229
|
+
|
|
230
|
+
let stateUpdate: Partial<SearchSourceState<T>> = {};
|
|
192
231
|
try {
|
|
193
232
|
const results = await this.query(searchString);
|
|
194
233
|
if (!results) return;
|
|
195
|
-
const { items, next } = results;
|
|
196
|
-
|
|
197
|
-
if (next || next === null) {
|
|
198
|
-
stateUpdate.next = next;
|
|
199
|
-
stateUpdate.hasNext = !!next;
|
|
200
|
-
} else {
|
|
201
|
-
stateUpdate.offset = (this.offset ?? 0) + items.length;
|
|
202
|
-
stateUpdate.hasNext = items.length === this.pageSize;
|
|
203
|
-
}
|
|
204
234
|
|
|
235
|
+
const { items } = results;
|
|
236
|
+
stateUpdate = this.updatePaginationStateFromQuery(results);
|
|
205
237
|
stateUpdate.items = await this.filterQueryResults(items);
|
|
206
238
|
} catch (e) {
|
|
207
239
|
stateUpdate.lastQueryError = e as Error;
|
|
@@ -215,13 +247,52 @@ export abstract class BaseSearchSource<T> implements SearchSource<T> {
|
|
|
215
247
|
cancelScheduledQuery() {
|
|
216
248
|
this.searchDebounced.cancel();
|
|
217
249
|
}
|
|
250
|
+
}
|
|
218
251
|
|
|
219
|
-
|
|
220
|
-
|
|
252
|
+
export abstract class BaseSearchSourceSync<T>
|
|
253
|
+
extends BaseSearchSourceBase<T>
|
|
254
|
+
implements SearchSourceSync<T>
|
|
255
|
+
{
|
|
256
|
+
protected searchDebounced!: DebouncedExecQueryFunction;
|
|
257
|
+
|
|
258
|
+
constructor(options?: SearchSourceOptions) {
|
|
259
|
+
const { debounceMs } = { ...DEFAULT_SEARCH_SOURCE_OPTIONS, ...options };
|
|
260
|
+
super(options);
|
|
261
|
+
this.setDebounceOptions({ debounceMs });
|
|
221
262
|
}
|
|
222
263
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
264
|
+
protected abstract query(searchQuery: string): QueryReturnValue<T>;
|
|
265
|
+
|
|
266
|
+
protected abstract filterQueryResults(items: T[]): T[];
|
|
267
|
+
|
|
268
|
+
setDebounceOptions = ({ debounceMs }: DebounceOptions) => {
|
|
269
|
+
this.searchDebounced = debounce(this.executeQuery.bind(this), debounceMs);
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
executeQuery(newSearchString?: string) {
|
|
273
|
+
if (!this.canExecuteQuery(newSearchString)) return;
|
|
274
|
+
|
|
275
|
+
const { hasNewSearchQuery, searchString } =
|
|
276
|
+
this.prepareStateForQuery(newSearchString);
|
|
277
|
+
|
|
278
|
+
let stateUpdate: Partial<SearchSourceState<T>> = {};
|
|
279
|
+
try {
|
|
280
|
+
const results = this.query(searchString);
|
|
281
|
+
if (!results) return;
|
|
282
|
+
|
|
283
|
+
const { items } = results;
|
|
284
|
+
stateUpdate = this.updatePaginationStateFromQuery(results);
|
|
285
|
+
stateUpdate.items = this.filterQueryResults(items);
|
|
286
|
+
} catch (e) {
|
|
287
|
+
stateUpdate.lastQueryError = e as Error;
|
|
288
|
+
} finally {
|
|
289
|
+
this.state.next(this.getStateAfterQuery(stateUpdate, hasNewSearchQuery));
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
search = (searchQuery?: string) => this.searchDebounced(searchQuery);
|
|
294
|
+
|
|
295
|
+
cancelScheduledQuery() {
|
|
296
|
+
this.searchDebounced.cancel();
|
|
226
297
|
}
|
|
227
298
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { BaseSearchSource } from './BaseSearchSource';
|
|
2
|
-
import type { SearchSourceOptions } from './BaseSearchSource';
|
|
3
2
|
import type { Channel } from '../channel';
|
|
4
3
|
import type { StreamChat } from '../client';
|
|
5
4
|
import type { ChannelFilters, ChannelOptions, ChannelSort } from '../types';
|
|
5
|
+
import type { SearchSourceOptions } from './types';
|
|
6
6
|
|
|
7
7
|
export class ChannelSearchSource extends BaseSearchSource<Channel> {
|
|
8
8
|
readonly type = 'channels';
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { BaseSearchSource } from './BaseSearchSource';
|
|
2
|
-
import type { SearchSourceOptions } from './BaseSearchSource';
|
|
3
2
|
import type {
|
|
4
3
|
ChannelFilters,
|
|
5
4
|
ChannelOptions,
|
|
@@ -10,6 +9,7 @@ import type {
|
|
|
10
9
|
SearchOptions,
|
|
11
10
|
} from '../types';
|
|
12
11
|
import type { StreamChat } from '../client';
|
|
12
|
+
import type { SearchSourceOptions } from './types';
|
|
13
13
|
|
|
14
14
|
export class MessageSearchSource extends BaseSearchSource<MessageResponse> {
|
|
15
15
|
readonly type = 'messages';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { BaseSearchSource } from './BaseSearchSource';
|
|
2
|
-
import type { SearchSourceOptions } from './BaseSearchSource';
|
|
3
2
|
import type { StreamChat } from '../client';
|
|
4
3
|
import type { UserFilters, UserOptions, UserResponse, UserSort } from '../types';
|
|
4
|
+
import type { SearchSourceOptions } from './types';
|
|
5
5
|
|
|
6
6
|
export class UserSearchSource extends BaseSearchSource<UserResponse> {
|
|
7
7
|
readonly type = 'users';
|
package/src/search/index.ts
CHANGED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2
|
+
export type SearchSourceState<T = any> = {
|
|
3
|
+
hasNext: boolean;
|
|
4
|
+
isActive: boolean;
|
|
5
|
+
isLoading: boolean;
|
|
6
|
+
items: T[] | undefined;
|
|
7
|
+
searchQuery: string;
|
|
8
|
+
lastQueryError?: Error;
|
|
9
|
+
next?: string | null;
|
|
10
|
+
offset?: number;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export type SearchSourceOptions = {
|
|
14
|
+
/** The number of milliseconds to debounce the search query. The default interval is 300ms. */
|
|
15
|
+
debounceMs?: number;
|
|
16
|
+
pageSize?: number;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export type SearchSourceType = 'channels' | 'users' | 'messages' | (string & {});
|
|
20
|
+
export type QueryReturnValue<T> = { items: T[]; next?: string | null };
|
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
|
|
|
@@ -4099,7 +4099,7 @@ export type QueryRemindersResponse = {
|
|
|
4099
4099
|
next?: string;
|
|
4100
4100
|
};
|
|
4101
4101
|
|
|
4102
|
-
export type HookType = 'webhook' | 'sqs' | 'sns';
|
|
4102
|
+
export type HookType = 'webhook' | 'sqs' | 'sns' | 'pending_message';
|
|
4103
4103
|
|
|
4104
4104
|
export type EventHook = {
|
|
4105
4105
|
id?: string;
|
|
@@ -4119,6 +4119,13 @@ export type EventHook = {
|
|
|
4119
4119
|
sns_key?: string;
|
|
4120
4120
|
sns_secret?: string;
|
|
4121
4121
|
sns_role_arn?: string;
|
|
4122
|
+
|
|
4123
|
+
// pending message config
|
|
4124
|
+
timeout_ms?: number;
|
|
4125
|
+
callback?: {
|
|
4126
|
+
mode: 'CALLBACK_MODE_NONE' | 'CALLBACK_MODE_REST' | 'CALLBACK_MODE_TWIRP';
|
|
4127
|
+
};
|
|
4128
|
+
|
|
4122
4129
|
created_at?: string;
|
|
4123
4130
|
updated_at?: string;
|
|
4124
4131
|
};
|
package/src/utils.ts
CHANGED
|
@@ -297,9 +297,9 @@ export const axiosParamsSerializer: AxiosRequestConfig['paramsSerializer'] = (pa
|
|
|
297
297
|
|
|
298
298
|
/**
|
|
299
299
|
* Takes the message object, parses the dates, sets `__html`
|
|
300
|
-
* and sets the status to `received` if missing; returns a new
|
|
300
|
+
* and sets the status to `received` if missing; returns a new LocalMessage object.
|
|
301
301
|
*
|
|
302
|
-
* @param {
|
|
302
|
+
* @param {LocalMessage} message `LocalMessage` object
|
|
303
303
|
*/
|
|
304
304
|
export function formatMessage(
|
|
305
305
|
message: MessageResponse | MessageResponseBase | LocalMessage,
|
|
@@ -330,6 +330,35 @@ export function formatMessage(
|
|
|
330
330
|
} as LocalMessage;
|
|
331
331
|
}
|
|
332
332
|
|
|
333
|
+
/**
|
|
334
|
+
* @private
|
|
335
|
+
*
|
|
336
|
+
* Takes a LocalMessage, parses the dates back to strings,
|
|
337
|
+
* and converts the message back to a MessageResponse.
|
|
338
|
+
*
|
|
339
|
+
* @param {MessageResponse} message `MessageResponse` object
|
|
340
|
+
*/
|
|
341
|
+
export function unformatMessage(message: LocalMessage): MessageResponse {
|
|
342
|
+
const toMessageResponseBase = (
|
|
343
|
+
msg: LocalMessage | null | undefined,
|
|
344
|
+
): MessageResponseBase | null => {
|
|
345
|
+
if (!msg) return null;
|
|
346
|
+
const newDateString = new Date().toISOString();
|
|
347
|
+
return {
|
|
348
|
+
...msg,
|
|
349
|
+
created_at: message.created_at ? message.created_at.toISOString() : newDateString,
|
|
350
|
+
deleted_at: message.deleted_at ? message.deleted_at.toISOString() : undefined,
|
|
351
|
+
pinned_at: message.pinned_at ? message.pinned_at.toISOString() : undefined,
|
|
352
|
+
updated_at: message.updated_at ? message.updated_at.toISOString() : newDateString,
|
|
353
|
+
};
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
return {
|
|
357
|
+
...toMessageResponseBase(message),
|
|
358
|
+
quoted_message: toMessageResponseBase((message as LocalMessage).quoted_message),
|
|
359
|
+
} as MessageResponse;
|
|
360
|
+
}
|
|
361
|
+
|
|
333
362
|
export const localMessageToNewMessagePayload = (localMessage: LocalMessage): Message => {
|
|
334
363
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
335
364
|
const {
|