@@ -91,7 +91,7 @@ Use the `npm install` command to install the beta Azure Communication Services U
91
91
92
92
``` bash
93
93
94
- npm install @azure/communication-react@1.13 .0-beta.1
94
+ npm install @azure/communication-react@1.16 .0-beta.1
95
95
96
96
```
97
97
@@ -100,8 +100,8 @@ you can most consistently use the API from the core libraries in your applicatio
100
100
101
101
``` bash
102
102
103
- npm install @azure/communication-calling@1.21 .1-beta.4
104
- npm install @azure/communication-chat@1.5 .0-beta.1
103
+ npm install @azure/communication-calling@1.24 .1-beta.2
104
+ npm install @azure/communication-chat@1.6 .0-beta.1
105
105
106
106
```
107
107
@@ -121,11 +121,13 @@ You need to replace the variable values for both common variable required to ini
121
121
122
122
` App.tsx `
123
123
124
- ``` javascript
125
- import { FileUploadHandler , FileUploadManager } from ' @azure/communication-react' ;
124
+ ``` typescript
126
125
import { initializeFileTypeIcons } from ' @fluentui/react-file-type-icons' ;
127
126
import {
128
127
ChatComposite ,
128
+ AttachmentUploadTask ,
129
+ AttachmentUploadOptions ,
130
+ AttachmentSelectionHandler ,
129
131
fromFlatCommunicationIdentifier ,
130
132
useAzureCommunicationChatAdapter
131
133
} from ' @azure/communication-react' ;
@@ -172,12 +174,9 @@ function App(): JSX.Element {
172
174
< ChatComposite
173
175
adapter = {chatAdapter }
174
176
options = {{
175
- fileSharing: {
176
- uploadHandler: fileUploadHandler,
177
- // If `fileDownloadHandler` is not provided. The file URL is opened in a new tab.
178
- downloadHandler: fileDownloadHandler,
179
- accept: ' image/png, image/jpeg, text/plain, .docx' ,
180
- multiple: true
177
+ attachmentOptions : {
178
+ uploadOptions : uploadOptions ,
179
+ downloadOptions : downloadOptions ,
181
180
}
182
181
}} / >
183
182
< / div >
@@ -190,35 +189,36 @@ function App(): JSX.Element {
190
189
return <h3 >Initializing ... < / h3 > ;
191
190
}
192
191
193
- const fileUploadHandler: FileUploadHandler = async (userId , fileUploads ) => {
194
- for (const fileUpload of fileUploads) {
192
+ const uploadOptions: AttachmentUploadOptions = {
193
+ // default is false
194
+ disableMultipleUploads: false ,
195
+ // define mime types
196
+ supportedMediaTypes: [" image/jpg" , " image/jpeg" ]
197
+ handleAttachmentSelection : attachmentSelectionHandler ,
198
+ }
199
+
200
+ const attachmentSelectionHandler: AttachmentSelectionHandler = async (uploadTasks ) => {
201
+ for (const task of uploadTasks ) {
195
202
try {
196
- const { name , url , extension } = await uploadFileToAzureBlob (fileUpload);
197
- fileUpload .notifyUploadCompleted ({ name, extension, url });
203
+ const uniqueFileName = ` ${task }-${v4 ()}-${task .file ?.name } ` ;
204
+ const url = await uploadFileToAzureBlob (task );
205
+ task .notifyUploadCompleted (uniqueFileName , url );
198
206
} catch (error ) {
199
207
if (error instanceof Error ) {
200
- fileUpload .notifyUploadFailed (error .message );
208
+ task .notifyUploadFailed (error .message );
201
209
}
202
210
}
203
211
}
204
212
}
205
213
206
- const uploadFileToAzureBlob = async (fileUpload : FileUploadManager ) => {
214
+ const uploadFileToAzureBlob = async (uploadTask : AttachmentUploadTask ) => {
207
215
// You need to handle the file upload here and upload it to Azure Blob Storage.
208
216
// This is how you can configure the upload
209
217
// Optionally, you can also update the file upload progress.
210
- fileUpload .notifyUploadProgressChanged (0.2 );
218
+ uploadTask .notifyUploadProgressChanged (0.2 );
211
219
return {
212
- name: ' SampleFile.jpg' , // File name displayed during download
213
220
url: ' https://sample.com/sample.jpg' , // Download URL of the file.
214
- extension: ' jpeg' // File extension used for file icon during download.
215
- };
216
-
217
- const fileDownloadHandler: FileDownloadHandler = async (userId , fileData ) => {
218
- return new URL (fileData .url );
219
- }
220
221
};
221
- }
222
222
223
223
` ` `
224
224
@@ -229,10 +229,10 @@ To enable Azure Blob Storage upload, we modify the `uploadFileToAzureBlob` metho
229
229
` App .tsx `
230
230
231
231
` ` ` javascript
232
- const uploadFileToAzureBlob = async (fileUpload : FileUploadManager ) => {
233
- const file = fileUpload .file ;
232
+ const uploadFileToAzureBlob = async (uploadTask : AttachmentUploadTask ) => {
233
+ const file = uploadTask .file ;
234
234
if (! file ) {
235
- throw new Error (" fileUpload .file is undefined" );
235
+ throw new Error (" uploadTask .file is undefined" );
236
236
}
237
237
238
238
const filename = file .name ;
@@ -258,16 +258,14 @@ const uploadFileToAzureBlob = async (fileUpload: FileUploadManager) => {
258
258
data: formData ,
259
259
onUploadProgress : (p ) => {
260
260
// Optionally, you can update the file upload progess.
261
- fileUpload .notifyUploadProgressChanged (p .loaded / p .total );
261
+ uploadTask .notifyUploadProgressChanged (p .loaded / p .total );
262
262
},
263
263
});
264
264
265
265
const storageBaseUrl = " https://<YOUR_STORAGE_ACCOUNT>.blob.core.windows.net" ;
266
266
267
267
return {
268
- name: filename,
269
268
url: ` ${storageBaseUrl }/${username }/${filename } ` ,
270
- extension: fileExtension,
271
269
};
272
270
};
273
271
` ` `
@@ -278,47 +276,85 @@ When an upload fails, the UI Library Chat Composite displays an error message.
278
276
279
277

280
278
281
- Here's sample code showcasing how you can fail an upload due to a size validation error by changing the ` fileUploadHandler ` :
279
+ Here's sample code showcasing how you can fail an upload due to a size validation error:
282
280
283
281
` App .tsx `
284
282
285
283
` ` ` javascript
286
- import { FileUploadHandler } from from ' @azure/communication-react' ;
284
+ import { AttachmentSelectionHandler } from from ' @azure/communication-react' ;
287
285
288
- const fileUploadHandler : FileUploadHandler = async (userId , fileUploads ) => {
289
- for (const fileUpload of fileUploads ) {
290
- if (fileUpload .file && fileUpload .file .size > 99 * 1024 * 1024 ) {
286
+ const attachmentSelectionHandler : AttachmentSelectionHandler = async (uploadTasks ) => {
287
+ for (const task of uploadTasks ) {
288
+ if (task .file && task .file .size > 99 * 1024 * 1024 ) {
291
289
// Notify ChatComposite about upload failure.
292
290
// Allows you to provide a custom error message.
293
- fileUpload .notifyUploadFailed (' File too big. Select a file under 99 MB.' );
291
+ task .notifyUploadFailed (' File too big. Select a file under 99 MB.' );
294
292
}
295
293
}
296
294
}
297
295
` ` `
298
296
299
297
## File downloads - advanced usage
300
298
301
- By default, the file ` url ` provided through ` notifyUploadCompleted ` method is used to trigger a file download. However, if you need to handle a download in a different way, you can provide a custom ` downloadHandler ` to ChatComposite. Next, we modify the ` fileDownloadHandler ` that we declared previously to check for an authorized user before allowing to download the file.
299
+ By default, the file ` url ` provided through ` notifyUploadCompleted ` method is used to trigger a file download. However, if you need to handle a download in a different way, you can provide a custom handler ` actionsForAttachment ` to ChatComposite.
302
300
303
301
` App .tsx `
304
302
305
303
` ` ` javascript
306
- import { FileDownloadHandler } from " communication-react" ;
304
+ import { AttachmentDownloadOptions } from " communication-react" ;
305
+
306
+ const downloadOptions: AttachmentDownloadOptions = {
307
+ actionsForAttachment: handler
308
+ }
307
309
308
- const isUnauthorizedUser = (userId: string): boolean => {
309
- // You need to write your own logic here for this example.
310
+ const handler = async (attachment : AttachmentMetadata , message ? : ChatMessage ) => {
311
+ // here we are returning a static action for all attachments and all messages
312
+ // alternately, you can provide custom menu actions based on properties in `attachment` or `message`
313
+ return [defaultAttachmentMenuAction ];
310
314
};
311
315
312
- const fileDownloadHandler: FileDownloadHandler = async (userId , fileData ) => {
313
- if (isUnauthorizedUser (userId)) {
314
- // Error message is displayed to the user.
315
- return { errorMessage: " You don’t have permission to download this file." };
316
- } else {
317
- // If this function returns a Promise that resolves a URL string,
318
- // the URL is opened in a new tab.
319
- return new URL (fileData .url );
316
+ const customHandler = = async (attachment : AttachmentMetadata , message ? : ChatMessage ) => {
317
+ if (attachment .extension === " pdf" ) {
318
+ return [
319
+ {
320
+ title: " Custom button" ,
321
+ icon: (<i className =" custom-icon" ></i >),
322
+ onClick : () => {
323
+ return new Promise ((resolve , reject ) => {
324
+ // custom logic here
325
+ window .alert (" custom button clicked" );
326
+ resolve ();
327
+ // or to reject("xxxxx") with a custom message
328
+ })
329
+ }
330
+ },
331
+ defaultAttachmentMenuAction
332
+ ];
333
+ } else if (message ?.senderId === " user1" ) {
334
+ return [
335
+ {
336
+ title: " Custom button 2" ,
337
+ icon: (<i className =" custom-icon-2" ></i >),
338
+ onClick : () => {
339
+ return new Promise ((resolve , reject ) => {
340
+ window .alert (" custom button 2 clicked" );
341
+ resolve ();
342
+ })
343
+ }
344
+ },
345
+ // you can also override the default action partially
346
+ {
347
+ ... defaultAttachmentMenuAction ,
348
+ onClick : () => {
349
+ return new Promise ((resolve , reject ) => {
350
+ window .alert (" default button clicked" );
351
+ resolve ();
352
+ })
353
+ }
354
+ }
355
+ ];
320
356
}
321
- };
357
+ }
322
358
` ` `
323
359
324
360
Download errors are displayed to users in an error bar on top of the Chat Composite.
0 commit comments