Skip to content

Commit 11e0516

Browse files
authored
Merge pull request #268318 from jpeng-ms/patch-10
[ACS][Chat] Added docs for Image Upload
2 parents 5a27f94 + ac66759 commit 11e0516

8 files changed

+170
-28
lines changed
398 KB
Loading
753 KB
Loading
486 KB
Loading
1.86 MB
Loading
1.03 MB
Loading
Lines changed: 167 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,33 @@ ms.service: azure-communication-services
99

1010
In this tutorial, you learn how to enable inline image support using the Azure Communication Services Chat SDK for JavaScript.
1111

12+
Inline images are images that are copied and pasted directly into the send box of the Teams client. For images uploaded via the "Upload from this device" menu or via drag-and-drop, such as images dragged directly to the send box in Teams, you need to refer to [this tutorial](../meeting-interop-features-file-attachment.md) as the part of the file sharing feature. (See the section "Handling Image Attachment.") To copy an image, the Teams user can either use their operating system's context menu to copy the image file and then paste it into the send box of their Teams client or use keyboard shortcuts.
13+
14+
There are two parts in this tutorial, you learn what you need to do:
15+
16+
- [when receiving an inline image](#handle-received-inline-images-in-new-message-event)
17+
- [when sending out an inline image](#handle-sending-inline-images-in-new-message-request)
18+
19+
20+
> [!NOTE]
21+
> The ability to send inline images is currently available in public preview and it's only available for JavaScript only. For receiving inline images, it's currently general available and available for both JavaScript and C# in a Teams interoperability chat.
22+
23+
1224
## Sample Code
25+
1326
Find the finalized code of this tutorial on [GitHub](https://github.com/Azure-Samples/communication-services-javascript-quickstarts/tree/main/join-chat-to-teams-meeting).
1427

15-
## Prerequisites
28+
## Handle received inline images in new message event
29+
30+
In this section, we learn how we can render inline images embedded in the message content of new message received event.
31+
32+
### Prerequisites
1633

1734
* You've gone through the quickstart - [Join your chat app to a Teams meeting](../../../quickstarts/chat/meeting-interop.md).
1835
* Create an Azure Communication Services resource. For details, see [Create an Azure Communication Services resource](../../../quickstarts/create-communication-resource.md). You need to **record your connection string** for this tutorial.
1936
* You've set up a Teams meeting using your business account and have the meeting URL ready.
2037
* You're using the Chat SDK for JavaScript (@azure/communication-chat) 1.4.0 or latest. See [here](https://www.npmjs.com/package/@azure/communication-chat).
2138

22-
## Goal
23-
24-
1. Be able to render preview images in the message thread
25-
2. Be able to render full scale image upon click on preview images
26-
27-
## Handle inline images for new messages
2839

2940

3041
In the [quickstart](../../../quickstarts/chat/meeting-interop.md), we've created an event handler for `chatMessageReceived` event, which would be trigger when we receive a new message from the Teams user. We have also appended incoming message content to `messageContainer` directly upon receiving the `chatMessageReceived` event from the `chatClient` like this:
@@ -97,18 +108,15 @@ chatClient.on("chatMessageReceived", (e) => {
97108
return;
98109
}
99110

100-
if (e.sender.communicationUserId != userId) {
101-
renderReceivedMessage(e);
102-
} else {
103-
renderSentMessage(e.message);
104-
}
111+
const isMyMessage = e.sender.communicationUserId === userId;
112+
renderReceivedMessage(e, isMyMessage);
105113
});
106114

107-
async function renderReceivedMessage(e) {
115+
function renderReceivedMessage(e, isMyMessage) {
108116
const messageContent = e.message;
109117

110118
const card = document.createElement('div');
111-
card.className = 'container lighter';
119+
card.className = isMyMessage ? "container darker" : "container lighter";
112120
card.innerHTML = messageContent;
113121

114122
messagesContainer.appendChild(card);
@@ -209,7 +217,7 @@ To show full scale image in an overlay, we need to add a new component as well:
209217

210218
```
211219

212-
with some CSS:
220+
With some CSS:
213221

214222
```css
215223

@@ -301,15 +309,15 @@ loadingImageOverlay.addEventListener('click', () => {
301309
Now we've concluded all the changes we need to render inline images for messages coming from real time notifications.
302310

303311

304-
## Run the code
312+
### Run the code
305313

306314
Webpack users can use the `webpack-dev-server` to build and run your app. Run the following command to bundle your application host on a local webserver:
307315

308316
```console
309317
npx webpack-dev-server --entry ./client.js --output bundle.js --debug --devtool inline-source-map
310318
```
311319

312-
## Demo
320+
### Demo
313321
Open your browser and navigate to `http://localhost:8080/`. Enter the meeting URL and the thread ID. Send some inline images from Teams client like this:
314322

315323
:::image type="content" source="./media/meeting-interop-features-inline-3.png" alt-text="A screenshot of Teams client shown a sent message reads: Here are some ideas, let me know what you think! The message also contains two inline images of room interior mockups.":::
@@ -320,5 +328,146 @@ Then you should see the new message being rendered along with preview images:
320328

321329
Upon clicking the preview image by the Azure Communication Services user, an overlay would be shown with the full scale image sent by the Teams user:
322330

323-
:::image type="content" source="./media/meeting-interop-features-inline-2.png" alt-text="A screenshot of sample app shown an overlay of a full scale image being presented.":::
331+
:::image type="content" source="./media/meeting-interop-features-inline-2.png" alt-text="A screenshot of sample app showing an overlay of a full scale image being presented.":::
332+
333+
334+
## Handle sending inline images in new message request
335+
336+
[!INCLUDE [Public Preview Notice](../../../includes/public-preview-include.md)]
337+
338+
In addition to handle messages with inline images, Chat SDK for JavaScript also provides a solution to allow the Communication User to send inline images to the Microsoft Teams user in an interoperability chat.
339+
340+
341+
### Prerequisites
342+
343+
* You've gone through the previous section for [handling-received-inline-images-in-new-message-event](#handle-received-inline-images-in-new-message-event)
344+
* You're using the Chat SDK for JavaScript (@azure/communication-chat) 1.6.0-beta.1 or latest. See [here](https://www.npmjs.com/package/@azure/communication-chat).
345+
346+
347+
Let's take a look of the new API from `ChatThreadClient`:
348+
349+
```js
350+
var imageAttachment = await chatThreadClient.uploadImage(blob, file.name, {
351+
"onUploadProgress": reportProgressCallback
352+
});
353+
```
354+
355+
Noticing the API takes in an image blob, file name string, and a function callback that reports upload progress.
356+
357+
Therefore, to send an image to other chat participant, we need to:
358+
359+
1. Upload the image via `uploadImage` API from `ChatThreadClient`, save the returned object to somewhere
360+
2. Compose the message content and set attachment to the returned object we have saved in previous step
361+
3. Send the new message via `sendMessage` API from `ChatThreadClient`
362+
4. Done!
363+
364+
365+
So let's begin to create a new file picker that accepts images like the following:
366+
367+
```html
368+
<label for="myfile">Attach images:</label>
369+
<input id="upload" type="file" id="myfile" name="myfile" accept="image/*" multiple>
370+
<input style="display: none;" id="upload-result"></input>
371+
```
372+
373+
Next we need to set up an event licenser for when there's a state change:
374+
375+
```js
376+
document.getElementById("upload").addEventListener("change", uploadImages);
377+
```
378+
379+
Here we need to create a new function for when state changes:
380+
381+
```js
382+
var uploadedImageModels = [];
383+
384+
async function uploadImages(e) {
385+
const files = e.target.files;
386+
if (files.length === 0) {
387+
return;
388+
}
389+
for (let key in files) {
390+
if (files.hasOwnProperty(key)) {
391+
await uploadImage(files[key]);
392+
}
393+
}
394+
}
395+
396+
async function uploadImage(file) {
397+
const buffer = await file.arrayBuffer();
398+
const blob = new Blob([new Uint8Array(buffer)], {type: file.type });
399+
const url = window.URL.createObjectURL(blob);
400+
document.getElementById("upload-result").innerHTML += `<img src="${url}" height="auto" width="100" />`;
401+
let uploadedImageModel = await chatThreadClient.uploadImage(blob, file.name, {
402+
imageBytesLength: file.size
403+
});
404+
uploadedImageModels.push(uploadedImageModel);
405+
}
406+
```
407+
408+
Noticing in this example, we have created a `FileReader` to read each image as `base64` encoded images, then create a `Blob` before calling the ChatSDK API to upload them. Also notice how we created a global `uploadedImageModels` to save the data models of uploaded images from the ChatSDK.
409+
410+
Lastly we need to modify the sendMessageButton event listener we created previously to attach images we just uploaded.
411+
412+
```js
413+
sendMessageButton.addEventListener("click", async () => {
414+
let message = messagebox.value;
415+
let attachments = uploadedImageModels;
416+
417+
// inject image tags for images we have selected
418+
// so they can be treated as inline images
419+
// alternatively, we can use some 3rd party libraries
420+
// to have a rich text editor with inline image support
421+
message += attachments.map((attachment) => `<img id="${attachment.id}" />`).join("");
422+
423+
let sendMessageRequest = {
424+
content: message,
425+
attachments: attachments,
426+
};
427+
428+
let sendMessageOptions = {
429+
senderDisplayName: "Jack",
430+
type: "html"
431+
};
432+
433+
let sendChatMessageResult = await chatThreadClient.sendMessage(
434+
sendMessageRequest,
435+
sendMessageOptions
436+
);
437+
let messageId = sendChatMessageResult.id;
438+
uploadedImageModels = [];
439+
440+
messagebox.value = "";
441+
document.getElementById("upload").value = "";
442+
console.log(`Message sent!, message id:${messageId}`);
443+
});
444+
445+
```
446+
447+
That's it, now let's run the code and see it in action.
448+
449+
### Run the code
450+
451+
Webpack users can use the `webpack-dev-server` to build and run your app. Run the following command to bundle your application host on a local webserver:
452+
453+
```console
454+
npx webpack-dev-server --entry ./client.js --output bundle.js --debug --devtool inline-source-map
455+
```
456+
457+
### Demo
458+
459+
Open your browser and navigate to `http://localhost:8080/`. Noticing we have a new section in the send box to attach images:
460+
461+
:::image type="content" source="./media/meeting-interop-features-inline-5.png" alt-text="A screenshot of sample app with a newly add section to attach images.":::
462+
463+
Then we can select images we wanted to attach:
464+
465+
:::image type="content" source="./media/meeting-interop-features-inline-6.png" alt-text="A screenshot of a file picker that shows a list of images user can attach to their message.":::
466+
467+
:::image type="content" source="./media/meeting-interop-features-inline-7.png" alt-text="A screenshot of the sample app showing 2 images attached.":::
468+
469+
The Teams user should now receive the image we just sent out when they click on send button:
470+
471+
:::image type="content" source="./media/meeting-interop-features-inline-8.png" alt-text="A screenshot of the sample app showing a sent message with 2 images embedded.":::
324472

473+
:::image type="content" source="./media/meeting-interop-features-inline-9.png" alt-text="A screenshot of Teams client showing a received message with 2 image embedded.":::

articles/communication-services/tutorials/chat-interop/meeting-interop-features-inline-image.md

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,14 @@ zone_pivot_groups: acs-js-csharp
1414

1515
# Tutorial: Enable inline image support in your Chat app
1616

17-
The Chat SDK works seamlessly with Microsoft Teams in the context of a meeting. Specifically, Chat SDK provides a solution to receive inline images sent by users from Microsoft Teams. Currently this feature is only available in the Chat SDK for JavaScript and C#.
18-
19-
## Add inline image support
20-
21-
Inline images are images that are copied and pasted directly into the send box of the Teams client. For images that were uploaded using the **Upload from this device** menu or via drag-and-drop, such as images dragged directly to the send box in Teams, see [Tutorial: Enable file attachment support in your Chat app](./meeting-interop-features-file-attachment.md) to enable file attachment support as part of the file sharing feature. For images, see the [Handle image attachments](./meeting-interop-features-file-attachment.md#handle-image-attachments) section. To copy an image, the Teams user can either use their operating system's context menu to copy the image file, and then paste it into the send box of their Teams client, or use keyboard shortcuts.
22-
23-
The Chat SDK for JavaScript provides `previewUrl` and `url` for each inline image. Some GIF images fetched from `previewUrl` might not be animated, and a static preview image may be returned instead. Developers need to use the `url` if the intention is to fetch animated images only.
24-
17+
The Chat SDK is designed to work with Microsoft Teams seamlessly. Specifically, Chat SDK provides a solution to receive inline images and send inline images to users from Microsoft Teams.
2518

2619
::: zone pivot="programming-language-javascript"
27-
[!INCLUDE [Teams Inline Image Interop with JavaScript SDK](./includes/meeting-interop-features-inline-image-javascript.md)]
20+
[!INCLUDE [Teams Inline Image Interop with JavaScript SDK](./includes/meeting-interop-features-inline-image-receiving-javascript.md)]
2821
::: zone-end
2922

3023
::: zone pivot="programming-language-csharp"
31-
[!INCLUDE [Teams Inline Image Interop with C# SDK](./includes/meeting-interop-features-inline-image-csharp.md)]
24+
[!INCLUDE [Teams Inline Image Interop with C# SDK](./includes/meeting-interop-features-inline-image-receiving-csharp.md)]
3225
::: zone-end
3326

3427

0 commit comments

Comments
 (0)