Show "no groups in common" warning for relevant message requests
This commit is contained in:
parent
05703c2719
commit
fe772af251
12 changed files with 321 additions and 122 deletions
|
@ -3142,6 +3142,10 @@
|
|||
"message": "No groups in common",
|
||||
"description": "Shown to indicate this user is not a member of any groups"
|
||||
},
|
||||
"no-groups-in-common-warning": {
|
||||
"message": "No groups in common. Review requests carefully.",
|
||||
"description": "When a user has no common groups, show this warning"
|
||||
},
|
||||
"acceptCall": {
|
||||
"message": "Answer",
|
||||
"description": "Shown in tooltip for the button to accept a call (audio or video)"
|
||||
|
@ -5165,6 +5169,18 @@
|
|||
"message": "Continue",
|
||||
"description": "aria-label for the 'next' button in the forward a message modal dialog"
|
||||
},
|
||||
"MessageRequestWarning__learn-more": {
|
||||
"message": "Learn more",
|
||||
"description": "Shown on the message request warning. Clicking this button will open a dialog with more information"
|
||||
},
|
||||
"MessageRequestWarning__dialog__details": {
|
||||
"message": "You have no groups in common with this person. Review requests carefully before accepting to avoid unwanted messages.",
|
||||
"description": "Shown in the message request warning dialog. Gives more information about message requests"
|
||||
},
|
||||
"MessageRequestWarning__dialog__learn-even-more": {
|
||||
"message": "About Message Requests",
|
||||
"description": "Shown in the message request warning dialog. Clicking this button will open a page on Signal's support site"
|
||||
},
|
||||
"ContactSpoofing__same-name": {
|
||||
"message": "Review requests carefully. Signal found another contact with the same name. $link$",
|
||||
"description": "Shown in the timeline warning when you have a message request from someone with the same name as someone else",
|
||||
|
|
|
@ -106,7 +106,12 @@
|
|||
}
|
||||
}
|
||||
|
||||
// Smooth scrolling
|
||||
// Utilities
|
||||
|
||||
@mixin rounded-corners() {
|
||||
// This ensures the borders are completely rounded. (A value like 100% would make it an ellipse.)
|
||||
border-radius: 9999px;
|
||||
}
|
||||
|
||||
@mixin smooth-scroll() {
|
||||
scroll-behavior: smooth;
|
||||
|
@ -472,7 +477,7 @@
|
|||
}
|
||||
|
||||
@mixin button-small {
|
||||
border-radius: 9999px; // This ensures the borders are completely rounded. (A value like 100% would make it an ellipse.)
|
||||
@include rounded-corners;
|
||||
padding: 7px 14px;
|
||||
}
|
||||
|
||||
|
|
|
@ -3934,6 +3934,46 @@ button.module-conversation-details__action-button {
|
|||
@include font-body-2-bold;
|
||||
}
|
||||
}
|
||||
|
||||
&__message-request-warning {
|
||||
@include font-body-2;
|
||||
|
||||
&__message {
|
||||
display: flex;
|
||||
margin-bottom: 12px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
user-select: none;
|
||||
|
||||
@include light-theme {
|
||||
color: $color-gray-60;
|
||||
}
|
||||
@include dark-theme {
|
||||
color: $color-gray-25;
|
||||
}
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
display: block;
|
||||
height: 14px;
|
||||
margin-right: 8px;
|
||||
width: 14px;
|
||||
|
||||
@include light-theme {
|
||||
@include color-svg(
|
||||
'../images/icons/v2/info-outline-24.svg',
|
||||
$color-gray-60
|
||||
);
|
||||
}
|
||||
@include dark-theme {
|
||||
@include color-svg(
|
||||
'../images/icons/v2/info-solid-24.svg',
|
||||
$color-gray-25
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Module: Message Request Actions
|
||||
|
|
|
@ -18,8 +18,6 @@
|
|||
}
|
||||
|
||||
@include button-reset;
|
||||
@include font-body-1-bold;
|
||||
|
||||
border-radius: 4px;
|
||||
padding: 8px 16px;
|
||||
text-align: center;
|
||||
|
@ -37,6 +35,16 @@
|
|||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
&--medium {
|
||||
@include font-body-1-bold;
|
||||
}
|
||||
|
||||
&--small {
|
||||
@include font-body-2;
|
||||
@include rounded-corners;
|
||||
padding: 6px 12px;
|
||||
}
|
||||
|
||||
&--primary {
|
||||
$color: $color-white;
|
||||
$background-color: $ultramarine-ui-light;
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
.module-ContactPill {
|
||||
@include rounded-corners;
|
||||
align-items: center;
|
||||
border-radius: 9999px; // This ensures the borders are completely rounded. (A value like 100% would make it an ellipse.)
|
||||
display: inline-flex;
|
||||
user-select: none;
|
||||
overflow: hidden;
|
||||
|
|
|
@ -279,9 +279,9 @@
|
|||
|
||||
&--join-call {
|
||||
@include font-body-1;
|
||||
@include rounded-corners;
|
||||
align-items: center;
|
||||
background-color: $color-accent-green;
|
||||
border-radius: 9999px; // This ensures the borders are completely rounded. (A value like 100% would make it an ellipse.)
|
||||
color: $color-white;
|
||||
display: flex;
|
||||
outline: none;
|
||||
|
|
|
@ -5,30 +5,39 @@ import React from 'react';
|
|||
import { storiesOf } from '@storybook/react';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
|
||||
import { Button, ButtonVariant } from './Button';
|
||||
import { Button, ButtonSize, ButtonVariant } from './Button';
|
||||
|
||||
const story = storiesOf('Components/Button', module);
|
||||
|
||||
story.add('Kitchen sink', () => (
|
||||
<>
|
||||
{[
|
||||
ButtonVariant.Primary,
|
||||
ButtonVariant.Secondary,
|
||||
ButtonVariant.SecondaryAffirmative,
|
||||
ButtonVariant.SecondaryDestructive,
|
||||
ButtonVariant.Destructive,
|
||||
].map(variant => (
|
||||
<React.Fragment key={variant}>
|
||||
<p>
|
||||
<Button onClick={action('onClick')} variant={variant}>
|
||||
Hello world
|
||||
</Button>
|
||||
</p>
|
||||
<p>
|
||||
<Button disabled onClick={action('onClick')} variant={variant}>
|
||||
Hello world
|
||||
</Button>
|
||||
</p>
|
||||
{[ButtonSize.Medium, ButtonSize.Small].map(size => (
|
||||
<React.Fragment key={size}>
|
||||
{[
|
||||
ButtonVariant.Primary,
|
||||
ButtonVariant.Secondary,
|
||||
ButtonVariant.SecondaryAffirmative,
|
||||
ButtonVariant.SecondaryDestructive,
|
||||
ButtonVariant.Destructive,
|
||||
].map(variant => (
|
||||
<React.Fragment key={variant}>
|
||||
<p>
|
||||
<Button onClick={action('onClick')} size={size} variant={variant}>
|
||||
Hello world
|
||||
</Button>
|
||||
</p>
|
||||
<p>
|
||||
<Button
|
||||
disabled
|
||||
onClick={action('onClick')}
|
||||
size={size}
|
||||
variant={variant}
|
||||
>
|
||||
Hello world
|
||||
</Button>
|
||||
</p>
|
||||
</React.Fragment>
|
||||
))}
|
||||
</React.Fragment>
|
||||
))}
|
||||
</>
|
||||
|
|
|
@ -6,6 +6,11 @@ import classNames from 'classnames';
|
|||
|
||||
import { assert } from '../util/assert';
|
||||
|
||||
export enum ButtonSize {
|
||||
Medium,
|
||||
Small,
|
||||
}
|
||||
|
||||
export enum ButtonVariant {
|
||||
Primary,
|
||||
Secondary,
|
||||
|
@ -17,6 +22,7 @@ export enum ButtonVariant {
|
|||
type PropsType = {
|
||||
className?: string;
|
||||
disabled?: boolean;
|
||||
size?: ButtonSize;
|
||||
variant?: ButtonVariant;
|
||||
} & (
|
||||
| {
|
||||
|
@ -41,6 +47,11 @@ type PropsType = {
|
|||
}
|
||||
);
|
||||
|
||||
const SIZE_CLASS_NAMES = new Map<ButtonSize, string>([
|
||||
[ButtonSize.Medium, 'module-Button--medium'],
|
||||
[ButtonSize.Small, 'module-Button--small'],
|
||||
]);
|
||||
|
||||
const VARIANT_CLASS_NAMES = new Map<ButtonVariant, string>([
|
||||
[ButtonVariant.Primary, 'module-Button--primary'],
|
||||
[ButtonVariant.Secondary, 'module-Button--secondary'],
|
||||
|
@ -61,6 +72,7 @@ export const Button = React.forwardRef<HTMLButtonElement, PropsType>(
|
|||
children,
|
||||
className,
|
||||
disabled = false,
|
||||
size = ButtonSize.Medium,
|
||||
variant = ButtonVariant.Primary,
|
||||
} = props;
|
||||
const ariaLabel = props['aria-label'];
|
||||
|
@ -75,13 +87,21 @@ export const Button = React.forwardRef<HTMLButtonElement, PropsType>(
|
|||
({ type } = props);
|
||||
}
|
||||
|
||||
const sizeClassName = SIZE_CLASS_NAMES.get(size);
|
||||
assert(sizeClassName, '<Button> size not found');
|
||||
|
||||
const variantClassName = VARIANT_CLASS_NAMES.get(variant);
|
||||
assert(variantClassName, '<Button> variant not found');
|
||||
|
||||
return (
|
||||
<button
|
||||
aria-label={ariaLabel}
|
||||
className={classNames('module-Button', variantClassName, className)}
|
||||
className={classNames(
|
||||
'module-Button',
|
||||
sizeClassName,
|
||||
variantClassName,
|
||||
className
|
||||
)}
|
||||
disabled={disabled}
|
||||
onClick={onClick}
|
||||
ref={ref}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2020 Signal Messenger, LLC
|
||||
// Copyright 2020-2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import * as React from 'react';
|
||||
|
@ -20,12 +20,15 @@ const getAvatarPath = () =>
|
|||
text('avatarPath', '/fixtures/kitten-4-112-112.jpg');
|
||||
const getPhoneNumber = () => text('phoneNumber', '+1 (646) 327-2700');
|
||||
|
||||
const updateSharedGroups = action('updateSharedGroups');
|
||||
|
||||
storiesOf('Components/Conversation/ConversationHero', module)
|
||||
.add('Direct (Three Other Groups)', () => {
|
||||
return (
|
||||
<div style={{ width: '480px' }}>
|
||||
<ConversationHero
|
||||
about={getAbout()}
|
||||
acceptedMessageRequest
|
||||
i18n={i18n}
|
||||
title={getTitle()}
|
||||
avatarPath={getAvatarPath()}
|
||||
|
@ -33,6 +36,7 @@ storiesOf('Components/Conversation/ConversationHero', module)
|
|||
profileName={getProfileName()}
|
||||
phoneNumber={getPhoneNumber()}
|
||||
conversationType="direct"
|
||||
updateSharedGroups={updateSharedGroups}
|
||||
sharedGroupNames={['NYC Rock Climbers', 'Dinner Party', 'Friends 🌿']}
|
||||
unblurAvatar={action('unblurAvatar')}
|
||||
/>
|
||||
|
@ -44,6 +48,7 @@ storiesOf('Components/Conversation/ConversationHero', module)
|
|||
<div style={{ width: '480px' }}>
|
||||
<ConversationHero
|
||||
about={getAbout()}
|
||||
acceptedMessageRequest
|
||||
i18n={i18n}
|
||||
title={getTitle()}
|
||||
avatarPath={getAvatarPath()}
|
||||
|
@ -51,6 +56,7 @@ storiesOf('Components/Conversation/ConversationHero', module)
|
|||
profileName={getProfileName()}
|
||||
phoneNumber={getPhoneNumber()}
|
||||
conversationType="direct"
|
||||
updateSharedGroups={updateSharedGroups}
|
||||
sharedGroupNames={['NYC Rock Climbers', 'Dinner Party']}
|
||||
unblurAvatar={action('unblurAvatar')}
|
||||
/>
|
||||
|
@ -62,6 +68,7 @@ storiesOf('Components/Conversation/ConversationHero', module)
|
|||
<div style={{ width: '480px' }}>
|
||||
<ConversationHero
|
||||
about={getAbout()}
|
||||
acceptedMessageRequest
|
||||
i18n={i18n}
|
||||
title={getTitle()}
|
||||
avatarPath={getAvatarPath()}
|
||||
|
@ -69,6 +76,7 @@ storiesOf('Components/Conversation/ConversationHero', module)
|
|||
profileName={getProfileName()}
|
||||
phoneNumber={getPhoneNumber()}
|
||||
conversationType="direct"
|
||||
updateSharedGroups={updateSharedGroups}
|
||||
sharedGroupNames={['NYC Rock Climbers']}
|
||||
unblurAvatar={action('unblurAvatar')}
|
||||
/>
|
||||
|
@ -80,6 +88,7 @@ storiesOf('Components/Conversation/ConversationHero', module)
|
|||
<div style={{ width: '480px' }}>
|
||||
<ConversationHero
|
||||
about={getAbout()}
|
||||
acceptedMessageRequest
|
||||
i18n={i18n}
|
||||
title={getTitle()}
|
||||
avatarPath={getAvatarPath()}
|
||||
|
@ -87,6 +96,7 @@ storiesOf('Components/Conversation/ConversationHero', module)
|
|||
profileName={text('profileName', '')}
|
||||
phoneNumber={getPhoneNumber()}
|
||||
conversationType="direct"
|
||||
updateSharedGroups={updateSharedGroups}
|
||||
sharedGroupNames={[]}
|
||||
unblurAvatar={action('unblurAvatar')}
|
||||
/>
|
||||
|
@ -98,6 +108,7 @@ storiesOf('Components/Conversation/ConversationHero', module)
|
|||
<div style={{ width: '480px' }}>
|
||||
<ConversationHero
|
||||
about={getAbout()}
|
||||
acceptedMessageRequest
|
||||
i18n={i18n}
|
||||
title={text('title', 'Cayce Bollard (profile)')}
|
||||
avatarPath={getAvatarPath()}
|
||||
|
@ -105,6 +116,7 @@ storiesOf('Components/Conversation/ConversationHero', module)
|
|||
profileName={getProfileName()}
|
||||
phoneNumber={getPhoneNumber()}
|
||||
conversationType="direct"
|
||||
updateSharedGroups={updateSharedGroups}
|
||||
sharedGroupNames={[]}
|
||||
unblurAvatar={action('unblurAvatar')}
|
||||
/>
|
||||
|
@ -116,6 +128,7 @@ storiesOf('Components/Conversation/ConversationHero', module)
|
|||
<div style={{ width: '480px' }}>
|
||||
<ConversationHero
|
||||
about={getAbout()}
|
||||
acceptedMessageRequest
|
||||
i18n={i18n}
|
||||
title={text('title', '+1 (646) 327-2700')}
|
||||
avatarPath={getAvatarPath()}
|
||||
|
@ -123,6 +136,7 @@ storiesOf('Components/Conversation/ConversationHero', module)
|
|||
profileName={text('profileName', '')}
|
||||
phoneNumber={getPhoneNumber()}
|
||||
conversationType="direct"
|
||||
updateSharedGroups={updateSharedGroups}
|
||||
sharedGroupNames={[]}
|
||||
unblurAvatar={action('unblurAvatar')}
|
||||
/>
|
||||
|
@ -135,6 +149,7 @@ storiesOf('Components/Conversation/ConversationHero', module)
|
|||
<ConversationHero
|
||||
i18n={i18n}
|
||||
title={text('title', 'Unknown contact')}
|
||||
acceptedMessageRequest
|
||||
avatarPath={getAvatarPath()}
|
||||
name={text('name', '')}
|
||||
profileName={text('profileName', '')}
|
||||
|
@ -142,6 +157,26 @@ storiesOf('Components/Conversation/ConversationHero', module)
|
|||
conversationType="direct"
|
||||
sharedGroupNames={[]}
|
||||
unblurAvatar={action('unblurAvatar')}
|
||||
updateSharedGroups={updateSharedGroups}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
})
|
||||
.add('Direct (No Groups, No Data, Not Accepted)', () => {
|
||||
return (
|
||||
<div style={{ width: '480px' }}>
|
||||
<ConversationHero
|
||||
i18n={i18n}
|
||||
title={text('title', 'Unknown contact')}
|
||||
acceptedMessageRequest={false}
|
||||
avatarPath={getAvatarPath()}
|
||||
name={text('name', '')}
|
||||
profileName={text('profileName', '')}
|
||||
phoneNumber={text('phoneNumber', '')}
|
||||
conversationType="direct"
|
||||
sharedGroupNames={[]}
|
||||
unblurAvatar={action('unblurAvatar')}
|
||||
updateSharedGroups={updateSharedGroups}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
@ -150,12 +185,14 @@ storiesOf('Components/Conversation/ConversationHero', module)
|
|||
return (
|
||||
<div style={{ width: '480px' }}>
|
||||
<ConversationHero
|
||||
acceptedMessageRequest
|
||||
i18n={i18n}
|
||||
title={text('title', 'NYC Rock Climbers')}
|
||||
name={text('groupName', 'NYC Rock Climbers')}
|
||||
conversationType="group"
|
||||
membersCount={numberKnob('membersCount', 22)}
|
||||
unblurAvatar={action('unblurAvatar')}
|
||||
updateSharedGroups={updateSharedGroups}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
@ -164,12 +201,14 @@ storiesOf('Components/Conversation/ConversationHero', module)
|
|||
return (
|
||||
<div style={{ width: '480px' }}>
|
||||
<ConversationHero
|
||||
acceptedMessageRequest
|
||||
i18n={i18n}
|
||||
title={text('title', 'NYC Rock Climbers')}
|
||||
name={text('groupName', 'NYC Rock Climbers')}
|
||||
conversationType="group"
|
||||
membersCount={1}
|
||||
unblurAvatar={action('unblurAvatar')}
|
||||
updateSharedGroups={updateSharedGroups}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
@ -178,12 +217,14 @@ storiesOf('Components/Conversation/ConversationHero', module)
|
|||
return (
|
||||
<div style={{ width: '480px' }}>
|
||||
<ConversationHero
|
||||
acceptedMessageRequest
|
||||
i18n={i18n}
|
||||
title={text('title', 'NYC Rock Climbers')}
|
||||
name={text('groupName', 'NYC Rock Climbers')}
|
||||
conversationType="group"
|
||||
membersCount={0}
|
||||
unblurAvatar={action('unblurAvatar')}
|
||||
updateSharedGroups={updateSharedGroups}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
@ -192,12 +233,14 @@ storiesOf('Components/Conversation/ConversationHero', module)
|
|||
return (
|
||||
<div style={{ width: '480px' }}>
|
||||
<ConversationHero
|
||||
acceptedMessageRequest
|
||||
i18n={i18n}
|
||||
title={text('title', 'Unknown group')}
|
||||
name={text('groupName', '')}
|
||||
conversationType="group"
|
||||
membersCount={0}
|
||||
unblurAvatar={action('unblurAvatar')}
|
||||
updateSharedGroups={updateSharedGroups}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
@ -212,6 +255,7 @@ storiesOf('Components/Conversation/ConversationHero', module)
|
|||
conversationType="direct"
|
||||
phoneNumber={getPhoneNumber()}
|
||||
unblurAvatar={action('unblurAvatar')}
|
||||
updateSharedGroups={updateSharedGroups}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
// Copyright 2020-2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import * as React from 'react';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import Measure from 'react-measure';
|
||||
import { Avatar, AvatarBlur, Props as AvatarProps } from '../Avatar';
|
||||
import { ContactName } from './ContactName';
|
||||
import { About } from './About';
|
||||
import { SharedGroupNames } from '../SharedGroupNames';
|
||||
import { LocalizerType } from '../../types/Util';
|
||||
import { ConfirmationDialog } from '../ConfirmationDialog';
|
||||
import { Button, ButtonSize, ButtonVariant } from '../Button';
|
||||
import { assert } from '../../util/assert';
|
||||
import { shouldBlurAvatar } from '../../util/shouldBlurAvatar';
|
||||
|
||||
export type Props = {
|
||||
|
@ -14,25 +18,34 @@ export type Props = {
|
|||
acceptedMessageRequest?: boolean;
|
||||
i18n: LocalizerType;
|
||||
isMe?: boolean;
|
||||
sharedGroupNames?: Array<string>;
|
||||
membersCount?: number;
|
||||
phoneNumber?: string;
|
||||
onHeightChange?: () => unknown;
|
||||
phoneNumber?: string;
|
||||
sharedGroupNames?: Array<string>;
|
||||
unblurAvatar: () => void;
|
||||
unblurredAvatarPath?: string;
|
||||
updateSharedGroups?: () => unknown;
|
||||
updateSharedGroups: () => unknown;
|
||||
} & Omit<AvatarProps, 'onClick' | 'size' | 'noteToSelf'>;
|
||||
|
||||
const renderMembershipRow = ({
|
||||
i18n,
|
||||
phoneNumber,
|
||||
sharedGroupNames = [],
|
||||
acceptedMessageRequest,
|
||||
conversationType,
|
||||
i18n,
|
||||
isMe,
|
||||
onClickMessageRequestWarning,
|
||||
phoneNumber,
|
||||
sharedGroupNames,
|
||||
}: Pick<
|
||||
Props,
|
||||
'i18n' | 'phoneNumber' | 'sharedGroupNames' | 'conversationType' | 'isMe'
|
||||
>) => {
|
||||
| 'acceptedMessageRequest'
|
||||
| 'conversationType'
|
||||
| 'i18n'
|
||||
| 'isMe'
|
||||
| 'phoneNumber'
|
||||
> &
|
||||
Required<Pick<Props, 'sharedGroupNames'>> & {
|
||||
onClickMessageRequestWarning: () => void;
|
||||
}) => {
|
||||
const className = 'module-conversation-hero__membership';
|
||||
|
||||
if (conversationType !== 'direct') {
|
||||
|
@ -54,12 +67,27 @@ const renderMembershipRow = ({
|
|||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (!phoneNumber) {
|
||||
if (acceptedMessageRequest) {
|
||||
if (phoneNumber) {
|
||||
return null;
|
||||
}
|
||||
return <div className={className}>{i18n('no-groups-in-common')}</div>;
|
||||
}
|
||||
|
||||
return null;
|
||||
return (
|
||||
<div className="module-conversation-hero__message-request-warning">
|
||||
<div className="module-conversation-hero__message-request-warning__message">
|
||||
{i18n('no-groups-in-common-warning')}
|
||||
</div>
|
||||
<Button
|
||||
onClick={onClickMessageRequestWarning}
|
||||
size={ButtonSize.Small}
|
||||
variant={ButtonVariant.SecondaryAffirmative}
|
||||
>
|
||||
{i18n('MessageRequestWarning__learn-more')}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const ConversationHero = ({
|
||||
|
@ -81,37 +109,31 @@ export const ConversationHero = ({
|
|||
unblurredAvatarPath,
|
||||
updateSharedGroups,
|
||||
}: Props): JSX.Element => {
|
||||
const firstRenderRef = React.useRef(true);
|
||||
const firstRenderRef = useRef(true);
|
||||
|
||||
// TODO: DESKTOP-686
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
React.useEffect(() => {
|
||||
// If any of the depenencies for this hook change then the height of this
|
||||
// component may have changed. The cleanup function notifies listeners of
|
||||
// any potential height changes.
|
||||
return () => {
|
||||
// Kick off the expensive hydration of the current sharedGroupNames
|
||||
if (updateSharedGroups) {
|
||||
updateSharedGroups();
|
||||
}
|
||||
const [height, setHeight] = useState<undefined | number>();
|
||||
const [
|
||||
isShowingMessageRequestWarning,
|
||||
setIsShowingMessageRequestWarning,
|
||||
] = useState(false);
|
||||
const closeMessageRequestWarning = () => {
|
||||
setIsShowingMessageRequestWarning(false);
|
||||
};
|
||||
|
||||
if (onHeightChange && !firstRenderRef.current) {
|
||||
onHeightChange();
|
||||
} else {
|
||||
firstRenderRef.current = false;
|
||||
}
|
||||
};
|
||||
}, [
|
||||
firstRenderRef,
|
||||
onHeightChange,
|
||||
// Avoid collisions in these dependencies by prefixing them
|
||||
// These dependencies may be dynamic, and therefore may cause height changes
|
||||
`mc-${membersCount}`,
|
||||
`n-${name}`,
|
||||
`pn-${profileName}`,
|
||||
sharedGroupNames.map(g => `g-${g}`).join(' '),
|
||||
]);
|
||||
/* eslint-enable react-hooks/exhaustive-deps */
|
||||
useEffect(() => {
|
||||
// Kick off the expensive hydration of the current sharedGroupNames
|
||||
updateSharedGroups();
|
||||
}, [updateSharedGroups]);
|
||||
|
||||
useEffect(() => {
|
||||
firstRenderRef.current = false;
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!firstRenderRef.current && onHeightChange) {
|
||||
onHeightChange();
|
||||
}
|
||||
}, [height, onHeightChange]);
|
||||
|
||||
let avatarBlur: AvatarBlur;
|
||||
let avatarOnClick: undefined | (() => void);
|
||||
|
@ -136,58 +158,92 @@ export const ConversationHero = ({
|
|||
|
||||
/* eslint-disable no-nested-ternary */
|
||||
return (
|
||||
<div className="module-conversation-hero">
|
||||
<Avatar
|
||||
i18n={i18n}
|
||||
blur={avatarBlur}
|
||||
color={color}
|
||||
noteToSelf={isMe}
|
||||
avatarPath={avatarPath}
|
||||
conversationType={conversationType}
|
||||
name={name}
|
||||
onClick={avatarOnClick}
|
||||
profileName={profileName}
|
||||
title={title}
|
||||
size={112}
|
||||
className="module-conversation-hero__avatar"
|
||||
/>
|
||||
<h1 className="module-conversation-hero__profile-name">
|
||||
{isMe ? (
|
||||
i18n('noteToSelf')
|
||||
) : (
|
||||
<ContactName
|
||||
title={title}
|
||||
name={name}
|
||||
profileName={profileName}
|
||||
phoneNumber={phoneNumber}
|
||||
i18n={i18n}
|
||||
/>
|
||||
<>
|
||||
<Measure
|
||||
bounds
|
||||
onResize={({ bounds }) => {
|
||||
assert(bounds, 'We should be measuring the bounds');
|
||||
setHeight(bounds.height);
|
||||
}}
|
||||
>
|
||||
{({ measureRef }) => (
|
||||
<div className="module-conversation-hero" ref={measureRef}>
|
||||
<Avatar
|
||||
i18n={i18n}
|
||||
blur={avatarBlur}
|
||||
color={color}
|
||||
noteToSelf={isMe}
|
||||
avatarPath={avatarPath}
|
||||
conversationType={conversationType}
|
||||
name={name}
|
||||
onClick={avatarOnClick}
|
||||
profileName={profileName}
|
||||
title={title}
|
||||
size={112}
|
||||
className="module-conversation-hero__avatar"
|
||||
/>
|
||||
<h1 className="module-conversation-hero__profile-name">
|
||||
{isMe ? (
|
||||
i18n('noteToSelf')
|
||||
) : (
|
||||
<ContactName
|
||||
title={title}
|
||||
name={name}
|
||||
profileName={profileName}
|
||||
phoneNumber={phoneNumber}
|
||||
i18n={i18n}
|
||||
/>
|
||||
)}
|
||||
</h1>
|
||||
{about && !isMe && (
|
||||
<div className="module-about__container">
|
||||
<About text={about} />
|
||||
</div>
|
||||
)}
|
||||
{!isMe ? (
|
||||
<div className="module-conversation-hero__with">
|
||||
{membersCount === 1
|
||||
? i18n('ConversationHero--members-1')
|
||||
: membersCount !== undefined
|
||||
? i18n('ConversationHero--members', [`${membersCount}`])
|
||||
: phoneNumberOnly
|
||||
? null
|
||||
: phoneNumber}
|
||||
</div>
|
||||
) : null}
|
||||
{renderMembershipRow({
|
||||
acceptedMessageRequest,
|
||||
conversationType,
|
||||
i18n,
|
||||
isMe,
|
||||
onClickMessageRequestWarning() {
|
||||
setIsShowingMessageRequestWarning(true);
|
||||
},
|
||||
phoneNumber,
|
||||
sharedGroupNames,
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
</h1>
|
||||
{about && !isMe && (
|
||||
<div className="module-about__container">
|
||||
<About text={about} />
|
||||
</div>
|
||||
</Measure>
|
||||
{isShowingMessageRequestWarning && (
|
||||
<ConfirmationDialog
|
||||
i18n={i18n}
|
||||
onClose={closeMessageRequestWarning}
|
||||
actions={[
|
||||
{
|
||||
text: i18n('MessageRequestWarning__dialog__learn-even-more'),
|
||||
action: () => {
|
||||
window.location.href =
|
||||
'https://support.signal.org/hc/articles/360007459591';
|
||||
closeMessageRequestWarning();
|
||||
},
|
||||
},
|
||||
]}
|
||||
>
|
||||
{i18n('MessageRequestWarning__dialog__details')}
|
||||
</ConfirmationDialog>
|
||||
)}
|
||||
{!isMe ? (
|
||||
<div className="module-conversation-hero__with">
|
||||
{membersCount === 1
|
||||
? i18n('ConversationHero--members-1')
|
||||
: membersCount !== undefined
|
||||
? i18n('ConversationHero--members', [`${membersCount}`])
|
||||
: phoneNumberOnly
|
||||
? null
|
||||
: phoneNumber}
|
||||
</div>
|
||||
) : null}
|
||||
{renderMembershipRow({
|
||||
conversationType,
|
||||
i18n,
|
||||
isMe,
|
||||
phoneNumber,
|
||||
sharedGroupNames,
|
||||
})}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
/* eslint-enable no-nested-ternary */
|
||||
};
|
||||
|
|
|
@ -315,6 +315,7 @@ const renderHeroRow = () => (
|
|||
conversationType="direct"
|
||||
sharedGroupNames={['NYC Rock Climbers', 'Dinner Party']}
|
||||
unblurAvatar={action('unblurAvatar')}
|
||||
updateSharedGroups={noop}
|
||||
/>
|
||||
);
|
||||
const renderLoadingRow = () => <TimelineLoadingRow state="loading" />;
|
||||
|
|
|
@ -16509,8 +16509,8 @@
|
|||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "ts/components/conversation/ConversationHero.js",
|
||||
"line": " const firstRenderRef = React.useRef(true);",
|
||||
"lineNumber": 49,
|
||||
"line": " const firstRenderRef = react_1.useRef(true);",
|
||||
"lineNumber": 61,
|
||||
"reasonCategory": "falseMatch",
|
||||
"updated": "2020-10-26T19:12:24.410Z",
|
||||
"reasonDetail": "Doesn't refer to a DOM element."
|
||||
|
@ -16518,8 +16518,8 @@
|
|||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "ts/components/conversation/ConversationHero.tsx",
|
||||
"line": " const firstRenderRef = React.useRef(true);",
|
||||
"lineNumber": 84,
|
||||
"line": " const firstRenderRef = useRef(true);",
|
||||
"lineNumber": 112,
|
||||
"reasonCategory": "falseMatch",
|
||||
"updated": "2020-10-26T19:12:24.410Z",
|
||||
"reasonDetail": "Doesn't refer to a DOM element."
|
||||
|
|
Loading…
Reference in a new issue