signal-desktop/ts/components/conversation/ConversationHero.tsx

284 lines
8 KiB
TypeScript
Raw Normal View History

2023-01-03 11:55:46 -08:00
// Copyright 2020 Signal Messenger, LLC
2020-10-30 15:34:04 -05:00
// SPDX-License-Identifier: AGPL-3.0-only
import React, { useEffect, useState } from 'react';
import type { Props as AvatarProps } from '../Avatar';
2022-12-09 13:37:45 -07:00
import { Avatar, AvatarSize, AvatarBlur } from '../Avatar';
2020-05-27 17:37:06 -04:00
import { ContactName } from './ContactName';
2021-01-25 20:01:19 -05:00
import { About } from './About';
2021-06-01 17:24:28 -07:00
import { GroupDescription } from './GroupDescription';
2021-04-16 10:51:26 -05:00
import { SharedGroupNames } from '../SharedGroupNames';
2021-11-02 18:01:13 -05:00
import type { LocalizerType, ThemeType } from '../../types/Util';
2022-07-21 20:44:35 -04:00
import type { HasStories } from '../../types/Stories';
2022-08-22 13:44:23 -04:00
import type { ViewUserStoriesActionCreatorType } from '../../state/ducks/stories';
import { StoryViewModeType } from '../../types/Stories';
import { ConfirmationDialog } from '../ConfirmationDialog';
import { shouldBlurAvatar } from '../../util/shouldBlurAvatar';
2021-09-21 16:45:25 -04:00
import { openLinkInWebBrowser } from '../../util/openLinkInWebBrowser';
2020-05-27 17:37:06 -04:00
export type Props = {
2021-01-25 20:01:19 -05:00
about?: string;
acceptedMessageRequest?: boolean;
2021-06-01 17:24:28 -07:00
groupDescription?: string;
2022-07-21 20:44:35 -04:00
hasStories?: HasStories;
id: string;
2020-05-27 17:37:06 -04:00
i18n: LocalizerType;
2021-05-07 17:21:10 -05:00
isMe: boolean;
2022-11-08 21:38:19 -05:00
isSignalConversation?: boolean;
2020-05-27 17:37:06 -04:00
membersCount?: number;
phoneNumber?: string;
sharedGroupNames?: ReadonlyArray<string>;
unblurAvatar: (conversationId: string) => void;
unblurredAvatarPath?: string;
updateSharedGroups: (conversationId: string) => unknown;
2021-11-02 18:01:13 -05:00
theme: ThemeType;
2022-08-22 13:44:23 -04:00
viewUserStories: ViewUserStoriesActionCreatorType;
toggleAboutContactModal: (conversationId: string) => unknown;
2020-05-27 17:37:06 -04:00
} & Omit<AvatarProps, 'onClick' | 'size' | 'noteToSelf'>;
const renderMembershipRow = ({
acceptedMessageRequest,
2020-05-27 17:37:06 -04:00
conversationType,
i18n,
2020-05-27 17:37:06 -04:00
isMe,
onClickMessageRequestWarning,
phoneNumber,
sharedGroupNames,
}: Pick<
Props,
| 'acceptedMessageRequest'
| 'conversationType'
| 'i18n'
| 'isMe'
| 'phoneNumber'
> &
Required<Pick<Props, 'sharedGroupNames'>> & {
onClickMessageRequestWarning: () => void;
}) => {
if (conversationType !== 'direct') {
return null;
}
2020-05-27 17:37:06 -04:00
if (isMe) {
return (
<div className="module-conversation-hero__note-to-self">
{i18n('icu:noteToSelfHero')}
</div>
);
2020-05-27 17:37:06 -04:00
}
if (sharedGroupNames.length > 0) {
2021-04-16 10:51:26 -05:00
return (
<div className="module-conversation-hero__membership">
<i className="module-conversation-hero__membership__chevron" />
2021-04-16 10:51:26 -05:00
<SharedGroupNames
i18n={i18n}
nameClassName="module-conversation-hero__membership__name"
2021-04-16 10:51:26 -05:00
sharedGroupNames={sharedGroupNames}
/>
</div>
);
2020-05-27 17:37:06 -04:00
}
if (acceptedMessageRequest) {
if (phoneNumber) {
return null;
}
return (
<div className="module-conversation-hero__membership">
{i18n('icu:no-groups-in-common')}
</div>
);
}
return (
<div className="module-conversation-hero__membership">
<div className="module-conversation-hero__membership__warning">
<i className="module-conversation-hero__membership__warning__icon" />
<span>{i18n('icu:no-groups-in-common-warning')}</span>
&nbsp;
<button
className="module-conversation-hero__membership__warning__learn-more"
type="button"
onClick={ev => {
ev.preventDefault();
onClickMessageRequestWarning();
}}
>
{i18n('icu:MessageRequestWarning__learn-more')}
</button>
</div>
</div>
);
2020-05-27 17:37:06 -04:00
};
2022-11-17 16:45:19 -08:00
export function ConversationHero({
2020-05-27 17:37:06 -04:00
i18n,
2021-01-25 20:01:19 -05:00
about,
acceptedMessageRequest,
2020-05-27 17:37:06 -04:00
avatarPath,
2021-11-02 18:01:13 -05:00
badge,
2020-05-27 17:37:06 -04:00
color,
conversationType,
2021-06-01 17:24:28 -07:00
groupDescription,
2022-07-21 20:44:35 -04:00
hasStories,
id,
2020-05-27 17:37:06 -04:00
isMe,
2022-11-08 21:38:19 -05:00
isSignalConversation,
2020-05-27 17:37:06 -04:00
membersCount,
2020-08-04 18:13:19 -07:00
sharedGroupNames = [],
2020-05-27 17:37:06 -04:00
phoneNumber,
profileName,
2021-11-02 18:01:13 -05:00
theme,
2020-07-23 18:35:32 -07:00
title,
unblurAvatar,
unblurredAvatarPath,
2020-08-06 17:50:54 -07:00
updateSharedGroups,
2022-07-21 20:44:35 -04:00
viewUserStories,
toggleAboutContactModal,
2022-11-17 16:45:19 -08:00
}: Props): JSX.Element {
2021-11-11 16:43:05 -06:00
const [isShowingMessageRequestWarning, setIsShowingMessageRequestWarning] =
useState(false);
const closeMessageRequestWarning = () => {
setIsShowingMessageRequestWarning(false);
};
2020-08-06 17:50:54 -07:00
useEffect(() => {
// Kick off the expensive hydration of the current sharedGroupNames
updateSharedGroups(id);
}, [id, updateSharedGroups]);
2022-07-21 20:44:35 -04:00
let avatarBlur: AvatarBlur = AvatarBlur.NoBlur;
let avatarOnClick: undefined | (() => void);
if (
shouldBlurAvatar({
acceptedMessageRequest,
avatarPath,
isMe,
sharedGroupNames,
unblurredAvatarPath,
})
) {
avatarBlur = AvatarBlur.BlurPictureWithClickToView;
avatarOnClick = () => unblurAvatar(id);
2022-07-21 20:44:35 -04:00
} else if (hasStories) {
avatarOnClick = () => {
2022-08-22 13:44:23 -04:00
viewUserStories({
conversationId: id,
storyViewMode: StoryViewModeType.User,
});
2022-07-21 20:44:35 -04:00
};
}
let titleElem: JSX.Element | undefined;
if (isMe) {
titleElem = <>{i18n('icu:noteToSelf')}</>;
} else if (isSignalConversation || conversationType !== 'direct') {
titleElem = (
<ContactName isSignalConversation={isSignalConversation} title={title} />
);
} else if (title) {
titleElem = (
<button
type="button"
className="module-conversation-hero__title"
onClick={ev => {
ev.preventDefault();
toggleAboutContactModal(id);
}}
>
<ContactName title={title} />
<i className="module-conversation-hero__title__chevron" />
</button>
);
}
2020-07-23 18:35:32 -07:00
2020-09-14 12:51:27 -07:00
/* eslint-disable no-nested-ternary */
2020-05-27 17:37:06 -04:00
return (
<>
<div className="module-conversation-hero">
<Avatar
acceptedMessageRequest={acceptedMessageRequest}
avatarPath={avatarPath}
2021-11-02 18:01:13 -05:00
badge={badge}
blur={avatarBlur}
className="module-conversation-hero__avatar"
color={color}
conversationType={conversationType}
i18n={i18n}
isMe={isMe}
noteToSelf={isMe}
onClick={avatarOnClick}
profileName={profileName}
sharedGroupNames={sharedGroupNames}
2022-12-09 13:37:45 -07:00
size={AvatarSize.EIGHTY}
2022-10-04 15:39:29 -06:00
// user may have stories, but we don't show that on Note to Self conversation
storyRing={isMe ? undefined : hasStories}
2021-11-02 18:01:13 -05:00
theme={theme}
title={title}
/>
<h1 className="module-conversation-hero__profile-name">
{titleElem}
2023-03-10 10:21:21 -08:00
{isMe && <span className="ContactModal__official-badge__large" />}
</h1>
{about && !isMe && (
<div className="module-about__container">
<About text={about} />
</div>
2020-05-27 17:37:06 -04:00
)}
{!isMe ? (
<div className="module-conversation-hero__with">
{groupDescription ? (
<GroupDescription
i18n={i18n}
title={title}
text={groupDescription}
/>
) : membersCount != null ? (
i18n('icu:ConversationHero--members', { count: membersCount })
) : null}
</div>
) : null}
2022-11-08 21:38:19 -05:00
{!isSignalConversation &&
renderMembershipRow({
acceptedMessageRequest,
conversationType,
i18n,
isMe,
onClickMessageRequestWarning() {
setIsShowingMessageRequestWarning(true);
},
phoneNumber,
sharedGroupNames,
})}
{!isSignalConversation && (
<div className="module-conversation-hero__linkNotification">
2023-03-29 17:03:25 -07:00
{i18n('icu:messageHistoryUnsynced')}
2022-11-08 21:38:19 -05:00
</div>
)}
</div>
{isShowingMessageRequestWarning && (
<ConfirmationDialog
2022-09-27 13:24:21 -07:00
dialogName="ConversationHere.messageRequestWarning"
i18n={i18n}
onClose={closeMessageRequestWarning}
actions={[
{
2023-03-29 17:03:25 -07:00
text: i18n('icu:MessageRequestWarning__dialog__learn-even-more'),
action: () => {
2021-09-21 16:45:25 -04:00
openLinkInWebBrowser(
'https://support.signal.org/hc/articles/360007459591'
);
closeMessageRequestWarning();
},
},
]}
>
2023-03-29 17:03:25 -07:00
{i18n('icu:MessageRequestWarning__dialog__details')}
</ConfirmationDialog>
2021-01-25 20:01:19 -05:00
)}
</>
2020-05-27 17:37:06 -04:00
);
2020-09-14 12:51:27 -07:00
/* eslint-enable no-nested-ternary */
2022-11-17 16:45:19 -08:00
}