Skip to content

Commit 765ce4f

Browse files
authored
[Calling] Send reaction component calling-component-binding and composite changes (#4003)
1 parent da732f8 commit 765ce4f

199 files changed

Lines changed: 312 additions & 15 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"type": "minor",
3+
"area": "feature",
4+
"workstream": "Send reaction data flow",
5+
"comment": "Send reaction button component",
6+
"packageName": "@azure/communication-react",
7+
"email": "mbellah@microsoft.com",
8+
"dependentChangeType": "patch"
9+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"type": "minor",
3+
"area": "feature",
4+
"workstream": "Send reaction data flow",
5+
"comment": "Send reaction button component",
6+
"packageName": "@azure/communication-react",
7+
"email": "mbellah@microsoft.com",
8+
"dependentChangeType": "patch"
9+
}

packages/calling-component-bindings/review/beta/calling-component-bindings.api.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import { PermissionConstraints } from '@azure/communication-calling';
4444
import { PhoneNumberIdentifier } from '@azure/communication-common';
4545
import { default as React_2 } from 'react';
4646
import { ReactElement } from 'react';
47+
import { Reaction } from '@azure/communication-calling';
4748
import { RemoteParticipantState } from '@internal/calling-stateful-client';
4849
import { ScreenShareButton } from '@internal/react-components';
4950
import { StartCallOptions } from '@azure/communication-calling';
@@ -172,6 +173,8 @@ export interface CommonCallingHandlers {
172173
// (undocumented)
173174
onRaiseHand: () => Promise<void>;
174175
// (undocumented)
176+
onReactionClicked: (reaction: Reaction) => Promise<void>;
177+
// (undocumented)
175178
onRemoveParticipant(userId: string): Promise<void>;
176179
// (undocumented)
177180
onRemoveParticipant(participant: CommunicationIdentifier): Promise<void>;
@@ -317,6 +320,15 @@ export type RaiseHandButtonSelector = (state: CallClientState, props: CallingBas
317320
// @public
318321
export const raiseHandButtonSelector: RaiseHandButtonSelector;
319322

323+
// @beta
324+
export type ReactionButtonSelector = (state: CallClientState, props: CallingBaseSelectorProps) => {
325+
checked?: boolean;
326+
disabled?: boolean;
327+
};
328+
329+
// @beta
330+
export const reactionButtonSelector: ReactionButtonSelector;
331+
320332
// @public
321333
export type ScreenShareButtonSelector = (state: CallClientState, props: CallingBaseSelectorProps) => {
322334
checked?: boolean;

packages/calling-component-bindings/src/callControlSelectors.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import {
1212
getIsScreenSharingOn,
1313
getLocalVideoStreams
1414
} from './baseSelectors';
15+
/* @conditional-compile-remove(reaction) */
16+
import { getLocalParticipantReactionState } from './baseSelectors';
1517
/* @conditional-compile-remove(capabilities) */
1618
import { getCapabilites, getRole } from './baseSelectors';
1719
/* @conditional-compile-remove(PSTN-calls) */ /* @conditional-compile-remove(raise-hand) */
@@ -168,6 +170,36 @@ export const raiseHandButtonSelector: RaiseHandButtonSelector = reselect.createS
168170
}
169171
);
170172

173+
/* @conditional-compile-remove(reaction) */
174+
/**
175+
* Selector type for {@link ReactionButton} component.
176+
*
177+
* @beta
178+
*/
179+
export type ReactionButtonSelector = (
180+
state: CallClientState,
181+
props: CallingBaseSelectorProps
182+
) => {
183+
checked?: boolean;
184+
disabled?: boolean;
185+
};
186+
187+
/* @conditional-compile-remove(reaction) */
188+
/**
189+
* Selector for {@link ReactionButton} component.
190+
*
191+
* @beta
192+
*/
193+
export const reactionButtonSelector: ReactionButtonSelector = reselect.createSelector(
194+
[getLocalParticipantReactionState, getCallState],
195+
(reaction, callState) => {
196+
return {
197+
checked: reaction ? true : false,
198+
disabled: callState !== 'Connected'
199+
};
200+
}
201+
);
202+
171203
/**
172204
* Selector for {@link ScreenShareButton} component.
173205
*

packages/calling-component-bindings/src/handlers/createCommonHandlers.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ import { CommunicationIdentifier } from '@azure/communication-common';
3434
import { Features } from '@azure/communication-calling';
3535
/* @conditional-compile-remove(close-captions) */
3636
import { TeamsCaptions } from '@azure/communication-calling';
37+
/* @conditional-compile-remove(reaction) */
38+
import { Reaction } from '@azure/communication-calling';
3739

3840
/**
3941
* Object containing all the handlers required for calling components.
@@ -60,6 +62,8 @@ export interface CommonCallingHandlers {
6062
onLowerHand: () => Promise<void>;
6163
/* @conditional-compile-remove(raise-hand) */
6264
onToggleRaiseHand: () => Promise<void>;
65+
/* @conditional-compile-remove(reaction) */
66+
onReactionClicked: (reaction: Reaction) => Promise<void>;
6367
/* @conditional-compile-remove(PSTN-calls) */
6468
onToggleHold: () => Promise<void>;
6569
/* @conditional-compile-remove(PSTN-calls) */
@@ -320,6 +324,22 @@ export const createDefaultCommonCallingHandlers = memoizeOne(
320324
}
321325
};
322326

327+
/* @conditional-compile-remove(reaction) */
328+
const onReactionClicked = async (reaction: Reaction): Promise<void> => {
329+
if (
330+
reaction === 'like' ||
331+
reaction === 'applause' ||
332+
reaction === 'heart' ||
333+
reaction === 'laugh' ||
334+
reaction === 'surprised'
335+
) {
336+
await call?.feature(Features.Reaction)?.sendReaction({ reactionType: reaction });
337+
} else {
338+
console.warn(`Can not recognize ${reaction} as meeting reaction`);
339+
}
340+
return;
341+
};
342+
323343
const onToggleMicrophone = async (): Promise<void> => {
324344
if (!call || !(_isInCall(call.state) || _isInLobbyOrConnecting(call.state))) {
325345
throw new Error(`Please invoke onToggleMicrophone after call is started`);
@@ -624,6 +644,8 @@ export const createDefaultCommonCallingHandlers = memoizeOne(
624644
onLowerHand,
625645
/* @conditional-compile-remove(raise-hand) */
626646
onToggleRaiseHand,
647+
/* @conditional-compile-remove(reaction) */
648+
onReactionClicked,
627649
/* @conditional-compile-remove(PSTN-calls) */
628650
onAddParticipant: notImplemented,
629651
onRemoveParticipant: notImplemented,

packages/calling-component-bindings/src/hooks/usePropsFor.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ import { AreEqual } from '@internal/acs-ui-common';
4141
import { ParticipantsButton } from '@internal/react-components';
4242
import { ErrorBarSelector, errorBarSelector } from '../errorBarSelector';
4343
import { CommonCallingHandlers } from '../handlers/createCommonHandlers';
44+
/* @conditional-compile-remove(reaction) */
45+
import { reactionButtonSelector } from '../callControlSelectors';
46+
/* @conditional-compile-remove(reaction) */
47+
import { ReactionButton } from '@internal/react-components';
4448

4549
/**
4650
* Primary hook to get all hooks necessary for a calling Component.
@@ -137,6 +141,10 @@ export const getSelector = <Component extends (props: any) => JSX.Element | unde
137141
if (component === RaiseHandButton) {
138142
return findConditionalCompiledSelector(component);
139143
}
144+
/* @conditional-compile-remove(reaction) */
145+
if (component === ReactionButton) {
146+
return findConditionalCompiledSelector(component);
147+
}
140148
return findSelector(component);
141149
};
142150

@@ -181,5 +189,9 @@ const findConditionalCompiledSelector = (component: (props: any) => JSX.Element
181189
case RaiseHandButton:
182190
/* @conditional-compile-remove(raise-hand) */
183191
return raiseHandButtonSelector;
192+
/* @conditional-compile-remove(reaction) */
193+
case ReactionButton:
194+
/* @conditional-compile-remove(reaction) */
195+
return reactionButtonSelector;
184196
}
185197
};

packages/calling-component-bindings/src/videoGallerySelector.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,11 @@ import {
3333
import { memoizeSpotlightedParticipantIds } from './utils/videoGalleryUtils';
3434
/* @conditional-compile-remove(raise-hand) */
3535
import { getLocalParticipantRaisedHand } from './baseSelectors';
36-
import { getRemoteParticipantsExcludingConsumers } from './getRemoteParticipantsExcludingConsumers';
3736
/* @conditional-compile-remove(reaction) */
3837
import { getLocalParticipantReactionState } from './baseSelectors';
3938
/* @conditional-compile-remove(reaction) */
4039
import { memoizedConvertToVideoTileReaction } from './utils/participantListSelectorUtils';
40+
import { getRemoteParticipantsExcludingConsumers } from './getRemoteParticipantsExcludingConsumers';
4141
/* @conditional-compile-remove(spotlight) */
4242
import { getSpotlightedParticipants } from './baseSelectors';
4343

packages/communication-react/review/beta/communication-react.api.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ import { PersonaSize } from '@fluentui/react';
7676
import { PhoneNumberIdentifier } from '@azure/communication-common';
7777
import { PropertyChangedEvent } from '@azure/communication-calling';
7878
import { default as React_2 } from 'react';
79+
import { Reaction as Reaction_2 } from '@azure/communication-calling';
7980
import { ReactionMessage } from '@azure/communication-calling';
8081
import type { RemoteParticipant } from '@azure/communication-calling';
8182
import { RemoteParticipantState as RemoteParticipantState_2 } from '@azure/communication-calling';
@@ -342,6 +343,8 @@ export interface CallAdapterCallOperations {
342343
leaveCall(forEveryone?: boolean): Promise<void>;
343344
lowerHand(): Promise<void>;
344345
mute(): Promise<void>;
346+
// @beta
347+
onReactionClicked(reaction: Reaction_2): Promise<void>;
345348
raiseHand(): Promise<void>;
346349
removeParticipant(userId: string): Promise<void>;
347350
// @beta
@@ -534,6 +537,7 @@ export type CallCompositeIcons = {
534537
ControlButtonRaiseHand?: JSX.Element;
535538
ControlButtonLowerHand?: JSX.Element;
536539
RaiseHandContextualMenuItem?: JSX.Element;
540+
ReactionContextualMenuItem?: JSX.Element;
537541
LowerHandContextualMenuItem?: JSX.Element;
538542
ReactionButtonIcon?: JSX.Element;
539543
ErrorBarCallCameraAccessDenied?: JSX.Element;
@@ -990,6 +994,8 @@ export interface CallWithChatAdapterManagement {
990994
loadPreviousChatMessages(messagesToLoad: number): Promise<boolean>;
991995
lowerHand(): Promise<void>;
992996
mute(): Promise<void>;
997+
// @beta
998+
onReactionClicked(reaction: Reaction_2): Promise<void>;
993999
queryCameras(): Promise<VideoDeviceInfo[]>;
9941000
queryMicrophones(): Promise<AudioDeviceInfo[]>;
9951001
querySpeakers(): Promise<AudioDeviceInfo[]>;
@@ -1860,6 +1866,9 @@ export type CommonCallControlOptions = {
18601866
raiseHandButton?: boolean | {
18611867
disabled: boolean;
18621868
};
1869+
reactionButton?: boolean | {
1870+
disabled: boolean;
1871+
};
18631872
onFetchCustomButtonProps?: CustomCallControlButtonCallback[];
18641873
holdButton?: boolean | {
18651874
disabled: boolean;
@@ -1898,6 +1907,8 @@ export interface CommonCallingHandlers {
18981907
// (undocumented)
18991908
onRaiseHand: () => Promise<void>;
19001909
// (undocumented)
1910+
onReactionClicked: (reaction: Reaction_2) => Promise<void>;
1911+
// (undocumented)
19011912
onRemoveParticipant(userId: string): Promise<void>;
19021913
// (undocumented)
19031914
onRemoveParticipant(participant: CommunicationIdentifier): Promise<void>;
@@ -2466,6 +2477,7 @@ export const DEFAULT_COMPOSITE_ICONS: {
24662477
ControlButtonRaiseHand: JSX.Element;
24672478
ControlButtonLowerHand: JSX.Element;
24682479
RaiseHandContextualMenuItem: JSX.Element;
2480+
ReactionContextualMenuItem?: JSX.Element | undefined;
24692481
LowerHandContextualMenuItem: JSX.Element;
24702482
ReactionButtonIcon: JSX.Element;
24712483
ErrorBarCallCameraAccessDenied: JSX.Element;
@@ -3654,7 +3666,7 @@ export type Reaction = {
36543666

36553667
// @beta
36563668
export interface ReactionButtonProps extends ControlBarButtonProps {
3657-
onReactionClicked: (emoji: string) => Promise<void>;
3669+
onReactionClicked: (reaction: string) => Promise<void>;
36583670
strings?: Partial<ReactionButtonStrings>;
36593671
}
36603672

packages/react-components/review/beta/react-components.api.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1901,7 +1901,7 @@ export const ReactionButton: (props: ReactionButtonProps) => JSX.Element;
19011901

19021902
// @beta
19031903
export interface ReactionButtonProps extends ControlBarButtonProps {
1904-
onReactionClicked: (emoji: string) => Promise<void>;
1904+
onReactionClicked: (reaction: string) => Promise<void>;
19051905
strings?: Partial<ReactionButtonStrings>;
19061906
}
19071907

packages/react-components/src/components/ReactionButton.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export interface ReactionButtonProps extends ControlBarButtonProps {
3838
/**
3939
* Click event to send reaction to meeting
4040
*/
41-
onReactionClicked: (emoji: string) => Promise<void>;
41+
onReactionClicked: (reaction: string) => Promise<void>;
4242
}
4343

4444
/* @conditional-compile-remove(reaction) */
@@ -117,6 +117,7 @@ export const ReactionButton = (props: ReactionButtonProps): JSX.Element => {
117117
onRenderIcon={props.onRenderIcon ?? onRenderIcon}
118118
strings={strings}
119119
labelKey={props.labelKey ?? 'reactionButtonLabel'}
120+
onRenderMenuIcon={() => <div />}
120121
/>
121122
);
122123
};

0 commit comments

Comments
 (0)