Skip to content

Commit ac5d71f

Browse files
authored
Update file-sharing-tutorial-acs-chat.md
1 parent 84988ba commit ac5d71f

File tree

1 file changed

+87
-51
lines changed

1 file changed

+87
-51
lines changed

articles/communication-services/tutorials/file-sharing-tutorial-acs-chat.md

Lines changed: 87 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ Use the `npm install` command to install the beta Azure Communication Services U
9191

9292
```bash
9393

94-
npm install @azure/communication-react@1.13.0-beta.1
94+
npm install @azure/communication-react@1.16.0-beta.1
9595

9696
```
9797

@@ -100,8 +100,8 @@ you can most consistently use the API from the core libraries in your applicatio
100100

101101
```bash
102102

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
105105

106106
```
107107

@@ -121,11 +121,13 @@ You need to replace the variable values for both common variable required to ini
121121

122122
`App.tsx`
123123

124-
```javascript
125-
import { FileUploadHandler, FileUploadManager } from '@azure/communication-react';
124+
```typescript
126125
import { initializeFileTypeIcons } from '@fluentui/react-file-type-icons';
127126
import {
128127
ChatComposite,
128+
AttachmentUploadTask,
129+
AttachmentUploadOptions,
130+
AttachmentSelectionHandler,
129131
fromFlatCommunicationIdentifier,
130132
useAzureCommunicationChatAdapter
131133
} from '@azure/communication-react';
@@ -172,12 +174,9 @@ function App(): JSX.Element {
172174
<ChatComposite
173175
adapter={chatAdapter}
174176
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,
181180
}
182181
}} />
183182
</div>
@@ -190,35 +189,36 @@ function App(): JSX.Element {
190189
return <h3>Initializing...</h3>;
191190
}
192191

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) {
195202
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);
198206
} catch (error) {
199207
if (error instanceof Error) {
200-
fileUpload.notifyUploadFailed(error.message);
208+
task.notifyUploadFailed(error.message);
201209
}
202210
}
203211
}
204212
}
205213

206-
const uploadFileToAzureBlob = async (fileUpload: FileUploadManager) => {
214+
const uploadFileToAzureBlob = async (uploadTask: AttachmentUploadTask) => {
207215
// You need to handle the file upload here and upload it to Azure Blob Storage.
208216
// This is how you can configure the upload
209217
// Optionally, you can also update the file upload progress.
210-
fileUpload.notifyUploadProgressChanged(0.2);
218+
uploadTask.notifyUploadProgressChanged(0.2);
211219
return {
212-
name: 'SampleFile.jpg', // File name displayed during download
213220
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-
}
220221
};
221-
}
222222

223223
```
224224
@@ -229,10 +229,10 @@ To enable Azure Blob Storage upload, we modify the `uploadFileToAzureBlob` metho
229229
`App.tsx`
230230
231231
```javascript
232-
const uploadFileToAzureBlob = async (fileUpload: FileUploadManager) => {
233-
const file = fileUpload.file;
232+
const uploadFileToAzureBlob = async (uploadTask: AttachmentUploadTask) => {
233+
const file = uploadTask.file;
234234
if (!file) {
235-
throw new Error("fileUpload.file is undefined");
235+
throw new Error("uploadTask.file is undefined");
236236
}
237237

238238
const filename = file.name;
@@ -258,16 +258,14 @@ const uploadFileToAzureBlob = async (fileUpload: FileUploadManager) => {
258258
data: formData,
259259
onUploadProgress: (p) => {
260260
// Optionally, you can update the file upload progess.
261-
fileUpload.notifyUploadProgressChanged(p.loaded / p.total);
261+
uploadTask.notifyUploadProgressChanged(p.loaded / p.total);
262262
},
263263
});
264264

265265
const storageBaseUrl = "https://<YOUR_STORAGE_ACCOUNT>.blob.core.windows.net";
266266

267267
return {
268-
name: filename,
269268
url: `${storageBaseUrl}/${username}/${filename}`,
270-
extension: fileExtension,
271269
};
272270
};
273271
```
@@ -278,47 +276,85 @@ When an upload fails, the UI Library Chat Composite displays an error message.
278276
279277
![File Upload Error Bar](./media/file-too-big.png "Screenshot that shows the File Upload Error Bar.")
280278
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:
282280
283281
`App.tsx`
284282
285283
```javascript
286-
import { FileUploadHandler } from from '@azure/communication-react';
284+
import { AttachmentSelectionHandler } from from '@azure/communication-react';
287285

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) {
291289
// Notify ChatComposite about upload failure.
292290
// 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.');
294292
}
295293
}
296294
}
297295
```
298296
299297
## File downloads - advanced usage
300298
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.
302300
303301
`App.tsx`
304302
305303
```javascript
306-
import { FileDownloadHandler } from "communication-react";
304+
import { AttachmentDownloadOptions } from "communication-react";
305+
306+
const downloadOptions: AttachmentDownloadOptions = {
307+
actionsForAttachment: handler
308+
}
307309

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];
310314
};
311315

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+
];
320356
}
321-
};
357+
}
322358
```
323359
324360
Download errors are displayed to users in an error bar on top of the Chat Composite.

0 commit comments

Comments
 (0)