Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

merging updates from ui lib repo to calling hero sample #221

Merged
merged 3 commits into from
Mar 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Calling/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ module.exports = {
}
],
eqeqeq: 'warn',
'header/header': ['error', 'line', ' Copyright (c) Microsoft Corporation.\n Licensed under the MIT license.'],
'header/header': ['error', 'line', ' Copyright (c) Microsoft Corporation.\n Licensed under the MIT License.'],
'react/display-name': 'off',
'@typescript-eslint/no-explicit-any': 'error',
'@typescript-eslint/no-unused-vars': ['warn', { varsIgnorePattern: '^_' }],
Expand Down
3,747 changes: 1,321 additions & 2,426 deletions Calling/package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Calling/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"@azure/communication-calling": "^1.22.1",
"@azure/communication-common": "^2.3.0",
"@azure/communication-identity": "^1.3.0",
"@azure/communication-react": "^1.13.0",
"@azure/communication-react": "^1.14.0",
"@azure/core-util": "1.5.0",
"@azure/logger": "^1.0.4",
"@babel/preset-react": "^7.12.7",
Expand Down
Binary file added Calling/public/assets/sounds/callBusy.mp3
Binary file not shown.
Binary file added Calling/public/assets/sounds/callEnded.mp3
Binary file not shown.
Binary file added Calling/public/assets/sounds/callRinging.mp3
Binary file not shown.
2 changes: 1 addition & 1 deletion Calling/public/index.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<!-- Copyright (c) Microsoft Corporation. -->
<!-- Licensed under the MIT license. -->
<!-- Licensed under the MIT License. -->

<!DOCTYPE html>
<html lang="en">
Expand Down
73 changes: 47 additions & 26 deletions Calling/src/app/App.tsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,39 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
// Licensed under the MIT License.

import { CommunicationUserIdentifier } from '@azure/communication-common';
import { ParticipantRole } from '@azure/communication-calling';
import { fromFlatCommunicationIdentifier, StartCallIdentifier } from '@azure/communication-react';

import { setLogLevel } from '@azure/logger';
import { initializeIcons, Spinner } from '@fluentui/react';
import { CallAdapterLocator } from '@azure/communication-react';
import React, { useEffect, useState } from 'react';
import {
addUserToRoom,
buildTime,
callingSDKVersion,
communicationReactSDKVersion,
createGroupId,
createRoom,
fetchTokenResponse,
getGroupIdFromUrl,
getRoomIdFromUrl,
getTeamsLinkFromUrl,
isLandscape,
isOnIphoneAndNotSafari,
navigateToHomePage,
WEB_APP_TITLE
} from './utils/AppUtils';

import { createRoom, getRoomIdFromUrl, addUserToRoom } from './utils/AppUtils';
import { useIsMobile } from './utils/useIsMobile';
import { useSecondaryInstanceCheck } from './utils/useSecondaryInstanceCheck';
import { CallError } from './views/CallError';
import { CallScreen } from './views/CallScreen';
import { HomeScreen } from './views/HomeScreen';
import { PageOpenInAnotherTab } from './views/PageOpenInAnotherTab';
import { UnsupportedBrowserPage } from './views/UnsupportedBrowserPage';

setLogLevel('verbose');
setLogLevel('error');

console.log(
`ACS sample calling app. Last Updated ${buildTime} using @azure/communication-calling:${callingSDKVersion} and @azure/communication-react:${communicationReactSDKVersion}`
);

initializeIcons();

Expand All @@ -44,7 +48,8 @@ const App = (): JSX.Element => {
const [userCredentialFetchError, setUserCredentialFetchError] = useState<boolean>(false);

// Call details to join a call - these are collected from the user on the home screen
const [callLocator, setCallLocator] = useState<CallAdapterLocator>(createGroupId());
const [callLocator, setCallLocator] = useState<CallAdapterLocator>();
const [targetCallees, setTargetCallees] = useState<StartCallIdentifier[]>([]);
const [displayName, setDisplayName] = useState<string>('');

// Get Azure Communications Service token from the server
Expand All @@ -63,18 +68,13 @@ const App = (): JSX.Element => {

const isMobileSession = useIsMobile();
const isLandscapeSession = isLandscape();
const isAppAlreadyRunningInAnotherTab = useSecondaryInstanceCheck();

useEffect(() => {
if (isMobileSession && isLandscapeSession) {
console.log('ACS Calling sample: Mobile landscape view is experimental behavior');
}
}, [isMobileSession, isLandscapeSession]);

if (isMobileSession && isAppAlreadyRunningInAnotherTab) {
return <PageOpenInAnotherTab />;
}

const supportedBrowser = !isOnIphoneAndNotSafari();
if (!supportedBrowser) {
return <UnsupportedBrowserPage />;
Expand All @@ -85,20 +85,32 @@ const App = (): JSX.Element => {
document.title = `home - ${WEB_APP_TITLE}`;
// Show a simplified join home screen if joining an existing call
const joiningExistingCall: boolean = !!getGroupIdFromUrl() || !!getTeamsLinkFromUrl() || !!getRoomIdFromUrl();

return (
<HomeScreen
joiningExistingCall={joiningExistingCall}
startCallHandler={async (callDetails) => {
setDisplayName(callDetails.displayName);

let callLocator: CallAdapterLocator | undefined =
callDetails.callLocator || getTeamsLinkFromUrl() || getGroupIdFromUrl();

callLocator = callLocator || getRoomIdFromUrl();
callDetails.callLocator ||
getRoomIdFromUrl() ||
getTeamsLinkFromUrl() ||
getGroupIdFromUrl() ||
createGroupId();

if (callDetails.option === 'Rooms') {
callLocator = getRoomIdFromUrl() || callDetails.callLocator;
}

callLocator = callLocator || createGroupId();
if (callDetails.option === 'TeamsAdhoc') {
const outboundTeamsUsers = callDetails.outboundTeamsUsers?.map((user) => {
return fromFlatCommunicationIdentifier(user) as StartCallIdentifier;
});
callLocator = undefined;
setTargetCallees(outboundTeamsUsers ?? []);
}

// There is an API call involved with creating a room so lets only create one if we know we have to
if (callDetails.option === 'StartRooms') {
let roomId = '';
try {
Expand All @@ -110,9 +122,13 @@ const App = (): JSX.Element => {
callLocator = { roomId: roomId };
}

if ('roomId' in callLocator) {
if (callLocator && 'roomId' in callLocator) {
if (userId && 'communicationUserId' in userId) {
await addUserToRoom(userId.communicationUserId, callLocator.roomId, callDetails.role ?? 'Presenter');
await addUserToRoom(
userId.communicationUserId,
callLocator.roomId,
callDetails.role as ParticipantRole
);
} else {
throw 'Invalid userId!';
}
Expand All @@ -121,7 +137,7 @@ const App = (): JSX.Element => {
setCallLocator(callLocator);

// Update window URL to have a joinable link
if (!joiningExistingCall) {
if (callLocator && !joiningExistingCall) {
window.history.pushState({}, document.title, window.location.origin + getJoinParams(callLocator));
}

Expand All @@ -144,14 +160,18 @@ const App = (): JSX.Element => {
);
}

if (!token || !userId || !displayName || !callLocator) {
if (!token || !userId || !displayName || (!targetCallees && !callLocator)) {
document.title = `credentials - ${WEB_APP_TITLE}`;
return <Spinner label={'Getting user credentials from server'} ariaLive="assertive" labelPosition="top" />;
}
return (
<React.StrictMode>
<CallScreen token={token} userId={userId} displayName={displayName} callLocator={callLocator} />
</React.StrictMode>
<CallScreen
token={token}
userId={userId}
displayName={displayName}
callLocator={callLocator}
targetCallees={targetCallees}
/>
);
}
default:
Expand All @@ -167,6 +187,7 @@ const getJoinParams = (locator: CallAdapterLocator): string => {
if ('roomId' in locator) {
return '?roomId=' + encodeURIComponent(locator.roomId);
}

return '?groupId=' + encodeURIComponent(locator.groupId);
};

Expand Down
2 changes: 1 addition & 1 deletion Calling/src/app/styles/CallScreen.styles.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
// Licensed under the MIT License.

import { IStackItemStyles, IStackStyles } from '@fluentui/react';

Expand Down
2 changes: 1 addition & 1 deletion Calling/src/app/styles/DisplayNameField.styles.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
// Licensed under the MIT License.

import { mergeStyles } from '@fluentui/react';

Expand Down
2 changes: 1 addition & 1 deletion Calling/src/app/styles/EndCall.styles.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
// Licensed under the MIT License.

import { IButtonStyles, IStackTokens, mergeStyles } from '@fluentui/react';

Expand Down
2 changes: 1 addition & 1 deletion Calling/src/app/styles/Footer.styles.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
// Licensed under the MIT License.

import { IButtonStyles, IStackStyles, IStackTokens, ITextFieldStyles, mergeStyles } from '@fluentui/react';

Expand Down
5 changes: 4 additions & 1 deletion Calling/src/app/styles/HomeScreen.styles.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
// Licensed under the MIT License.

import { IStackTokens, mergeStyles } from '@fluentui/react';

Expand Down Expand Up @@ -59,3 +59,6 @@ export const buttonStyle = mergeStyles({
borderRadius: 3,
padding: '0.625rem'
});
export const outboundTextField = mergeStyles({
paddingTop: '0.5rem'
});
2 changes: 1 addition & 1 deletion Calling/src/app/styles/StartCallButton.styles.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
// Licensed under the MIT License.

import { mergeStyles } from '@fluentui/react';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
// Licensed under the MIT License.

import React, { useState, useMemo, createContext, useContext } from 'react';
import { FluentThemeProvider, lightTheme, darkTheme } from '@azure/communication-react';
Expand Down
2 changes: 1 addition & 1 deletion Calling/src/app/theming/ThemeSelector.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
// Licensed under the MIT License.

import React from 'react';
import { ChoiceGroup, IChoiceGroupOption, concatStyleSets } from '@fluentui/react';
Expand Down
2 changes: 1 addition & 1 deletion Calling/src/app/utils/AppUtils.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
// Licensed under the MIT License.

import { createRandomDisplayName, getGroupIdFromUrl } from './AppUtils';

Expand Down
50 changes: 30 additions & 20 deletions Calling/src/app/utils/AppUtils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
// Licensed under the MIT License.

import { GroupLocator, ParticipantRole, RoomLocator, TeamsMeetingLinkLocator } from '@azure/communication-calling';
import { GroupLocator, TeamsMeetingLinkLocator } from '@azure/communication-calling';
import { ParticipantRole, RoomCallLocator } from '@azure/communication-calling';

import { v1 as generateGUID } from 'uuid';

Expand Down Expand Up @@ -38,24 +39,6 @@ export const getGroupIdFromUrl = (): GroupLocator | undefined => {

export const createGroupId = (): GroupLocator => ({ groupId: generateGUID() });

/**
* Get teams meeting link from the url's query params.
*/
export const getTeamsLinkFromUrl = (): TeamsMeetingLinkLocator | undefined => {
const urlParams = new URLSearchParams(window.location.search);
const teamsLink = urlParams.get('teamsLink');
return teamsLink ? { meetingLink: teamsLink } : undefined;
};

/**
* Get room id from the url's query params.
*/
export const getRoomIdFromUrl = (): RoomLocator | undefined => {
const urlParams = new URLSearchParams(window.location.search);
const roomId = urlParams.get('roomId');
return roomId ? { roomId } : undefined;
};

/**
* Create an ACS room
*/
Expand Down Expand Up @@ -89,6 +72,24 @@ export const addUserToRoom = async (userId: string, roomId: string, role: Partic
}
};

/**
* Get teams meeting link from the url's query params.
*/
export const getTeamsLinkFromUrl = (): TeamsMeetingLinkLocator | undefined => {
const urlParams = new URLSearchParams(window.location.search);
const teamsLink = urlParams.get('teamsLink');
return teamsLink ? { meetingLink: teamsLink } : undefined;
};

/**
* Get room id from the url's query params.
*/
export const getRoomIdFromUrl = (): RoomCallLocator | undefined => {
const urlParams = new URLSearchParams(window.location.search);
const roomId = urlParams.get('roomId');
return roomId ? { roomId } : undefined;
};

/*
* TODO:
* Remove this method once the SDK improves error handling for unsupported browser.
Expand All @@ -107,3 +108,12 @@ export const navigateToHomePage = (): void => {
};

export const WEB_APP_TITLE = document.title;

declare let __BUILDTIME__: string; // Injected by webpack
export const buildTime = __BUILDTIME__;

declare let __CALLINGVERSION__: string; // Injected by webpack
export const callingSDKVersion = __CALLINGVERSION__;

declare let __COMMUNICATIONREACTVERSION__: string; //Injected by webpack
export const communicationReactSDKVersion = __COMMUNICATIONREACTVERSION__;
2 changes: 1 addition & 1 deletion Calling/src/app/utils/credential.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
// Licensed under the MIT License.

import { AzureCommunicationTokenCredential, CommunicationTokenRefreshOptions } from '@azure/communication-common';
import { AbortSignalLike } from '@azure/abort-controller';
Expand Down
2 changes: 1 addition & 1 deletion Calling/src/app/utils/localStorage.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
// Licensed under the MIT License.

export const localStorageAvailable = typeof Storage !== 'undefined';

Expand Down
2 changes: 1 addition & 1 deletion Calling/src/app/utils/useIsMobile.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
// Licensed under the MIT License.

import { useEffect, useState } from 'react';
import MobileDetect from 'mobile-detect';
Expand Down
2 changes: 1 addition & 1 deletion Calling/src/app/utils/useSecondaryInstanceCheck.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
// Licensed under the MIT License.

import { useEffect, useState } from 'react';

Expand Down
8 changes: 8 additions & 0 deletions Calling/src/app/utils/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

/**
* Function to detect iOS devices like IPhones, IPads, and IPods
*/
export const isIOS = (): boolean =>
/iPad|iPhone|iPod/.test(navigator.platform) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1);
Loading
Loading