Contact info modal for call link join requests
This commit is contained in:
69
ts/components/CallLinkPendingParticipantModal.stories.tsx
Normal file
69
ts/components/CallLinkPendingParticipantModal.stories.tsx
Normal file
@@ -0,0 +1,69 @@
|
||||
// Copyright 2024 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import React from 'react';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
import { setupI18n } from '../util/setupI18n';
|
||||
import enMessages from '../../_locales/en/messages.json';
|
||||
import type { CallLinkPendingParticipantModalProps } from './CallLinkPendingParticipantModal';
|
||||
import { CallLinkPendingParticipantModal } from './CallLinkPendingParticipantModal';
|
||||
import type { ComponentMeta } from '../storybook/types';
|
||||
import { getDefaultConversation } from '../test-both/helpers/getDefaultConversation';
|
||||
|
||||
const i18n = setupI18n('en', enMessages);
|
||||
|
||||
const conversation = getDefaultConversation({
|
||||
acceptedMessageRequest: true,
|
||||
hasMessages: true,
|
||||
});
|
||||
const conversationWithSharedGroups = getDefaultConversation({
|
||||
acceptedMessageRequest: true,
|
||||
aboutText: 'likes to chat',
|
||||
hasMessages: true,
|
||||
sharedGroupNames: ['Axolotl lovers'],
|
||||
});
|
||||
const systemContact = getDefaultConversation({
|
||||
acceptedMessageRequest: true,
|
||||
systemGivenName: 'Alice',
|
||||
phoneNumber: '+1 555 123-4567',
|
||||
hasMessages: true,
|
||||
});
|
||||
|
||||
export default {
|
||||
title: 'Components/CallLinkPendingParticipantModal',
|
||||
component: CallLinkPendingParticipantModal,
|
||||
args: {
|
||||
i18n,
|
||||
conversation,
|
||||
approveUser: action('approveUser'),
|
||||
denyUser: action('denyUser'),
|
||||
toggleAboutContactModal: action('toggleAboutContactModal'),
|
||||
onClose: action('onClose'),
|
||||
updateSharedGroups: action('updateSharedGroups'),
|
||||
},
|
||||
} satisfies ComponentMeta<CallLinkPendingParticipantModalProps>;
|
||||
|
||||
export function Default(
|
||||
args: CallLinkPendingParticipantModalProps
|
||||
): JSX.Element {
|
||||
return <CallLinkPendingParticipantModal {...args} />;
|
||||
}
|
||||
|
||||
export function SystemContact(
|
||||
args: CallLinkPendingParticipantModalProps
|
||||
): JSX.Element {
|
||||
return (
|
||||
<CallLinkPendingParticipantModal {...args} conversation={systemContact} />
|
||||
);
|
||||
}
|
||||
|
||||
export function WithSharedGroups(
|
||||
args: CallLinkPendingParticipantModalProps
|
||||
): JSX.Element {
|
||||
return (
|
||||
<CallLinkPendingParticipantModal
|
||||
{...args}
|
||||
conversation={conversationWithSharedGroups}
|
||||
/>
|
||||
);
|
||||
}
|
140
ts/components/CallLinkPendingParticipantModal.tsx
Normal file
140
ts/components/CallLinkPendingParticipantModal.tsx
Normal file
@@ -0,0 +1,140 @@
|
||||
// Copyright 2024 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import React, { useCallback, useEffect, useMemo } from 'react';
|
||||
import { Modal } from './Modal';
|
||||
import type { LocalizerType } from '../types/I18N';
|
||||
import { Avatar, AvatarSize } from './Avatar';
|
||||
import type { PendingUserActionPayloadType } from '../state/ducks/calling';
|
||||
import type { ConversationType } from '../state/ducks/conversations';
|
||||
import { InContactsIcon } from './InContactsIcon';
|
||||
import { isInSystemContacts } from '../util/isInSystemContacts';
|
||||
import { ThemeType } from '../types/Util';
|
||||
import { Theme } from '../util/theme';
|
||||
import { UserText } from './UserText';
|
||||
import { SharedGroupNames } from './SharedGroupNames';
|
||||
|
||||
export type CallLinkPendingParticipantModalProps = {
|
||||
readonly i18n: LocalizerType;
|
||||
readonly conversation: ConversationType;
|
||||
readonly approveUser: (payload: PendingUserActionPayloadType) => void;
|
||||
readonly denyUser: (payload: PendingUserActionPayloadType) => void;
|
||||
readonly onClose: () => void;
|
||||
readonly toggleAboutContactModal: (conversationId: string) => void;
|
||||
readonly updateSharedGroups: (conversationId: string) => void;
|
||||
};
|
||||
|
||||
export function CallLinkPendingParticipantModal({
|
||||
i18n,
|
||||
conversation,
|
||||
approveUser,
|
||||
denyUser,
|
||||
onClose,
|
||||
toggleAboutContactModal,
|
||||
updateSharedGroups,
|
||||
}: CallLinkPendingParticipantModalProps): JSX.Element {
|
||||
useEffect(() => {
|
||||
// Kick off the expensive hydration of the current sharedGroupNames
|
||||
updateSharedGroups(conversation.id);
|
||||
}, [conversation.id, updateSharedGroups]);
|
||||
|
||||
const serviceId = useMemo(() => {
|
||||
return conversation.serviceId;
|
||||
}, [conversation]);
|
||||
|
||||
const handleApprove = useCallback(() => {
|
||||
approveUser({ serviceId });
|
||||
onClose();
|
||||
}, [approveUser, onClose, serviceId]);
|
||||
|
||||
const handleDeny = useCallback(() => {
|
||||
denyUser({ serviceId });
|
||||
onClose();
|
||||
}, [denyUser, onClose, serviceId]);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
modalName="CallLinkPendingParticipantModal"
|
||||
moduleClassName="CallLinkPendingParticipantModal"
|
||||
hasXButton
|
||||
i18n={i18n}
|
||||
onClose={onClose}
|
||||
theme={Theme.Dark}
|
||||
>
|
||||
<Avatar
|
||||
acceptedMessageRequest={conversation.acceptedMessageRequest}
|
||||
avatarUrl={conversation.avatarUrl}
|
||||
badge={undefined}
|
||||
color={conversation.color}
|
||||
conversationType="direct"
|
||||
i18n={i18n}
|
||||
isMe={conversation.isMe}
|
||||
profileName={conversation.profileName}
|
||||
sharedGroupNames={conversation.sharedGroupNames}
|
||||
size={AvatarSize.EIGHTY}
|
||||
title={conversation.title}
|
||||
theme={ThemeType.dark}
|
||||
unblurredAvatarUrl={conversation.unblurredAvatarUrl}
|
||||
/>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
onClick={ev => {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
toggleAboutContactModal(conversation.id);
|
||||
}}
|
||||
className="CallLinkPendingParticipantModal__NameButton"
|
||||
>
|
||||
<div className="CallLinkPendingParticipantModal__Title">
|
||||
<UserText text={conversation.title} />
|
||||
{isInSystemContacts(conversation) && (
|
||||
<span>
|
||||
{' '}
|
||||
<InContactsIcon
|
||||
className="module-in-contacts-icon__icon CallLinkPendingParticipantModal__InContactsIcon"
|
||||
i18n={i18n}
|
||||
/>
|
||||
</span>
|
||||
)}
|
||||
<span className="CallLinkPendingParticipantModal__AboutIcon" />
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<div className="CallLinkPendingParticipantModal__SharedGroupInfo">
|
||||
{conversation.sharedGroupNames?.length ? (
|
||||
<SharedGroupNames
|
||||
i18n={i18n}
|
||||
sharedGroupNames={conversation.sharedGroupNames || []}
|
||||
/>
|
||||
) : (
|
||||
i18n('icu:no-groups-in-common-warning')
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="CallLinkPendingParticipantModal__Hr" />
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className="CallLinkPendingParticipantModal__ActionButton"
|
||||
onClick={handleApprove}
|
||||
>
|
||||
<div className="CallLinkPendingParticipantModal__ButtonIcon">
|
||||
<div className="CallLinkPendingParticipantModal__ButtonIconContent CallLinkPendingParticipantModal__ButtonIconContent--approve" />
|
||||
</div>
|
||||
{i18n('icu:CallLinkPendingParticipantModal__ApproveButtonLabel')}
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className="CallLinkPendingParticipantModal__ActionButton"
|
||||
onClick={handleDeny}
|
||||
>
|
||||
<div className="CallLinkPendingParticipantModal__ButtonIcon">
|
||||
<div className="CallLinkPendingParticipantModal__ButtonIconContent CallLinkPendingParticipantModal__ButtonIconContent--deny" />
|
||||
</div>
|
||||
{i18n('icu:CallLinkPendingParticipantModal__DenyButtonLabel')}
|
||||
</button>
|
||||
</Modal>
|
||||
);
|
||||
}
|
@@ -139,6 +139,9 @@ const createProps = (storyProps: Partial<PropsType> = {}): PropsType => ({
|
||||
stopRingtone: action('stop-ringtone'),
|
||||
switchToPresentationView: action('switch-to-presentation-view'),
|
||||
switchFromPresentationView: action('switch-from-presentation-view'),
|
||||
toggleCallLinkPendingParticipantModal: action(
|
||||
'toggle-call-link-pending-participant-modal'
|
||||
),
|
||||
toggleParticipants: action('toggle-participants'),
|
||||
togglePip: action('toggle-pip'),
|
||||
toggleScreenRecordingPermissionsDialog: action(
|
||||
|
@@ -139,6 +139,7 @@ export type PropsType = {
|
||||
switchFromPresentationView: () => void;
|
||||
hangUpActiveCall: (reason: string) => void;
|
||||
togglePip: () => void;
|
||||
toggleCallLinkPendingParticipantModal: (contactId: string) => void;
|
||||
toggleScreenRecordingPermissionsDialog: () => unknown;
|
||||
toggleSettings: () => void;
|
||||
isConversationTooBigToRing: boolean;
|
||||
@@ -199,6 +200,7 @@ function ActiveCallManager({
|
||||
startCall,
|
||||
switchToPresentationView,
|
||||
switchFromPresentationView,
|
||||
toggleCallLinkPendingParticipantModal,
|
||||
toggleParticipants,
|
||||
togglePip,
|
||||
toggleScreenRecordingPermissionsDialog,
|
||||
@@ -475,6 +477,9 @@ function ActiveCallManager({
|
||||
stickyControls={showParticipantsList}
|
||||
switchToPresentationView={switchToPresentationView}
|
||||
switchFromPresentationView={switchFromPresentationView}
|
||||
toggleCallLinkPendingParticipantModal={
|
||||
toggleCallLinkPendingParticipantModal
|
||||
}
|
||||
toggleScreenRecordingPermissionsDialog={
|
||||
toggleScreenRecordingPermissionsDialog
|
||||
}
|
||||
@@ -571,6 +576,7 @@ export function CallManager({
|
||||
switchToPresentationView,
|
||||
toggleParticipants,
|
||||
togglePip,
|
||||
toggleCallLinkPendingParticipantModal,
|
||||
toggleScreenRecordingPermissionsDialog,
|
||||
toggleSettings,
|
||||
}: PropsType): JSX.Element | null {
|
||||
@@ -661,6 +667,9 @@ export function CallManager({
|
||||
startCall={startCall}
|
||||
switchFromPresentationView={switchFromPresentationView}
|
||||
switchToPresentationView={switchToPresentationView}
|
||||
toggleCallLinkPendingParticipantModal={
|
||||
toggleCallLinkPendingParticipantModal
|
||||
}
|
||||
toggleParticipants={toggleParticipants}
|
||||
togglePip={togglePip}
|
||||
toggleScreenRecordingPermissionsDialog={
|
||||
|
@@ -217,6 +217,9 @@ const createProps = (
|
||||
stickyControls: false,
|
||||
switchToPresentationView: action('switch-to-presentation-view'),
|
||||
switchFromPresentationView: action('switch-from-presentation-view'),
|
||||
toggleCallLinkPendingParticipantModal: action(
|
||||
'toggle-call-link-pending-participant-modal'
|
||||
),
|
||||
toggleParticipants: action('toggle-participants'),
|
||||
togglePip: action('toggle-pip'),
|
||||
toggleScreenRecordingPermissionsDialog: action(
|
||||
|
@@ -125,6 +125,7 @@ export type PropsType = {
|
||||
stickyControls: boolean;
|
||||
switchToPresentationView: () => void;
|
||||
switchFromPresentationView: () => void;
|
||||
toggleCallLinkPendingParticipantModal: (contactId: string) => void;
|
||||
toggleParticipants: () => void;
|
||||
togglePip: () => void;
|
||||
toggleScreenRecordingPermissionsDialog: () => unknown;
|
||||
@@ -214,6 +215,7 @@ export function CallScreen({
|
||||
stickyControls,
|
||||
switchToPresentationView,
|
||||
switchFromPresentationView,
|
||||
toggleCallLinkPendingParticipantModal,
|
||||
toggleParticipants,
|
||||
togglePip,
|
||||
toggleScreenRecordingPermissionsDialog,
|
||||
@@ -864,6 +866,9 @@ export function CallScreen({
|
||||
approveUser={approveUser}
|
||||
batchUserAction={batchUserAction}
|
||||
denyUser={denyUser}
|
||||
toggleCallLinkPendingParticipantModal={
|
||||
toggleCallLinkPendingParticipantModal
|
||||
}
|
||||
/>
|
||||
) : null}
|
||||
{/* We render the local preview first and set the footer flex direction to row-reverse
|
||||
|
@@ -18,6 +18,9 @@ const createProps = (storyProps: Partial<PropsType> = {}): PropsType => ({
|
||||
approveUser: action('approve-user'),
|
||||
batchUserAction: action('batch-user-action'),
|
||||
denyUser: action('deny-user'),
|
||||
toggleCallLinkPendingParticipantModal: action(
|
||||
'toggle-call-link-pending-participant-modal'
|
||||
),
|
||||
...storyProps,
|
||||
});
|
||||
|
||||
|
@@ -35,6 +35,9 @@ export type PropsType = {
|
||||
readonly approveUser: (payload: PendingUserActionPayloadType) => void;
|
||||
readonly batchUserAction: (payload: BatchUserActionPayloadType) => void;
|
||||
readonly denyUser: (payload: PendingUserActionPayloadType) => void;
|
||||
readonly toggleCallLinkPendingParticipantModal: (
|
||||
conversationId: string
|
||||
) => void;
|
||||
};
|
||||
|
||||
export function CallingPendingParticipants({
|
||||
@@ -44,6 +47,7 @@ export function CallingPendingParticipants({
|
||||
approveUser,
|
||||
batchUserAction,
|
||||
denyUser,
|
||||
toggleCallLinkPendingParticipantModal,
|
||||
}: PropsType): JSX.Element | null {
|
||||
const [isExpanded, setIsExpanded] = useState(defaultIsExpanded ?? false);
|
||||
const [confirmDialogState, setConfirmDialogState] =
|
||||
@@ -241,7 +245,15 @@ export function CallingPendingParticipants({
|
||||
className="module-calling-participants-list__contact"
|
||||
key={index}
|
||||
>
|
||||
<div className="module-calling-participants-list__avatar-and-name">
|
||||
<button
|
||||
type="button"
|
||||
onClick={ev => {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
toggleCallLinkPendingParticipantModal(participant.id);
|
||||
}}
|
||||
className="module-calling-participants-list__avatar-and-name CallingPendingParticipants__ParticipantButton"
|
||||
>
|
||||
<Avatar
|
||||
acceptedMessageRequest={participant.acceptedMessageRequest}
|
||||
avatarUrl={participant.avatarUrl}
|
||||
@@ -268,7 +280,7 @@ export function CallingPendingParticipants({
|
||||
/>
|
||||
</span>
|
||||
) : null}
|
||||
</div>
|
||||
</button>
|
||||
{renderApprovalButtons(participant)}
|
||||
</li>
|
||||
))}
|
||||
@@ -303,7 +315,15 @@ export function CallingPendingParticipants({
|
||||
return (
|
||||
<div className="CallingPendingParticipants CallingPendingParticipants--Compact module-calling-participants-list">
|
||||
<div className="CallingPendingParticipants__CompactParticipant">
|
||||
<div className="module-calling-participants-list__avatar-and-name">
|
||||
<button
|
||||
type="button"
|
||||
onClick={ev => {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
toggleCallLinkPendingParticipantModal(participant.id);
|
||||
}}
|
||||
className="module-calling-participants-list__avatar-and-name CallingPendingParticipants__ParticipantButton"
|
||||
>
|
||||
<Avatar
|
||||
acceptedMessageRequest={participant.acceptedMessageRequest}
|
||||
avatarUrl={participant.avatarUrl}
|
||||
@@ -326,12 +346,13 @@ export function CallingPendingParticipants({
|
||||
i18n={i18n}
|
||||
/>
|
||||
) : null}
|
||||
<span className="CallingPendingParticipants__ParticipantAboutIcon" />
|
||||
</div>
|
||||
<div className="CallingPendingParticipants__WouldLikeToJoin">
|
||||
{i18n('icu:CallingPendingParticipants__WouldLikeToJoin')}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
{renderApprovalButtons(participant)}
|
||||
</div>
|
||||
{participants.length > 1 && (
|
||||
|
@@ -36,6 +36,9 @@ export type PropsType = {
|
||||
// CallLinkEditModal
|
||||
callLinkEditModalRoomId: string | null;
|
||||
renderCallLinkEditModal: () => JSX.Element;
|
||||
// CallLinkPendingParticipantModal
|
||||
callLinkPendingParticipantContactId: string | undefined;
|
||||
renderCallLinkPendingParticipantModal: () => JSX.Element;
|
||||
// ConfirmLeaveCallModal
|
||||
confirmLeaveCallModalState: StartCallData | null;
|
||||
renderConfirmLeaveCallModal: () => JSX.Element;
|
||||
@@ -118,6 +121,9 @@ export function GlobalModalContainer({
|
||||
// CallLinkEditModal
|
||||
callLinkEditModalRoomId,
|
||||
renderCallLinkEditModal,
|
||||
// CallLinkPendingParticipantModal
|
||||
callLinkPendingParticipantContactId,
|
||||
renderCallLinkPendingParticipantModal,
|
||||
// ConfirmLeaveCallModal
|
||||
confirmLeaveCallModalState,
|
||||
renderConfirmLeaveCallModal,
|
||||
@@ -268,6 +274,12 @@ export function GlobalModalContainer({
|
||||
return renderContactModal();
|
||||
}
|
||||
|
||||
// This needs to be after the about contact modal because the pending participant modal
|
||||
// opens the about contact modal
|
||||
if (callLinkPendingParticipantContactId) {
|
||||
return renderCallLinkPendingParticipantModal();
|
||||
}
|
||||
|
||||
if (isStoriesSettingsVisible) {
|
||||
return renderStoriesSettings();
|
||||
}
|
||||
|
@@ -38,6 +38,12 @@ const conversationWithAbout = getDefaultConversation({
|
||||
aboutText: '😀 About Me',
|
||||
hasMessages: true,
|
||||
});
|
||||
const conversationWithSharedGroups = getDefaultConversation({
|
||||
acceptedMessageRequest: true,
|
||||
aboutText: 'likes to chat',
|
||||
hasMessages: true,
|
||||
sharedGroupNames: ['Axolotl lovers'],
|
||||
});
|
||||
const systemContact = getDefaultConversation({
|
||||
acceptedMessageRequest: true,
|
||||
systemGivenName: 'Alice',
|
||||
@@ -110,3 +116,13 @@ export function SystemContact(args: PropsType): JSX.Element {
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export function WithSharedGroups(args: PropsType): JSX.Element {
|
||||
return (
|
||||
<AboutContactModal
|
||||
{...args}
|
||||
conversation={conversationWithSharedGroups}
|
||||
isSignalConnection
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@@ -94,6 +94,7 @@ export type GlobalModalsStateType = ReadonlyDeep<{
|
||||
aboutContactModalContactId?: string;
|
||||
callLinkAddNameModalRoomId: string | null;
|
||||
callLinkEditModalRoomId: string | null;
|
||||
callLinkPendingParticipantContactId: string | undefined;
|
||||
confirmLeaveCallModalState: StartCallData | null;
|
||||
contactModalState?: ContactModalStateType;
|
||||
deleteMessagesProps?: DeleteMessagesPropsType;
|
||||
@@ -149,6 +150,8 @@ const TOGGLE_ADD_USER_TO_ANOTHER_GROUP_MODAL =
|
||||
const TOGGLE_CALL_LINK_ADD_NAME_MODAL =
|
||||
'globalModals/TOGGLE_CALL_LINK_ADD_NAME_MODAL';
|
||||
const TOGGLE_CALL_LINK_EDIT_MODAL = 'globalModals/TOGGLE_CALL_LINK_EDIT_MODAL';
|
||||
const TOGGLE_CALL_LINK_PENDING_PARTICIPANT_MODAL =
|
||||
'globalModals/TOGGLE_CALL_LINK_PENDING_PARTICIPANT_MODAL';
|
||||
const TOGGLE_ABOUT_MODAL = 'globalModals/TOGGLE_ABOUT_MODAL';
|
||||
const TOGGLE_SIGNAL_CONNECTIONS_MODAL =
|
||||
'globalModals/TOGGLE_SIGNAL_CONNECTIONS_MODAL';
|
||||
@@ -266,6 +269,11 @@ type ToggleCallLinkEditModalActionType = ReadonlyDeep<{
|
||||
payload: string | null;
|
||||
}>;
|
||||
|
||||
type ToggleCallLinkPendingParticipantModalActionType = ReadonlyDeep<{
|
||||
type: typeof TOGGLE_CALL_LINK_PENDING_PARTICIPANT_MODAL;
|
||||
payload: string | undefined;
|
||||
}>;
|
||||
|
||||
type ToggleAboutContactModalActionType = ReadonlyDeep<{
|
||||
type: typeof TOGGLE_ABOUT_MODAL;
|
||||
payload: string | undefined;
|
||||
@@ -393,6 +401,7 @@ export type GlobalModalsActionType = ReadonlyDeep<
|
||||
| ToggleAddUserToAnotherGroupModalActionType
|
||||
| ToggleCallLinkAddNameModalActionType
|
||||
| ToggleCallLinkEditModalActionType
|
||||
| ToggleCallLinkPendingParticipantModalActionType
|
||||
| ToggleConfirmationModalActionType
|
||||
| ToggleConfirmLeaveCallModalActionType
|
||||
| ToggleDeleteMessagesModalActionType
|
||||
@@ -435,6 +444,7 @@ export const actions = {
|
||||
toggleAddUserToAnotherGroupModal,
|
||||
toggleCallLinkAddNameModal,
|
||||
toggleCallLinkEditModal,
|
||||
toggleCallLinkPendingParticipantModal,
|
||||
toggleConfirmationModal,
|
||||
toggleConfirmLeaveCallModal,
|
||||
toggleDeleteMessagesModal,
|
||||
@@ -757,6 +767,15 @@ function toggleCallLinkEditModal(
|
||||
};
|
||||
}
|
||||
|
||||
function toggleCallLinkPendingParticipantModal(
|
||||
contactId?: string
|
||||
): ToggleCallLinkPendingParticipantModalActionType {
|
||||
return {
|
||||
type: TOGGLE_CALL_LINK_PENDING_PARTICIPANT_MODAL,
|
||||
payload: contactId,
|
||||
};
|
||||
}
|
||||
|
||||
function toggleAboutContactModal(
|
||||
contactId?: string
|
||||
): ToggleAboutContactModalActionType {
|
||||
@@ -974,6 +993,7 @@ export function getEmptyState(): GlobalModalsStateType {
|
||||
hasConfirmationModal: false,
|
||||
callLinkAddNameModalRoomId: null,
|
||||
callLinkEditModalRoomId: null,
|
||||
callLinkPendingParticipantContactId: undefined,
|
||||
confirmLeaveCallModalState: null,
|
||||
editNicknameAndNoteModalProps: null,
|
||||
isProfileEditorVisible: false,
|
||||
@@ -1109,6 +1129,13 @@ export function reducer(
|
||||
};
|
||||
}
|
||||
|
||||
if (action.type === TOGGLE_CALL_LINK_PENDING_PARTICIPANT_MODAL) {
|
||||
return {
|
||||
...state,
|
||||
callLinkPendingParticipantContactId: action.payload,
|
||||
};
|
||||
}
|
||||
|
||||
if (action.type === TOGGLE_DELETE_MESSAGES_MODAL) {
|
||||
return {
|
||||
...state,
|
||||
|
@@ -32,6 +32,12 @@ export const getCallLinkAddNameModalRoomId = createSelector(
|
||||
({ callLinkAddNameModalRoomId }) => callLinkAddNameModalRoomId
|
||||
);
|
||||
|
||||
export const getCallLinkPendingParticipantContactId = createSelector(
|
||||
getGlobalModalsState,
|
||||
({ callLinkPendingParticipantContactId }) =>
|
||||
callLinkPendingParticipantContactId
|
||||
);
|
||||
|
||||
export const getConfirmLeaveCallModalState = createSelector(
|
||||
getGlobalModalsState,
|
||||
({ confirmLeaveCallModalState }) => confirmLeaveCallModalState
|
||||
|
41
ts/state/smart/CallLinkPendingParticipantModal.tsx
Normal file
41
ts/state/smart/CallLinkPendingParticipantModal.tsx
Normal file
@@ -0,0 +1,41 @@
|
||||
// Copyright 2024 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
import React, { memo } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { CallLinkPendingParticipantModal } from '../../components/CallLinkPendingParticipantModal';
|
||||
import { useCallingActions } from '../ducks/calling';
|
||||
import { getIntl } from '../selectors/user';
|
||||
import { useConversationsActions } from '../ducks/conversations';
|
||||
import { useGlobalModalActions } from '../ducks/globalModals';
|
||||
import { getConversationSelector } from '../selectors/conversations';
|
||||
import { getCallLinkPendingParticipantContactId } from '../selectors/globalModals';
|
||||
import { strictAssert } from '../../util/assert';
|
||||
|
||||
export const SmartCallLinkPendingParticipantModal = memo(
|
||||
function SmartCallLinkPendingParticipantModal(): JSX.Element | null {
|
||||
const contactId = useSelector(getCallLinkPendingParticipantContactId);
|
||||
strictAssert(contactId, 'Expected contactId to be set');
|
||||
|
||||
const i18n = useSelector(getIntl);
|
||||
const getConversation = useSelector(getConversationSelector);
|
||||
|
||||
const { updateSharedGroups } = useConversationsActions();
|
||||
const { approveUser, denyUser } = useCallingActions();
|
||||
const { toggleAboutContactModal, toggleCallLinkPendingParticipantModal } =
|
||||
useGlobalModalActions();
|
||||
|
||||
const conversation = getConversation(contactId);
|
||||
|
||||
return (
|
||||
<CallLinkPendingParticipantModal
|
||||
i18n={i18n}
|
||||
conversation={conversation}
|
||||
approveUser={approveUser}
|
||||
denyUser={denyUser}
|
||||
onClose={toggleCallLinkPendingParticipantModal}
|
||||
updateSharedGroups={updateSharedGroups}
|
||||
toggleAboutContactModal={toggleAboutContactModal}
|
||||
/>
|
||||
);
|
||||
}
|
||||
);
|
@@ -458,8 +458,11 @@ export const SmartCallManager = memo(function SmartCallManager() {
|
||||
toggleSettings,
|
||||
} = useCallingActions();
|
||||
const { pauseVoiceNotePlayer } = useAudioPlayerActions();
|
||||
const { showContactModal, showShareCallLinkViaSignal } =
|
||||
useGlobalModalActions();
|
||||
const {
|
||||
showContactModal,
|
||||
showShareCallLinkViaSignal,
|
||||
toggleCallLinkPendingParticipantModal,
|
||||
} = useGlobalModalActions();
|
||||
|
||||
return (
|
||||
<CallManager
|
||||
@@ -513,6 +516,9 @@ export const SmartCallManager = memo(function SmartCallManager() {
|
||||
stopRingtone={stopRingtone}
|
||||
switchFromPresentationView={switchFromPresentationView}
|
||||
switchToPresentationView={switchToPresentationView}
|
||||
toggleCallLinkPendingParticipantModal={
|
||||
toggleCallLinkPendingParticipantModal
|
||||
}
|
||||
toggleParticipants={toggleParticipants}
|
||||
togglePip={togglePip}
|
||||
toggleScreenRecordingPermissionsDialog={
|
||||
|
@@ -29,6 +29,7 @@ import { SmartNotePreviewModal } from './NotePreviewModal';
|
||||
import { SmartCallLinkEditModal } from './CallLinkEditModal';
|
||||
import { SmartCallLinkAddNameModal } from './CallLinkAddNameModal';
|
||||
import { SmartConfirmLeaveCallModal } from './ConfirmLeaveCallModal';
|
||||
import { SmartCallLinkPendingParticipantModal } from './CallLinkPendingParticipantModal';
|
||||
|
||||
function renderCallLinkAddNameModal(): JSX.Element {
|
||||
return <SmartCallLinkAddNameModal />;
|
||||
@@ -38,6 +39,10 @@ function renderCallLinkEditModal(): JSX.Element {
|
||||
return <SmartCallLinkEditModal />;
|
||||
}
|
||||
|
||||
function renderCallLinkPendingParticipantModal(): JSX.Element {
|
||||
return <SmartCallLinkPendingParticipantModal />;
|
||||
}
|
||||
|
||||
function renderConfirmLeaveCallModal(): JSX.Element {
|
||||
return <SmartConfirmLeaveCallModal />;
|
||||
}
|
||||
@@ -107,6 +112,7 @@ export const SmartGlobalModalContainer = memo(
|
||||
addUserToAnotherGroupModalContactId,
|
||||
callLinkAddNameModalRoomId,
|
||||
callLinkEditModalRoomId,
|
||||
callLinkPendingParticipantContactId,
|
||||
confirmLeaveCallModalState,
|
||||
contactModalState,
|
||||
deleteMessagesProps,
|
||||
@@ -188,6 +194,9 @@ export const SmartGlobalModalContainer = memo(
|
||||
}
|
||||
callLinkAddNameModalRoomId={callLinkAddNameModalRoomId}
|
||||
callLinkEditModalRoomId={callLinkEditModalRoomId}
|
||||
callLinkPendingParticipantContactId={
|
||||
callLinkPendingParticipantContactId
|
||||
}
|
||||
confirmLeaveCallModalState={confirmLeaveCallModalState}
|
||||
contactModalState={contactModalState}
|
||||
editHistoryMessages={editHistoryMessages}
|
||||
@@ -213,6 +222,9 @@ export const SmartGlobalModalContainer = memo(
|
||||
renderAddUserToAnotherGroup={renderAddUserToAnotherGroup}
|
||||
renderCallLinkAddNameModal={renderCallLinkAddNameModal}
|
||||
renderCallLinkEditModal={renderCallLinkEditModal}
|
||||
renderCallLinkPendingParticipantModal={
|
||||
renderCallLinkPendingParticipantModal
|
||||
}
|
||||
renderConfirmLeaveCallModal={renderConfirmLeaveCallModal}
|
||||
renderContactModal={renderContactModal}
|
||||
renderEditHistoryMessagesModal={renderEditHistoryMessagesModal}
|
||||
|
Reference in New Issue
Block a user