signal-desktop/ts/state/smart/ConversationHeader.tsx

188 lines
6.2 KiB
TypeScript
Raw Normal View History

2023-01-03 19:55:46 +00:00
// Copyright 2020 Signal Messenger, LLC
2020-10-30 20:34:04 +00:00
// SPDX-License-Identifier: AGPL-3.0-only
import React from 'react';
import { useSelector } from 'react-redux';
2020-10-30 17:52:21 +00:00
import { pick } from 'lodash';
2022-07-22 00:44:35 +00:00
import type { ConversationType } from '../ducks/conversations';
import type { StateType } from '../reducer';
import {
ConversationHeader,
OutgoingCallButtonStyle,
} from '../../components/conversation/ConversationHeader';
2021-11-02 23:01:13 +00:00
import { getPreferredBadgeSelector } from '../selectors/badges';
import {
2023-08-16 20:54:39 +00:00
getConversationByServiceIdSelector,
getConversationSelector,
getHasPanelOpen,
getSelectedMessageIds,
isMissingRequiredProfileSharing,
} from '../selectors/conversations';
2020-11-13 19:57:55 +00:00
import { CallMode } from '../../types/Calling';
2023-07-18 23:57:38 +00:00
import { getActiveCall, useCallingActions } from '../ducks/calling';
import { isAnybodyElseInGroupCall } from '../ducks/callingHelpers';
import {
getConversationCallMode,
useConversationsActions,
} from '../ducks/conversations';
import { getHasStoriesSelector } from '../selectors/stories2';
2020-11-20 17:19:28 +00:00
import { getOwn } from '../../util/getOwn';
2022-07-22 00:44:35 +00:00
import { getUserACI, getIntl, getTheme } from '../selectors/user';
import { isConversationSMSOnly } from '../../util/isConversationSMSOnly';
2022-07-22 00:44:35 +00:00
import { missingCaseError } from '../../util/missingCaseError';
import { strictAssert } from '../../util/assert';
2022-11-09 02:38:19 +00:00
import { isSignalConversation } from '../../util/isSignalConversation';
import { useSearchActions } from '../ducks/search';
import { useStoriesActions } from '../ducks/stories';
import { getCannotLeaveBecauseYouAreLastAdmin } from '../../components/conversation/conversation-details/ConversationDetails';
import { getGroupMemberships } from '../../util/getGroupMemberships';
2020-10-30 17:52:21 +00:00
export type OwnProps = {
2020-10-30 17:52:21 +00:00
id: string;
};
2020-10-30 17:52:21 +00:00
const getOutgoingCallButtonStyle = (
conversation: ConversationType,
state: StateType
): OutgoingCallButtonStyle => {
2020-11-20 17:19:28 +00:00
const { calling } = state;
const ourAci = getUserACI(state);
strictAssert(ourAci, 'getOutgoingCallButtonStyle missing our uuid');
2020-11-20 17:19:28 +00:00
if (getActiveCall(calling)) {
return OutgoingCallButtonStyle.None;
}
const conversationCallMode = getConversationCallMode(conversation);
switch (conversationCallMode) {
case null:
return OutgoingCallButtonStyle.None;
case CallMode.Direct:
return OutgoingCallButtonStyle.Both;
2020-11-20 17:19:28 +00:00
case CallMode.Group: {
const call = getOwn(calling.callsByConversation, conversation.id);
if (
call?.callMode === CallMode.Group &&
isAnybodyElseInGroupCall(call.peekInfo, ourAci)
2020-11-20 17:19:28 +00:00
) {
return OutgoingCallButtonStyle.Join;
}
return OutgoingCallButtonStyle.JustVideo;
2020-11-20 17:19:28 +00:00
}
default:
throw missingCaseError(conversationCallMode);
}
};
export function SmartConversationHeader({ id }: OwnProps): JSX.Element {
const conversationSelector = useSelector(getConversationSelector);
const conversation = conversationSelector(id);
2020-10-30 17:52:21 +00:00
if (!conversation) {
throw new Error('Could not find conversation');
}
const isAdmin = Boolean(conversation.areWeAdmin);
const hasStoriesSelector = useSelector(getHasStoriesSelector);
const hasStories = hasStoriesSelector(id);
2020-10-30 17:52:21 +00:00
const badgeSelector = useSelector(getPreferredBadgeSelector);
const badge = badgeSelector(conversation.badges);
const i18n = useSelector(getIntl);
const hasPanelShowing = useSelector<StateType, boolean>(getHasPanelOpen);
const outgoingCallButtonStyle = useSelector<
StateType,
OutgoingCallButtonStyle
>(state => getOutgoingCallButtonStyle(conversation, state));
const theme = useSelector(getTheme);
2020-10-30 17:52:21 +00:00
const {
destroyMessages,
leaveGroup,
onArchive,
onMarkUnread,
onMoveToInbox,
popPanelForConversation,
pushPanelForConversation,
setDisappearingMessages,
setMuteExpiration,
setPinned,
toggleSelectMode,
} = useConversationsActions();
const {
onOutgoingAudioCallInConversation,
onOutgoingVideoCallInConversation,
} = useCallingActions();
const { searchInConversation } = useSearchActions();
const { viewUserStories } = useStoriesActions();
2020-10-30 17:52:21 +00:00
2023-08-16 20:54:39 +00:00
const conversationByServiceIdSelector = useSelector(
getConversationByServiceIdSelector
);
const groupMemberships = getGroupMemberships(
conversation,
2023-08-16 20:54:39 +00:00
conversationByServiceIdSelector
);
const cannotLeaveBecauseYouAreLastAdmin =
getCannotLeaveBecauseYouAreLastAdmin(groupMemberships.memberships, isAdmin);
const selectedMessageIds = useSelector(getSelectedMessageIds);
const isSelectMode = selectedMessageIds != null;
return (
<ConversationHeader
{...pick(conversation, [
'acceptedMessageRequest',
'announcementsOnly',
'areWeAdmin',
'avatarPath',
'canChangeTimer',
'color',
'expireTimer',
'groupVersion',
'isArchived',
'isMe',
'isPinned',
'isVerified',
'left',
'markedUnread',
'muteExpiresAt',
'name',
'phoneNumber',
'profileName',
'sharedGroupNames',
'title',
'type',
'unblurredAvatarPath',
])}
badge={badge}
cannotLeaveBecauseYouAreLastAdmin={cannotLeaveBecauseYouAreLastAdmin}
destroyMessages={destroyMessages}
hasPanelShowing={hasPanelShowing}
hasStories={hasStories}
i18n={i18n}
id={id}
isMissingMandatoryProfileSharing={isMissingRequiredProfileSharing(
conversation
)}
isSignalConversation={isSignalConversation(conversation)}
isSMSOnly={isConversationSMSOnly(conversation)}
leaveGroup={leaveGroup}
onArchive={onArchive}
onMarkUnread={onMarkUnread}
onMoveToInbox={onMoveToInbox}
onOutgoingAudioCallInConversation={onOutgoingAudioCallInConversation}
onOutgoingVideoCallInConversation={onOutgoingVideoCallInConversation}
outgoingCallButtonStyle={outgoingCallButtonStyle}
popPanelForConversation={popPanelForConversation}
pushPanelForConversation={pushPanelForConversation}
searchInConversation={searchInConversation}
setDisappearingMessages={setDisappearingMessages}
setMuteExpiration={setMuteExpiration}
setPinned={setPinned}
theme={theme}
isSelectMode={isSelectMode}
toggleSelectMode={toggleSelectMode}
viewUserStories={viewUserStories}
/>
);
}