Raise Hand in Group Calls
This commit is contained in:
parent
45aeaeefd4
commit
d6db3f7943
33 changed files with 1050 additions and 51 deletions
|
@ -116,6 +116,7 @@ export type GroupCallStateType = {
|
|||
localDemuxId: number | undefined;
|
||||
joinState: GroupCallJoinState;
|
||||
peekInfo?: GroupCallPeekInfoType;
|
||||
raisedHands?: Array<number>;
|
||||
remoteParticipants: Array<GroupCallParticipantInfoType>;
|
||||
remoteAudioLevels?: Map<number, number>;
|
||||
} & GroupCallRingStateType;
|
||||
|
@ -222,11 +223,15 @@ type IncomingGroupCallType = ReadonlyDeep<{
|
|||
ringerAci: AciString;
|
||||
}>;
|
||||
|
||||
export type SendGroupCallRaiseHandType = ReadonlyDeep<{
|
||||
conversationId: string;
|
||||
raise: boolean;
|
||||
}>;
|
||||
|
||||
export type SendGroupCallReactionType = ReadonlyDeep<{
|
||||
conversationId: string;
|
||||
value: string;
|
||||
}>;
|
||||
|
||||
type SendGroupCallReactionLocalCopyType = ReadonlyDeep<{
|
||||
conversationId: string;
|
||||
value: string;
|
||||
|
@ -445,6 +450,7 @@ const CHANGE_IO_DEVICE_FULFILLED = 'calling/CHANGE_IO_DEVICE_FULFILLED';
|
|||
const CLOSE_NEED_PERMISSION_SCREEN = 'calling/CLOSE_NEED_PERMISSION_SCREEN';
|
||||
const DECLINE_DIRECT_CALL = 'calling/DECLINE_DIRECT_CALL';
|
||||
const GROUP_CALL_AUDIO_LEVELS_CHANGE = 'calling/GROUP_CALL_AUDIO_LEVELS_CHANGE';
|
||||
const GROUP_CALL_RAISED_HANDS_CHANGE = 'calling/GROUP_CALL_RAISED_HANDS_CHANGE';
|
||||
const GROUP_CALL_STATE_CHANGE = 'calling/GROUP_CALL_STATE_CHANGE';
|
||||
const GROUP_CALL_REACTIONS_RECEIVED = 'calling/GROUP_CALL_REACTIONS_RECEIVED';
|
||||
const GROUP_CALL_REACTIONS_EXPIRED = 'calling/GROUP_CALL_REACTIONS_EXPIRED';
|
||||
|
@ -455,6 +461,7 @@ const MARK_CALL_TRUSTED = 'calling/MARK_CALL_TRUSTED';
|
|||
const MARK_CALL_UNTRUSTED = 'calling/MARK_CALL_UNTRUSTED';
|
||||
const OUTGOING_CALL = 'calling/OUTGOING_CALL';
|
||||
const PEEK_GROUP_CALL_FULFILLED = 'calling/PEEK_GROUP_CALL_FULFILLED';
|
||||
const RAISE_HAND_GROUP_CALL = 'calling/RAISE_HAND_GROUP_CALL';
|
||||
const REFRESH_IO_DEVICES = 'calling/REFRESH_IO_DEVICES';
|
||||
const REMOTE_SHARING_SCREEN_CHANGE = 'calling/REMOTE_SHARING_SCREEN_CHANGE';
|
||||
const REMOTE_VIDEO_CHANGE = 'calling/REMOTE_VIDEO_CHANGE';
|
||||
|
@ -525,6 +532,16 @@ type GroupCallAudioLevelsChangeActionType = ReadonlyDeep<{
|
|||
payload: GroupCallAudioLevelsChangeActionPayloadType;
|
||||
}>;
|
||||
|
||||
type GroupCallRaisedHandsChangeActionPayloadType = ReadonlyDeep<{
|
||||
conversationId: string;
|
||||
raisedHands: ReadonlyArray<number>;
|
||||
}>;
|
||||
|
||||
type GroupCallRaisedHandsChangeActionType = ReadonlyDeep<{
|
||||
type: 'calling/GROUP_CALL_RAISED_HANDS_CHANGE';
|
||||
payload: GroupCallRaisedHandsChangeActionPayloadType;
|
||||
}>;
|
||||
|
||||
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||
export type GroupCallStateChangeActionType = {
|
||||
type: 'calling/GROUP_CALL_STATE_CHANGE';
|
||||
|
@ -580,6 +597,11 @@ type KeyChangeOkActionType = ReadonlyDeep<{
|
|||
payload: null;
|
||||
}>;
|
||||
|
||||
type SendGroupCallRaiseHandActionType = ReadonlyDeep<{
|
||||
type: 'calling/RAISE_HAND_GROUP_CALL';
|
||||
payload: SendGroupCallRaiseHandType;
|
||||
}>;
|
||||
|
||||
export type SendGroupCallReactionActionType = ReadonlyDeep<{
|
||||
type: 'calling/SEND_GROUP_CALL_REACTION';
|
||||
payload: SendGroupCallReactionLocalCopyType;
|
||||
|
@ -692,6 +714,7 @@ export type CallingActionType =
|
|||
| ConversationRemovedActionType
|
||||
| DeclineCallActionType
|
||||
| GroupCallAudioLevelsChangeActionType
|
||||
| GroupCallRaisedHandsChangeActionType
|
||||
| GroupCallStateChangeActionType
|
||||
| GroupCallReactionsReceivedActionType
|
||||
| GroupCallReactionsExpiredActionType
|
||||
|
@ -950,6 +973,12 @@ function receiveGroupCallReactions(
|
|||
};
|
||||
}
|
||||
|
||||
function groupCallRaisedHandsChange(
|
||||
payload: GroupCallRaisedHandsChangeActionPayloadType
|
||||
): GroupCallRaisedHandsChangeActionType {
|
||||
return { type: GROUP_CALL_RAISED_HANDS_CHANGE, payload };
|
||||
}
|
||||
|
||||
function groupCallStateChange(
|
||||
payload: GroupCallStateChangeArgumentType
|
||||
): ThunkAction<void, RootStateType, unknown, GroupCallStateChangeActionType> {
|
||||
|
@ -1075,6 +1104,19 @@ function keyChangeOk(
|
|||
};
|
||||
}
|
||||
|
||||
function sendGroupCallRaiseHand(
|
||||
payload: SendGroupCallRaiseHandType
|
||||
): ThunkAction<void, RootStateType, unknown, SendGroupCallRaiseHandActionType> {
|
||||
return dispatch => {
|
||||
calling.sendGroupCallRaiseHand(payload.conversationId, payload.raise);
|
||||
|
||||
dispatch({
|
||||
type: RAISE_HAND_GROUP_CALL,
|
||||
payload,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function sendGroupCallReaction(
|
||||
payload: SendGroupCallReactionType
|
||||
): ThunkAction<
|
||||
|
@ -1612,6 +1654,7 @@ export const actions = {
|
|||
declineCall,
|
||||
getPresentingSources,
|
||||
groupCallAudioLevelsChange,
|
||||
groupCallRaisedHandsChange,
|
||||
groupCallStateChange,
|
||||
hangUpActiveCall,
|
||||
keyChangeOk,
|
||||
|
@ -1630,6 +1673,7 @@ export const actions = {
|
|||
remoteSharingScreenChange,
|
||||
remoteVideoChange,
|
||||
returnToActiveCall,
|
||||
sendGroupCallRaiseHand,
|
||||
sendGroupCallReaction,
|
||||
setGroupCallVideoRequest,
|
||||
setIsCallActive,
|
||||
|
@ -2137,6 +2181,7 @@ export function reducer(
|
|||
localDemuxId,
|
||||
peekInfo: newPeekInfo,
|
||||
remoteParticipants,
|
||||
raisedHands: existingCall?.raisedHands ?? [],
|
||||
...newRingState,
|
||||
},
|
||||
},
|
||||
|
@ -2267,6 +2312,29 @@ export function reducer(
|
|||
};
|
||||
}
|
||||
|
||||
if (action.type === GROUP_CALL_RAISED_HANDS_CHANGE) {
|
||||
const { conversationId, raisedHands } = action.payload;
|
||||
|
||||
const { activeCallState } = state;
|
||||
const existingCall = getGroupCall(conversationId, state);
|
||||
|
||||
if (
|
||||
state.activeCallState?.conversationId !== conversationId ||
|
||||
!activeCallState ||
|
||||
!existingCall
|
||||
) {
|
||||
return state;
|
||||
}
|
||||
|
||||
return {
|
||||
...state,
|
||||
callsByConversation: {
|
||||
...callsByConversation,
|
||||
[conversationId]: { ...existingCall, raisedHands: [...raisedHands] },
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
if (action.type === REMOTE_SHARING_SCREEN_CHANGE) {
|
||||
const { conversationId, isSharingScreen } = action.payload;
|
||||
const call = getOwn(state.callsByConversation, conversationId);
|
||||
|
|
|
@ -13,6 +13,7 @@ import { getActiveCall } from '../ducks/calling';
|
|||
import type { ConversationType } from '../ducks/conversations';
|
||||
import { getIncomingCall } from '../selectors/calling';
|
||||
import { isGroupCallOutboundRingEnabled } from '../../util/isGroupCallOutboundRingEnabled';
|
||||
import { isGroupCallRaiseHandEnabled } from '../../util/isGroupCallRaiseHandEnabled';
|
||||
import { isGroupCallReactionsEnabled } from '../../util/isGroupCallReactionsEnabled';
|
||||
import type {
|
||||
ActiveCallBaseType,
|
||||
|
@ -201,6 +202,8 @@ const mapStateToActiveCallProp = (
|
|||
const remoteParticipants: Array<GroupCallRemoteParticipantType> = [];
|
||||
const peekedParticipants: Array<ConversationType> = [];
|
||||
const conversationsByDemuxId: ConversationsByDemuxIdType = new Map();
|
||||
const { localDemuxId } = call;
|
||||
const raisedHands: Set<number> = new Set(call.raisedHands ?? []);
|
||||
|
||||
const { memberships = [] } = conversation;
|
||||
|
||||
|
@ -243,6 +246,7 @@ const mapStateToActiveCallProp = (
|
|||
demuxId: remoteParticipant.demuxId,
|
||||
hasRemoteAudio: remoteParticipant.hasRemoteAudio,
|
||||
hasRemoteVideo: remoteParticipant.hasRemoteVideo,
|
||||
isHandRaised: raisedHands.has(remoteParticipant.demuxId),
|
||||
presenting: remoteParticipant.presenting,
|
||||
sharingScreen: remoteParticipant.sharingScreen,
|
||||
speakerTime: remoteParticipant.speakerTime,
|
||||
|
@ -254,6 +258,17 @@ const mapStateToActiveCallProp = (
|
|||
);
|
||||
}
|
||||
|
||||
if (localDemuxId !== undefined) {
|
||||
conversationsByDemuxId.set(localDemuxId, getMe(state));
|
||||
}
|
||||
|
||||
// Filter raisedHands to ensure valid demuxIds.
|
||||
raisedHands.forEach(demuxId => {
|
||||
if (!conversationsByDemuxId.has(demuxId)) {
|
||||
raisedHands.delete(demuxId);
|
||||
}
|
||||
});
|
||||
|
||||
for (
|
||||
let i = 0;
|
||||
i < activeCallState.safetyNumberChangedAcis.length;
|
||||
|
@ -293,9 +308,10 @@ const mapStateToActiveCallProp = (
|
|||
groupMembers,
|
||||
isConversationTooBigToRing: isConversationTooBigToRing(conversation),
|
||||
joinState: call.joinState,
|
||||
localDemuxId: call.localDemuxId,
|
||||
localDemuxId,
|
||||
maxDevices: peekInfo.maxDevices,
|
||||
peekedParticipants,
|
||||
raisedHands,
|
||||
remoteParticipants,
|
||||
remoteAudioLevels: call.remoteAudioLevels || new Map<number, number>(),
|
||||
} satisfies ActiveGroupCallType;
|
||||
|
@ -360,6 +376,7 @@ const mapStateToProps = (state: StateType) => {
|
|||
getPreferredBadge: getPreferredBadgeSelector(state),
|
||||
i18n: getIntl(state),
|
||||
isGroupCallOutboundRingEnabled: isGroupCallOutboundRingEnabled(),
|
||||
isGroupCallRaiseHandEnabled: isGroupCallRaiseHandEnabled(),
|
||||
isGroupCallReactionsEnabled: isGroupCallReactionsEnabled(),
|
||||
incomingCall,
|
||||
me: getMe(state),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue