import React from 'react';
import { Avatar, AvatarSize } from '../avatar/Avatar';
import { contextMenu } from 'react-contexify';
import styled from 'styled-components';
import { ConversationNotificationSettingType } from '../../models/conversationAttributes';
import {
getSelectedMessageIds,
isMessageDetailView,
isMessageSelectionMode,
isRightPanelShowing,
} from '../../state/selectors/conversations';
import { useDispatch, useSelector } from 'react-redux';
import {
deleteMessagesById,
deleteMessagesByIdForEveryone,
} from '../../interactions/conversations/unsendingInteractions';
import {
closeMessageDetailsView,
closeRightPanel,
openRightPanel,
resetSelectedMessageIds,
} from '../../state/ducks/conversations';
import { callRecipient } from '../../interactions/conversationInteractions';
import { getHasIncomingCall, getHasOngoingCall } from '../../state/selectors/call';
import {
useConversationUsername,
useExpireTimer,
useIsKickedFromGroup,
useIsRequest,
} from '../../hooks/useParamSelector';
import {
SessionButton,
SessionButtonColor,
SessionButtonShape,
SessionButtonType,
} from '../basic/SessionButton';
import { SessionIconButton } from '../icon';
import { ConversationHeaderMenu } from '../menu/ConversationHeaderMenu';
import { Flex } from '../basic/Flex';
import { ExpirationTimerOptions } from '../../util/expiringMessages';
import {
useSelectedConversationKey,
useSelectedIsActive,
useSelectedIsBlocked,
useSelectedIsGroup,
useSelectedIsKickedFromGroup,
useSelectedisNoteToSelf,
useSelectedIsPrivate,
useSelectedIsPublic,
useSelectedMembers,
useSelectedNotificationSetting,
useSelectedSubscriberCount,
} from '../../state/selectors/selectedConversation';
export interface TimerOption {
name: string;
value: number;
}
const SelectionOverlay = () => {
const selectedMessageIds = useSelector(getSelectedMessageIds);
const selectedConversationKey = useSelectedConversationKey();
const isPublic = useSelectedIsPublic();
const dispatch = useDispatch();
const { i18n } = window;
function onCloseOverlay() {
dispatch(resetSelectedMessageIds());
}
function onDeleteSelectedMessages() {
if (selectedConversationKey) {
void deleteMessagesById(selectedMessageIds, selectedConversationKey);
}
}
function onDeleteSelectedMessagesForEveryone() {
if (selectedConversationKey) {
void deleteMessagesByIdForEveryone(selectedMessageIds, selectedConversationKey);
}
}
const isOnlyServerDeletable = isPublic;
const deleteMessageButtonText = i18n('delete');
const deleteForEveryoneMessageButtonText = i18n('deleteForEveryone');
return (
{!isOnlyServerDeletable && (
)}
);
};
const TripleDotContainer = styled.div`
user-select: none;
flex-grow: 0;
flex-shrink: 0;
`;
const TripleDotsMenu = (props: { triggerId: string; showBackButton: boolean }) => {
const { showBackButton } = props;
if (showBackButton) {
return null;
}
return (
{
contextMenu.show({
id: props.triggerId,
event: e,
});
}}
data-testid="three-dots-conversation-options"
>
);
};
const ExpirationLength = (props: { expirationSettingName?: string }) => {
const { expirationSettingName } = props;
if (!expirationSettingName) {
return null;
}
return (
);
};
const AvatarHeader = (props: {
pubkey: string;
showBackButton: boolean;
onAvatarClick?: (pubkey: string) => void;
}) => {
const { pubkey, onAvatarClick, showBackButton } = props;
return (
{
// do not allow right panel to appear if another button is shown on the SessionConversation
if (onAvatarClick && !showBackButton) {
onAvatarClick(pubkey);
}
}}
pubkey={pubkey}
dataTestId="conversation-options-avatar"
/>
);
};
const BackButton = (props: { onGoBack: () => void; showBackButton: boolean }) => {
const { onGoBack, showBackButton } = props;
if (!showBackButton) {
return null;
}
return (
);
};
const CallButton = () => {
const isPrivate = useSelectedIsPrivate();
const isBlocked = useSelectedIsBlocked();
const activeAt = useSelectedIsActive();
const isMe = useSelectedisNoteToSelf();
const selectedConvoKey = useSelectedConversationKey();
const hasIncomingCall = useSelector(getHasIncomingCall);
const hasOngoingCall = useSelector(getHasOngoingCall);
const canCall = !(hasIncomingCall || hasOngoingCall);
const isRequest = useIsRequest(selectedConvoKey);
if (!isPrivate || isMe || !selectedConvoKey || isBlocked || !activeAt || isRequest) {
return null;
}
return (
{
void callRecipient(selectedConvoKey, canCall);
}}
/>
);
};
export const StyledSubtitleContainer = styled.div`
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
span:last-child {
margin-bottom: 0;
}
`;
export type ConversationHeaderTitleProps = {
conversationKey: string;
isMe: boolean;
isGroup: boolean;
isPublic: boolean;
members: Array;
isKickedFromGroup: boolean;
currentNotificationSetting?: ConversationNotificationSettingType;
};
/**
* The subtitle beneath a conversation title when looking at a conversation screen.
* @param props props for subtitle. Text to be displayed
* @returns JSX Element of the subtitle of conversation header
*/
export const ConversationHeaderSubtitle = (props: { text?: string | null }): JSX.Element | null => {
const { text } = props;
if (!text) {
return null;
}
return {text};
};
const ConversationHeaderTitle = () => {
const dispatch = useDispatch();
const notificationSetting = useSelectedNotificationSetting();
const isRightPanelOn = useSelector(isRightPanelShowing);
const subscriberCount = useSelectedSubscriberCount();
const selectedConvoKey = useSelectedConversationKey();
const convoName = useConversationUsername(selectedConvoKey);
const isPublic = useSelectedIsPublic();
const isKickedFromGroup = useSelectedIsKickedFromGroup();
const isMe = useSelectedisNoteToSelf();
const isGroup = useSelectedIsGroup();
const members = useSelectedMembers();
if (!selectedConvoKey) {
return null;
}
const { i18n } = window;
if (isMe) {
return {i18n('noteToSelf')}
;
}
let memberCount = 0;
if (isGroup) {
if (isPublic) {
memberCount = subscriberCount || 0;
} else {
memberCount = members.length;
}
}
let memberCountText = '';
if (isGroup && memberCount > 0 && !isKickedFromGroup) {
const count = String(memberCount);
memberCountText = isPublic ? i18n('activeMembers', [count]) : i18n('members', [count]);
}
const notificationSubtitle = notificationSetting
? window.i18n('notificationSubtitle', [notificationSetting])
: null;
const fullTextSubtitle = memberCountText
? `${memberCountText} ● ${notificationSubtitle}`
: `${notificationSubtitle}`;
return (
{
if (isRightPanelOn) {
dispatch(closeRightPanel());
} else {
dispatch(openRightPanel());
}
}}
role="button"
>
{convoName}
);
};
export const ConversationHeaderWithDetails = () => {
const isSelectionMode = useSelector(isMessageSelectionMode);
const isMessageDetailOpened = useSelector(isMessageDetailView);
const selectedConvoKey = useSelectedConversationKey();
const dispatch = useDispatch();
const isKickedFromGroup = useIsKickedFromGroup(selectedConvoKey);
const expireTimerSetting = useExpireTimer(selectedConvoKey);
if (!selectedConvoKey) {
return null;
}
const expirationSettingName = expireTimerSetting
? ExpirationTimerOptions.getName(expireTimerSetting || 0)
: undefined;
const triggerId = 'conversation-header';
return (
{
dispatch(closeMessageDetailsView());
}}
showBackButton={isMessageDetailOpened}
/>
{!isSelectionMode && (
{!isKickedFromGroup && (
)}
{
dispatch(openRightPanel());
}}
pubkey={selectedConvoKey}
showBackButton={isMessageDetailOpened}
/>
)}
{isSelectionMode &&
}
);
};