Use parallel-prettier for lint

This commit is contained in:
Fedor Indutny 2022-03-22 13:45:34 -07:00 committed by GitHub
parent 67702254fb
commit 356f123092
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 817 additions and 562 deletions

View file

@ -28,35 +28,33 @@ type PropsType = {
onClose: () => void;
} & PropsDataType;
export const AddGroupMemberErrorDialog: FunctionComponent<PropsType> =
props => {
const { i18n, onClose } = props;
export const AddGroupMemberErrorDialog: FunctionComponent<
PropsType
> = props => {
const { i18n, onClose } = props;
let title: string;
let body: ReactNode;
switch (props.mode) {
case AddGroupMemberErrorDialogMode.MaximumGroupSize: {
const { maximumNumberOfContacts } = props;
title = i18n('chooseGroupMembers__maximum-group-size__title');
body = i18n('chooseGroupMembers__maximum-group-size__body', [
maximumNumberOfContacts.toString(),
]);
break;
}
case AddGroupMemberErrorDialogMode.RecommendedMaximumGroupSize: {
const { recommendedMaximumNumberOfContacts } = props;
title = i18n(
'chooseGroupMembers__maximum-recommended-group-size__title'
);
body = i18n(
'chooseGroupMembers__maximum-recommended-group-size__body',
[recommendedMaximumNumberOfContacts.toString()]
);
break;
}
default:
throw missingCaseError(props);
let title: string;
let body: ReactNode;
switch (props.mode) {
case AddGroupMemberErrorDialogMode.MaximumGroupSize: {
const { maximumNumberOfContacts } = props;
title = i18n('chooseGroupMembers__maximum-group-size__title');
body = i18n('chooseGroupMembers__maximum-group-size__body', [
maximumNumberOfContacts.toString(),
]);
break;
}
case AddGroupMemberErrorDialogMode.RecommendedMaximumGroupSize: {
const { recommendedMaximumNumberOfContacts } = props;
title = i18n('chooseGroupMembers__maximum-recommended-group-size__title');
body = i18n('chooseGroupMembers__maximum-recommended-group-size__body', [
recommendedMaximumNumberOfContacts.toString(),
]);
break;
}
default:
throw missingCaseError(props);
}
return <Alert body={body} i18n={i18n} onClose={onClose} title={title} />;
};
return <Alert body={body} i18n={i18n} onClose={onClose} title={title} />;
};

View file

@ -52,20 +52,21 @@ export const CompositionUpload = forwardRef<HTMLInputElement, PropsType>(
AttachmentToastType | undefined
>();
const onFileInputChange: ChangeEventHandler<HTMLInputElement> =
async event => {
const files = event.target.files || [];
const onFileInputChange: ChangeEventHandler<
HTMLInputElement
> = async event => {
const files = event.target.files || [];
await processAttachments({
addAttachment,
addPendingAttachment,
conversationId,
files: Array.from(files),
draftAttachments,
onShowToast: setToastType,
removeAttachment,
});
};
await processAttachments({
addAttachment,
addPendingAttachment,
conversationId,
files: Array.from(files),
draftAttachments,
onShowToast: setToastType,
removeAttachment,
});
};
function closeToast() {
setToastType(undefined);

View file

@ -20,73 +20,70 @@ type PropsType = {
theme: ThemeType;
};
export const NewlyCreatedGroupInvitedContactsDialog: FunctionComponent<PropsType> =
({ contacts, getPreferredBadge, i18n, onClose, theme }) => {
let title: string;
let body: ReactNode;
if (contacts.length === 1) {
const contact = contacts[0];
export const NewlyCreatedGroupInvitedContactsDialog: FunctionComponent<
PropsType
> = ({ contacts, getPreferredBadge, i18n, onClose, theme }) => {
let title: string;
let body: ReactNode;
if (contacts.length === 1) {
const contact = contacts[0];
title = i18n('NewlyCreatedGroupInvitedContactsDialog--title--one');
body = (
<>
<GroupDialog.Paragraph>
<Intl
i18n={i18n}
id="NewlyCreatedGroupInvitedContactsDialog--body--user-paragraph--one"
components={[<ContactName title={contact.title} />]}
/>
</GroupDialog.Paragraph>
<GroupDialog.Paragraph>
{i18n(
'NewlyCreatedGroupInvitedContactsDialog--body--info-paragraph'
)}
</GroupDialog.Paragraph>
</>
);
} else {
title = i18n('NewlyCreatedGroupInvitedContactsDialog--title--many', [
contacts.length.toString(),
]);
body = (
<>
<GroupDialog.Paragraph>
{i18n(
'NewlyCreatedGroupInvitedContactsDialog--body--user-paragraph--many'
)}
</GroupDialog.Paragraph>
<GroupDialog.Paragraph>
{i18n(
'NewlyCreatedGroupInvitedContactsDialog--body--info-paragraph'
)}
</GroupDialog.Paragraph>
<GroupDialog.Contacts
contacts={contacts}
getPreferredBadge={getPreferredBadge}
title = i18n('NewlyCreatedGroupInvitedContactsDialog--title--one');
body = (
<>
<GroupDialog.Paragraph>
<Intl
i18n={i18n}
theme={theme}
id="NewlyCreatedGroupInvitedContactsDialog--body--user-paragraph--one"
components={[<ContactName title={contact.title} />]}
/>
</>
);
}
return (
<GroupDialog
i18n={i18n}
onClickPrimaryButton={onClose}
primaryButtonText={i18n('Confirmation--confirm')}
secondaryButtonText={i18n(
'NewlyCreatedGroupInvitedContactsDialog--body--learn-more'
)}
onClickSecondaryButton={() => {
openLinkInWebBrowser(
'https://support.signal.org/hc/articles/360007319331-Group-chats'
);
}}
onClose={onClose}
title={title}
>
{body}
</GroupDialog>
</GroupDialog.Paragraph>
<GroupDialog.Paragraph>
{i18n('NewlyCreatedGroupInvitedContactsDialog--body--info-paragraph')}
</GroupDialog.Paragraph>
</>
);
};
} else {
title = i18n('NewlyCreatedGroupInvitedContactsDialog--title--many', [
contacts.length.toString(),
]);
body = (
<>
<GroupDialog.Paragraph>
{i18n(
'NewlyCreatedGroupInvitedContactsDialog--body--user-paragraph--many'
)}
</GroupDialog.Paragraph>
<GroupDialog.Paragraph>
{i18n('NewlyCreatedGroupInvitedContactsDialog--body--info-paragraph')}
</GroupDialog.Paragraph>
<GroupDialog.Contacts
contacts={contacts}
getPreferredBadge={getPreferredBadge}
i18n={i18n}
theme={theme}
/>
</>
);
}
return (
<GroupDialog
i18n={i18n}
onClickPrimaryButton={onClose}
primaryButtonText={i18n('Confirmation--confirm')}
secondaryButtonText={i18n(
'NewlyCreatedGroupInvitedContactsDialog--body--learn-more'
)}
onClickSecondaryButton={() => {
openLinkInWebBrowser(
'https://support.signal.org/hc/articles/360007319331-Group-chats'
);
}}
onClose={onClose}
title={title}
>
{body}
</GroupDialog>
);
};

View file

@ -60,305 +60,302 @@ enum ConfirmationStateType {
ConfirmingGroupRemoval,
}
export const ContactSpoofingReviewDialog: FunctionComponent<PropsType> =
props => {
const {
getPreferredBadge,
i18n,
onBlock,
onBlockAndReportSpam,
onClose,
onDelete,
onShowContactModal,
onUnblock,
removeMember,
theme,
} = props;
export const ContactSpoofingReviewDialog: FunctionComponent<
PropsType
> = props => {
const {
getPreferredBadge,
i18n,
onBlock,
onBlockAndReportSpam,
onClose,
onDelete,
onShowContactModal,
onUnblock,
removeMember,
theme,
} = props;
const [confirmationState, setConfirmationState] = useState<
| undefined
| {
type: ConfirmationStateType.ConfirmingGroupRemoval;
affectedConversation: ConversationType;
group: ConversationType;
}
| {
type:
| ConfirmationStateType.ConfirmingDelete
| ConfirmationStateType.ConfirmingBlock;
affectedConversation: ConversationType;
}
>();
if (confirmationState) {
const { type, affectedConversation } = confirmationState;
switch (type) {
case ConfirmationStateType.ConfirmingDelete:
case ConfirmationStateType.ConfirmingBlock:
return (
<MessageRequestActionsConfirmation
i18n={i18n}
onBlock={() => {
onBlock(affectedConversation.id);
}}
onBlockAndReportSpam={() => {
onBlockAndReportSpam(affectedConversation.id);
}}
onUnblock={() => {
onUnblock(affectedConversation.id);
}}
onDelete={() => {
onDelete(affectedConversation.id);
}}
title={affectedConversation.title}
conversationType="direct"
state={
type === ConfirmationStateType.ConfirmingDelete
? MessageRequestState.deleting
: MessageRequestState.blocking
}
onChangeState={messageRequestState => {
switch (messageRequestState) {
case MessageRequestState.blocking:
setConfirmationState({
type: ConfirmationStateType.ConfirmingBlock,
affectedConversation,
});
break;
case MessageRequestState.deleting:
setConfirmationState({
type: ConfirmationStateType.ConfirmingDelete,
affectedConversation,
});
break;
case MessageRequestState.unblocking:
assert(
false,
'Got unexpected MessageRequestState.unblocking state. Clearing confiration state'
);
setConfirmationState(undefined);
break;
case MessageRequestState.default:
setConfirmationState(undefined);
break;
default:
throw missingCaseError(messageRequestState);
}
}}
/>
);
case ConfirmationStateType.ConfirmingGroupRemoval: {
const { group } = confirmationState;
return (
<RemoveGroupMemberConfirmationDialog
conversation={affectedConversation}
group={group}
i18n={i18n}
onClose={() => {
setConfirmationState(undefined);
}}
onRemove={() => {
removeMember(affectedConversation.id);
}}
/>
);
}
default:
throw missingCaseError(type);
const [confirmationState, setConfirmationState] = useState<
| undefined
| {
type: ConfirmationStateType.ConfirmingGroupRemoval;
affectedConversation: ConversationType;
group: ConversationType;
}
| {
type:
| ConfirmationStateType.ConfirmingDelete
| ConfirmationStateType.ConfirmingBlock;
affectedConversation: ConversationType;
}
>();
if (confirmationState) {
const { type, affectedConversation } = confirmationState;
switch (type) {
case ConfirmationStateType.ConfirmingDelete:
case ConfirmationStateType.ConfirmingBlock:
return (
<MessageRequestActionsConfirmation
i18n={i18n}
onBlock={() => {
onBlock(affectedConversation.id);
}}
onBlockAndReportSpam={() => {
onBlockAndReportSpam(affectedConversation.id);
}}
onUnblock={() => {
onUnblock(affectedConversation.id);
}}
onDelete={() => {
onDelete(affectedConversation.id);
}}
title={affectedConversation.title}
conversationType="direct"
state={
type === ConfirmationStateType.ConfirmingDelete
? MessageRequestState.deleting
: MessageRequestState.blocking
}
onChangeState={messageRequestState => {
switch (messageRequestState) {
case MessageRequestState.blocking:
setConfirmationState({
type: ConfirmationStateType.ConfirmingBlock,
affectedConversation,
});
break;
case MessageRequestState.deleting:
setConfirmationState({
type: ConfirmationStateType.ConfirmingDelete,
affectedConversation,
});
break;
case MessageRequestState.unblocking:
assert(
false,
'Got unexpected MessageRequestState.unblocking state. Clearing confiration state'
);
setConfirmationState(undefined);
break;
case MessageRequestState.default:
setConfirmationState(undefined);
break;
default:
throw missingCaseError(messageRequestState);
}
}}
/>
);
case ConfirmationStateType.ConfirmingGroupRemoval: {
const { group } = confirmationState;
return (
<RemoveGroupMemberConfirmationDialog
conversation={affectedConversation}
group={group}
i18n={i18n}
onClose={() => {
setConfirmationState(undefined);
}}
onRemove={() => {
removeMember(affectedConversation.id);
}}
/>
);
}
default:
throw missingCaseError(type);
}
}
let title: string;
let contents: ReactChild;
let title: string;
let contents: ReactChild;
switch (props.type) {
case ContactSpoofingType.DirectConversationWithSameTitle: {
const { possiblyUnsafeConversation, safeConversation } = props;
assert(
possiblyUnsafeConversation.type === 'direct',
'<ContactSpoofingReviewDialog> expected a direct conversation for the "possibly unsafe" conversation'
);
assert(
safeConversation.type === 'direct',
'<ContactSpoofingReviewDialog> expected a direct conversation for the "safe" conversation'
);
switch (props.type) {
case ContactSpoofingType.DirectConversationWithSameTitle: {
const { possiblyUnsafeConversation, safeConversation } = props;
assert(
possiblyUnsafeConversation.type === 'direct',
'<ContactSpoofingReviewDialog> expected a direct conversation for the "possibly unsafe" conversation'
);
assert(
safeConversation.type === 'direct',
'<ContactSpoofingReviewDialog> expected a direct conversation for the "safe" conversation'
);
title = i18n('ContactSpoofingReviewDialog__title');
contents = (
<>
<p>{i18n('ContactSpoofingReviewDialog__description')}</p>
<h2>
{i18n('ContactSpoofingReviewDialog__possibly-unsafe-title')}
</h2>
<ContactSpoofingReviewDialogPerson
conversation={possiblyUnsafeConversation}
getPreferredBadge={getPreferredBadge}
i18n={i18n}
theme={theme}
>
<div className="module-ContactSpoofingReviewDialog__buttons">
title = i18n('ContactSpoofingReviewDialog__title');
contents = (
<>
<p>{i18n('ContactSpoofingReviewDialog__description')}</p>
<h2>{i18n('ContactSpoofingReviewDialog__possibly-unsafe-title')}</h2>
<ContactSpoofingReviewDialogPerson
conversation={possiblyUnsafeConversation}
getPreferredBadge={getPreferredBadge}
i18n={i18n}
theme={theme}
>
<div className="module-ContactSpoofingReviewDialog__buttons">
<Button
variant={ButtonVariant.SecondaryDestructive}
onClick={() => {
setConfirmationState({
type: ConfirmationStateType.ConfirmingDelete,
affectedConversation: possiblyUnsafeConversation,
});
}}
>
{i18n('MessageRequests--delete')}
</Button>
<Button
variant={ButtonVariant.SecondaryDestructive}
onClick={() => {
setConfirmationState({
type: ConfirmationStateType.ConfirmingBlock,
affectedConversation: possiblyUnsafeConversation,
});
}}
>
{i18n('MessageRequests--block')}
</Button>
</div>
</ContactSpoofingReviewDialogPerson>
<hr />
<h2>{i18n('ContactSpoofingReviewDialog__safe-title')}</h2>
<ContactSpoofingReviewDialogPerson
conversation={safeConversation}
getPreferredBadge={getPreferredBadge}
i18n={i18n}
onClick={() => {
onShowContactModal(safeConversation.id);
}}
theme={theme}
/>
</>
);
break;
}
case ContactSpoofingType.MultipleGroupMembersWithSameTitle: {
const { group, collisionInfoByTitle } = props;
const unsortedConversationInfos = concat(
// This empty array exists to appease Lodash's type definitions.
[],
...Object.values(collisionInfoByTitle)
);
const conversationInfos = orderBy(unsortedConversationInfos, [
// We normally use an `Intl.Collator` to sort by title. We do this instead, as
// we only really care about stability (not perfect ordering).
'title',
'id',
]);
title = i18n('ContactSpoofingReviewDialog__group__title');
contents = (
<>
<p>
{i18n('ContactSpoofingReviewDialog__group__description', [
conversationInfos.length.toString(),
])}
</p>
<h2>{i18n('ContactSpoofingReviewDialog__group__members-header')}</h2>
{conversationInfos.map((conversationInfo, index) => {
let button: ReactNode;
if (group.areWeAdmin) {
button = (
<Button
variant={ButtonVariant.SecondaryDestructive}
variant={ButtonVariant.SecondaryAffirmative}
onClick={() => {
setConfirmationState({
type: ConfirmationStateType.ConfirmingDelete,
affectedConversation: possiblyUnsafeConversation,
type: ConfirmationStateType.ConfirmingGroupRemoval,
affectedConversation: conversationInfo.conversation,
group,
});
}}
>
{i18n('MessageRequests--delete')}
{i18n('RemoveGroupMemberConfirmation__remove-button')}
</Button>
);
} else if (conversationInfo.conversation.isBlocked) {
button = (
<Button
variant={ButtonVariant.SecondaryAffirmative}
onClick={() => {
onUnblock(conversationInfo.conversation.id);
}}
>
{i18n('MessageRequests--unblock')}
</Button>
);
} else if (!isInSystemContacts(conversationInfo.conversation)) {
button = (
<Button
variant={ButtonVariant.SecondaryDestructive}
onClick={() => {
setConfirmationState({
type: ConfirmationStateType.ConfirmingBlock,
affectedConversation: possiblyUnsafeConversation,
affectedConversation: conversationInfo.conversation,
});
}}
>
{i18n('MessageRequests--block')}
</Button>
</div>
</ContactSpoofingReviewDialogPerson>
<hr />
<h2>{i18n('ContactSpoofingReviewDialog__safe-title')}</h2>
<ContactSpoofingReviewDialogPerson
conversation={safeConversation}
getPreferredBadge={getPreferredBadge}
i18n={i18n}
onClick={() => {
onShowContactModal(safeConversation.id);
}}
theme={theme}
/>
</>
);
break;
}
case ContactSpoofingType.MultipleGroupMembersWithSameTitle: {
const { group, collisionInfoByTitle } = props;
const unsortedConversationInfos = concat(
// This empty array exists to appease Lodash's type definitions.
[],
...Object.values(collisionInfoByTitle)
);
const conversationInfos = orderBy(unsortedConversationInfos, [
// We normally use an `Intl.Collator` to sort by title. We do this instead, as
// we only really care about stability (not perfect ordering).
'title',
'id',
]);
title = i18n('ContactSpoofingReviewDialog__group__title');
contents = (
<>
<p>
{i18n('ContactSpoofingReviewDialog__group__description', [
conversationInfos.length.toString(),
])}
</p>
<h2>
{i18n('ContactSpoofingReviewDialog__group__members-header')}
</h2>
{conversationInfos.map((conversationInfo, index) => {
let button: ReactNode;
if (group.areWeAdmin) {
button = (
<Button
variant={ButtonVariant.SecondaryAffirmative}
onClick={() => {
setConfirmationState({
type: ConfirmationStateType.ConfirmingGroupRemoval,
affectedConversation: conversationInfo.conversation,
group,
});
}}
>
{i18n('RemoveGroupMemberConfirmation__remove-button')}
</Button>
);
} else if (conversationInfo.conversation.isBlocked) {
button = (
<Button
variant={ButtonVariant.SecondaryAffirmative}
onClick={() => {
onUnblock(conversationInfo.conversation.id);
}}
>
{i18n('MessageRequests--unblock')}
</Button>
);
} else if (!isInSystemContacts(conversationInfo.conversation)) {
button = (
<Button
variant={ButtonVariant.SecondaryDestructive}
onClick={() => {
setConfirmationState({
type: ConfirmationStateType.ConfirmingBlock,
affectedConversation: conversationInfo.conversation,
});
}}
>
{i18n('MessageRequests--block')}
</Button>
);
}
const { oldName } = conversationInfo;
const newName =
conversationInfo.conversation.profileName ||
conversationInfo.conversation.title;
return (
<>
{index !== 0 && <hr />}
<ContactSpoofingReviewDialogPerson
key={conversationInfo.conversation.id}
conversation={conversationInfo.conversation}
getPreferredBadge={getPreferredBadge}
i18n={i18n}
theme={theme}
>
{Boolean(oldName) && oldName !== newName && (
<div className="module-ContactSpoofingReviewDialogPerson__info__property module-ContactSpoofingReviewDialogPerson__info__property--callout">
<Intl
i18n={i18n}
id="ContactSpoofingReviewDialog__group__name-change-info"
components={{
oldName: <Emojify text={oldName} />,
newName: <Emojify text={newName} />,
}}
/>
</div>
)}
{button && (
<div className="module-ContactSpoofingReviewDialog__buttons">
{button}
</div>
)}
</ContactSpoofingReviewDialogPerson>
</>
);
})}
</>
);
break;
}
default:
throw missingCaseError(props);
}
}
return (
<Modal
hasXButton
i18n={i18n}
moduleClassName="module-ContactSpoofingReviewDialog"
onClose={onClose}
title={title}
>
{contents}
</Modal>
);
};
const { oldName } = conversationInfo;
const newName =
conversationInfo.conversation.profileName ||
conversationInfo.conversation.title;
return (
<>
{index !== 0 && <hr />}
<ContactSpoofingReviewDialogPerson
key={conversationInfo.conversation.id}
conversation={conversationInfo.conversation}
getPreferredBadge={getPreferredBadge}
i18n={i18n}
theme={theme}
>
{Boolean(oldName) && oldName !== newName && (
<div className="module-ContactSpoofingReviewDialogPerson__info__property module-ContactSpoofingReviewDialogPerson__info__property--callout">
<Intl
i18n={i18n}
id="ContactSpoofingReviewDialog__group__name-change-info"
components={{
oldName: <Emojify text={oldName} />,
newName: <Emojify text={newName} />,
}}
/>
</div>
)}
{button && (
<div className="module-ContactSpoofingReviewDialog__buttons">
{button}
</div>
)}
</ContactSpoofingReviewDialogPerson>
</>
);
})}
</>
);
break;
}
default:
throw missingCaseError(props);
}
return (
<Modal
hasXButton
i18n={i18n}
moduleClassName="module-ContactSpoofingReviewDialog"
onClose={onClose}
title={title}
>
{contents}
</Modal>
);
};

View file

@ -22,58 +22,59 @@ type PropsType = {
theme: ThemeType;
};
export const ContactSpoofingReviewDialogPerson: FunctionComponent<PropsType> =
({ children, conversation, getPreferredBadge, i18n, onClick, theme }) => {
assert(
conversation.type === 'direct',
'<ContactSpoofingReviewDialogPerson> expected a direct conversation'
);
export const ContactSpoofingReviewDialogPerson: FunctionComponent<
PropsType
> = ({ children, conversation, getPreferredBadge, i18n, onClick, theme }) => {
assert(
conversation.type === 'direct',
'<ContactSpoofingReviewDialogPerson> expected a direct conversation'
);
const contents = (
<>
<Avatar
{...conversation}
badge={getPreferredBadge(conversation.badges)}
conversationType={conversation.type}
size={AvatarSize.FIFTY_TWO}
className="module-ContactSpoofingReviewDialogPerson__avatar"
i18n={i18n}
theme={theme}
const contents = (
<>
<Avatar
{...conversation}
badge={getPreferredBadge(conversation.badges)}
conversationType={conversation.type}
size={AvatarSize.FIFTY_TWO}
className="module-ContactSpoofingReviewDialogPerson__avatar"
i18n={i18n}
theme={theme}
/>
<div className="module-ContactSpoofingReviewDialogPerson__info">
<ContactName
module="module-ContactSpoofingReviewDialogPerson__info__contact-name"
title={conversation.title}
/>
<div className="module-ContactSpoofingReviewDialogPerson__info">
<ContactName
module="module-ContactSpoofingReviewDialogPerson__info__contact-name"
title={conversation.title}
/>
{conversation.phoneNumber ? (
<div className="module-ContactSpoofingReviewDialogPerson__info__property">
{conversation.phoneNumber}
</div>
) : null}
{conversation.phoneNumber ? (
<div className="module-ContactSpoofingReviewDialogPerson__info__property">
<SharedGroupNames
i18n={i18n}
sharedGroupNames={conversation.sharedGroupNames || []}
/>
{conversation.phoneNumber}
</div>
{children}
) : null}
<div className="module-ContactSpoofingReviewDialogPerson__info__property">
<SharedGroupNames
i18n={i18n}
sharedGroupNames={conversation.sharedGroupNames || []}
/>
</div>
</>
);
if (onClick) {
return (
<button
type="button"
className="module-ContactSpoofingReviewDialogPerson"
onClick={onClick}
>
{contents}
</button>
);
}
{children}
</div>
</>
);
if (onClick) {
return (
<div className="module-ContactSpoofingReviewDialogPerson">{contents}</div>
<button
type="button"
className="module-ContactSpoofingReviewDialogPerson"
onClick={onClick}
>
{contents}
</button>
);
};
}
return (
<div className="module-ContactSpoofingReviewDialogPerson">{contents}</div>
);
};

View file

@ -20,34 +20,35 @@ type PropsType = {
onRemove: () => void;
};
export const RemoveGroupMemberConfirmationDialog: FunctionComponent<PropsType> =
({ conversation, group, i18n, onClose, onRemove }) => {
const descriptionKey = isAccessControlEnabled(
group.accessControlAddFromInviteLink
)
? 'RemoveGroupMemberConfirmation__description__with-link'
: 'RemoveGroupMemberConfirmation__description';
export const RemoveGroupMemberConfirmationDialog: FunctionComponent<
PropsType
> = ({ conversation, group, i18n, onClose, onRemove }) => {
const descriptionKey = isAccessControlEnabled(
group.accessControlAddFromInviteLink
)
? 'RemoveGroupMemberConfirmation__description__with-link'
: 'RemoveGroupMemberConfirmation__description';
return (
<ConfirmationDialog
actions={[
{
action: onRemove,
text: i18n('RemoveGroupMemberConfirmation__remove-button'),
style: 'negative',
},
]}
i18n={i18n}
onClose={onClose}
title={
<Intl
i18n={i18n}
id={descriptionKey}
components={{
name: <ContactName title={conversation.title} />,
}}
/>
}
/>
);
};
return (
<ConfirmationDialog
actions={[
{
action: onRemove,
text: i18n('RemoveGroupMemberConfirmation__remove-button'),
style: 'negative',
},
]}
i18n={i18n}
onClose={onClose}
title={
<Intl
i18n={i18n}
id={descriptionKey}
components={{
name: <ContactName title={conversation.title} />,
}}
/>
}
/>
);
};

View file

@ -25,103 +25,100 @@ type PropsType = {
setMuteExpiration: (muteExpiresAt: undefined | number) => unknown;
};
export const ConversationNotificationsSettings: FunctionComponent<PropsType> =
({
conversationType,
dontNotifyForMentionsIfMuted,
i18n,
muteExpiresAt,
setMuteExpiration,
setDontNotifyForMentionsIfMuted,
}) => {
const muteOptions = useMemo(
() => [
...(isMuted(muteExpiresAt)
? []
: [
{
disabled: true,
text: i18n('notMuted'),
value: -1,
},
]),
...getMuteOptions(muteExpiresAt, i18n).map(
({ disabled, name, value }) => ({
disabled,
text: name,
value,
})
),
],
[i18n, muteExpiresAt]
export const ConversationNotificationsSettings: FunctionComponent<
PropsType
> = ({
conversationType,
dontNotifyForMentionsIfMuted,
i18n,
muteExpiresAt,
setMuteExpiration,
setDontNotifyForMentionsIfMuted,
}) => {
const muteOptions = useMemo(
() => [
...(isMuted(muteExpiresAt)
? []
: [
{
disabled: true,
text: i18n('notMuted'),
value: -1,
},
]),
...getMuteOptions(muteExpiresAt, i18n).map(
({ disabled, name, value }) => ({
disabled,
text: name,
value,
})
),
],
[i18n, muteExpiresAt]
);
const onMuteChange = (rawValue: string) => {
const ms = parseIntOrThrow(
rawValue,
'NotificationSettings: mute ms was not an integer'
);
setMuteExpiration(ms);
};
const onMuteChange = (rawValue: string) => {
const ms = parseIntOrThrow(
rawValue,
'NotificationSettings: mute ms was not an integer'
);
setMuteExpiration(ms);
};
const onChangeDontNotifyForMentionsIfMuted = (rawValue: string) => {
setDontNotifyForMentionsIfMuted(rawValue === 'yes');
};
const onChangeDontNotifyForMentionsIfMuted = (rawValue: string) => {
setDontNotifyForMentionsIfMuted(rawValue === 'yes');
};
return (
<div className="conversation-details-panel">
<PanelSection>
return (
<div className="conversation-details-panel">
<PanelSection>
<PanelRow
icon={
<ConversationDetailsIcon
ariaLabel={i18n('muteNotificationsTitle')}
icon={IconType.mute}
/>
}
label={i18n('muteNotificationsTitle')}
right={
<Select options={muteOptions} onChange={onMuteChange} value={-1} />
}
/>
{conversationType === 'group' && (
<PanelRow
icon={
<ConversationDetailsIcon
ariaLabel={i18n('muteNotificationsTitle')}
icon={IconType.mute}
ariaLabel={i18n(
'ConversationNotificationsSettings__mentions__label'
)}
icon={IconType.mention}
/>
}
label={i18n('muteNotificationsTitle')}
label={i18n('ConversationNotificationsSettings__mentions__label')}
info={i18n('ConversationNotificationsSettings__mentions__info')}
right={
<Select
options={muteOptions}
onChange={onMuteChange}
value={-1}
options={[
{
text: i18n(
'ConversationNotificationsSettings__mentions__select__always-notify'
),
value: 'no',
},
{
text: i18n(
'ConversationNotificationsSettings__mentions__select__dont-notify-for-mentions-if-muted'
),
value: 'yes',
},
]}
onChange={onChangeDontNotifyForMentionsIfMuted}
value={dontNotifyForMentionsIfMuted ? 'yes' : 'no'}
/>
}
/>
{conversationType === 'group' && (
<PanelRow
icon={
<ConversationDetailsIcon
ariaLabel={i18n(
'ConversationNotificationsSettings__mentions__label'
)}
icon={IconType.mention}
/>
}
label={i18n('ConversationNotificationsSettings__mentions__label')}
info={i18n('ConversationNotificationsSettings__mentions__info')}
right={
<Select
options={[
{
text: i18n(
'ConversationNotificationsSettings__mentions__select__always-notify'
),
value: 'no',
},
{
text: i18n(
'ConversationNotificationsSettings__mentions__select__dont-notify-for-mentions-if-muted'
),
value: 'yes',
},
]}
onChange={onChangeDontNotifyForMentionsIfMuted}
value={dontNotifyForMentionsIfMuted ? 'yes' : 'no'}
/>
}
/>
)}
</PanelSection>
</div>
);
};
)}
</PanelSection>
</div>
);
};

View file

@ -6,5 +6,6 @@ import React from 'react';
type PropsType = Record<string, never>;
export const SearchResultsLoadingFakeHeader: FunctionComponent<PropsType> =
() => <div className="module-SearchResultsLoadingFakeHeader" />;
export const SearchResultsLoadingFakeHeader: FunctionComponent<
PropsType
> = () => <div className="module-SearchResultsLoadingFakeHeader" />;