2023-01-03 11:55:46 -08:00
|
|
|
// Copyright 2020 Signal Messenger, LLC
|
2020-11-06 11:36:37 -06:00
|
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
|
|
|
|
import { createSelector } from 'reselect';
|
|
|
|
|
2021-10-26 14:15:33 -05:00
|
|
|
import type { StateType } from '../reducer';
|
|
|
|
import type {
|
2020-12-02 12:11:54 -06:00
|
|
|
CallingStateType,
|
|
|
|
CallsByConversationType,
|
2024-02-22 13:19:50 -08:00
|
|
|
AdhocCallsType,
|
|
|
|
CallLinksByRoomIdType,
|
2020-12-02 12:11:54 -06:00
|
|
|
DirectCallStateType,
|
2021-06-17 10:15:10 -07:00
|
|
|
GroupCallStateType,
|
2024-09-19 09:29:14 +10:00
|
|
|
ActiveCallStateType,
|
2020-12-02 12:11:54 -06:00
|
|
|
} from '../ducks/calling';
|
2024-10-25 10:46:54 +10:00
|
|
|
import { getRingingCall as getRingingCallHelper } from '../ducks/callingHelpers';
|
2024-10-02 09:29:59 -07:00
|
|
|
import type { PresentedSource } from '../../types/Calling';
|
2024-08-06 12:29:13 -07:00
|
|
|
import { CallMode } from '../../types/CallDisposition';
|
2024-10-09 09:35:24 -07:00
|
|
|
import { isCallLinkAdmin, type CallLinkType } from '../../types/CallLink';
|
2022-07-08 13:46:25 -07:00
|
|
|
import { getUserACI } from './user';
|
2020-12-07 14:43:19 -06:00
|
|
|
import { getOwn } from '../../util/getOwn';
|
2023-08-10 18:43:33 +02:00
|
|
|
import type { AciString } from '../../types/ServiceId';
|
2020-11-06 11:36:37 -06:00
|
|
|
|
2021-06-17 10:15:10 -07:00
|
|
|
export type CallStateType = DirectCallStateType | GroupCallStateType;
|
|
|
|
|
2020-12-02 12:11:54 -06:00
|
|
|
const getCalling = (state: StateType): CallingStateType => state.calling;
|
|
|
|
|
2024-03-13 13:44:13 -07:00
|
|
|
export const getAvailableMicrophones = createSelector(
|
|
|
|
getCalling,
|
|
|
|
({ availableMicrophones }) => availableMicrophones
|
|
|
|
);
|
|
|
|
|
|
|
|
export const getSelectedMicrophone = createSelector(
|
|
|
|
getCalling,
|
|
|
|
({ selectedMicrophone }) => selectedMicrophone
|
|
|
|
);
|
|
|
|
|
|
|
|
export const getAvailableSpeakers = createSelector(
|
|
|
|
getCalling,
|
|
|
|
({ availableSpeakers }) => availableSpeakers
|
|
|
|
);
|
|
|
|
|
|
|
|
export const getSelectedSpeaker = createSelector(
|
|
|
|
getCalling,
|
|
|
|
({ selectedSpeaker }) => selectedSpeaker
|
|
|
|
);
|
|
|
|
|
|
|
|
export const getAvailableCameras = createSelector(
|
|
|
|
getCalling,
|
|
|
|
({ availableCameras }) => availableCameras
|
|
|
|
);
|
|
|
|
|
|
|
|
export const getSelectedCamera = createSelector(
|
|
|
|
getCalling,
|
|
|
|
({ selectedCamera }) => selectedCamera
|
|
|
|
);
|
|
|
|
|
2021-06-17 10:15:10 -07:00
|
|
|
export const getActiveCallState = createSelector(
|
2021-01-29 17:58:28 -05:00
|
|
|
getCalling,
|
2024-09-19 09:29:14 +10:00
|
|
|
(state: CallingStateType) => {
|
|
|
|
if (state.activeCallState?.state !== 'Active') {
|
|
|
|
return undefined;
|
|
|
|
}
|
|
|
|
|
|
|
|
return state.activeCallState;
|
|
|
|
}
|
2021-01-29 17:58:28 -05:00
|
|
|
);
|
|
|
|
|
2020-12-07 14:43:19 -06:00
|
|
|
export const getCallsByConversation = createSelector(
|
2020-12-02 12:11:54 -06:00
|
|
|
getCalling,
|
|
|
|
(state: CallingStateType): CallsByConversationType =>
|
|
|
|
state.callsByConversation
|
|
|
|
);
|
2020-11-06 11:36:37 -06:00
|
|
|
|
2024-02-22 13:19:50 -08:00
|
|
|
export const getAdhocCalls = createSelector(
|
|
|
|
getCalling,
|
|
|
|
(state: CallingStateType): AdhocCallsType => state.adhocCalls
|
|
|
|
);
|
|
|
|
|
|
|
|
export const getCallLinksByRoomId = createSelector(
|
|
|
|
getCalling,
|
|
|
|
(state: CallingStateType): CallLinksByRoomIdType => state.callLinks
|
|
|
|
);
|
|
|
|
|
|
|
|
export type CallLinkSelectorType = (roomId: string) => CallLinkType | undefined;
|
|
|
|
|
|
|
|
export const getCallLinkSelector = createSelector(
|
|
|
|
getCallLinksByRoomId,
|
|
|
|
(callLinksByRoomId: CallLinksByRoomIdType): CallLinkSelectorType =>
|
2024-05-17 16:22:51 -07:00
|
|
|
(roomId: string): CallLinkType | undefined =>
|
|
|
|
getOwn(callLinksByRoomId, roomId)
|
|
|
|
);
|
|
|
|
|
|
|
|
export const getAllCallLinks = createSelector(
|
|
|
|
getCallLinksByRoomId,
|
|
|
|
(lookup): Array<CallLinkType> => Object.values(lookup)
|
2024-02-22 13:19:50 -08:00
|
|
|
);
|
|
|
|
|
2024-10-09 09:35:24 -07:00
|
|
|
export const getHasAnyAdminCallLinks = createSelector(
|
|
|
|
getAllCallLinks,
|
|
|
|
(callLinks): boolean => callLinks.some(callLink => isCallLinkAdmin(callLink))
|
|
|
|
);
|
|
|
|
|
2021-06-17 10:15:10 -07:00
|
|
|
export type CallSelectorType = (
|
|
|
|
conversationId: string
|
|
|
|
) => CallStateType | undefined;
|
2020-12-07 14:43:19 -06:00
|
|
|
export const getCallSelector = createSelector(
|
|
|
|
getCallsByConversation,
|
2021-11-11 16:43:05 -06:00
|
|
|
(callsByConversation: CallsByConversationType): CallSelectorType =>
|
|
|
|
(conversationId: string) =>
|
|
|
|
getOwn(callsByConversation, conversationId)
|
2021-06-17 10:15:10 -07:00
|
|
|
);
|
|
|
|
|
2024-02-22 13:19:50 -08:00
|
|
|
export type AdhocCallSelectorType = (
|
|
|
|
conversationId: string
|
|
|
|
) => GroupCallStateType | undefined;
|
|
|
|
export const getAdhocCallSelector = createSelector(
|
|
|
|
getAdhocCalls,
|
|
|
|
(adhocCalls: AdhocCallsType): AdhocCallSelectorType =>
|
|
|
|
(roomId: string) =>
|
|
|
|
getOwn(adhocCalls, roomId)
|
|
|
|
);
|
|
|
|
|
2021-06-17 10:15:10 -07:00
|
|
|
export const getActiveCall = createSelector(
|
|
|
|
getActiveCallState,
|
|
|
|
getCallSelector,
|
2024-02-22 13:19:50 -08:00
|
|
|
getAdhocCallSelector,
|
|
|
|
(
|
|
|
|
activeCallState,
|
|
|
|
callSelector,
|
|
|
|
adhocCallSelector
|
|
|
|
): undefined | CallStateType => {
|
|
|
|
const { callMode, conversationId } = activeCallState || {};
|
|
|
|
if (!conversationId) {
|
|
|
|
return undefined;
|
2021-06-17 10:15:10 -07:00
|
|
|
}
|
|
|
|
|
2024-02-22 13:19:50 -08:00
|
|
|
return callMode === CallMode.Adhoc
|
|
|
|
? adhocCallSelector(conversationId)
|
|
|
|
: callSelector(conversationId);
|
2021-06-17 10:15:10 -07:00
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
export const isInCall = createSelector(
|
|
|
|
getActiveCall,
|
|
|
|
(call: CallStateType | undefined): boolean => Boolean(call)
|
2020-12-07 14:43:19 -06:00
|
|
|
);
|
|
|
|
|
2022-08-04 21:07:46 -04:00
|
|
|
export const isInFullScreenCall = createSelector(
|
2024-09-19 09:29:14 +10:00
|
|
|
getActiveCallState,
|
|
|
|
(activeCallState: undefined | ActiveCallStateType): boolean =>
|
2024-10-15 10:48:36 -05:00
|
|
|
Boolean(activeCallState && !activeCallState.pip)
|
2022-08-04 21:07:46 -04:00
|
|
|
);
|
|
|
|
|
2024-10-25 10:46:54 +10:00
|
|
|
export const getRingingCall = createSelector(
|
2020-11-06 11:36:37 -06:00
|
|
|
getCallsByConversation,
|
2024-10-25 10:46:54 +10:00
|
|
|
getActiveCallState,
|
2022-07-08 13:46:25 -07:00
|
|
|
getUserACI,
|
2020-12-02 12:11:54 -06:00
|
|
|
(
|
2021-08-20 11:06:15 -05:00
|
|
|
callsByConversation: CallsByConversationType,
|
2024-10-25 10:46:54 +10:00
|
|
|
activeCallState: ActiveCallStateType | undefined,
|
2023-08-10 18:43:33 +02:00
|
|
|
ourAci: AciString | undefined
|
2022-02-23 10:48:40 -08:00
|
|
|
): undefined | DirectCallStateType | GroupCallStateType => {
|
2023-08-10 18:43:33 +02:00
|
|
|
if (!ourAci) {
|
2022-02-23 10:48:40 -08:00
|
|
|
return undefined;
|
|
|
|
}
|
|
|
|
|
2024-10-25 10:46:54 +10:00
|
|
|
return getRingingCallHelper(callsByConversation, activeCallState, ourAci);
|
2022-02-23 10:48:40 -08:00
|
|
|
}
|
2020-11-06 11:36:37 -06:00
|
|
|
);
|
2022-05-25 11:03:27 -07:00
|
|
|
|
2022-11-16 20:52:04 -06:00
|
|
|
export const areAnyCallsActiveOrRinging = createSelector(
|
|
|
|
getActiveCall,
|
2024-10-25 10:46:54 +10:00
|
|
|
getRingingCall,
|
|
|
|
(activeCall, ringingCall): boolean => Boolean(activeCall || ringingCall)
|
2022-11-16 20:52:04 -06:00
|
|
|
);
|
2024-10-02 09:29:59 -07:00
|
|
|
|
|
|
|
export const getPresentingSource = createSelector(
|
|
|
|
getActiveCallState,
|
|
|
|
(activeCallState): PresentedSource | undefined =>
|
|
|
|
activeCallState?.presentingSource
|
|
|
|
);
|