mirror of
https://github.com/signalapp/Signal-Desktop.git
synced 2026-04-24 18:38:15 +01:00
Make valid-i18n-keys rule strict and fix most exceptions
This commit is contained in:
@@ -60,16 +60,8 @@ export function GroupV1Migration(props: PropsType): React.ReactElement {
|
||||
i18n('GroupV1--Migration--invited--you')
|
||||
) : (
|
||||
<>
|
||||
{renderUsers(
|
||||
invitedMembers,
|
||||
i18n,
|
||||
'GroupV1--Migration--invited'
|
||||
)}
|
||||
{renderUsers(
|
||||
droppedMembers,
|
||||
i18n,
|
||||
'GroupV1--Migration--removed'
|
||||
)}
|
||||
{renderUsers(invitedMembers, i18n, 'invited')}
|
||||
{renderUsers(droppedMembers, i18n, 'removed')}
|
||||
</>
|
||||
)}
|
||||
</p>
|
||||
@@ -106,31 +98,52 @@ export function GroupV1Migration(props: PropsType): React.ReactElement {
|
||||
function renderUsers(
|
||||
members: Array<ConversationType>,
|
||||
i18n: LocalizerType,
|
||||
keyPrefix: string
|
||||
kind: 'invited' | 'removed'
|
||||
): React.ReactElement | null {
|
||||
if (!members || members.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (members.length === 1) {
|
||||
const contact = <ContactName title={members[0].title} />;
|
||||
return (
|
||||
<p>
|
||||
<Intl
|
||||
i18n={i18n}
|
||||
id={`${keyPrefix}--one`}
|
||||
components={{
|
||||
contact: <ContactName title={members[0].title} />,
|
||||
}}
|
||||
/>
|
||||
{kind === 'invited' && (
|
||||
<Intl
|
||||
i18n={i18n}
|
||||
id="GroupV1--Migration--invited--one"
|
||||
components={{ contact }}
|
||||
/>
|
||||
)}
|
||||
{kind === 'removed' && (
|
||||
<Intl
|
||||
i18n={i18n}
|
||||
id="GroupV1--Migration--removed--one"
|
||||
components={{ contact }}
|
||||
/>
|
||||
)}
|
||||
</p>
|
||||
);
|
||||
}
|
||||
|
||||
const count = members.length.toString();
|
||||
|
||||
return (
|
||||
<p>
|
||||
{i18n(`${keyPrefix}--many`, {
|
||||
count: members.length.toString(),
|
||||
})}
|
||||
{kind === 'invited' && members.length > 1 && (
|
||||
<Intl
|
||||
i18n={i18n}
|
||||
id="GroupV1--Migration--invited--many"
|
||||
components={{ count }}
|
||||
/>
|
||||
)}
|
||||
{kind === 'removed' && members.length > 1 && (
|
||||
<Intl
|
||||
i18n={i18n}
|
||||
id="GroupV1--Migration--removed--many"
|
||||
components={{ count }}
|
||||
/>
|
||||
)}
|
||||
</p>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -40,6 +40,26 @@ export function MandatoryProfileSharingActions({
|
||||
}: Props): JSX.Element {
|
||||
const [mrState, setMrState] = React.useState(MessageRequestState.default);
|
||||
|
||||
const firstNameContact = (
|
||||
<strong
|
||||
key="name"
|
||||
className="module-message-request-actions__message__name"
|
||||
>
|
||||
<ContactName firstName={firstName} title={title} preferFirstName />
|
||||
</strong>
|
||||
);
|
||||
|
||||
const learnMore = (
|
||||
<a
|
||||
href="https://support.signal.org/hc/articles/360007459591"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="module-message-request-actions__message__learn-more"
|
||||
>
|
||||
{i18n('MessageRequests--learn-more')}
|
||||
</a>
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
{mrState !== MessageRequestState.default ? (
|
||||
@@ -62,34 +82,19 @@ export function MandatoryProfileSharingActions({
|
||||
) : null}
|
||||
<div className="module-message-request-actions">
|
||||
<p className="module-message-request-actions__message">
|
||||
<Intl
|
||||
i18n={i18n}
|
||||
id={`MessageRequests--profile-sharing--${conversationType}`}
|
||||
components={{
|
||||
firstName: (
|
||||
<strong
|
||||
key="name"
|
||||
className="module-message-request-actions__message__name"
|
||||
>
|
||||
<ContactName
|
||||
firstName={firstName}
|
||||
title={title}
|
||||
preferFirstName
|
||||
/>
|
||||
</strong>
|
||||
),
|
||||
learnMore: (
|
||||
<a
|
||||
href="https://support.signal.org/hc/articles/360007459591"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="module-message-request-actions__message__learn-more"
|
||||
>
|
||||
{i18n('MessageRequests--learn-more')}
|
||||
</a>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
{conversationType === 'direct' ? (
|
||||
<Intl
|
||||
i18n={i18n}
|
||||
id="MessageRequests--profile-sharing--direct"
|
||||
components={{ firstName: firstNameContact, learnMore }}
|
||||
/>
|
||||
) : (
|
||||
<Intl
|
||||
i18n={i18n}
|
||||
id="MessageRequests--profile-sharing--group"
|
||||
components={{ firstName: firstNameContact, learnMore }}
|
||||
/>
|
||||
)}
|
||||
</p>
|
||||
<div className="module-message-request-actions__buttons">
|
||||
<Button
|
||||
|
||||
@@ -1251,7 +1251,10 @@ export class Message extends React.PureComponent<Props, State> {
|
||||
}
|
||||
|
||||
if (giftBadge.state === GiftBadgeStates.Unopened) {
|
||||
const description = i18n(`icu:message--donation--unopened--${direction}`);
|
||||
const description =
|
||||
direction === 'incoming'
|
||||
? i18n('icu:message--donation--unopened--incoming')
|
||||
: i18n('icu:message--donation--unopened--outgoing');
|
||||
const isRTL = getDirection(description) === 'rtl';
|
||||
const { metadataWidth } = this.state;
|
||||
|
||||
@@ -1931,26 +1934,23 @@ export class Message extends React.PureComponent<Props, State> {
|
||||
isTapToViewError,
|
||||
} = this.props;
|
||||
|
||||
const incomingString = isTapToViewExpired
|
||||
? i18n('Message--tap-to-view-expired')
|
||||
: i18n(
|
||||
`Message--tap-to-view--incoming${
|
||||
isVideo(attachments) ? '-video' : ''
|
||||
}`
|
||||
);
|
||||
const outgoingString = i18n('Message--tap-to-view--outgoing');
|
||||
const isDownloadPending = this.isAttachmentPending();
|
||||
|
||||
if (isDownloadPending) {
|
||||
return;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-nested-ternary
|
||||
return isTapToViewError
|
||||
? i18n('incomingError')
|
||||
: direction === 'outgoing'
|
||||
? outgoingString
|
||||
: incomingString;
|
||||
if (isTapToViewError) {
|
||||
return i18n('incomingError');
|
||||
}
|
||||
if (direction === 'outgoing') {
|
||||
return i18n('Message--tap-to-view--outgoing');
|
||||
}
|
||||
if (isTapToViewExpired) {
|
||||
return i18n('Message--tap-to-view-expired');
|
||||
}
|
||||
if (isVideo(attachments)) {
|
||||
return i18n('Message--tap-to-view--incoming-video');
|
||||
}
|
||||
return i18n('Message--tap-to-view--incoming');
|
||||
}
|
||||
|
||||
public renderTapToView(): JSX.Element {
|
||||
|
||||
@@ -26,6 +26,7 @@ import * as log from '../../logging/log';
|
||||
import { formatDateTimeLong } from '../../util/timestamp';
|
||||
import { DurationInSeconds } from '../../util/durations';
|
||||
import { format as formatRelativeTime } from '../../util/expirationTimer';
|
||||
import { missingCaseError } from '../../util';
|
||||
|
||||
export type Contact = Pick<
|
||||
ConversationType,
|
||||
@@ -200,24 +201,49 @@ export class MessageDetail extends React.Component<Props> {
|
||||
);
|
||||
}
|
||||
|
||||
private renderContactGroupHeaderText(
|
||||
sendStatus: undefined | SendStatus
|
||||
): string {
|
||||
const { i18n } = this.props;
|
||||
|
||||
if (sendStatus === undefined) {
|
||||
return i18n('from');
|
||||
}
|
||||
|
||||
switch (sendStatus) {
|
||||
case SendStatus.Failed:
|
||||
return i18n('MessageDetailsHeader--Failed');
|
||||
case SendStatus.Pending:
|
||||
return i18n('MessageDetailsHeader--Pending');
|
||||
case SendStatus.Sent:
|
||||
return i18n('MessageDetailsHeader--Sent');
|
||||
case SendStatus.Delivered:
|
||||
return i18n('MessageDetailsHeader--Delivered');
|
||||
case SendStatus.Read:
|
||||
return i18n('MessageDetailsHeader--Read');
|
||||
case SendStatus.Viewed:
|
||||
return i18n('MessageDetailsHeader--Viewed');
|
||||
default:
|
||||
throw missingCaseError(sendStatus);
|
||||
}
|
||||
}
|
||||
|
||||
private renderContactGroup(
|
||||
sendStatus: undefined | SendStatus,
|
||||
contacts: undefined | ReadonlyArray<Contact>
|
||||
): ReactNode {
|
||||
const { i18n } = this.props;
|
||||
if (!contacts || !contacts.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const i18nKey =
|
||||
sendStatus === undefined ? 'from' : `MessageDetailsHeader--${sendStatus}`;
|
||||
|
||||
const sortedContacts = [...contacts].sort((a, b) =>
|
||||
contactSortCollator.compare(a.title, b.title)
|
||||
);
|
||||
|
||||
const headerText = this.renderContactGroupHeaderText(sendStatus);
|
||||
|
||||
return (
|
||||
<div key={i18nKey} className="module-message-detail__contact-group">
|
||||
<div key={headerText} className="module-message-detail__contact-group">
|
||||
<div
|
||||
className={classNames(
|
||||
'module-message-detail__contact-group__header',
|
||||
@@ -225,8 +251,7 @@ export class MessageDetail extends React.Component<Props> {
|
||||
`module-message-detail__contact-group__header--${sendStatus}`
|
||||
)}
|
||||
>
|
||||
{/* eslint-disable-next-line local-rules/valid-i18n-keys */}
|
||||
{i18n(i18nKey)}
|
||||
{headerText}
|
||||
</div>
|
||||
{sortedContacts.map(contact => this.renderContact(contact))}
|
||||
</div>
|
||||
|
||||
@@ -35,6 +35,15 @@ export function MessageRequestActions({
|
||||
}: Props): JSX.Element {
|
||||
const [mrState, setMrState] = React.useState(MessageRequestState.default);
|
||||
|
||||
const name = (
|
||||
<strong
|
||||
key="name"
|
||||
className="module-message-request-actions__message__name"
|
||||
>
|
||||
<ContactName firstName={firstName} title={title} preferFirstName />
|
||||
</strong>
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
{mrState !== MessageRequestState.default ? (
|
||||
@@ -53,26 +62,34 @@ export function MessageRequestActions({
|
||||
) : null}
|
||||
<div className="module-message-request-actions">
|
||||
<p className="module-message-request-actions__message">
|
||||
<Intl
|
||||
i18n={i18n}
|
||||
id={`MessageRequests--message-${conversationType}${
|
||||
isBlocked ? '-blocked' : ''
|
||||
}`}
|
||||
components={{
|
||||
name: (
|
||||
<strong
|
||||
key="name"
|
||||
className="module-message-request-actions__message__name"
|
||||
>
|
||||
<ContactName
|
||||
firstName={firstName}
|
||||
title={title}
|
||||
preferFirstName
|
||||
/>
|
||||
</strong>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
{conversationType === 'direct' && isBlocked && (
|
||||
<Intl
|
||||
i18n={i18n}
|
||||
id="MessageRequests--message-direct-blocked"
|
||||
components={{ name }}
|
||||
/>
|
||||
)}
|
||||
{conversationType === 'direct' && !isBlocked && (
|
||||
<Intl
|
||||
i18n={i18n}
|
||||
id="MessageRequests--message-direct"
|
||||
components={{ name }}
|
||||
/>
|
||||
)}
|
||||
{conversationType === 'group' && isBlocked && (
|
||||
<Intl
|
||||
i18n={i18n}
|
||||
id="MessageRequests--message-group-blocked"
|
||||
components={{ name }}
|
||||
/>
|
||||
)}
|
||||
{conversationType === 'group' && !isBlocked && (
|
||||
<Intl
|
||||
i18n={i18n}
|
||||
id="MessageRequests--message-group"
|
||||
components={{ name }}
|
||||
/>
|
||||
)}
|
||||
</p>
|
||||
<div className="module-message-request-actions__buttons">
|
||||
<Button
|
||||
|
||||
@@ -132,13 +132,23 @@ export function MessageRequestActionsConfirmation({
|
||||
onChangeState(MessageRequestState.default);
|
||||
}}
|
||||
title={
|
||||
<Intl
|
||||
i18n={i18n}
|
||||
id={`MessageRequests--delete-${conversationType}-confirm-title`}
|
||||
components={{
|
||||
title: <ContactName key="name" title={title} />,
|
||||
}}
|
||||
/>
|
||||
conversationType === 'direct' ? (
|
||||
<Intl
|
||||
i18n={i18n}
|
||||
id="MessageRequests--delete-direct-confirm-title"
|
||||
components={{
|
||||
title: <ContactName key="name" title={title} />,
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<Intl
|
||||
i18n={i18n}
|
||||
id="MessageRequests--delete-group-confirm-title"
|
||||
components={{
|
||||
title: <ContactName key="name" title={title} />,
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
actions={[
|
||||
{
|
||||
|
||||
@@ -35,32 +35,30 @@ export function SafetyNumberNotification({
|
||||
i18n,
|
||||
toggleSafetyNumberModal,
|
||||
}: Props): JSX.Element {
|
||||
const changeKey = isGroup
|
||||
? 'safetyNumberChangedGroup'
|
||||
: 'safetyNumberChanged';
|
||||
|
||||
const name = (
|
||||
<span
|
||||
key="external-1"
|
||||
className="module-safety-number-notification__contact"
|
||||
>
|
||||
<ContactName
|
||||
title={contact.title}
|
||||
module="module-safety-number-notification__contact"
|
||||
/>
|
||||
</span>
|
||||
);
|
||||
return (
|
||||
<SystemMessage
|
||||
icon="safety-number"
|
||||
contents={
|
||||
// eslint-disable-next-line local-rules/valid-i18n-keys
|
||||
<Intl
|
||||
id={changeKey}
|
||||
components={{
|
||||
name: (
|
||||
<span
|
||||
key="external-1"
|
||||
className="module-safety-number-notification__contact"
|
||||
>
|
||||
<ContactName
|
||||
title={contact.title}
|
||||
module="module-safety-number-notification__contact"
|
||||
/>
|
||||
</span>
|
||||
),
|
||||
}}
|
||||
i18n={i18n}
|
||||
/>
|
||||
isGroup ? (
|
||||
<Intl
|
||||
id="safetyNumberChangedGroup"
|
||||
components={{ name }}
|
||||
i18n={i18n}
|
||||
/>
|
||||
) : (
|
||||
<Intl id="safetyNumberChanged" components={{ name }} i18n={i18n} />
|
||||
)
|
||||
}
|
||||
button={
|
||||
<Button
|
||||
|
||||
@@ -41,51 +41,46 @@ export type Props = PropsData & PropsHousekeeping;
|
||||
export function TimerNotification(props: Props): JSX.Element {
|
||||
const { disabled, i18n, title, type } = props;
|
||||
|
||||
let changeKey: string;
|
||||
let timespan: string;
|
||||
if (props.disabled) {
|
||||
changeKey = 'disabledDisappearingMessages';
|
||||
timespan = ''; // Set to the empty string to satisfy types
|
||||
} else {
|
||||
changeKey = 'theyChangedTheTimer';
|
||||
timespan = expirationTimer.format(i18n, props.expireTimer);
|
||||
}
|
||||
|
||||
const name = <ContactName key="external-1" title={title} />;
|
||||
|
||||
let message: ReactNode;
|
||||
switch (type) {
|
||||
case 'fromOther':
|
||||
message = (
|
||||
// eslint-disable-next-line local-rules/valid-i18n-keys
|
||||
message = props.disabled ? (
|
||||
<Intl
|
||||
i18n={i18n}
|
||||
id={changeKey}
|
||||
components={{
|
||||
name: <ContactName key="external-1" title={title} />,
|
||||
time: timespan,
|
||||
}}
|
||||
id="disabledDisappearingMessages"
|
||||
components={{ name }}
|
||||
/>
|
||||
) : (
|
||||
<Intl
|
||||
i18n={i18n}
|
||||
id="theyChangedTheTimer"
|
||||
components={{ name, time: timespan }}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
case 'fromMe':
|
||||
message = disabled
|
||||
? i18n('youDisabledDisappearingMessages')
|
||||
: i18n('youChangedTheTimer', {
|
||||
time: timespan,
|
||||
});
|
||||
: i18n('youChangedTheTimer', { time: timespan });
|
||||
break;
|
||||
case 'fromSync':
|
||||
message = disabled
|
||||
? i18n('disappearingMessagesDisabled')
|
||||
: i18n('timerSetOnSync', {
|
||||
time: timespan,
|
||||
});
|
||||
: i18n('timerSetOnSync', { time: timespan });
|
||||
break;
|
||||
case 'fromMember':
|
||||
message = disabled
|
||||
? i18n('disappearingMessagesDisabledByMember')
|
||||
: i18n('timerSetByMember', {
|
||||
time: timespan,
|
||||
});
|
||||
: i18n('timerSetByMember', { time: timespan });
|
||||
break;
|
||||
default:
|
||||
log.warn('TimerNotification: unsupported type provided:', type);
|
||||
|
||||
@@ -30,42 +30,64 @@ type PropsHousekeeping = {
|
||||
|
||||
export type Props = PropsData & PropsHousekeeping;
|
||||
|
||||
function UnsupportedMessageContents({ canProcessNow, contact, i18n }: Props) {
|
||||
const { isMe } = contact;
|
||||
const contactName = (
|
||||
<span key="external-1" className="module-unsupported-message__contact">
|
||||
<ContactName
|
||||
title={contact.title}
|
||||
module="module-unsupported-message__contact"
|
||||
/>
|
||||
</span>
|
||||
);
|
||||
if (isMe) {
|
||||
if (canProcessNow) {
|
||||
return (
|
||||
<Intl
|
||||
id="Message--unsupported-message-ask-to-resend"
|
||||
components={{ contact: contactName }}
|
||||
i18n={i18n}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Intl
|
||||
id="Message--from-me-unsupported-message"
|
||||
components={{ contact: contactName }}
|
||||
i18n={i18n}
|
||||
/>
|
||||
);
|
||||
}
|
||||
if (canProcessNow) {
|
||||
return (
|
||||
<Intl
|
||||
id="Message--from-me-unsupported-message-ask-to-resend"
|
||||
components={{ contact: contactName }}
|
||||
i18n={i18n}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Intl
|
||||
id="Message--from-me-unsupported-message"
|
||||
components={{ contact: contactName }}
|
||||
i18n={i18n}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export function UnsupportedMessage({
|
||||
canProcessNow,
|
||||
contact,
|
||||
i18n,
|
||||
}: Props): JSX.Element {
|
||||
const { isMe } = contact;
|
||||
|
||||
const otherStringId = canProcessNow
|
||||
? 'Message--unsupported-message-ask-to-resend'
|
||||
: 'Message--unsupported-message';
|
||||
const meStringId = canProcessNow
|
||||
? 'Message--from-me-unsupported-message-ask-to-resend'
|
||||
: 'Message--from-me-unsupported-message';
|
||||
const stringId = isMe ? meStringId : otherStringId;
|
||||
const icon = canProcessNow ? 'unsupported--can-process' : 'unsupported';
|
||||
|
||||
return (
|
||||
<SystemMessage
|
||||
icon={icon}
|
||||
icon={canProcessNow ? 'unsupported--can-process' : 'unsupported'}
|
||||
contents={
|
||||
// eslint-disable-next-line local-rules/valid-i18n-keys
|
||||
<Intl
|
||||
id={stringId}
|
||||
components={{
|
||||
contact: (
|
||||
<span
|
||||
key="external-1"
|
||||
className="module-unsupported-message__contact"
|
||||
>
|
||||
<ContactName
|
||||
title={contact.title}
|
||||
module="module-unsupported-message__contact"
|
||||
/>
|
||||
</span>
|
||||
),
|
||||
}}
|
||||
<UnsupportedMessageContents
|
||||
canProcessNow={canProcessNow}
|
||||
contact={contact}
|
||||
i18n={i18n}
|
||||
/>
|
||||
}
|
||||
|
||||
@@ -25,45 +25,43 @@ type PropsHousekeeping = {
|
||||
export type Props = PropsData & PropsHousekeeping;
|
||||
|
||||
export class VerificationNotification extends React.Component<Props> {
|
||||
public getStringId(): string {
|
||||
const { isLocal, type } = this.props;
|
||||
public renderContents(): JSX.Element {
|
||||
const { contact, isLocal, type, i18n } = this.props;
|
||||
|
||||
const name = (
|
||||
<ContactName
|
||||
key="external-1"
|
||||
title={contact.title}
|
||||
module="module-verification-notification__contact"
|
||||
/>
|
||||
);
|
||||
|
||||
switch (type) {
|
||||
case 'markVerified':
|
||||
return isLocal
|
||||
? 'youMarkedAsVerified'
|
||||
: 'youMarkedAsVerifiedOtherDevice';
|
||||
return isLocal ? (
|
||||
<Intl id="youMarkedAsVerified" components={{ name }} i18n={i18n} />
|
||||
) : (
|
||||
<Intl
|
||||
id="youMarkedAsVerifiedOtherDevice"
|
||||
components={{ name }}
|
||||
i18n={i18n}
|
||||
/>
|
||||
);
|
||||
case 'markNotVerified':
|
||||
return isLocal
|
||||
? 'youMarkedAsNotVerified'
|
||||
: 'youMarkedAsNotVerifiedOtherDevice';
|
||||
return isLocal ? (
|
||||
<Intl id="youMarkedAsNotVerified" components={{ name }} i18n={i18n} />
|
||||
) : (
|
||||
<Intl
|
||||
id="youMarkedAsNotVerifiedOtherDevice"
|
||||
components={{ name }}
|
||||
i18n={i18n}
|
||||
/>
|
||||
);
|
||||
default:
|
||||
throw missingCaseError(type);
|
||||
}
|
||||
}
|
||||
|
||||
public renderContents(): JSX.Element {
|
||||
const { contact, i18n } = this.props;
|
||||
const id = this.getStringId();
|
||||
|
||||
return (
|
||||
// eslint-disable-next-line local-rules/valid-i18n-keys
|
||||
<Intl
|
||||
id={id}
|
||||
components={{
|
||||
name: (
|
||||
<ContactName
|
||||
key="external-1"
|
||||
title={contact.title}
|
||||
module="module-verification-notification__contact"
|
||||
/>
|
||||
),
|
||||
}}
|
||||
i18n={i18n}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
public override render(): JSX.Element {
|
||||
const { type } = this.props;
|
||||
const icon = type === 'markVerified' ? 'verified' : 'verified-not';
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright 2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
/* eslint-disable local-rules/valid-i18n-keys */
|
||||
|
||||
import React, {
|
||||
useEffect,
|
||||
useMemo,
|
||||
@@ -212,7 +210,8 @@ export function ChooseGroupMembersModal({
|
||||
if (virtualIndex === 0) {
|
||||
return {
|
||||
type: RowType.Header,
|
||||
i18nKey: 'contactsHeader',
|
||||
// eslint-disable-next-line @typescript-eslint/no-shadow
|
||||
getHeaderText: i18n => i18n('contactsHeader'),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -250,7 +249,8 @@ export function ChooseGroupMembersModal({
|
||||
if (virtualIndex === 0) {
|
||||
return {
|
||||
type: RowType.Header,
|
||||
i18nKey: 'findByPhoneNumberHeader',
|
||||
// eslint-disable-next-line @typescript-eslint/no-shadow
|
||||
getHeaderText: i18n => i18n('findByPhoneNumberHeader'),
|
||||
};
|
||||
}
|
||||
if (virtualIndex === 1) {
|
||||
@@ -268,7 +268,8 @@ export function ChooseGroupMembersModal({
|
||||
if (virtualIndex === 0) {
|
||||
return {
|
||||
type: RowType.Header,
|
||||
i18nKey: 'findByUsernameHeader',
|
||||
// eslint-disable-next-line @typescript-eslint/no-shadow
|
||||
getHeaderText: i18n => i18n('findByUsernameHeader'),
|
||||
};
|
||||
}
|
||||
if (virtualIndex === 1) {
|
||||
@@ -307,16 +308,18 @@ export function ChooseGroupMembersModal({
|
||||
|
||||
let item;
|
||||
switch (row?.type) {
|
||||
case RowType.Header:
|
||||
case RowType.Header: {
|
||||
const headerText = row.getHeaderText(i18n);
|
||||
item = (
|
||||
<div
|
||||
className="module-conversation-list__item--header"
|
||||
aria-label={i18n(row.i18nKey)}
|
||||
aria-label={headerText}
|
||||
>
|
||||
{i18n(row.i18nKey)}
|
||||
{headerText}
|
||||
</div>
|
||||
);
|
||||
break;
|
||||
}
|
||||
case RowType.ContactCheckbox:
|
||||
item = (
|
||||
<ContactCheckbox
|
||||
|
||||
@@ -618,8 +618,7 @@ function ConversationDetailsCallButton({
|
||||
onClick={onClick}
|
||||
variant={ButtonVariant.Details}
|
||||
>
|
||||
{/* eslint-disable-next-line local-rules/valid-i18n-keys */}
|
||||
{i18n(type)}
|
||||
{type === 'audio' ? i18n('audio') : i18n('video')}
|
||||
</Button>
|
||||
);
|
||||
|
||||
|
||||
@@ -71,11 +71,25 @@ function MediaSection({
|
||||
const first = section.mediaItems[0];
|
||||
const { message } = first;
|
||||
const date = moment(getMessageTimestamp(message));
|
||||
const header =
|
||||
section.type === 'yearMonth'
|
||||
? date.format(MONTH_FORMAT)
|
||||
: // eslint-disable-next-line local-rules/valid-i18n-keys
|
||||
i18n(section.type);
|
||||
|
||||
function getHeader(): string {
|
||||
switch (section.type) {
|
||||
case 'yearMonth':
|
||||
return date.format(MONTH_FORMAT);
|
||||
case 'today':
|
||||
return i18n('today');
|
||||
case 'yesterday':
|
||||
return i18n('yesterday');
|
||||
case 'thisWeek':
|
||||
return i18n('thisWeek');
|
||||
case 'thisMonth':
|
||||
return i18n('thisMonth');
|
||||
default:
|
||||
throw missingCaseError(section);
|
||||
}
|
||||
}
|
||||
|
||||
const header = getHeader();
|
||||
|
||||
return (
|
||||
<AttachmentSection
|
||||
|
||||
Reference in New Issue
Block a user