Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
SDK Obrolan dirancang untuk bekerja dengan Microsoft Teams dengan mulus. Secara khusus, Chat SDK menyediakan solusi untuk menerima gambar sebaris dan mengirim gambar sebaris kepada pengguna dari Microsoft Teams.
Dalam tutorial ini, Anda mempelajari cara mengaktifkan dukungan gambar sebaris dengan menggunakan Azure Communication Services Chat SDK untuk JavaScript.
Gambar sebaris adalah gambar yang disalin dan ditempelkan langsung ke dalam kotak kirim klien Teams. Untuk gambar yang diunggah melalui menu Unggah dari perangkat ini atau melalui seret dan letakkan, seperti gambar yang diseret langsung ke kotak kirim di Teams, Anda perlu merujuk ke tutorial ini sebagai bagian dari fitur berbagi file. (Lihat bagian "Menangani lampiran gambar.")
Untuk menyalin gambar, pengguna Teams memiliki dua opsi:
- Gunakan menu konteks sistem operasi mereka untuk menyalin file gambar lalu tempelkan ke dalam kotak kirim klien Teams mereka.
- Gunakan pintasan keyboard.
Dalam tutorial ini, Anda mempelajari apa yang perlu Anda lakukan ketika Anda:
Nota
Kemampuan untuk mengirim gambar sebaris saat ini tersedia dalam pratinjau publik. Ini hanya tersedia untuk JavaScript. Untuk menerima gambar sebaris, saat ini sudah tersedia secara umum. Ini tersedia untuk JavaScript dan C# dalam obrolan interoperabilitas Teams.
Prasyarat
- Panduan memulai cepat cara menghubungkan aplikasi Obrolan Anda ke rapat Teams.
- Buat sumber daya Azure Communication Services. Untuk detailnya selengkapnya, lihat Membuat sumber daya Azure Communication Services. Anda perlu merekam string koneksi Anda untuk tutorial ini.
- Siapkan rapat Teams dengan menggunakan akun bisnis Anda dan siapkan URL rapat.
- Gunakan Chat SDK untuk JavaScript (@azure/communication-chat) 1.4.0 atau yang terbaru. Untuk informasi selengkapnya, lihat Pustaka klien Azure Communication Chat untuk JavaScript.
Contoh kode
Temukan kode akhir tutorial ini di GitHub.
Menangani gambar sebaris yang diterima dalam peristiwa pesan baru
Di bagian ini, Anda mempelajari cara merender gambar sebaris yang disematkan dalam konten pesan dari peristiwa pesan baru yang diterima.
Dalam mulai cepat, Anda membuat penanganan aktivitas untuk peristiwa tersebut chatMessageReceived
, yang dipicu saat Anda menerima pesan baru dari pengguna Teams. Anda juga menambahkan konten pesan masuk ke messageContainer
langsung saat menerima event chatMessageReceived
dari chatClient
, seperti ini:
chatClient.on("chatMessageReceived", (e) => {
console.log("Notification chatMessageReceived!");
// Check whether the notification is intended for the current thread
if (threadIdInput.value != e.threadId) {
return;
}
if (e.sender.communicationUserId != userId) {
renderReceivedMessage(e.message);
}
else {
renderSentMessage(e.message);
}
});
async function renderReceivedMessage(message) {
messages += '<div class="container lighter">' + message + '</div>';
messagesContainer.innerHTML = messages;
}
Dari peristiwa masuk jenis ChatMessageReceivedEvent
, properti bernama attachments
berisi informasi tentang gambar sebaris. Ini semua yang Anda butuhkan untuk merender gambar sebaris di UI Anda:
export interface ChatMessageReceivedEvent extends BaseChatMessageEvent {
/**
* Content of the message.
*/
message: string;
/**
* Metadata of the message.
*/
metadata: Record<string, string>;
/**
* Chat message attachment.
*/
attachments?: ChatAttachment[];
}
export interface ChatAttachment {
/** Id of the attachment */
id: string;
/** The type of attachment. */
attachmentType: ChatAttachmentType;
/** The name of the attachment content. */
name?: string;
/** The URL where the attachment can be downloaded */
url?: string;
/** The URL where the preview of attachment can be downloaded */
previewUrl?: string;
}
export type ChatAttachmentType = "image" | "unknown";
Sekarang kembali ke kode sebelumnya untuk menambahkan beberapa logika tambahan, seperti cuplikan kode berikut:
chatClient.on("chatMessageReceived", (e) => {
console.log("Notification chatMessageReceived!");
// Check whether the notification is intended for the current thread
if (threadIdInput.value != e.threadId) {
return;
}
const isMyMessage = e.sender.communicationUserId === userId;
renderReceivedMessage(e, isMyMessage);
});
function renderReceivedMessage(e, isMyMessage) {
const messageContent = e.message;
const card = document.createElement('div');
card.className = isMyMessage ? "container darker" : "container lighter";
card.innerHTML = messageContent;
messagesContainer.appendChild(card);
// Filter out inline images from attachments
const imageAttachments = e.attachments.filter((e) =>
e.attachmentType.toLowerCase() === 'image');
// Fetch and render preview images
fetchPreviewImages(imageAttachments);
// Set up onclick event handler to fetch full-scale image
setImgHandler(card, imageAttachments);
}
function setImgHandler(element, imageAttachments) {
// Do nothing if there are no image attachments
if (!imageAttachments.length > 0) {
return;
}
const imgs = element.getElementsByTagName('img');
for (const img of imgs) {
img.addEventListener('click', (e) => {
// Fetch full-scale image upon click
fetchFullScaleImage(e, imageAttachments);
});
}
}
async function fetchPreviewImages(attachments) {
if (!attachments.length > 0) {
return;
}
// Since each message could contain more than one inline image
// we need to fetch them individually
const result = await Promise.all(
attachments.map(async (attachment) => {
// Fetch preview image from its 'previewURL'
const response = await fetch(attachment.previewUrl, {
method: 'GET',
headers: {
// The token here should be the same one from chat initialization
'Authorization': 'Bearer ' + tokenString,
},
});
// The response would be in an image blob, so we can render it directly
return {
id: attachment.id,
content: await response.blob(),
};
}),
);
result.forEach((imageResult) => {
const urlCreator = window.URL || window.webkitURL;
const url = urlCreator.createObjectURL(imageResult.content);
// Look up the image ID and replace its 'src' with object URL
document.getElementById(imageResult.id).src = url;
});
}
Dalam contoh ini, Anda membuat dua fungsi pembantu, fetchPreviewImages
dan setImgHandler
. Yang pertama mengambil gambar pratinjau langsung dari previewURL
yang disediakan di setiap objek ChatAttachment
dengan header otentikasi. Demikian pula, Anda menyiapkan onclick
peristiwa untuk setiap gambar dalam fungsi setImgHandler
. Di penanganan aktivitas, Anda mengambil gambar skala penuh dari properti url
dari ChatAttachment
objek dengan header autentikasi.
Sekarang Anda perlu mengekspos token ke tingkat global karena Anda perlu membuat header autentikasi dengannya. Anda perlu mengubah kode berikut:
// New variable for token string
var tokenString = '';
async function init() {
....
let tokenResponse = await identityClient.getToken(identityResponse, [
"voip",
"chat"
]);
const { token, expiresOn } = tokenResponse;
// Save to token string
tokenString = token;
...
}
Untuk menampilkan gambar skala penuh dalam overlay, Anda juga perlu menambahkan komponen baru:
<div class="overlay" id="overlay-container">
<div class="content">
<img id="full-scale-image" src="" alt="" />
</div>
</div>
Menggunakan sedikit CSS:
/* let's make chat popup scrollable */
.chat-popup {
...
max-height: 650px;
overflow-y: scroll;
}
.overlay {
position: fixed;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, .7);
top: 0;
left: 0;
z-index: 100;
}
.overlay .content {
position: fixed;
width: 100%;
height: 100%;
text-align: center;
overflow: hidden;
z-index: 100;
margin: auto;
background-color: rgba(0, 0, 0, .7);
}
.overlay img {
position: absolute;
display: block;
max-height: 90%;
max-width: 90%;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
#overlay-container {
display: none
}
Sekarang setelah Anda memiliki overlay yang disiapkan, saatnya untuk mengerjakan logika untuk merender gambar skala penuh. Ingat bahwa Anda membuat onClick
penanganan aktivitas untuk memanggil fungsi fetchFullScaleImage
:
const overlayContainer = document.getElementById('overlay-container');
const loadingImageOverlay = document.getElementById('full-scale-image');
function fetchFullScaleImage(e, imageAttachments) {
// Get the image ID from the clicked image element
const link = imageAttachments.filter((attachment) =>
attachment.id === e.target.id)[0].url;
loadingImageOverlay.src = '';
// Fetch the image
fetch(link, {
method: 'GET',
headers: {'Authorization': 'Bearer ' + tokenString},
}).then(async (result) => {
// Now we set image blob to our overlay element
const content = await result.blob();
const urlCreator = window.URL || window.webkitURL;
const url = urlCreator.createObjectURL(content);
loadingImageOverlay.src = url;
});
// Show overlay
overlayContainer.style.display = 'block';
}
Satu hal terakhir yang ingin Anda tambahkan adalah kemampuan untuk menutup overlay saat gambar diklik:
loadingImageOverlay.addEventListener('click', () => {
overlayContainer.style.display = 'none';
});
Sekarang Anda telah membuat semua perubahan yang Anda butuhkan untuk merender gambar sebaris untuk pesan yang berasal dari pemberitahuan real-time.
Menjalankan kode
Pengguna webpack dapat menggunakan webpack-dev-server
untuk membuat dan menjalankan aplikasi Anda. Jalankan perintah berikut untuk menggabungkan host aplikasi Anda di server web lokal:
npx webpack-dev-server --entry ./client.js --output bundle.js --debug --devtool inline-source-map
Demo
Buka browser Anda dan buka http://localhost:8080/
. Masukkan URL rapat dan ID utas. Kirim beberapa gambar sebaris dari klien Teams.
Kemudian Anda akan melihat pesan baru yang dirender bersama dengan gambar pratinjau.
Setelah pengguna Azure Communication Services memilih gambar pratinjau, overlay muncul dengan gambar skala penuh yang dikirim oleh pengguna Teams.
Menangani pengiriman gambar sebaris dalam permintaan pesan baru
Penting
Fitur Azure Communication Services ini saat ini dalam pratinjau. Fitur dalam pratinjau tersedia untuk umum dan dapat digunakan oleh semua pelanggan Microsoft baru dan yang sudah ada.
API pratinjau dan SDK disediakan tanpa perjanjian tingkat layanan. Kami menyarankan agar Anda tidak menggunakannya untuk beban kerja produksi. Fitur tertentu mungkin tidak didukung atau kemampuan mungkin dibatasi.
Untuk informasi lebih lanjut, lihat Supplemental Terms of Use for Microsoft Azure Previews.
Selain menangani pesan dengan gambar sebaris, Chat SDK untuk JavaScript juga menyediakan solusi untuk memungkinkan pengguna komunikasi mengirim gambar sebaris ke pengguna Microsoft Teams dalam obrolan interoperabilitas.
Lihat API baru dari ChatThreadClient
:
var imageAttachment = await chatThreadClient.uploadImage(blob, file.name, {
"onUploadProgress": reportProgressCallback
});
API ini menerima blob gambar, string nama file, dan fungsi callback yang melaporkan kemajuan pengunggahan.
Untuk mengirim gambar ke peserta obrolan lain, Anda perlu:
- Unggah gambar melalui
uploadImage
API dariChatThreadClient
, dan simpan objek yang dikembalikan. - Buat konten pesan dan atur lampiran ke objek yang dikembalikan yang Anda simpan di langkah sebelumnya.
- Kirim pesan baru melalui
sendMessage
API dariChatThreadClient
.
Buat pemilih file baru yang menerima gambar:
<label for="myfile">Attach images:</label>
<input id="upload" type="file" id="myfile" name="myfile" accept="image/*" multiple>
<input style="display: none;" id="upload-result"></input>
Sekarang siapkan pendengar peristiwa saat ada perubahan status:
document.getElementById("upload").addEventListener("change", uploadImages);
Anda perlu membuat fungsi baru saat status berubah:
var uploadedImageModels = [];
async function uploadImages(e) {
const files = e.target.files;
if (files.length === 0) {
return;
}
for (let key in files) {
if (files.hasOwnProperty(key)) {
await uploadImage(files[key]);
}
}
}
async function uploadImage(file) {
const buffer = await file.arrayBuffer();
const blob = new Blob([new Uint8Array(buffer)], {type: file.type });
const url = window.URL.createObjectURL(blob);
document.getElementById("upload-result").innerHTML += `<img src="${url}" height="auto" width="100" />`;
let uploadedImageModel = await chatThreadClient.uploadImage(blob, file.name, {
imageBytesLength: file.size
});
uploadedImageModels.push(uploadedImageModel);
}
Dalam contoh ini, Anda membuat FileReader
untuk membaca setiap gambar sebagai base64
gambar yang dikodekan, lalu membuat Blob
sebelum memanggil ChatSDK API untuk mengunggahnya. Anda membuat variabel global uploadedImageModels
untuk menyimpan model data dari gambar yang diunggah melalui Chat SDK.
Terakhir, Anda perlu memodifikasi pendengar acara yang sendMessageButton
Anda buat sebelumnya untuk melampirkan gambar yang Anda unggah.
sendMessageButton.addEventListener("click", async () => {
let message = messagebox.value;
let attachments = uploadedImageModels;
// Inject image tags for images we have selected
// so they can be treated as inline images
// Alternatively, we can use some third-party libraries
// to have a rich text editor with inline image support
message += attachments.map((attachment) => `<img id="${attachment.id}" />`).join("");
let sendMessageRequest = {
content: message,
attachments: attachments,
};
let sendMessageOptions = {
senderDisplayName: "Jack",
type: "html"
};
let sendChatMessageResult = await chatThreadClient.sendMessage(
sendMessageRequest,
sendMessageOptions
);
let messageId = sendChatMessageResult.id;
uploadedImageModels = [];
messagebox.value = "";
document.getElementById("upload").value = "";
console.log(`Message sent!, message id:${messageId}`);
});
Itu saja. Sekarang jalankan kode untuk melihatnya beraksi.
Menjalankan kode
Pengguna webpack dapat menggunakan webpack-dev-server
untuk membuat dan menjalankan aplikasi Anda. Jalankan perintah berikut untuk menggabungkan host aplikasi Anda di server web lokal:
npx webpack-dev-server --entry ./client.js --output bundle.js --debug --devtool inline-source-map
Demo
Buka browser Anda dan buka http://localhost:8080/
. Anda memiliki bagian baru dalam kotak kirim untuk melampirkan gambar.
Selanjutnya, Anda dapat memilih gambar yang ingin Anda lampirkan.
Pengguna Teams sekarang akan menerima gambar yang baru saja Anda kirim ketika mereka memilih Kirim.
Tutorial ini menunjukkan kepada Anda cara mengaktifkan dukungan gambar sebaris dengan menggunakan Azure Communication Services Chat SDK untuk C#.
Dalam tutorial ini, Anda akan belajar cara:
- Menangani gambar dalam baris untuk pesan baru.
Prasyarat
- Tinjau cara cepat Menghubungkan aplikasi obrolan Anda ke rapat Teams.
- Buat sumber daya Azure Communication Services. Untuk detailnya selengkapnya, lihat Membuat sumber daya Azure Communication Services. Anda perlu merekam string koneksi Anda untuk tutorial ini.
- Siapkan rapat Teams dengan menggunakan akun bisnis Anda dan siapkan URL rapat.
- Gunakan Chat SDK untuk C# (Azure.Communication.Chat) 1.3.0 atau yang terbaru. Untuk informasi selengkapnya, lihat Pustaka klien Azure Communication Chat untuk .NET.
Maksud
- Ambil properti
previewUri
untuk lampiran gambar yang disusun sebaris.
Menangani gambar dalam baris untuk pesan baru
Dalam mulai cepat, Anda melakukan polling untuk pesan dan menambahkan pesan baru ke messageList
properti . Anda membangun fungsionalitas ini nanti untuk menyertakan penguraian dan pengambilan gambar sebaris.
CommunicationUserIdentifier currentUser = new(user_Id_);
AsyncPageable<ChatMessage> allMessages = chatThreadClient.GetMessagesAsync();
SortedDictionary<long, string> messageList = [];
int textMessages = 0;
await foreach (ChatMessage message in allMessages)
{
if (message.Type == ChatMessageType.Html || message.Type == ChatMessageType.Text)
{
textMessages++;
var userPrefix = message.Sender.Equals(currentUser) ? "[you]:" : "";
var strippedMessage = StripHtml(message.Content.Message);
messageList.Add(long.Parse(message.SequenceId), $"{userPrefix}{strippedMessage}");
}
}
Dari peristiwa masuk jenis ChatMessageReceivedEvent
, properti bernama attachments
berisi informasi tentang gambar sebaris. Hanya itu yang Anda butuhkan untuk merender gambar sebaris di UI Anda.
public class ChatAttachment
{
public ChatAttachment(string id, ChatAttachmentType attachmentType)
public ChatAttachmentType AttachmentType { get }
public string Id { get }
public string Name { get }
public System.Uri PreviewUrl { get }
public System.Uri Url { get }
}
public struct ChatAttachmentType : System.IEquatable<AttachmentType>
{
public ChatAttachmentType(string value)
public static File { get }
public static Image { get }
}
JSON berikut adalah contoh seperti apa yang ChatAttachment
mungkin terlihat untuk lampiran gambar:
"attachments": [
{
"id": "9d89acb2-c4e4-4cab-b94a-7c12a61afe30",
"attachmentType": "image",
"name": "Screenshot.png",
"url": "https://contoso.communication.azure.com/chat/threads/19:9d89acb29d89acb2@thread.v2/images/9d89acb2-c4e4-4cab-b94a-7c12a61afe30/views/original?api-version=2023-11-03",
"previewUrl": "https://contoso.communication.azure.com/chat/threads/19:9d89acb29d89acb2@thread.v2/images/9d89acb2-c4e4-4cab-b94a-7c12a61afe30/views/small?api-version=2023-11-03"
}
]
Sekarang kembali dan ganti kode untuk menambahkan logika tambahan untuk mengurai dan mengambil lampiran gambar:
CommunicationUserIdentifier currentUser = new(user_Id_);
AsyncPageable<ChatMessage> allMessages = chatThreadClient.GetMessagesAsync();
SortedDictionary<long, string> messageList = [];
int textMessages = 0;
await foreach (ChatMessage message in allMessages)
{
// Get message attachments that are of type 'image'
IEnumerable<ChatAttachment> imageAttachments = message.Content.Attachments.Where(x => x.AttachmentType == ChatAttachmentType.Image);
// Fetch image and render
var chatAttachmentImageUris = new List<Uri>();
foreach (ChatAttachment imageAttachment in imageAttachments)
{
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", communicationTokenCredential.GetToken().Token);
var response = await client.GetAsync(imageAttachment.PreviewUri);
var randomAccessStream = await response.Content.ReadAsStreamAsync();
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
{
var bitmapImage = new BitmapImage();
await bitmapImage.SetSourceAsync(randomAccessStream.AsRandomAccessStream());
InlineImage.Source = bitmapImage;
});
chatAttachmentImageUris.Add(imageAttachment.PreviewUri);
}
// Build message list
if (message.Type == ChatMessageType.Html || message.Type == ChatMessageType.Text)
{
textMessages++;
var userPrefix = message.Sender.Equals(currentUser) ? "[you]:" : "";
var strippedMessage = StripHtml(message.Content.Message);
var chatAttachments = chatAttachmentImageUris.Count > 0 ? "[Attachments]:\n" + string.Join(",\n", chatAttachmentImageUris) : "";
messageList.Add(long.Parse(message.SequenceId), $"{userPrefix}{strippedMessage}\n{chatAttachments}");
}
Dalam contoh ini, Anda mengambil semua lampiran dari pesan jenis Image
lalu mengambil masing-masing gambar. Anda harus menggunakan Anda Token
di Bearer
bagian header permintaan untuk tujuan otorisasi. Setelah gambar diunduh, Anda dapat menetapkannya ke InlineImage
elemen tampilan.
Anda juga menyertakan daftar URI lampiran yang akan ditampilkan bersama dengan pesan dalam daftar pesan teks.
Demo
- Jalankan aplikasi dari lingkungan pengembangan terintegrasi (IDE).
- Masukkan tautan rapat Teams.
- Bergabung dalam rapat.
- Akui pengguna di sisi Teams.
- Kirim pesan dari aplikasi Teams dengan gambar.
URL yang disertakan dengan pesan muncul di daftar pesan. Gambar terakhir yang diterima dirender di bagian bawah jendela.
Langkah selanjutnya
- Pelajari selengkapnya tentang fitur interoperabilitas lain yang didukung.
- Lihat sampel Pahlawan Obrolan kami.
- Pelajari lebih lanjut tentang cara kerja Chat.