Instantly share code, notes, and snippets.
Last active
October 20, 2023 21:51
-
Star
(0)
0
You must be signed in to star a gist -
Fork
(0)
0
You must be signed in to fork a gist
-
Save edwardlee-msft/dd4832673aa462b6e6bcaab72d7ae01e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { AzureCommunicationTokenCredential, CommunicationUserIdentifier } from '@azure/communication-common'; | |
import { | |
CallComposite, | |
ChatComposite, | |
CustomCallControlButtonCallback, | |
CustomCallControlButtonCallbackArgs, | |
CustomCallControlButtonProps, | |
fromFlatCommunicationIdentifier, | |
useAzureCommunicationCallAdapter, | |
useAzureCommunicationChatAdapter | |
} from '@azure/communication-react'; | |
import React, { CSSProperties, useEffect, useMemo, useRef, useState } from 'react'; | |
import { v4 as uuidv4 } from 'uuid'; | |
import { ChatClient } from '@azure/communication-chat'; | |
/** | |
* Authentication information needed for your client application to use | |
* Azure Communication Services. | |
* | |
* For this quickstart, you can obtain these from the Azure portal as described here: | |
* https://docs.microsoft.com/en-us/azure/communication-services/quickstarts/identity/quick-create-identity | |
* | |
* In a real application, your backend service would provide these to the client | |
* application after the user goes through your authentication flow. | |
*/ | |
const ENDPOINT_URL = '<Azure Communication Services Resource Endpoint>'; | |
const USER_ID = '<Azure Communication Services Identifier>'; | |
const TOKEN = '<Azure Communication Services Access Token>'; | |
/** | |
* Display name for the local participant. | |
* In a real application, this would be part of the user data that your | |
* backend services provides to the client application after the user | |
* goes through your authentication flow. | |
*/ | |
const DISPLAY_NAME = '<Display Name>'; | |
/** | |
* Entry point of your application. | |
*/ | |
function App(): JSX.Element { | |
// Arguments that would usually be provided by your backend service or | |
// (indirectly) by the user. | |
const { endpointUrl, userId, token, displayName, groupId, threadId } = useAzureCommunicationServiceArgs(); | |
// A well-formed token is required to initialize the chat and calling adapters. | |
const credential = useMemo(() => { | |
try { | |
return new AzureCommunicationTokenCredential(token); | |
} catch { | |
console.error('Failed to construct token credential'); | |
return undefined; | |
} | |
}, [token]); | |
// Memoize arguments to `useAzureCommunicationCallAdapter` so that | |
// a new adapter is only created when an argument changes. | |
const callAdapterArgs = useMemo( | |
() => ({ | |
userId: fromFlatCommunicationIdentifier(userId) as CommunicationUserIdentifier, | |
displayName, | |
credential, | |
locator: { groupId } | |
}), | |
[userId, credential, displayName, groupId] | |
); | |
const callAdapter = useAzureCommunicationCallAdapter(callAdapterArgs); | |
// Memoize arguments to `useAzureCommunicationChatAdapter` so that | |
// a new adapter is only created when an argument changes. | |
const chatAdapterArgs = useMemo( | |
() => ({ | |
endpoint: endpointUrl, | |
userId: fromFlatCommunicationIdentifier(userId) as CommunicationUserIdentifier, | |
displayName, | |
credential, | |
threadId | |
}), | |
[endpointUrl, userId, displayName, credential, threadId] | |
); | |
const chatAdapter = useAzureCommunicationChatAdapter(chatAdapterArgs); | |
if (!!callAdapter && !!chatAdapter) { | |
return ( | |
<div style={{ height: '100vh', display: 'flex'}}> | |
<div style={containerStyle}> | |
<ChatComposite adapter={chatAdapter} /> | |
</div> | |
<div style={containerStyle}> | |
<CallComposite | |
adapter={callAdapter} | |
options={{ | |
callControls: { | |
onFetchCustomButtonProps: onFetchCustomButtonPropsExample | |
}}}/> | |
</div> | |
</div> | |
); | |
} | |
if (credential === undefined) { | |
return <h3>Failed to construct credential. Provided token is malformed.</h3>; | |
} | |
return <h3>Initializing...</h3>; | |
} | |
const containerStyle: CSSProperties = { | |
border: 'solid 0.125rem olive', | |
margin: '0.5rem', | |
width: '50vw', | |
}; | |
/** | |
* This hook returns all the arguments required to use the Azure Communication services | |
* that would be provided by your backend service after user authentication | |
* depending on the user-flow (e.g. which chat thread to use). | |
*/ | |
function useAzureCommunicationServiceArgs(): { | |
endpointUrl: string; | |
userId: string; | |
token: string; | |
displayName: string; | |
groupId: string; | |
threadId: string; | |
} { | |
const [threadId, setThreadId] = useState(''); | |
// For the quickstart, create a new thread with just the local participant in it. | |
useEffect(() => { | |
(async () => { | |
const client = new ChatClient(ENDPOINT_URL, new AzureCommunicationTokenCredential(TOKEN)); | |
const { chatThread } = await client.createChatThread( | |
{ | |
topic: 'Composites Quickstarts' | |
}, | |
{ | |
participants: [ | |
{ | |
id: fromFlatCommunicationIdentifier(USER_ID), | |
displayName: DISPLAY_NAME | |
} | |
] | |
} | |
); | |
setThreadId(chatThread?.id ?? ''); | |
})(); | |
}, []); | |
// For the quickstart, generate a random group ID. | |
// The group Id must be a UUID. | |
const groupId = useRef(uuidv4()); | |
return { | |
endpointUrl: ENDPOINT_URL, | |
userId: USER_ID, | |
token: TOKEN, | |
displayName: DISPLAY_NAME, | |
groupId: groupId.current, | |
threadId | |
}; | |
} | |
const onFetchCustomButtonPropsExample: CustomCallControlButtonCallback[] = [ | |
(args: CustomCallControlButtonCallbackArgs): CustomCallControlButtonProps => { | |
return { | |
placement: 'primary', | |
// Icon that is registered by the composites. | |
iconName: 'Link', | |
strings: { | |
label: 'Feedback', | |
tooltipContent: 'Feedback' | |
}, | |
showLabel: args.displayType !== 'compact', | |
onItemClick: () => { | |
window.open('https://feedback.azure.com/d365community/forum/81ff6d2b-0c25-ec11-b6e6-000d3a4f0858', '_blank')?.focus(); | |
} | |
}; | |
} | |
]; | |
export default App; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment