quickblox-react-ui-kit 0.4.2-beta.6 → 0.4.2-beta.7
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/.env +1 -0
- package/dist/hooks/useQuickBloxUIKit.d.ts +2 -4
- package/dist/index-ui.js +3146 -2315
- package/dist/index-ui.js.map +1 -1
- package/media-recorder-js.d.ts +133 -0
- package/package.json +2 -1
- package/src/Data/DefaultConfigurations.ts +2 -2
- package/src/Presentation/Views/Dialog/MessageItem/MessageItem.tsx +2 -2
- package/src/Presentation/Views/Dialog/useDialogViewModel.ts +86 -64
- package/src/Presentation/Views/DialogList/useDialogListViewModel.ts +27 -28
- package/src/Presentation/layouts/Desktop/QuickBloxUIKitDesktopLayout.tsx +28 -26
- package/src/Presentation/ui-components/Message/Bubble/AudioBubble/AudioBubble.scss +3 -1
- package/src/QBconfig.ts +2 -2
- package/src/hooks/useQuickBloxUIKit.ts +128 -160
- package/tsconfig.json +2 -1
- package/webpack.config.js +14 -1
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
declare module 'media-recorder-js' {
|
|
2
|
+
interface QBMediaRecorderConstructorProps {
|
|
3
|
+
/** Preferred MIME type */
|
|
4
|
+
mimeType?: string
|
|
5
|
+
workerPath?: string
|
|
6
|
+
/**
|
|
7
|
+
* The minimum number of milliseconds of data to return
|
|
8
|
+
* in a single Blob, fire 'ondataavaible' callback
|
|
9
|
+
* (isn't need to use with 'audio/wav' of 'audio/mp3')
|
|
10
|
+
*
|
|
11
|
+
* @default 1000
|
|
12
|
+
*/
|
|
13
|
+
timeslice?: number
|
|
14
|
+
/**
|
|
15
|
+
* What to do with a muted input MediaStreamTrack,
|
|
16
|
+
* e.g. insert black frames/zero audio volume in the recording
|
|
17
|
+
* or ignore altogether
|
|
18
|
+
*
|
|
19
|
+
* @default true
|
|
20
|
+
*/
|
|
21
|
+
ignoreMutedMedia?: boolean
|
|
22
|
+
/** Recording start event handler */
|
|
23
|
+
onstart?: VoidFunction
|
|
24
|
+
/** Recording stop event handler */
|
|
25
|
+
onstop?: (file: Blob) => void
|
|
26
|
+
/** Recording pause event handler */
|
|
27
|
+
onpause?: VoidFunction
|
|
28
|
+
/** Recording resume event handler */
|
|
29
|
+
onresume?: VoidFunction
|
|
30
|
+
/** Error event handler */
|
|
31
|
+
onerror?: (error: unknown) => void
|
|
32
|
+
/**
|
|
33
|
+
* `dataavailable` event handler.
|
|
34
|
+
* The Blob of recorded data is contained in this event (callback
|
|
35
|
+
* isn't supported if use 'audio/wav' of 'audio/mp3' for recording)
|
|
36
|
+
*/
|
|
37
|
+
ondataavailable?: (event: { data: Blob }) => void
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
class QBMediaRecorder {
|
|
41
|
+
constructor(config: QBMediaRecorderConstructorProps)
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Switch recording Blob objects to the specified
|
|
45
|
+
* MIME type if `MediaRecorder` support it.
|
|
46
|
+
*/
|
|
47
|
+
toggleMimeType(mimeType: string): void
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Returns current `MediaRecorder` state
|
|
51
|
+
*/
|
|
52
|
+
getState(): 'inactive' | 'recording' | 'paused'
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Starts recording a stream.
|
|
56
|
+
* Fires `onstart` callback.
|
|
57
|
+
*/
|
|
58
|
+
start(stream: MediaStream): void
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Stops recording a stream
|
|
62
|
+
*
|
|
63
|
+
* @fires `onstop` callback and passing there Blob recorded
|
|
64
|
+
*/
|
|
65
|
+
stop(): void
|
|
66
|
+
|
|
67
|
+
/** Pausing stream recording */
|
|
68
|
+
pause(): void
|
|
69
|
+
|
|
70
|
+
/** Resumes stream recording */
|
|
71
|
+
resume(): void
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Change record source
|
|
75
|
+
*/
|
|
76
|
+
change(stream: MediaStream): void
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Create a file from blob and download as file.
|
|
80
|
+
* This method will call `stop` if recording is in progress.
|
|
81
|
+
*
|
|
82
|
+
* @param {string} filename Name of video file to be downloaded
|
|
83
|
+
* (default to `Date.now()`)
|
|
84
|
+
*/
|
|
85
|
+
download(filename?: string): void
|
|
86
|
+
|
|
87
|
+
_getBlobRecorded(): Blob
|
|
88
|
+
|
|
89
|
+
callbacks: Pick<
|
|
90
|
+
QBMediaRecorderConstructorProps,
|
|
91
|
+
| 'onstart'
|
|
92
|
+
| 'onstop'
|
|
93
|
+
| 'onpause'
|
|
94
|
+
| 'onresume'
|
|
95
|
+
| 'ondataavailable'
|
|
96
|
+
| 'onerror'
|
|
97
|
+
>
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Checks capability of recording in the environment.
|
|
101
|
+
* Checks `MediaRecorder`, `MediaRecorder.isTypeSupported` and `Blob`.
|
|
102
|
+
*/
|
|
103
|
+
static isAvailable(): boolean
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Checks if AudioContext API is available.
|
|
107
|
+
* Checks `window.AudioContext` or `window.webkitAudioContext`.
|
|
108
|
+
*/
|
|
109
|
+
static isAudioContext(): boolean
|
|
110
|
+
/**
|
|
111
|
+
* The `QBMediaRecorder.isTypeSupported()` static method returns
|
|
112
|
+
* a Boolean which is true if the MIME type specified is one
|
|
113
|
+
* the user agent should be able to successfully record.
|
|
114
|
+
* @param mimeType The MIME media type to check.
|
|
115
|
+
*
|
|
116
|
+
* @returns true if the `MediaRecorder` implementation is capable of
|
|
117
|
+
* recording `Blob` objects for the specified MIME type. Recording may
|
|
118
|
+
* still fail if there are insufficient resources to support the
|
|
119
|
+
* recording and encoding process. If the value is false, the user
|
|
120
|
+
* agent is incapable of recording the specified format.
|
|
121
|
+
*/
|
|
122
|
+
|
|
123
|
+
static isTypeSupported(mimeType: string): boolean
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Return supported mime types
|
|
127
|
+
* @param type video or audio (dafault to 'video')
|
|
128
|
+
*/
|
|
129
|
+
static getSupportedMimeTypes(type: 'audio' | 'video' = 'video'): string[]
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export default QBMediaRecorder
|
|
133
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "quickblox-react-ui-kit",
|
|
3
|
-
"version": "0.4.2-beta.
|
|
3
|
+
"version": "0.4.2-beta.7",
|
|
4
4
|
"main": "dist/index-ui.js",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"dependencies": {
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
"qb-ai-rephrase": "^0.1.2",
|
|
14
14
|
"qb-ai-translate": "^0.1.2",
|
|
15
15
|
"quickblox": "^2.19.2",
|
|
16
|
+
"media-recorder-js": "^2.1.0",
|
|
16
17
|
"react": "^18.2.0",
|
|
17
18
|
"react-dom": "^18.2.0",
|
|
18
19
|
"react-router-dom": "^6.11.1",
|
|
@@ -145,7 +145,7 @@ export class DefaultConfigurations {
|
|
|
145
145
|
},
|
|
146
146
|
configAIApi: {
|
|
147
147
|
AIAnswerAssistWidgetConfig: {
|
|
148
|
-
smartChatAssistantId: '
|
|
148
|
+
smartChatAssistantId: '',
|
|
149
149
|
organizationName: 'Quickblox',
|
|
150
150
|
openAIModel: 'gpt-3.5-turbo',
|
|
151
151
|
apiKey: '',
|
|
@@ -158,7 +158,7 @@ export class DefaultConfigurations {
|
|
|
158
158
|
},
|
|
159
159
|
},
|
|
160
160
|
AITranslateWidgetConfig: {
|
|
161
|
-
smartChatAssistantId: '
|
|
161
|
+
smartChatAssistantId: '',
|
|
162
162
|
organizationName: 'Quickblox',
|
|
163
163
|
openAIModel: 'gpt-3.5-turbo',
|
|
164
164
|
apiKey: '',
|
|
@@ -346,7 +346,7 @@ export default function MessageItem({
|
|
|
346
346
|
}
|
|
347
347
|
>
|
|
348
348
|
{message.attachments && message.attachments.length > 0 ? (
|
|
349
|
-
|
|
349
|
+
<>
|
|
350
350
|
{message.attachments.map((attachment) => {
|
|
351
351
|
return (
|
|
352
352
|
<AttachmentBubble
|
|
@@ -355,7 +355,7 @@ export default function MessageItem({
|
|
|
355
355
|
/>
|
|
356
356
|
);
|
|
357
357
|
})}
|
|
358
|
-
|
|
358
|
+
</>
|
|
359
359
|
) : (
|
|
360
360
|
<TextBubble
|
|
361
361
|
text={
|
|
@@ -90,11 +90,38 @@ export default function useDialogViewModel(
|
|
|
90
90
|
});
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
+
const getSender = async (sender_id: number) => {
|
|
94
|
+
const getUser: GetUsersByIdsUseCase = new GetUsersByIdsUseCase(
|
|
95
|
+
new UsersRepository(
|
|
96
|
+
currentContext.storage.LOCAL_DATA_SOURCE,
|
|
97
|
+
currentContext.storage.REMOTE_DATA_SOURCE,
|
|
98
|
+
),
|
|
99
|
+
[sender_id],
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
let userEntity: UserEntity | undefined;
|
|
103
|
+
|
|
104
|
+
await getUser
|
|
105
|
+
.execute()
|
|
106
|
+
// eslint-disable-next-line promise/always-return
|
|
107
|
+
.then((data) => {
|
|
108
|
+
// eslint-disable-next-line prefer-destructuring
|
|
109
|
+
userEntity = data[0];
|
|
110
|
+
})
|
|
111
|
+
.catch((e) => {
|
|
112
|
+
console.log('have ERROR get users :', JSON.stringify(e));
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
return userEntity;
|
|
116
|
+
};
|
|
117
|
+
|
|
93
118
|
async function getMessages(currentPagination?: Pagination) {
|
|
94
119
|
setLoading(true);
|
|
95
120
|
|
|
96
121
|
let participants: Array<number> = [];
|
|
97
122
|
let userDictionary: Record<number, UserEntity> = {};
|
|
123
|
+
let userMissingDictionary: Record<number, UserEntity> = {};
|
|
124
|
+
let messagesDialog: MessageEntity[] = [];
|
|
98
125
|
|
|
99
126
|
if (dialog?.type === DialogType.group) {
|
|
100
127
|
participants = (dialog as GroupDialogEntity).participantIds;
|
|
@@ -124,7 +151,6 @@ export default function useDialogViewModel(
|
|
|
124
151
|
return obj;
|
|
125
152
|
}, {});
|
|
126
153
|
|
|
127
|
-
setLoading(false);
|
|
128
154
|
setError('');
|
|
129
155
|
})
|
|
130
156
|
.catch((e) => {
|
|
@@ -152,88 +178,84 @@ export default function useDialogViewModel(
|
|
|
152
178
|
} messages:${JSON.stringify(data)}`,
|
|
153
179
|
);
|
|
154
180
|
|
|
155
|
-
|
|
156
|
-
const obj = { ...message };
|
|
157
|
-
|
|
158
|
-
console.log('have sender id:', message.sender_id);
|
|
159
|
-
|
|
160
|
-
if (userDictionary) {
|
|
161
|
-
obj.sender = userDictionary[message.sender_id];
|
|
162
|
-
if (
|
|
163
|
-
obj.sender &&
|
|
164
|
-
obj.sender.full_name &&
|
|
165
|
-
regex &&
|
|
166
|
-
!regex.test(obj.sender.full_name)
|
|
167
|
-
) {
|
|
168
|
-
obj.sender.full_name = 'Unknown';
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
return obj;
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
console.log(`result messages:${JSON.stringify(ResultMessages)}`);
|
|
176
|
-
// setMessages(ResultMessages);
|
|
177
|
-
setMessages((prevState) => {
|
|
178
|
-
const newItems: MessageEntity[] =
|
|
179
|
-
currentPagination === undefined ||
|
|
180
|
-
currentPagination?.getCurrentPage() === 0
|
|
181
|
-
? [...ResultMessages]
|
|
182
|
-
: [...prevState, ...ResultMessages];
|
|
183
|
-
|
|
184
|
-
return newItems;
|
|
185
|
-
});
|
|
186
|
-
// eslint-disable-next-line promise/always-return
|
|
187
|
-
// if (
|
|
188
|
-
// dialog?.type === DialogType.private ||
|
|
189
|
-
// dialog?.type === DialogType.group
|
|
190
|
-
// ) {
|
|
191
|
-
// const updDialog = { ...dialog };
|
|
192
|
-
//
|
|
193
|
-
// updDialog.unreadMessageCount = 0;
|
|
194
|
-
// setDialog(updDialog);
|
|
195
|
-
//
|
|
196
|
-
// informDataSources(updDialog);
|
|
197
|
-
//
|
|
198
|
-
// }
|
|
199
|
-
setLoading(false);
|
|
181
|
+
messagesDialog = data.ResultData;
|
|
200
182
|
setPagination(data.CurrentPagination);
|
|
201
183
|
setError('');
|
|
202
184
|
})
|
|
203
185
|
.catch((e) => {
|
|
204
|
-
console.log('have ERROR get
|
|
186
|
+
console.log('have ERROR get messages :', JSON.stringify(e));
|
|
205
187
|
setLoading(false);
|
|
206
188
|
setError((e as unknown as Error).message);
|
|
207
189
|
});
|
|
208
|
-
//
|
|
209
190
|
|
|
210
|
-
|
|
211
|
-
}
|
|
191
|
+
//
|
|
212
192
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
new UsersRepository(
|
|
216
|
-
currentContext.storage.LOCAL_DATA_SOURCE,
|
|
217
|
-
currentContext.storage.REMOTE_DATA_SOURCE,
|
|
218
|
-
),
|
|
219
|
-
[sender_id],
|
|
193
|
+
const senderIds = Array.from(
|
|
194
|
+
new Set(messagesDialog.map((msg) => msg.sender_id)),
|
|
220
195
|
);
|
|
196
|
+
const missingSenderIds = senderIds.filter((id) => !(id in userDictionary));
|
|
221
197
|
|
|
222
|
-
|
|
198
|
+
const getMissingSenderUsersFromDialogByIdsUseCase: GetUsersByIdsUseCase =
|
|
199
|
+
new GetUsersByIdsUseCase(
|
|
200
|
+
new UsersRepository(LOCAL_DATA_SOURCE, REMOTE_DATA_SOURCE),
|
|
201
|
+
missingSenderIds,
|
|
202
|
+
);
|
|
223
203
|
|
|
224
|
-
await
|
|
204
|
+
await getMissingSenderUsersFromDialogByIdsUseCase
|
|
225
205
|
.execute()
|
|
226
206
|
// eslint-disable-next-line promise/always-return
|
|
227
207
|
.then((data) => {
|
|
228
|
-
|
|
229
|
-
|
|
208
|
+
userMissingDictionary = data.reduce((acc, item) => {
|
|
209
|
+
const obj = acc;
|
|
210
|
+
|
|
211
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
212
|
+
// @ts-ignore
|
|
213
|
+
acc[item.id] = item;
|
|
214
|
+
|
|
215
|
+
return obj;
|
|
216
|
+
}, {});
|
|
217
|
+
|
|
218
|
+
setError('');
|
|
230
219
|
})
|
|
231
220
|
.catch((e) => {
|
|
232
|
-
console.log('have ERROR get users :', JSON.stringify(e));
|
|
221
|
+
console.log('have ERROR get missing users :', JSON.stringify(e));
|
|
222
|
+
setLoading(false);
|
|
223
|
+
setError((e as unknown as Error).message);
|
|
233
224
|
});
|
|
234
225
|
|
|
235
|
-
|
|
236
|
-
|
|
226
|
+
userDictionary = { ...userDictionary, ...userMissingDictionary };
|
|
227
|
+
|
|
228
|
+
const ResultMessages = messagesDialog.map((message) => {
|
|
229
|
+
const obj = { ...message };
|
|
230
|
+
|
|
231
|
+
if (userDictionary) {
|
|
232
|
+
obj.sender = userDictionary[message.sender_id];
|
|
233
|
+
if (
|
|
234
|
+
obj.sender &&
|
|
235
|
+
obj.sender.full_name &&
|
|
236
|
+
regex &&
|
|
237
|
+
!regex.test(obj.sender.full_name)
|
|
238
|
+
) {
|
|
239
|
+
obj.sender.full_name = 'Unknown';
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return obj;
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
console.log(`result messages:${JSON.stringify(ResultMessages)}`);
|
|
247
|
+
setMessages((prevState) => {
|
|
248
|
+
const newItems: MessageEntity[] =
|
|
249
|
+
currentPagination === undefined ||
|
|
250
|
+
currentPagination?.getCurrentPage() === 0
|
|
251
|
+
? [...ResultMessages]
|
|
252
|
+
: [...prevState, ...ResultMessages];
|
|
253
|
+
|
|
254
|
+
return newItems;
|
|
255
|
+
});
|
|
256
|
+
setLoading(false);
|
|
257
|
+
console.log('EXECUTE USE CASE MessagesViewModelWithMockUseCase EXECUTED');
|
|
258
|
+
}
|
|
237
259
|
|
|
238
260
|
const dialogUpdateHandler = (dialogInfo: DialogEventInfo) => {
|
|
239
261
|
console.log('call dialogUpdateHandler in useDialogViewModel');
|
|
@@ -157,6 +157,27 @@ export default function useDialogListViewModel(
|
|
|
157
157
|
});
|
|
158
158
|
}
|
|
159
159
|
|
|
160
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars,@typescript-eslint/no-empty-function
|
|
161
|
+
function informDataSources(item: DialogEntity) {
|
|
162
|
+
const updateCurrentDialogInDataSourceUseCase: UpdateCurrentDialogInDataSourceUseCase =
|
|
163
|
+
new UpdateCurrentDialogInDataSourceUseCase(
|
|
164
|
+
new DialogsRepository(
|
|
165
|
+
currentContext.storage.LOCAL_DATA_SOURCE,
|
|
166
|
+
remoteDataSourceMock,
|
|
167
|
+
),
|
|
168
|
+
item as GroupDialogEntity,
|
|
169
|
+
QBConfig,
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
updateCurrentDialogInDataSourceUseCase.execute().catch((e) => {
|
|
173
|
+
console.log(
|
|
174
|
+
'Error updateCurrentDialogInDataSourceUseCase: ',
|
|
175
|
+
stringifyError(e),
|
|
176
|
+
);
|
|
177
|
+
throw new Error(stringifyError(e));
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
|
|
160
181
|
const dialogUpdateHandler = (dialogInfo: DialogEventInfo) => {
|
|
161
182
|
console.log('call dialogUpdateHandler in useDialogListView:', dialogInfo);
|
|
162
183
|
if (
|
|
@@ -256,7 +277,12 @@ export default function useDialogListViewModel(
|
|
|
256
277
|
setDialogs((prevDialogs) => {
|
|
257
278
|
const newDialogs = prevDialogs.map((dialog) => {
|
|
258
279
|
if (dialog.id === dialogInfo.dialogInfo?.id) {
|
|
259
|
-
|
|
280
|
+
const updatedDialogInfo = {
|
|
281
|
+
...dialogInfo.dialogInfo,
|
|
282
|
+
unreadMessageCount: 0,
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
return updatedDialogInfo as PublicDialogEntity;
|
|
260
286
|
}
|
|
261
287
|
|
|
262
288
|
return dialog;
|
|
@@ -270,12 +296,6 @@ export default function useDialogListViewModel(
|
|
|
270
296
|
new Date(a.updatedAt).getTime();
|
|
271
297
|
});
|
|
272
298
|
|
|
273
|
-
// const sortedData = [...newDialogs].sort((a, b) => {
|
|
274
|
-
// return (
|
|
275
|
-
// new Date(b.lastMessage.dateSent).getTime() - new Date(a.lastMessage.dateSent).getTime()
|
|
276
|
-
// );
|
|
277
|
-
// });
|
|
278
|
-
|
|
279
299
|
return sortedData;
|
|
280
300
|
});
|
|
281
301
|
}
|
|
@@ -534,27 +554,6 @@ export default function useDialogListViewModel(
|
|
|
534
554
|
return Promise.resolve(resultEnity);
|
|
535
555
|
};
|
|
536
556
|
|
|
537
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars,@typescript-eslint/no-empty-function
|
|
538
|
-
function informDataSources(item: DialogEntity) {
|
|
539
|
-
const updateCurrentDialogInDataSourceUseCase: UpdateCurrentDialogInDataSourceUseCase =
|
|
540
|
-
new UpdateCurrentDialogInDataSourceUseCase(
|
|
541
|
-
new DialogsRepository(
|
|
542
|
-
currentContext.storage.LOCAL_DATA_SOURCE,
|
|
543
|
-
remoteDataSourceMock,
|
|
544
|
-
),
|
|
545
|
-
item as GroupDialogEntity,
|
|
546
|
-
QBConfig,
|
|
547
|
-
);
|
|
548
|
-
|
|
549
|
-
updateCurrentDialogInDataSourceUseCase.execute().catch((e) => {
|
|
550
|
-
console.log(
|
|
551
|
-
'Error updateCurrentDialogInDataSourceUseCase: ',
|
|
552
|
-
stringifyError(e),
|
|
553
|
-
);
|
|
554
|
-
throw new Error(stringifyError(e));
|
|
555
|
-
});
|
|
556
|
-
}
|
|
557
|
-
|
|
558
557
|
return {
|
|
559
558
|
get entity(): DialogEntity {
|
|
560
559
|
return newDialog as DialogEntity;
|
|
@@ -435,32 +435,34 @@ const QuickBloxUIKitDesktopLayout: React.FC<
|
|
|
435
435
|
/>
|
|
436
436
|
) : null
|
|
437
437
|
}
|
|
438
|
-
renderDialogList={(handleSelectDialog) =>
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
searchedDialogs.
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
438
|
+
renderDialogList={(handleSelectDialog) => (
|
|
439
|
+
<>
|
|
440
|
+
{dialogsViewModel?.loading && (
|
|
441
|
+
<div
|
|
442
|
+
className="dialog-list__loader-container"
|
|
443
|
+
style={{
|
|
444
|
+
display: 'flex',
|
|
445
|
+
flexDirection: 'row',
|
|
446
|
+
alignItems: 'center',
|
|
447
|
+
justifyContent: 'center',
|
|
448
|
+
}}
|
|
449
|
+
>
|
|
450
|
+
<Loader size="md" className="dialog-list__loader" />
|
|
451
|
+
</div>
|
|
452
|
+
)}
|
|
453
|
+
{searchedDialogs.length > 0 ? (
|
|
454
|
+
searchedDialogs.map((dlg, index) =>
|
|
455
|
+
renderDialogItem(dlg, index, handleSelectDialog),
|
|
456
|
+
)
|
|
457
|
+
) : (
|
|
458
|
+
<Placeholder
|
|
459
|
+
icon={<ChatSvg />}
|
|
460
|
+
text="There are no dialogs."
|
|
461
|
+
className="dialog-empty-chat-placeholder"
|
|
462
|
+
/>
|
|
463
|
+
)}
|
|
464
|
+
</>
|
|
465
|
+
)}
|
|
464
466
|
/>
|
|
465
467
|
) : null
|
|
466
468
|
}
|
package/src/QBconfig.ts
CHANGED
|
@@ -10,7 +10,7 @@ export const QBConfig: QBUIKitConfig = {
|
|
|
10
10
|
},
|
|
11
11
|
configAIApi: {
|
|
12
12
|
AIAnswerAssistWidgetConfig: {
|
|
13
|
-
smartChatAssistantId: '
|
|
13
|
+
smartChatAssistantId: '',
|
|
14
14
|
organizationName: 'Quickblox',
|
|
15
15
|
openAIModel: 'gpt-3.5-turbo',
|
|
16
16
|
apiKey: '',
|
|
@@ -23,7 +23,7 @@ export const QBConfig: QBUIKitConfig = {
|
|
|
23
23
|
},
|
|
24
24
|
},
|
|
25
25
|
AITranslateWidgetConfig: {
|
|
26
|
-
smartChatAssistantId: '
|
|
26
|
+
smartChatAssistantId: '',
|
|
27
27
|
organizationName: 'Quickblox',
|
|
28
28
|
openAIModel: 'gpt-3.5-turbo',
|
|
29
29
|
apiKey: '',
|