remove i18n from props everywhere where possible
This commit is contained in:
parent
4b9d2c0692
commit
dd9341a196
|
@ -53,7 +53,6 @@ const NoImage = (props: {
|
|||
<ClosedGroupAvatar
|
||||
size={size}
|
||||
memberAvatars={memberAvatars}
|
||||
i18n={window.i18n}
|
||||
onAvatarClick={props.onAvatarClick}
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
import React from 'react';
|
||||
import { Avatar, AvatarSize } from '../Avatar';
|
||||
import { LocalizerType } from '../../types/Util';
|
||||
import { ConversationAvatar } from '../session/usingClosedConversationDetails';
|
||||
|
||||
interface Props {
|
||||
size: number;
|
||||
memberAvatars: Array<ConversationAvatar>; // this is added by usingClosedConversationDetails
|
||||
i18n: LocalizerType;
|
||||
onAvatarClick?: () => void;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,15 +4,12 @@ import classNames from 'classnames';
|
|||
import { Avatar, AvatarSize } from './Avatar';
|
||||
import { Emojify } from './conversation/Emojify';
|
||||
|
||||
import { LocalizerType } from '../types/Util';
|
||||
|
||||
interface Props {
|
||||
phoneNumber: string;
|
||||
isMe?: boolean;
|
||||
name?: string;
|
||||
profileName?: string;
|
||||
avatarPath?: string;
|
||||
i18n: LocalizerType;
|
||||
onClick?: () => void;
|
||||
}
|
||||
|
||||
|
@ -28,16 +25,16 @@ export class ContactListItem extends React.Component<Props> {
|
|||
}
|
||||
|
||||
public render() {
|
||||
const { i18n, name, onClick, isMe, phoneNumber, profileName } = this.props;
|
||||
const { name, onClick, isMe, phoneNumber, profileName } = this.props;
|
||||
|
||||
const title = name ? name : phoneNumber;
|
||||
const displayName = isMe ? i18n('me') : title;
|
||||
const displayName = isMe ? window.i18n('me') : title;
|
||||
|
||||
const profileElement =
|
||||
!isMe && profileName && !name ? (
|
||||
<span className="module-contact-list-item__text__profile-name">
|
||||
~
|
||||
<Emojify text={profileName} i18n={i18n} key={`emojify-list-item-${phoneNumber}`} />
|
||||
<Emojify text={profileName} key={`emojify-list-item-${phoneNumber}`} />
|
||||
</span>
|
||||
) : null;
|
||||
|
||||
|
@ -55,7 +52,7 @@ export class ContactListItem extends React.Component<Props> {
|
|||
{this.renderAvatar()}
|
||||
<div className="module-contact-list-item__text">
|
||||
<div className="module-contact-list-item__text__name">
|
||||
<Emojify text={displayName} i18n={i18n} /> {profileElement}
|
||||
<Emojify text={displayName} /> {profileElement}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -9,8 +9,6 @@ import { Timestamp } from './conversation/Timestamp';
|
|||
import { ContactName } from './conversation/ContactName';
|
||||
import { TypingAnimation } from './conversation/TypingAnimation';
|
||||
|
||||
import { LocalizerType } from '../types/Util';
|
||||
|
||||
import {
|
||||
ConversationAvatar,
|
||||
usingClosedConversationDetails,
|
||||
|
@ -31,7 +29,6 @@ export interface ConversationListItemProps extends ConversationType {
|
|||
}
|
||||
|
||||
type PropsHousekeeping = {
|
||||
i18n: LocalizerType;
|
||||
style?: Object;
|
||||
onClick?: (id: string) => void;
|
||||
onDeleteMessages?: () => void;
|
||||
|
@ -120,7 +117,7 @@ class ConversationListItem extends React.PureComponent<Props> {
|
|||
}
|
||||
|
||||
public renderMessage() {
|
||||
const { lastMessage, isTyping, unreadCount, i18n } = this.props;
|
||||
const { lastMessage, isTyping, unreadCount } = this.props;
|
||||
|
||||
if (!lastMessage && !isTyping) {
|
||||
return null;
|
||||
|
@ -140,15 +137,9 @@ class ConversationListItem extends React.PureComponent<Props> {
|
|||
)}
|
||||
>
|
||||
{isTyping ? (
|
||||
<TypingAnimation i18n={i18n} />
|
||||
<TypingAnimation />
|
||||
) : (
|
||||
<MessageBody
|
||||
isGroup={true}
|
||||
text={text}
|
||||
disableJumbomoji={true}
|
||||
disableLinks={true}
|
||||
i18n={i18n}
|
||||
/>
|
||||
<MessageBody isGroup={true} text={text} disableJumbomoji={true} disableLinks={true} />
|
||||
)}
|
||||
</div>
|
||||
{lastMessage && lastMessage.status ? (
|
||||
|
@ -221,12 +212,12 @@ class ConversationListItem extends React.PureComponent<Props> {
|
|||
}
|
||||
|
||||
private renderUser() {
|
||||
const { name, phoneNumber, profileName, isMe, i18n } = this.props;
|
||||
const { name, phoneNumber, profileName, isMe } = this.props;
|
||||
|
||||
const shortenedPubkey = PubKey.shorten(phoneNumber);
|
||||
|
||||
const displayedPubkey = profileName ? shortenedPubkey : phoneNumber;
|
||||
const displayName = isMe ? i18n('noteToSelf') : profileName;
|
||||
const displayName = isMe ? window.i18n('noteToSelf') : profileName;
|
||||
|
||||
let shouldShowPubkey = false;
|
||||
if ((!name || name.length === 0) && (!displayName || displayName.length === 0)) {
|
||||
|
@ -240,7 +231,6 @@ class ConversationListItem extends React.PureComponent<Props> {
|
|||
name={name}
|
||||
profileName={displayName}
|
||||
module="module-conversation__user"
|
||||
i18n={window.i18n}
|
||||
boldProfileName={true}
|
||||
shouldShowPubkey={shouldShowPubkey}
|
||||
/>
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
import React from 'react';
|
||||
|
||||
import { LocalizerType, RenderTextCallbackType } from '../types/Util';
|
||||
import { RenderTextCallbackType } from '../types/Util';
|
||||
|
||||
type FullJSX = Array<JSX.Element | string> | JSX.Element | string;
|
||||
|
||||
interface Props {
|
||||
/** The translation string id */
|
||||
id: string;
|
||||
i18n: LocalizerType;
|
||||
components?: Array<FullJSX>;
|
||||
renderText?: RenderTextCallbackType;
|
||||
}
|
||||
|
@ -31,9 +30,9 @@ export class Intl extends React.Component<Props> {
|
|||
}
|
||||
|
||||
public render() {
|
||||
const { id, i18n, renderText } = this.props;
|
||||
const { id, renderText } = this.props;
|
||||
|
||||
const text = i18n(id);
|
||||
const text = window.i18n(id);
|
||||
const results: Array<any> = [];
|
||||
const FIND_REPLACEMENTS = /\$[^$]+\$/g;
|
||||
|
||||
|
|
|
@ -6,11 +6,10 @@ import { AddNewLines } from './conversation/AddNewLines';
|
|||
|
||||
import { SizeClassType } from '../util/emoji';
|
||||
|
||||
import { LocalizerType, RenderTextCallbackType } from '../types/Util';
|
||||
import { RenderTextCallbackType } from '../types/Util';
|
||||
|
||||
interface Props {
|
||||
text: string;
|
||||
i18n: LocalizerType;
|
||||
}
|
||||
|
||||
const renderNewLines: RenderTextCallbackType = ({ text, key }) => (
|
||||
|
@ -18,30 +17,20 @@ const renderNewLines: RenderTextCallbackType = ({ text, key }) => (
|
|||
);
|
||||
|
||||
const renderEmoji = ({
|
||||
i18n,
|
||||
text,
|
||||
key,
|
||||
sizeClass,
|
||||
renderNonEmoji,
|
||||
}: {
|
||||
i18n: LocalizerType;
|
||||
text: string;
|
||||
key: number;
|
||||
sizeClass?: SizeClassType;
|
||||
renderNonEmoji: RenderTextCallbackType;
|
||||
}) => (
|
||||
<Emojify
|
||||
i18n={i18n}
|
||||
key={key}
|
||||
text={text}
|
||||
sizeClass={sizeClass}
|
||||
renderNonEmoji={renderNonEmoji}
|
||||
/>
|
||||
);
|
||||
}) => <Emojify key={key} text={text} sizeClass={sizeClass} renderNonEmoji={renderNonEmoji} />;
|
||||
|
||||
export class MessageBodyHighlight extends React.Component<Props> {
|
||||
public render() {
|
||||
const { text, i18n } = this.props;
|
||||
const { text } = this.props;
|
||||
const results: Array<any> = [];
|
||||
const FIND_BEGIN_END = /<<left>>(.+?)<<right>>/g;
|
||||
|
||||
|
@ -50,7 +39,7 @@ export class MessageBodyHighlight extends React.Component<Props> {
|
|||
let count = 1;
|
||||
|
||||
if (!match) {
|
||||
return <MessageBody disableJumbomoji={true} disableLinks={true} text={text} i18n={i18n} />;
|
||||
return <MessageBody disableJumbomoji={true} disableLinks={true} text={text} />;
|
||||
}
|
||||
|
||||
const sizeClass = '';
|
||||
|
@ -63,7 +52,6 @@ export class MessageBodyHighlight extends React.Component<Props> {
|
|||
text: beforeText,
|
||||
sizeClass,
|
||||
key: count++,
|
||||
i18n,
|
||||
renderNonEmoji: renderNewLines,
|
||||
})
|
||||
);
|
||||
|
@ -76,7 +64,6 @@ export class MessageBodyHighlight extends React.Component<Props> {
|
|||
text: toHighlight,
|
||||
sizeClass,
|
||||
key: count++,
|
||||
i18n,
|
||||
renderNonEmoji: renderNewLines,
|
||||
})}
|
||||
</span>
|
||||
|
@ -93,7 +80,6 @@ export class MessageBodyHighlight extends React.Component<Props> {
|
|||
text: text.slice(last),
|
||||
sizeClass,
|
||||
key: count++,
|
||||
i18n,
|
||||
renderNonEmoji: renderNewLines,
|
||||
})
|
||||
);
|
||||
|
|
|
@ -6,7 +6,6 @@ import { MessageBodyHighlight } from './MessageBodyHighlight';
|
|||
import { Timestamp } from './conversation/Timestamp';
|
||||
import { ContactName } from './conversation/ContactName';
|
||||
|
||||
import { LocalizerType } from '../types/Util';
|
||||
import { DefaultTheme, withTheme } from 'styled-components';
|
||||
|
||||
export type MessageSearchResultProps = {
|
||||
|
@ -37,7 +36,6 @@ export type MessageSearchResultProps = {
|
|||
type PropsHousekeeping = {
|
||||
isSelected?: boolean;
|
||||
theme: DefaultTheme;
|
||||
i18n: LocalizerType;
|
||||
onClick: (conversationId: string, messageId?: string) => void;
|
||||
};
|
||||
|
||||
|
@ -45,15 +43,19 @@ type Props = MessageSearchResultProps & PropsHousekeeping;
|
|||
|
||||
class MessageSearchResultInner extends React.PureComponent<Props> {
|
||||
public renderFromName() {
|
||||
const { from, i18n, to } = this.props;
|
||||
const { from, to } = this.props;
|
||||
|
||||
if (from.isMe && to.isMe) {
|
||||
return (
|
||||
<span className="module-message-search-result__header__name">{i18n('noteToSelf')}</span>
|
||||
<span className="module-message-search-result__header__name">
|
||||
{window.i18n('noteToSelf')}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
if (from.isMe) {
|
||||
return <span className="module-message-search-result__header__name">{i18n('you')}</span>;
|
||||
return (
|
||||
<span className="module-message-search-result__header__name">{window.i18n('you')}</span>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -61,7 +63,6 @@ class MessageSearchResultInner extends React.PureComponent<Props> {
|
|||
phoneNumber={from.phoneNumber}
|
||||
name={from.name}
|
||||
profileName={from.profileName}
|
||||
i18n={i18n}
|
||||
module="module-message-search-result__header__name"
|
||||
shouldShowPubkey={false}
|
||||
/>
|
||||
|
@ -69,19 +70,18 @@ class MessageSearchResultInner extends React.PureComponent<Props> {
|
|||
}
|
||||
|
||||
public renderFrom() {
|
||||
const { i18n, to } = this.props;
|
||||
const { to } = this.props;
|
||||
const fromName = this.renderFromName();
|
||||
|
||||
if (!to.isMe) {
|
||||
return (
|
||||
<div className="module-message-search-result__header__from">
|
||||
{fromName} {i18n('to')}{' '}
|
||||
{fromName} {window.i18n('to')}{' '}
|
||||
<span className="module-mesages-search-result__header__group">
|
||||
<ContactName
|
||||
phoneNumber={to.phoneNumber}
|
||||
name={to.name}
|
||||
profileName={to.profileName}
|
||||
i18n={i18n}
|
||||
shouldShowPubkey={false}
|
||||
/>
|
||||
</span>
|
||||
|
@ -107,17 +107,7 @@ class MessageSearchResultInner extends React.PureComponent<Props> {
|
|||
}
|
||||
|
||||
public render() {
|
||||
const {
|
||||
from,
|
||||
i18n,
|
||||
id,
|
||||
isSelected,
|
||||
conversationId,
|
||||
onClick,
|
||||
receivedAt,
|
||||
snippet,
|
||||
to,
|
||||
} = this.props;
|
||||
const { from, id, isSelected, conversationId, onClick, receivedAt, snippet, to } = this.props;
|
||||
|
||||
if (!from || !to) {
|
||||
return null;
|
||||
|
@ -145,7 +135,7 @@ class MessageSearchResultInner extends React.PureComponent<Props> {
|
|||
</div>
|
||||
</div>
|
||||
<div className="module-message-search-result__body">
|
||||
<MessageBodyHighlight text={snippet} i18n={i18n} />
|
||||
<MessageBodyHighlight text={snippet} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -2,8 +2,6 @@ import React from 'react';
|
|||
import { ConversationListItemProps, ConversationListItemWithDetails } from './ConversationListItem';
|
||||
import { MessageSearchResult, MessageSearchResultProps } from './MessageSearchResult';
|
||||
|
||||
import { LocalizerType } from '../types/Util';
|
||||
|
||||
export type SearchResultsProps = {
|
||||
contacts: Array<ConversationListItemProps>;
|
||||
conversations: Array<ConversationListItemProps>;
|
||||
|
@ -13,7 +11,6 @@ export type SearchResultsProps = {
|
|||
};
|
||||
|
||||
type PropsHousekeeping = {
|
||||
i18n: LocalizerType;
|
||||
openConversationExternal: (id: string, messageId?: string) => void;
|
||||
};
|
||||
|
||||
|
@ -25,7 +22,6 @@ export class SearchResults extends React.Component<Props> {
|
|||
conversations,
|
||||
contacts,
|
||||
hideMessagesHeader,
|
||||
i18n,
|
||||
messages,
|
||||
openConversationExternal,
|
||||
searchTerm,
|
||||
|
@ -40,37 +36,37 @@ export class SearchResults extends React.Component<Props> {
|
|||
<div className="module-search-results">
|
||||
{noResults ? (
|
||||
<div className="module-search-results__no-results">
|
||||
{i18n('noSearchResults', [searchTerm])}
|
||||
{window.i18n('noSearchResults', [searchTerm])}
|
||||
</div>
|
||||
) : null}
|
||||
{haveConversations ? (
|
||||
<div className="module-search-results__conversations">
|
||||
<div className="module-search-results__conversations-header">
|
||||
{i18n('conversationsHeader')}
|
||||
{window.i18n('conversationsHeader')}
|
||||
</div>
|
||||
{conversations.map(conversation => (
|
||||
<ConversationListItemWithDetails
|
||||
key={conversation.phoneNumber}
|
||||
{...conversation}
|
||||
onClick={openConversationExternal}
|
||||
i18n={i18n}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
) : null}
|
||||
{haveContacts ? this.renderContacts(i18n('contactsHeader'), contacts) : null}
|
||||
{haveContacts ? this.renderContacts(window.i18n('contactsHeader'), contacts) : null}
|
||||
|
||||
{haveMessages ? (
|
||||
<div className="module-search-results__messages">
|
||||
{hideMessagesHeader ? null : (
|
||||
<div className="module-search-results__messages-header">{i18n('messagesHeader')}</div>
|
||||
<div className="module-search-results__messages-header">
|
||||
{window.i18n('messagesHeader')}
|
||||
</div>
|
||||
)}
|
||||
{messages.map(message => (
|
||||
<MessageSearchResult
|
||||
key={message.id}
|
||||
{...message}
|
||||
onClick={openConversationExternal}
|
||||
i18n={i18n}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
@ -79,7 +75,7 @@ export class SearchResults extends React.Component<Props> {
|
|||
);
|
||||
}
|
||||
private renderContacts(header: string, items: Array<ConversationListItemProps>) {
|
||||
const { i18n, openConversationExternal } = this.props;
|
||||
const { openConversationExternal } = this.props;
|
||||
|
||||
return (
|
||||
<div className="module-search-results__contacts">
|
||||
|
@ -89,7 +85,6 @@ export class SearchResults extends React.Component<Props> {
|
|||
key={contact.phoneNumber}
|
||||
{...contact}
|
||||
onClick={openConversationExternal}
|
||||
i18n={i18n}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
|
|
@ -58,7 +58,6 @@ export class AttachmentList extends React.Component<Props> {
|
|||
<Image
|
||||
key={imageKey}
|
||||
alt={window.i18n('stagedImageAttachment', [attachment.fileName])}
|
||||
i18n={window.i18n}
|
||||
attachment={attachment}
|
||||
softCorners={true}
|
||||
playIconOverlay={isVideoAttachment(attachment)}
|
||||
|
@ -78,7 +77,6 @@ export class AttachmentList extends React.Component<Props> {
|
|||
<StagedGenericAttachment
|
||||
key={genericKey}
|
||||
attachment={attachment}
|
||||
i18n={window.i18n}
|
||||
onClose={onCloseAttachment}
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -2,13 +2,11 @@ import React from 'react';
|
|||
import classNames from 'classnames';
|
||||
|
||||
import { Emojify } from './Emojify';
|
||||
import { LocalizerType } from '../../types/Util';
|
||||
|
||||
type Props = {
|
||||
phoneNumber: string;
|
||||
name?: string;
|
||||
profileName?: string;
|
||||
i18n: LocalizerType;
|
||||
module?: string;
|
||||
boldProfileName?: Boolean;
|
||||
compact?: Boolean;
|
||||
|
@ -20,7 +18,6 @@ export const ContactName = (props: Props) => {
|
|||
phoneNumber,
|
||||
name,
|
||||
profileName,
|
||||
i18n,
|
||||
module,
|
||||
boldProfileName,
|
||||
compact,
|
||||
|
@ -35,16 +32,16 @@ export const ContactName = (props: Props) => {
|
|||
fontWeight: 'bold',
|
||||
}
|
||||
: {}) as React.CSSProperties;
|
||||
const textProfile = profileName || name || i18n('anonymous');
|
||||
const textProfile = profileName || name || window.i18n('anonymous');
|
||||
const profileElement = shouldShowProfile ? (
|
||||
<span style={styles} className={`${prefix}__profile-name`}>
|
||||
<Emojify text={textProfile} i18n={i18n} />
|
||||
<Emojify text={textProfile} />
|
||||
</span>
|
||||
) : null;
|
||||
|
||||
const pubKeyElement = shouldShowPubkey ? (
|
||||
<span className={`${prefix}__profile-number`}>
|
||||
<Emojify text={title} i18n={i18n} />
|
||||
<Emojify text={title} />
|
||||
</span>
|
||||
) : null;
|
||||
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
import React from 'react';
|
||||
|
||||
import classNames from 'classnames';
|
||||
import is from '@sindresorhus/is';
|
||||
|
||||
import { getRegex, SizeClassType } from '../../util/emoji';
|
||||
|
||||
import { LocalizerType, RenderTextCallbackType } from '../../types/Util';
|
||||
import { RenderTextCallbackType } from '../../types/Util';
|
||||
import { Twemoji } from 'react-emoji-render';
|
||||
|
||||
interface Props {
|
||||
|
@ -14,7 +11,6 @@ interface Props {
|
|||
sizeClass?: SizeClassType;
|
||||
/** Allows you to customize now non-newlines are rendered. Simplest is just a <span>. */
|
||||
renderNonEmoji?: RenderTextCallbackType;
|
||||
i18n: LocalizerType;
|
||||
isGroup?: boolean;
|
||||
convoId: string;
|
||||
}
|
||||
|
@ -26,7 +22,7 @@ export class Emojify extends React.Component<Props> {
|
|||
};
|
||||
|
||||
public render() {
|
||||
const { text, sizeClass, renderNonEmoji, i18n, isGroup, convoId } = this.props;
|
||||
const { text, sizeClass, renderNonEmoji, isGroup, convoId } = this.props;
|
||||
const results: Array<any> = [];
|
||||
const regex = getRegex();
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@ type Props = {
|
|||
export const GroupNotification = (props: Props) => {
|
||||
function renderChange(change: Change) {
|
||||
const { isMe, contacts, type, newName } = change;
|
||||
const { i18n } = window;
|
||||
|
||||
const people = compact(
|
||||
flatten(
|
||||
|
@ -47,7 +46,7 @@ export const GroupNotification = (props: Props) => {
|
|||
|
||||
switch (type) {
|
||||
case 'name':
|
||||
return `${i18n('titleIsNow', [newName || ''])}.`;
|
||||
return `${window.i18n('titleIsNow', [newName || ''])}.`;
|
||||
case 'add':
|
||||
if (!contacts || !contacts.length) {
|
||||
throw new Error('Group update add is missing contacts');
|
||||
|
@ -55,10 +54,10 @@ export const GroupNotification = (props: Props) => {
|
|||
|
||||
const joinKey = contacts.length > 1 ? 'multipleJoinedTheGroup' : 'joinedTheGroup';
|
||||
|
||||
return <Intl i18n={i18n} id={joinKey} components={[people]} />;
|
||||
return <Intl id={joinKey} components={[people]} />;
|
||||
case 'remove':
|
||||
if (isMe) {
|
||||
return i18n('youLeftTheGroup');
|
||||
return window.i18n('youLeftTheGroup');
|
||||
}
|
||||
|
||||
if (!contacts || !contacts.length) {
|
||||
|
@ -67,10 +66,10 @@ export const GroupNotification = (props: Props) => {
|
|||
|
||||
const leftKey = contacts.length > 1 ? 'multipleLeftTheGroup' : 'leftTheGroup';
|
||||
|
||||
return <Intl i18n={i18n} id={leftKey} components={[people]} />;
|
||||
return <Intl id={leftKey} components={[people]} />;
|
||||
case 'kicked':
|
||||
if (isMe) {
|
||||
return i18n('youGotKickedFromGroup');
|
||||
return window.i18n('youGotKickedFromGroup');
|
||||
}
|
||||
|
||||
if (!contacts || !contacts.length) {
|
||||
|
@ -79,9 +78,9 @@ export const GroupNotification = (props: Props) => {
|
|||
|
||||
const kickedKey = contacts.length > 1 ? 'multipleKickedFromTheGroup' : 'kickedFromTheGroup';
|
||||
|
||||
return <Intl i18n={i18n} id={kickedKey} components={[people]} />;
|
||||
return <Intl id={kickedKey} components={[people]} />;
|
||||
case 'general':
|
||||
return i18n('updatedTheGroup');
|
||||
return window.i18n('updatedTheGroup');
|
||||
default:
|
||||
throw missingCaseError(type);
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ import React from 'react';
|
|||
import classNames from 'classnames';
|
||||
|
||||
import { Spinner } from '../basic/Spinner';
|
||||
import { LocalizerType } from '../../types/Util';
|
||||
import { AttachmentType } from '../../types/Attachment';
|
||||
import { useEncryptedFileFetch } from '../../hooks/useEncryptedFileFetch';
|
||||
|
||||
|
@ -29,7 +28,6 @@ type Props = {
|
|||
playIconOverlay?: boolean;
|
||||
softCorners?: boolean;
|
||||
|
||||
i18n: LocalizerType;
|
||||
onClick?: (attachment: AttachmentType) => void;
|
||||
onClickClose?: (attachment: AttachmentType) => void;
|
||||
onError?: () => void;
|
||||
|
@ -48,7 +46,6 @@ export const Image = (props: Props) => {
|
|||
curveTopRight,
|
||||
darkOverlay,
|
||||
height,
|
||||
i18n,
|
||||
onClick,
|
||||
onClickClose,
|
||||
onError,
|
||||
|
@ -114,7 +111,7 @@ export const Image = (props: Props) => {
|
|||
<img
|
||||
className="module-image__caption-icon"
|
||||
src="images/caption-shadow.svg"
|
||||
alt={i18n('imageCaptionIconAlt')}
|
||||
alt={window.i18n('imageCaptionIconAlt')}
|
||||
/>
|
||||
) : null}
|
||||
<div
|
||||
|
|
|
@ -13,16 +13,12 @@ import {
|
|||
|
||||
import { Image } from './Image';
|
||||
|
||||
import { LocalizerType } from '../../types/Util';
|
||||
|
||||
type Props = {
|
||||
attachments: Array<AttachmentType>;
|
||||
withContentAbove?: boolean;
|
||||
withContentBelow?: boolean;
|
||||
bottomOverlay?: boolean;
|
||||
|
||||
i18n: LocalizerType;
|
||||
|
||||
onError: () => void;
|
||||
onClickAttachment?: (attachment: AttachmentType) => void;
|
||||
};
|
||||
|
@ -32,7 +28,6 @@ export const ImageGrid = (props: Props) => {
|
|||
const {
|
||||
attachments,
|
||||
bottomOverlay,
|
||||
i18n,
|
||||
onError,
|
||||
onClickAttachment,
|
||||
withContentAbove,
|
||||
|
@ -58,8 +53,7 @@ export const ImageGrid = (props: Props) => {
|
|||
return (
|
||||
<div className={classNames('module-image-grid', 'module-image-grid--one-image')}>
|
||||
<Image
|
||||
alt={getAlt(attachments[0], i18n)}
|
||||
i18n={i18n}
|
||||
alt={getAlt(attachments[0])}
|
||||
bottomOverlay={withBottomOverlay}
|
||||
curveTopLeft={curveTopLeft}
|
||||
curveTopRight={curveTopRight}
|
||||
|
@ -81,8 +75,7 @@ export const ImageGrid = (props: Props) => {
|
|||
return (
|
||||
<div className="module-image-grid">
|
||||
<Image
|
||||
alt={getAlt(attachments[0], i18n)}
|
||||
i18n={i18n}
|
||||
alt={getAlt(attachments[0])}
|
||||
attachment={attachments[0]}
|
||||
bottomOverlay={withBottomOverlay}
|
||||
curveTopLeft={curveTopLeft}
|
||||
|
@ -95,8 +88,7 @@ export const ImageGrid = (props: Props) => {
|
|||
onError={onError}
|
||||
/>
|
||||
<Image
|
||||
alt={getAlt(attachments[1], i18n)}
|
||||
i18n={i18n}
|
||||
alt={getAlt(attachments[1])}
|
||||
bottomOverlay={withBottomOverlay}
|
||||
curveTopRight={curveTopRight}
|
||||
curveBottomRight={curveBottomRight}
|
||||
|
@ -116,8 +108,7 @@ export const ImageGrid = (props: Props) => {
|
|||
return (
|
||||
<div className="module-image-grid">
|
||||
<Image
|
||||
alt={getAlt(attachments[0], i18n)}
|
||||
i18n={i18n}
|
||||
alt={getAlt(attachments[0])}
|
||||
bottomOverlay={withBottomOverlay}
|
||||
curveTopLeft={curveTopLeft}
|
||||
curveBottomLeft={curveBottomLeft}
|
||||
|
@ -131,8 +122,7 @@ export const ImageGrid = (props: Props) => {
|
|||
/>
|
||||
<div className="module-image-grid__column">
|
||||
<Image
|
||||
alt={getAlt(attachments[1], i18n)}
|
||||
i18n={i18n}
|
||||
alt={getAlt(attachments[1])}
|
||||
curveTopRight={curveTopRight}
|
||||
height={99}
|
||||
width={99}
|
||||
|
@ -143,8 +133,7 @@ export const ImageGrid = (props: Props) => {
|
|||
onError={onError}
|
||||
/>
|
||||
<Image
|
||||
alt={getAlt(attachments[2], i18n)}
|
||||
i18n={i18n}
|
||||
alt={getAlt(attachments[2])}
|
||||
bottomOverlay={withBottomOverlay}
|
||||
curveBottomRight={curveBottomRight}
|
||||
height={99}
|
||||
|
@ -166,8 +155,7 @@ export const ImageGrid = (props: Props) => {
|
|||
<div className="module-image-grid__column">
|
||||
<div className="module-image-grid__row">
|
||||
<Image
|
||||
alt={getAlt(attachments[0], i18n)}
|
||||
i18n={i18n}
|
||||
alt={getAlt(attachments[0])}
|
||||
curveTopLeft={curveTopLeft}
|
||||
attachment={attachments[0]}
|
||||
playIconOverlay={isVideoAttachment(attachments[0])}
|
||||
|
@ -178,8 +166,7 @@ export const ImageGrid = (props: Props) => {
|
|||
onError={onError}
|
||||
/>
|
||||
<Image
|
||||
alt={getAlt(attachments[1], i18n)}
|
||||
i18n={i18n}
|
||||
alt={getAlt(attachments[1])}
|
||||
curveTopRight={curveTopRight}
|
||||
playIconOverlay={isVideoAttachment(attachments[1])}
|
||||
height={149}
|
||||
|
@ -192,8 +179,7 @@ export const ImageGrid = (props: Props) => {
|
|||
</div>
|
||||
<div className="module-image-grid__row">
|
||||
<Image
|
||||
alt={getAlt(attachments[2], i18n)}
|
||||
i18n={i18n}
|
||||
alt={getAlt(attachments[2])}
|
||||
bottomOverlay={withBottomOverlay}
|
||||
curveBottomLeft={curveBottomLeft}
|
||||
playIconOverlay={isVideoAttachment(attachments[2])}
|
||||
|
@ -205,8 +191,7 @@ export const ImageGrid = (props: Props) => {
|
|||
onError={onError}
|
||||
/>
|
||||
<Image
|
||||
alt={getAlt(attachments[3], i18n)}
|
||||
i18n={i18n}
|
||||
alt={getAlt(attachments[3])}
|
||||
bottomOverlay={withBottomOverlay}
|
||||
curveBottomRight={curveBottomRight}
|
||||
playIconOverlay={isVideoAttachment(attachments[3])}
|
||||
|
@ -231,8 +216,7 @@ export const ImageGrid = (props: Props) => {
|
|||
<div className="module-image-grid__column">
|
||||
<div className="module-image-grid__row">
|
||||
<Image
|
||||
alt={getAlt(attachments[0], i18n)}
|
||||
i18n={i18n}
|
||||
alt={getAlt(attachments[0])}
|
||||
curveTopLeft={curveTopLeft}
|
||||
attachment={attachments[0]}
|
||||
playIconOverlay={isVideoAttachment(attachments[0])}
|
||||
|
@ -243,8 +227,7 @@ export const ImageGrid = (props: Props) => {
|
|||
onError={onError}
|
||||
/>
|
||||
<Image
|
||||
alt={getAlt(attachments[1], i18n)}
|
||||
i18n={i18n}
|
||||
alt={getAlt(attachments[1])}
|
||||
curveTopRight={curveTopRight}
|
||||
playIconOverlay={isVideoAttachment(attachments[1])}
|
||||
height={149}
|
||||
|
@ -257,8 +240,7 @@ export const ImageGrid = (props: Props) => {
|
|||
</div>
|
||||
<div className="module-image-grid__row">
|
||||
<Image
|
||||
alt={getAlt(attachments[2], i18n)}
|
||||
i18n={i18n}
|
||||
alt={getAlt(attachments[2])}
|
||||
bottomOverlay={withBottomOverlay}
|
||||
curveBottomLeft={curveBottomLeft}
|
||||
playIconOverlay={isVideoAttachment(attachments[2])}
|
||||
|
@ -270,8 +252,7 @@ export const ImageGrid = (props: Props) => {
|
|||
onError={onError}
|
||||
/>
|
||||
<Image
|
||||
alt={getAlt(attachments[3], i18n)}
|
||||
i18n={i18n}
|
||||
alt={getAlt(attachments[3])}
|
||||
bottomOverlay={withBottomOverlay}
|
||||
playIconOverlay={isVideoAttachment(attachments[3])}
|
||||
height={99}
|
||||
|
@ -282,8 +263,7 @@ export const ImageGrid = (props: Props) => {
|
|||
onError={onError}
|
||||
/>
|
||||
<Image
|
||||
alt={getAlt(attachments[4], i18n)}
|
||||
i18n={i18n}
|
||||
alt={getAlt(attachments[4])}
|
||||
bottomOverlay={withBottomOverlay}
|
||||
curveBottomRight={curveBottomRight}
|
||||
playIconOverlay={isVideoAttachment(attachments[4])}
|
||||
|
|
|
@ -216,7 +216,6 @@ class MessageInner extends React.PureComponent<MessageRegularProps, State> {
|
|||
withContentAbove={withContentAbove}
|
||||
withContentBelow={withContentBelow}
|
||||
bottomOverlay={!collapseMetadata}
|
||||
i18n={window.i18n}
|
||||
onError={this.handleImageErrorBound}
|
||||
onClickAttachment={(attachment: AttachmentType) => {
|
||||
if (multiSelectMode) {
|
||||
|
@ -358,7 +357,6 @@ class MessageInner extends React.PureComponent<MessageRegularProps, State> {
|
|||
withContentAbove={withContentAbove}
|
||||
withContentBelow={true}
|
||||
onError={this.handleImageErrorBound}
|
||||
i18n={window.i18n}
|
||||
/>
|
||||
) : null}
|
||||
<div
|
||||
|
@ -380,7 +378,6 @@ class MessageInner extends React.PureComponent<MessageRegularProps, State> {
|
|||
url={first.image.url}
|
||||
attachment={first.image}
|
||||
onError={this.handleImageErrorBound}
|
||||
i18n={window.i18n}
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
|
@ -423,7 +420,6 @@ class MessageInner extends React.PureComponent<MessageRegularProps, State> {
|
|||
|
||||
return (
|
||||
<Quote
|
||||
i18n={window.i18n}
|
||||
onClick={(e: any) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
@ -519,7 +515,6 @@ class MessageInner extends React.PureComponent<MessageRegularProps, State> {
|
|||
>
|
||||
<MessageBody
|
||||
text={contents || ''}
|
||||
i18n={window.i18n}
|
||||
isGroup={conversationType === 'group'}
|
||||
convoId={convoId}
|
||||
disableLinks={multiSelectMode}
|
||||
|
@ -872,7 +867,6 @@ class MessageInner extends React.PureComponent<MessageRegularProps, State> {
|
|||
name={authorName}
|
||||
profileName={authorProfileName}
|
||||
module="module-message__author"
|
||||
i18n={window.i18n}
|
||||
boldProfileName={true}
|
||||
shouldShowPubkey={Boolean(isPublic)}
|
||||
/>
|
||||
|
|
|
@ -6,7 +6,7 @@ import { AddNewLines } from './AddNewLines';
|
|||
import { AddMentions } from './AddMentions';
|
||||
import { Linkify } from './Linkify';
|
||||
|
||||
import { LocalizerType, RenderTextCallbackType } from '../../types/Util';
|
||||
import { RenderTextCallbackType } from '../../types/Util';
|
||||
|
||||
interface Props {
|
||||
text: string;
|
||||
|
@ -15,7 +15,6 @@ interface Props {
|
|||
/** If set, links will be left alone instead of turned into clickable `<a>` tags. */
|
||||
disableLinks?: boolean;
|
||||
isGroup?: boolean;
|
||||
i18n: LocalizerType;
|
||||
convoId: string;
|
||||
}
|
||||
|
||||
|
@ -44,7 +43,6 @@ const renderNewLines: RenderTextCallbackType = ({
|
|||
};
|
||||
|
||||
const renderEmoji = ({
|
||||
i18n,
|
||||
text,
|
||||
key,
|
||||
sizeClass,
|
||||
|
@ -52,7 +50,6 @@ const renderEmoji = ({
|
|||
isGroup,
|
||||
convoId,
|
||||
}: {
|
||||
i18n: LocalizerType;
|
||||
text: string;
|
||||
key: number;
|
||||
sizeClass?: SizeClassType;
|
||||
|
@ -61,7 +58,6 @@ const renderEmoji = ({
|
|||
convoId?: string;
|
||||
}) => (
|
||||
<Emojify
|
||||
i18n={i18n}
|
||||
key={key}
|
||||
text={text}
|
||||
sizeClass={sizeClass}
|
||||
|
@ -87,13 +83,12 @@ export class MessageBody extends React.Component<Props> {
|
|||
}
|
||||
|
||||
public render() {
|
||||
const { text, disableJumbomoji, disableLinks, i18n, isGroup, convoId } = this.props;
|
||||
const { text, disableJumbomoji, disableLinks, isGroup, convoId } = this.props;
|
||||
const sizeClass = disableJumbomoji ? undefined : getSizeClass(text);
|
||||
|
||||
if (disableLinks) {
|
||||
return this.renderJsxSelectable(
|
||||
renderEmoji({
|
||||
i18n,
|
||||
text,
|
||||
sizeClass,
|
||||
key: 0,
|
||||
|
@ -109,7 +104,6 @@ export class MessageBody extends React.Component<Props> {
|
|||
text={text}
|
||||
renderNonLink={({ key, text: nonLinkText }) => {
|
||||
return renderEmoji({
|
||||
i18n,
|
||||
text: nonLinkText,
|
||||
sizeClass,
|
||||
key,
|
||||
|
|
|
@ -60,7 +60,6 @@ export class MessageDetail extends React.Component<Props> {
|
|||
}
|
||||
|
||||
public renderContact(contact: Contact) {
|
||||
const { i18n } = window;
|
||||
const errors = contact.errors || [];
|
||||
|
||||
const statusComponent = !contact.isOutgoingKeyError ? (
|
||||
|
@ -81,7 +80,6 @@ export class MessageDetail extends React.Component<Props> {
|
|||
phoneNumber={contact.phoneNumber}
|
||||
name={contact.name}
|
||||
profileName={contact.profileName}
|
||||
i18n={i18n}
|
||||
shouldShowPubkey={true}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -7,7 +7,6 @@ import * as MIME from '../../../ts/types/MIME';
|
|||
import * as GoogleChrome from '../../../ts/util/GoogleChrome';
|
||||
|
||||
import { MessageBody } from './MessageBody';
|
||||
import { ColorType, LocalizerType } from '../../types/Util';
|
||||
import { ContactName } from './ContactName';
|
||||
import { PubKey } from '../../session/types';
|
||||
import { ConversationTypeEnum } from '../../models/conversation';
|
||||
|
@ -19,7 +18,6 @@ interface QuoteProps {
|
|||
authorPhoneNumber: string;
|
||||
authorProfileName?: string;
|
||||
authorName?: string;
|
||||
i18n: LocalizerType;
|
||||
isFromMe: boolean;
|
||||
isIncoming: boolean;
|
||||
conversationType: ConversationTypeEnum;
|
||||
|
@ -66,25 +64,23 @@ function getObjectUrl(thumbnail: Attachment | undefined): string | undefined {
|
|||
}
|
||||
|
||||
function getTypeLabel({
|
||||
i18n,
|
||||
contentType,
|
||||
isVoiceMessage,
|
||||
}: {
|
||||
i18n: LocalizerType;
|
||||
contentType: MIME.MIMEType;
|
||||
isVoiceMessage: boolean;
|
||||
}): string | undefined {
|
||||
if (GoogleChrome.isVideoTypeSupported(contentType)) {
|
||||
return i18n('video');
|
||||
return window.i18n('video');
|
||||
}
|
||||
if (GoogleChrome.isImageTypeSupported(contentType)) {
|
||||
return i18n('photo');
|
||||
return window.i18n('photo');
|
||||
}
|
||||
if (MIME.isAudio(contentType) && isVoiceMessage) {
|
||||
return i18n('voiceMessage');
|
||||
return window.i18n('voiceMessage');
|
||||
}
|
||||
if (MIME.isAudio(contentType)) {
|
||||
return i18n('audio');
|
||||
return window.i18n('audio');
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -109,7 +105,7 @@ export const QuoteIcon = (props: any) => {
|
|||
};
|
||||
|
||||
export const QuoteImage = (props: any) => {
|
||||
const { url, i18n, icon, contentType, handleImageErrorBound } = props;
|
||||
const { url, icon, contentType, handleImageErrorBound } = props;
|
||||
|
||||
const { loading, urlToLoad } = useEncryptedFileFetch(url, contentType);
|
||||
const srcData = !loading ? urlToLoad : '';
|
||||
|
@ -129,7 +125,7 @@ export const QuoteImage = (props: any) => {
|
|||
|
||||
return (
|
||||
<div className="module-quote__icon-container">
|
||||
<img src={srcData} alt={i18n('quoteThumbnailAlt')} onError={handleImageErrorBound} />
|
||||
<img src={srcData} alt={window.i18n('quoteThumbnailAlt')} onError={handleImageErrorBound} />
|
||||
{iconElement}
|
||||
</div>
|
||||
);
|
||||
|
@ -168,7 +164,7 @@ export const QuoteGenericFile = (props: any) => {
|
|||
};
|
||||
|
||||
export const QuoteIconContainer = (props: any) => {
|
||||
const { attachment, i18n, imageBroken, handleImageErrorBound } = props;
|
||||
const { attachment, imageBroken, handleImageErrorBound } = props;
|
||||
|
||||
if (!attachment) {
|
||||
return null;
|
||||
|
@ -179,7 +175,7 @@ export const QuoteIconContainer = (props: any) => {
|
|||
|
||||
if (GoogleChrome.isVideoTypeSupported(contentType)) {
|
||||
return objectUrl && !imageBroken ? (
|
||||
<QuoteImage url={objectUrl} i18n={i18n} icon={'play'} />
|
||||
<QuoteImage url={objectUrl} icon={'play'} />
|
||||
) : (
|
||||
<QuoteIcon icon="movie" />
|
||||
);
|
||||
|
@ -188,7 +184,6 @@ export const QuoteIconContainer = (props: any) => {
|
|||
return objectUrl && !imageBroken ? (
|
||||
<QuoteImage
|
||||
url={objectUrl}
|
||||
i18n={i18n}
|
||||
contentType={contentType}
|
||||
handleImageErrorBound={handleImageErrorBound}
|
||||
/>
|
||||
|
@ -203,7 +198,7 @@ export const QuoteIconContainer = (props: any) => {
|
|||
};
|
||||
|
||||
export const QuoteText = (props: any) => {
|
||||
const { i18n, text, attachment, isIncoming, conversationType, convoId } = props;
|
||||
const { text, attachment, isIncoming, conversationType, convoId } = props;
|
||||
const isGroup = conversationType === ConversationTypeEnum.GROUP;
|
||||
|
||||
if (text) {
|
||||
|
@ -215,13 +210,7 @@ export const QuoteText = (props: any) => {
|
|||
isIncoming ? 'module-quote__primary__text--incoming' : null
|
||||
)}
|
||||
>
|
||||
<MessageBody
|
||||
isGroup={isGroup}
|
||||
convoId={convoId}
|
||||
text={text}
|
||||
disableLinks={true}
|
||||
i18n={i18n}
|
||||
/>
|
||||
<MessageBody isGroup={isGroup} convoId={convoId} text={text} disableLinks={true} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -232,7 +221,7 @@ export const QuoteText = (props: any) => {
|
|||
|
||||
const { contentType, isVoiceMessage } = attachment;
|
||||
|
||||
const typeLabel = getTypeLabel({ i18n, contentType, isVoiceMessage });
|
||||
const typeLabel = getTypeLabel({ contentType, isVoiceMessage });
|
||||
if (typeLabel) {
|
||||
return (
|
||||
<div
|
||||
|
@ -254,7 +243,6 @@ export const QuoteAuthor = (props: any) => {
|
|||
authorProfileName,
|
||||
authorPhoneNumber,
|
||||
authorName,
|
||||
i18n,
|
||||
isFromMe,
|
||||
isIncoming,
|
||||
isPublic,
|
||||
|
@ -268,13 +256,12 @@ export const QuoteAuthor = (props: any) => {
|
|||
)}
|
||||
>
|
||||
{isFromMe ? (
|
||||
i18n('you')
|
||||
window.i18n('you')
|
||||
) : (
|
||||
<ContactName
|
||||
phoneNumber={PubKey.shorten(authorPhoneNumber)}
|
||||
name={authorName}
|
||||
profileName={authorProfileName}
|
||||
i18n={i18n}
|
||||
compact={true}
|
||||
shouldShowPubkey={Boolean(isPublic)}
|
||||
/>
|
||||
|
@ -284,7 +271,7 @@ export const QuoteAuthor = (props: any) => {
|
|||
};
|
||||
|
||||
export const QuoteReferenceWarning = (props: any) => {
|
||||
const { i18n, isIncoming, referencedMessageNotFound } = props;
|
||||
const { isIncoming, referencedMessageNotFound } = props;
|
||||
|
||||
if (!referencedMessageNotFound) {
|
||||
return null;
|
||||
|
@ -309,7 +296,7 @@ export const QuoteReferenceWarning = (props: any) => {
|
|||
isIncoming ? 'module-quote__reference-warning__text--incoming' : null
|
||||
)}
|
||||
>
|
||||
{i18n('originalMessageNotFound')}
|
||||
{window.i18n('originalMessageNotFound')}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
import React from 'react';
|
||||
|
||||
import { AttachmentType, getExtensionForDisplay } from '../../types/Attachment';
|
||||
import { LocalizerType } from '../../types/Util';
|
||||
|
||||
interface Props {
|
||||
attachment: AttachmentType;
|
||||
onClose: (attachment: AttachmentType) => void;
|
||||
i18n: LocalizerType;
|
||||
}
|
||||
|
||||
export class StagedGenericAttachment extends React.Component<Props> {
|
||||
|
|
|
@ -20,7 +20,6 @@ export const StagedLinkPreview = (props: Props) => {
|
|||
const { isLoaded, onClose, title, image, domain, description, url } = props;
|
||||
|
||||
const isImage = image && isImageAttachment(image);
|
||||
const i18n = window.i18n;
|
||||
if (isLoaded && !(title && domain)) {
|
||||
return <></>;
|
||||
}
|
||||
|
@ -33,18 +32,17 @@ export const StagedLinkPreview = (props: Props) => {
|
|||
)}
|
||||
>
|
||||
{!isLoaded ? (
|
||||
<div className="module-staged-link-preview__loading">{i18n('loading')}</div>
|
||||
<div className="module-staged-link-preview__loading">{window.i18n('loading')}</div>
|
||||
) : null}
|
||||
{isLoaded && image && isImage ? (
|
||||
<div className="module-staged-link-preview__icon-container">
|
||||
<Image
|
||||
alt={i18n('stagedPreviewThumbnail', [domain])}
|
||||
alt={window.i18n('stagedPreviewThumbnail', [domain])}
|
||||
softCorners={true}
|
||||
height={72}
|
||||
width={72}
|
||||
url={image.url}
|
||||
attachment={image}
|
||||
i18n={i18n}
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
|
@ -65,7 +63,7 @@ export const StagedLinkPreview = (props: Props) => {
|
|||
onClick={() => {
|
||||
onClose(url || '');
|
||||
}}
|
||||
aria-label={i18n('close')}
|
||||
aria-label={window.i18n('close')}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -28,7 +28,7 @@ export const TimerNotification = (props: Props) => {
|
|||
|
||||
switch (type) {
|
||||
case 'fromOther':
|
||||
return <Intl i18n={window.i18n} id={changeKey} components={[contact, timespan]} />;
|
||||
return <Intl id={changeKey} components={[contact, timespan]} />;
|
||||
case 'fromMe':
|
||||
return disabled
|
||||
? window.i18n('youDisabledDisappearingMessages')
|
||||
|
|
|
@ -68,7 +68,7 @@ export const Timestamp = (props: Props) => {
|
|||
|
||||
let dateString;
|
||||
if (messageAgeInDays > daysBeforeRelativeTiming) {
|
||||
dateString = formatRelativeTime(timestamp, { i18n: window.i18n, extended });
|
||||
dateString = formatRelativeTime(timestamp, { extended });
|
||||
} else {
|
||||
dateString = moment(timestamp).fromNow();
|
||||
// Prevent times reading "NOW AGO"
|
||||
|
|
|
@ -1,19 +1,16 @@
|
|||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { LocalizerType } from '../../types/Util';
|
||||
|
||||
interface Props {
|
||||
i18n: LocalizerType;
|
||||
color?: string;
|
||||
}
|
||||
|
||||
export class TypingAnimation extends React.Component<Props> {
|
||||
public render() {
|
||||
const { i18n, color } = this.props;
|
||||
const { color } = this.props;
|
||||
|
||||
return (
|
||||
<div className="module-typing-animation" title={i18n('typingAlt')}>
|
||||
<div className="module-typing-animation" title={window.i18n('typingAlt')}>
|
||||
<div
|
||||
className={classNames(
|
||||
'module-typing-animation__dot',
|
||||
|
|
|
@ -31,7 +31,7 @@ export const TypingBubble = (props: TypingBubbleProps) => {
|
|||
|
||||
return (
|
||||
<TypingBubbleContainer {...props}>
|
||||
<TypingAnimation i18n={window.i18n} />
|
||||
<TypingAnimation />
|
||||
</TypingBubbleContainer>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -6,7 +6,6 @@ import { SessionButton, SessionButtonColor, SessionButtonType } from '../session
|
|||
import { ContactType, SessionMemberListItem } from '../session/SessionMemberListItem';
|
||||
import { DefaultTheme } from 'styled-components';
|
||||
import { ToastUtils } from '../../session/utils';
|
||||
import { LocalizerType } from '../../types/Util';
|
||||
import autoBind from 'auto-bind';
|
||||
import { ConversationController } from '../../session/conversations';
|
||||
|
||||
|
@ -25,7 +24,6 @@ interface Props {
|
|||
existingZombies: Array<string>;
|
||||
admins: Array<string>; // used for closed group
|
||||
|
||||
i18n: LocalizerType;
|
||||
onSubmit: (membersLeft: Array<string>) => void;
|
||||
onClose: () => void;
|
||||
theme: DefaultTheme;
|
||||
|
|
|
@ -5,10 +5,8 @@ import { ItemClickEvent } from './types/ItemClickEvent';
|
|||
import { MediaGridItem } from './MediaGridItem';
|
||||
import { MediaItemType } from '../../LightboxGallery';
|
||||
import { missingCaseError } from '../../../util/missingCaseError';
|
||||
import { LocalizerType } from '../../../types/Util';
|
||||
|
||||
interface Props {
|
||||
i18n: LocalizerType;
|
||||
type: 'media' | 'documents';
|
||||
mediaItems: Array<MediaItemType>;
|
||||
onItemClick?: (event: ItemClickEvent) => void;
|
||||
|
@ -28,7 +26,7 @@ export class AttachmentSection extends React.Component<Props> {
|
|||
}
|
||||
|
||||
private renderItems() {
|
||||
const { i18n, mediaItems, type } = this.props;
|
||||
const { mediaItems, type } = this.props;
|
||||
|
||||
return mediaItems.map((mediaItem, position, array) => {
|
||||
const shouldShowSeparator = position < array.length - 1;
|
||||
|
@ -38,12 +36,7 @@ export class AttachmentSection extends React.Component<Props> {
|
|||
switch (type) {
|
||||
case 'media':
|
||||
return (
|
||||
<MediaGridItem
|
||||
key={`${message.id}-${index}`}
|
||||
mediaItem={mediaItem}
|
||||
onClick={onClick}
|
||||
i18n={i18n}
|
||||
/>
|
||||
<MediaGridItem key={`${message.id}-${index}`} mediaItem={mediaItem} onClick={onClick} />
|
||||
);
|
||||
case 'documents':
|
||||
return (
|
||||
|
|
|
@ -114,7 +114,6 @@ export class MediaGallery extends React.Component<Props, State> {
|
|||
<div className="module-media-gallery__sections">
|
||||
<AttachmentSection
|
||||
key="mediaItems"
|
||||
i18n={window.i18n}
|
||||
type={type}
|
||||
mediaItems={mediaItems}
|
||||
onItemClick={onItemClick}
|
||||
|
|
|
@ -2,18 +2,17 @@ import React, { useState } from 'react';
|
|||
import classNames from 'classnames';
|
||||
|
||||
import { isImageTypeSupported, isVideoTypeSupported } from '../../../util/GoogleChrome';
|
||||
import { LocalizerType } from '../../../types/Util';
|
||||
import { MediaItemType } from '../../LightboxGallery';
|
||||
import { useEncryptedFileFetch } from '../../../hooks/useEncryptedFileFetch';
|
||||
|
||||
type Props = {
|
||||
mediaItem: MediaItemType;
|
||||
onClick?: () => void;
|
||||
i18n: LocalizerType;
|
||||
};
|
||||
|
||||
const MediaGridItemContent = (props: Props) => {
|
||||
const { mediaItem, i18n } = props;
|
||||
const { mediaItem } = props;
|
||||
const i18n = window.i18n;
|
||||
const { attachment, contentType } = mediaItem;
|
||||
|
||||
const urlToDecrypt = mediaItem.thumbnailObjectUrl || '';
|
||||
|
|
|
@ -144,12 +144,12 @@ const showResetSessionIDDialogIfNeeded = async () => {
|
|||
|
||||
const cleanUpMediasInterval = DURATION.MINUTES * 30;
|
||||
|
||||
const setupTheme = (dispatch: Dispatch<any>) => {
|
||||
const setupTheme = () => {
|
||||
const theme = window.Events.getThemeSetting();
|
||||
window.setTheme(theme);
|
||||
|
||||
const newThemeObject = theme === 'dark' ? darkTheme : lightTheme;
|
||||
dispatch(applyTheme(newThemeObject));
|
||||
window?.inboxStore?.dispatch(applyTheme(newThemeObject));
|
||||
};
|
||||
|
||||
// Do this only if we created a new Session ID, or if we already received the initial configuration message
|
||||
|
@ -273,7 +273,7 @@ const triggerAvatarReUploadIfNeeded = async () => {
|
|||
/**
|
||||
* This function is called only once: on app startup with a logged in user
|
||||
*/
|
||||
const doAppStartUp = (dispatch: Dispatch<any>) => {
|
||||
const doAppStartUp = () => {
|
||||
if (window.lokiFeatureFlags.useOnionRequests || window.lokiFeatureFlags.useFileOnionRequests) {
|
||||
// Initialize paths for onion requests
|
||||
void OnionPaths.buildNewOnionPathsOneAtATime();
|
||||
|
@ -282,7 +282,7 @@ const doAppStartUp = (dispatch: Dispatch<any>) => {
|
|||
// init the messageQueue. In the constructor, we add all not send messages
|
||||
// this call does nothing except calling the constructor, which will continue sending message in the pipeline
|
||||
void getMessageQueue().processAllPending();
|
||||
void setupTheme(dispatch);
|
||||
void setupTheme();
|
||||
|
||||
// keep that one to make sure our users upgrade to new sessionIDS
|
||||
void showResetSessionIDDialogIfNeeded();
|
||||
|
@ -310,7 +310,6 @@ const doAppStartUp = (dispatch: Dispatch<any>) => {
|
|||
* The panel with buttons to switch between the message/contact/settings/theme views
|
||||
*/
|
||||
export const ActionsPanel = () => {
|
||||
const dispatch = useDispatch();
|
||||
const [startCleanUpMedia, setStartCleanUpMedia] = useState(false);
|
||||
|
||||
const ourPrimaryConversation = useSelector(getOurPrimaryConversation);
|
||||
|
@ -318,7 +317,7 @@ export const ActionsPanel = () => {
|
|||
// this maxi useEffect is called only once: when the component is mounted.
|
||||
// For the action panel, it means this is called only one per app start/with a user loggedin
|
||||
useEffect(() => {
|
||||
void doAppStartUp(dispatch);
|
||||
void doAppStartUp();
|
||||
}, []);
|
||||
|
||||
// wait for cleanUpMediasInterval and then start cleaning up medias
|
||||
|
|
|
@ -42,7 +42,6 @@ export class LeftPaneContactSection extends React.Component<Props> {
|
|||
key={item.id}
|
||||
style={style}
|
||||
{...item}
|
||||
i18n={window.i18n}
|
||||
onClick={this.props.openConversationExternal}
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -93,7 +93,6 @@ export class LeftPaneMessageSection extends React.Component<Props, State> {
|
|||
style={style}
|
||||
{...conversation}
|
||||
onClick={openConversationExternal}
|
||||
i18n={window.i18n}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
@ -108,7 +107,6 @@ export class LeftPaneMessageSection extends React.Component<Props, State> {
|
|||
{...searchResults}
|
||||
contacts={contacts}
|
||||
openConversationExternal={openConversationExternal}
|
||||
i18n={window.i18n}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -154,7 +154,7 @@ class SessionPasswordModalInner extends React.Component<Props, State> {
|
|||
*/
|
||||
private validatePassword(firstPassword: string) {
|
||||
// if user did not fill the first password field, we can't do anything
|
||||
const errorFirstInput = PasswordUtil.validatePassword(firstPassword, window.i18n);
|
||||
const errorFirstInput = PasswordUtil.validatePassword(firstPassword);
|
||||
if (errorFirstInput !== null) {
|
||||
this.setState({
|
||||
error: errorFirstInput,
|
||||
|
|
|
@ -83,8 +83,7 @@ export const SessionQuotedMessageComposition = (props: Props) => {
|
|||
|
||||
{hasImageAttachment && (
|
||||
<Image
|
||||
alt={getAlt(firstImageAttachment, window.i18n)}
|
||||
i18n={window.i18n}
|
||||
alt={getAlt(firstImageAttachment)}
|
||||
attachment={firstImageAttachment}
|
||||
height={100}
|
||||
width={100}
|
||||
|
|
|
@ -93,8 +93,7 @@ export const ConversationHeaderMenu = (props: PropsConversationHeaderMenu) => {
|
|||
left,
|
||||
isBlocked,
|
||||
timerOptions,
|
||||
onSetDisappearingMessages,
|
||||
window.i18n
|
||||
onSetDisappearingMessages
|
||||
)}
|
||||
{getNotificationForConvoMenuItem(
|
||||
isKickedFromGroup,
|
||||
|
@ -102,31 +101,22 @@ export const ConversationHeaderMenu = (props: PropsConversationHeaderMenu) => {
|
|||
isBlocked,
|
||||
notificationForConvo,
|
||||
currentNotificationSetting,
|
||||
onSetNotificationForConvo,
|
||||
window.i18n
|
||||
onSetNotificationForConvo
|
||||
)}
|
||||
{getBlockMenuItem(isMe, isPrivate, isBlocked, onBlockUser, onUnblockUser, window.i18n)}
|
||||
{getBlockMenuItem(isMe, isPrivate, isBlocked, onBlockUser, onUnblockUser)}
|
||||
|
||||
{getCopyMenuItem(isPublic, isGroup, onCopyPublicKey, window.i18n)}
|
||||
{getMarkAllReadMenuItem(onMarkAllRead, window.i18n)}
|
||||
{getChangeNicknameMenuItem(isMe, onChangeNickname, isGroup, window.i18n)}
|
||||
{getClearNicknameMenuItem(isMe, hasNickname, onClearNickname, isGroup, window.i18n)}
|
||||
{getDeleteMessagesMenuItem(isPublic, onDeleteMessages, window.i18n)}
|
||||
{getAddModeratorsMenuItem(isAdmin, isKickedFromGroup, onAddModerators, window.i18n)}
|
||||
{getRemoveModeratorsMenuItem(isAdmin, isKickedFromGroup, onRemoveModerators, window.i18n)}
|
||||
{getUpdateGroupNameMenuItem(isAdmin, isKickedFromGroup, left, onUpdateGroupName, window.i18n)}
|
||||
{getLeaveGroupMenuItem(isKickedFromGroup, left, isGroup, isPublic, onLeaveGroup, window.i18n)}
|
||||
{getCopyMenuItem(isPublic, isGroup, onCopyPublicKey)}
|
||||
{getMarkAllReadMenuItem(onMarkAllRead)}
|
||||
{getChangeNicknameMenuItem(isMe, onChangeNickname, isGroup)}
|
||||
{getClearNicknameMenuItem(isMe, hasNickname, onClearNickname, isGroup)}
|
||||
{getDeleteMessagesMenuItem(isPublic, onDeleteMessages)}
|
||||
{getAddModeratorsMenuItem(isAdmin, isKickedFromGroup, onAddModerators)}
|
||||
{getRemoveModeratorsMenuItem(isAdmin, isKickedFromGroup, onRemoveModerators)}
|
||||
{getUpdateGroupNameMenuItem(isAdmin, isKickedFromGroup, left, onUpdateGroupName)}
|
||||
{getLeaveGroupMenuItem(isKickedFromGroup, left, isGroup, isPublic, onLeaveGroup)}
|
||||
{/* TODO: add delete group */}
|
||||
{getInviteContactMenuItem(isGroup, isPublic, onInviteContacts, window.i18n)}
|
||||
{getDeleteContactMenuItem(
|
||||
isMe,
|
||||
isGroup,
|
||||
isPublic,
|
||||
left,
|
||||
isKickedFromGroup,
|
||||
onDeleteContact,
|
||||
window.i18n
|
||||
)}
|
||||
{getInviteContactMenuItem(isGroup, isPublic, onInviteContacts)}
|
||||
{getDeleteContactMenuItem(isMe, isGroup, isPublic, left, isKickedFromGroup, onDeleteContact)}
|
||||
</Menu>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -67,26 +67,17 @@ export const ConversationListItemContextMenu = (props: PropsContextConversationI
|
|||
type === ConversationTypeEnum.PRIVATE,
|
||||
isBlocked,
|
||||
onBlockContact,
|
||||
onUnblockContact,
|
||||
window.i18n
|
||||
onUnblockContact
|
||||
)}
|
||||
{getCopyMenuItem(isPublic, isGroup, onCopyPublicKey, window.i18n)}
|
||||
{getMarkAllReadMenuItem(onMarkAllRead, window.i18n)}
|
||||
{getChangeNicknameMenuItem(isMe, onChangeNickname, isGroup, window.i18n)}
|
||||
{getClearNicknameMenuItem(isMe, hasNickname, onClearNickname, isGroup, window.i18n)}
|
||||
{getCopyMenuItem(isPublic, isGroup, onCopyPublicKey)}
|
||||
{getMarkAllReadMenuItem(onMarkAllRead)}
|
||||
{getChangeNicknameMenuItem(isMe, onChangeNickname, isGroup)}
|
||||
{getClearNicknameMenuItem(isMe, hasNickname, onClearNickname, isGroup)}
|
||||
|
||||
{getDeleteMessagesMenuItem(isPublic, onDeleteMessages, window.i18n)}
|
||||
{getInviteContactMenuItem(isGroup, isPublic, onInviteContacts, window.i18n)}
|
||||
{getDeleteContactMenuItem(
|
||||
isMe,
|
||||
isGroup,
|
||||
isPublic,
|
||||
left,
|
||||
isKickedFromGroup,
|
||||
onDeleteContact,
|
||||
window.i18n
|
||||
)}
|
||||
{getLeaveGroupMenuItem(isKickedFromGroup, left, isGroup, isPublic, onLeaveGroup, window.i18n)}
|
||||
{getDeleteMessagesMenuItem(isPublic, onDeleteMessages)}
|
||||
{getInviteContactMenuItem(isGroup, isPublic, onInviteContacts)}
|
||||
{getDeleteContactMenuItem(isMe, isGroup, isPublic, left, isKickedFromGroup, onDeleteContact)}
|
||||
{getLeaveGroupMenuItem(isKickedFromGroup, left, isGroup, isPublic, onLeaveGroup)}
|
||||
</Menu>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
import React from 'react';
|
||||
import { LocalizerType } from '../../../types/Util';
|
||||
import { NotificationForConvoOption, TimerOption } from '../../conversation/ConversationHeader';
|
||||
import { Item, Submenu } from 'react-contexify';
|
||||
import {
|
||||
ConversationNotificationSetting,
|
||||
ConversationNotificationSettingType,
|
||||
} from '../../../models/conversation';
|
||||
import { ConversationNotificationSettingType } from '../../../models/conversation';
|
||||
|
||||
function showTimerOptions(
|
||||
isPublic: boolean,
|
||||
|
@ -90,11 +86,10 @@ function showInviteContact(isGroup: boolean, isPublic: boolean): boolean {
|
|||
export function getInviteContactMenuItem(
|
||||
isGroup: boolean | undefined,
|
||||
isPublic: boolean | undefined,
|
||||
action: any,
|
||||
i18n: LocalizerType
|
||||
action: any
|
||||
): JSX.Element | null {
|
||||
if (showInviteContact(Boolean(isGroup), Boolean(isPublic))) {
|
||||
return <Item onClick={action}>{i18n('inviteContacts')}</Item>;
|
||||
return <Item onClick={action}>{window.i18n('inviteContacts')}</Item>;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -105,8 +100,7 @@ export function getDeleteContactMenuItem(
|
|||
isPublic: boolean | undefined,
|
||||
isLeft: boolean | undefined,
|
||||
isKickedFromGroup: boolean | undefined,
|
||||
action: any,
|
||||
i18n: LocalizerType
|
||||
action: any
|
||||
): JSX.Element | null {
|
||||
if (
|
||||
showDeleteContact(
|
||||
|
@ -118,9 +112,9 @@ export function getDeleteContactMenuItem(
|
|||
)
|
||||
) {
|
||||
if (isPublic) {
|
||||
return <Item onClick={action}>{i18n('leaveGroup')}</Item>;
|
||||
return <Item onClick={action}>{window.i18n('leaveGroup')}</Item>;
|
||||
}
|
||||
return <Item onClick={action}>{i18n('delete')}</Item>;
|
||||
return <Item onClick={action}>{window.i18n('delete')}</Item>;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -130,13 +124,12 @@ export function getLeaveGroupMenuItem(
|
|||
left: boolean | undefined,
|
||||
isGroup: boolean | undefined,
|
||||
isPublic: boolean | undefined,
|
||||
action: any,
|
||||
i18n: LocalizerType
|
||||
action: any
|
||||
): JSX.Element | null {
|
||||
if (
|
||||
showLeaveGroup(Boolean(isKickedFromGroup), Boolean(left), Boolean(isGroup), Boolean(isPublic))
|
||||
) {
|
||||
return <Item onClick={action}>{i18n('leaveGroup')}</Item>;
|
||||
return <Item onClick={action}>{window.i18n('leaveGroup')}</Item>;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -145,11 +138,10 @@ export function getUpdateGroupNameMenuItem(
|
|||
isAdmin: boolean | undefined,
|
||||
isKickedFromGroup: boolean | undefined,
|
||||
left: boolean | undefined,
|
||||
action: any,
|
||||
i18n: LocalizerType
|
||||
action: any
|
||||
): JSX.Element | null {
|
||||
if (showUpdateGroupName(Boolean(isAdmin), Boolean(isKickedFromGroup), Boolean(left))) {
|
||||
return <Item onClick={action}>{i18n('editGroup')}</Item>;
|
||||
return <Item onClick={action}>{window.i18n('editGroup')}</Item>;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -157,11 +149,10 @@ export function getUpdateGroupNameMenuItem(
|
|||
export function getRemoveModeratorsMenuItem(
|
||||
isAdmin: boolean | undefined,
|
||||
isKickedFromGroup: boolean | undefined,
|
||||
action: any,
|
||||
i18n: LocalizerType
|
||||
action: any
|
||||
): JSX.Element | null {
|
||||
if (showRemoveModerators(Boolean(isAdmin), Boolean(isKickedFromGroup))) {
|
||||
return <Item onClick={action}>{i18n('removeModerators')}</Item>;
|
||||
return <Item onClick={action}>{window.i18n('removeModerators')}</Item>;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -169,11 +160,10 @@ export function getRemoveModeratorsMenuItem(
|
|||
export function getAddModeratorsMenuItem(
|
||||
isAdmin: boolean | undefined,
|
||||
isKickedFromGroup: boolean | undefined,
|
||||
action: any,
|
||||
i18n: LocalizerType
|
||||
action: any
|
||||
): JSX.Element | null {
|
||||
if (showAddModerators(Boolean(isAdmin), Boolean(isKickedFromGroup))) {
|
||||
return <Item onClick={action}>{i18n('addModerators')}</Item>;
|
||||
return <Item onClick={action}>{window.i18n('addModerators')}</Item>;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -181,18 +171,17 @@ export function getAddModeratorsMenuItem(
|
|||
export function getCopyMenuItem(
|
||||
isPublic: boolean | undefined,
|
||||
isGroup: boolean | undefined,
|
||||
action: any,
|
||||
i18n: LocalizerType
|
||||
action: any
|
||||
): JSX.Element | null {
|
||||
if (showCopyId(Boolean(isPublic), Boolean(isGroup))) {
|
||||
const copyIdLabel = isPublic ? i18n('copyOpenGroupURL') : i18n('copySessionID');
|
||||
const copyIdLabel = isPublic ? window.i18n('copyOpenGroupURL') : window.i18n('copySessionID');
|
||||
return <Item onClick={action}>{copyIdLabel}</Item>;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function getMarkAllReadMenuItem(action: any, i18n: LocalizerType): JSX.Element | null {
|
||||
return <Item onClick={action}>{i18n('markAllAsRead')}</Item>;
|
||||
export function getMarkAllReadMenuItem(action: any): JSX.Element | null {
|
||||
return <Item onClick={action}>{window.i18n('markAllAsRead')}</Item>;
|
||||
}
|
||||
|
||||
export function getDisappearingMenuItem(
|
||||
|
@ -201,8 +190,7 @@ export function getDisappearingMenuItem(
|
|||
left: boolean | undefined,
|
||||
isBlocked: boolean | undefined,
|
||||
timerOptions: Array<TimerOption>,
|
||||
action: any,
|
||||
i18n: LocalizerType
|
||||
action: any
|
||||
): JSX.Element | null {
|
||||
if (
|
||||
showTimerOptions(
|
||||
|
@ -216,7 +204,7 @@ export function getDisappearingMenuItem(
|
|||
return (
|
||||
// Remove the && false to make context menu work with RTL support
|
||||
<Submenu
|
||||
label={i18n('disappearingMessages') as any}
|
||||
label={window.i18n('disappearingMessages') as any}
|
||||
// rtl={isRtlMode && false}
|
||||
>
|
||||
{(timerOptions || []).map(item => (
|
||||
|
@ -241,15 +229,14 @@ export function getNotificationForConvoMenuItem(
|
|||
isBlocked: boolean | undefined,
|
||||
notificationForConvoOptions: Array<NotificationForConvoOption>,
|
||||
currentNotificationSetting: ConversationNotificationSettingType,
|
||||
action: (selected: ConversationNotificationSettingType) => any,
|
||||
i18n: LocalizerType
|
||||
action: (selected: ConversationNotificationSettingType) => any
|
||||
): JSX.Element | null {
|
||||
if (showNotificationConvo(Boolean(isKickedFromGroup), Boolean(left), Boolean(isBlocked))) {
|
||||
// const isRtlMode = isRtlBody();
|
||||
return (
|
||||
// Remove the && false to make context menu work with RTL support
|
||||
<Submenu
|
||||
label={i18n('notificationForConvo') as any}
|
||||
label={window.i18n('notificationForConvo') as any}
|
||||
// rtl={isRtlMode && false}
|
||||
>
|
||||
{(notificationForConvoOptions || []).map(item => (
|
||||
|
@ -277,11 +264,10 @@ export function isRtlBody(): boolean {
|
|||
export function getShowMemberMenuItem(
|
||||
isPublic: boolean | undefined,
|
||||
isGroup: boolean | undefined,
|
||||
action: any,
|
||||
i18n: LocalizerType
|
||||
action: any
|
||||
): JSX.Element | null {
|
||||
if (showMemberMenu(Boolean(isPublic), Boolean(isGroup))) {
|
||||
return <Item onClick={action}>{i18n('groupMembers')}</Item>;
|
||||
return <Item onClick={action}>{window.i18n('groupMembers')}</Item>;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -291,11 +277,10 @@ export function getBlockMenuItem(
|
|||
isPrivate: boolean | undefined,
|
||||
isBlocked: boolean | undefined,
|
||||
actionBlock: any,
|
||||
actionUnblock: any,
|
||||
i18n: LocalizerType
|
||||
actionUnblock: any
|
||||
): JSX.Element | null {
|
||||
if (showBlock(Boolean(isMe), Boolean(isPrivate))) {
|
||||
const blockTitle = isBlocked ? i18n('unblockUser') : i18n('blockUser');
|
||||
const blockTitle = isBlocked ? window.i18n('unblockUser') : window.i18n('blockUser');
|
||||
const blockHandler = isBlocked ? actionUnblock : actionBlock;
|
||||
return <Item onClick={blockHandler}>{blockTitle}</Item>;
|
||||
}
|
||||
|
@ -306,11 +291,10 @@ export function getClearNicknameMenuItem(
|
|||
isMe: boolean | undefined,
|
||||
hasNickname: boolean | undefined,
|
||||
action: any,
|
||||
isGroup: boolean | undefined,
|
||||
i18n: LocalizerType
|
||||
isGroup: boolean | undefined
|
||||
): JSX.Element | null {
|
||||
if (showClearNickname(Boolean(isMe), Boolean(hasNickname), Boolean(isGroup))) {
|
||||
return <Item onClick={action}>{i18n('clearNickname')}</Item>;
|
||||
return <Item onClick={action}>{window.i18n('clearNickname')}</Item>;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -318,22 +302,20 @@ export function getClearNicknameMenuItem(
|
|||
export function getChangeNicknameMenuItem(
|
||||
isMe: boolean | undefined,
|
||||
action: any,
|
||||
isGroup: boolean | undefined,
|
||||
i18n: LocalizerType
|
||||
isGroup: boolean | undefined
|
||||
): JSX.Element | null {
|
||||
if (showChangeNickname(Boolean(isMe), Boolean(isGroup))) {
|
||||
return <Item onClick={action}>{i18n('changeNickname')}</Item>;
|
||||
return <Item onClick={action}>{window.i18n('changeNickname')}</Item>;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function getDeleteMessagesMenuItem(
|
||||
isPublic: boolean | undefined,
|
||||
action: any,
|
||||
i18n: LocalizerType
|
||||
action: any
|
||||
): JSX.Element | null {
|
||||
if (showDeleteMessages(Boolean(isPublic))) {
|
||||
return <Item onClick={action}>{i18n('deleteMessages')}</Item>;
|
||||
return <Item onClick={action}>{window.i18n('deleteMessages')}</Item>;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ export function validatePassword(password: string, verifyPassword: string) {
|
|||
};
|
||||
}
|
||||
|
||||
const error = PasswordUtil.validatePassword(trimmedPassword, window.i18n);
|
||||
const error = PasswordUtil.validatePassword(trimmedPassword);
|
||||
if (error) {
|
||||
return {
|
||||
passwordErrorString: error,
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { LocalizerType } from '../../types/Util';
|
||||
import { fromHexToArray } from '../utils/String';
|
||||
|
||||
export class PubKey {
|
||||
|
@ -100,20 +99,17 @@ export class PubKey {
|
|||
/**
|
||||
* Returns a localized string of the error, or undefined in the given pubkey is valid.
|
||||
*/
|
||||
public static validateWithError(
|
||||
pubkey: string,
|
||||
i18n: LocalizerType = window.i18n
|
||||
): string | undefined {
|
||||
public static validateWithError(pubkey: string): string | undefined {
|
||||
// Check if it's hex
|
||||
const isHex = pubkey.replace(/[\s]*/g, '').match(/^[0-9a-fA-F]+$/);
|
||||
if (!isHex) {
|
||||
return i18n('invalidSessionId');
|
||||
return window.i18n('invalidSessionId');
|
||||
}
|
||||
|
||||
// Check if the pubkey length is 33 and leading with 05 or of length 32
|
||||
const len = pubkey.length;
|
||||
if ((len !== 33 * 2 || !/^05/.test(pubkey)) && len !== 32 * 2) {
|
||||
return i18n('invalidPubkeyFormat');
|
||||
return window.i18n('invalidPubkeyFormat');
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
|
|
@ -82,18 +82,6 @@ export interface ConversationType {
|
|||
avatarPath?: string; // absolute filepath to the avatar
|
||||
groupAdmins?: Array<string>; // admins for closed groups and moderators for open groups
|
||||
members?: Array<string>; // members for closed groups only
|
||||
|
||||
onClick?: () => void;
|
||||
onBlockContact?: () => void;
|
||||
onUnblockContact?: () => void;
|
||||
onCopyPublicKey?: () => void;
|
||||
onDeleteContact?: () => void;
|
||||
onLeaveGroup?: () => void;
|
||||
onDeleteMessages?: () => void;
|
||||
onInviteContacts?: () => void;
|
||||
onMarkAllRead?: () => void;
|
||||
onClearNickname?: () => void;
|
||||
onChangeNickname?: () => void;
|
||||
}
|
||||
|
||||
export type ConversationLookupType = {
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
import { LocalizerType } from '../../types/Util';
|
||||
|
||||
// State
|
||||
|
||||
export type UserStateType = {
|
||||
ourNumber: string;
|
||||
i18n: LocalizerType;
|
||||
};
|
||||
|
||||
// Actions
|
||||
|
@ -37,7 +34,6 @@ function userChanged(attributes: { ourNumber: string; ourPrimary: string }): Use
|
|||
function getEmptyState(): UserStateType {
|
||||
return {
|
||||
ourNumber: 'missing',
|
||||
i18n: () => 'missing',
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -10,8 +10,8 @@ import {
|
|||
|
||||
import { getIntl, getOurNumber } from './user';
|
||||
import { BlockedNumberController } from '../../util';
|
||||
import { LocalizerType } from '../../types/Util';
|
||||
import { ConversationTypeEnum } from '../../models/conversation';
|
||||
import { LocalizerType } from '../../types/Util';
|
||||
|
||||
export const getConversations = (state: StateType): ConversationsStateType => state.conversations;
|
||||
|
||||
|
@ -49,20 +49,20 @@ export const getMessagesOfSelectedConversation = createSelector(
|
|||
(state: ConversationsStateType): Array<MessageTypeInConvo> => state.messages
|
||||
);
|
||||
|
||||
function getConversationTitle(conversation: ConversationType, i18n: LocalizerType): string {
|
||||
function getConversationTitle(conversation: ConversationType, testingi18n?: LocalizerType): string {
|
||||
if (conversation.name) {
|
||||
return conversation.name;
|
||||
}
|
||||
|
||||
if (conversation.type === 'group') {
|
||||
return i18n('unknown');
|
||||
return (testingi18n || window.i18n)('unknown');
|
||||
}
|
||||
return conversation.id;
|
||||
}
|
||||
|
||||
const collator = new Intl.Collator();
|
||||
|
||||
export const _getConversationComparator = (i18n: LocalizerType) => {
|
||||
export const _getConversationComparator = (testingi18n?: LocalizerType) => {
|
||||
return (left: ConversationType, right: ConversationType): number => {
|
||||
const leftActiveAt = left.activeAt;
|
||||
const rightActiveAt = right.activeAt;
|
||||
|
@ -75,8 +75,8 @@ export const _getConversationComparator = (i18n: LocalizerType) => {
|
|||
if (leftActiveAt && rightActiveAt && leftActiveAt !== rightActiveAt) {
|
||||
return rightActiveAt - leftActiveAt;
|
||||
}
|
||||
const leftTitle = getConversationTitle(left, i18n || window?.i18n).toLowerCase();
|
||||
const rightTitle = getConversationTitle(right, i18n || window?.i18n).toLowerCase();
|
||||
const leftTitle = getConversationTitle(left, testingi18n).toLowerCase();
|
||||
const rightTitle = getConversationTitle(right, testingi18n).toLowerCase();
|
||||
|
||||
return collator.compare(leftTitle, rightTitle);
|
||||
};
|
||||
|
@ -120,7 +120,7 @@ export const _getLeftPaneLists = (
|
|||
};
|
||||
}
|
||||
|
||||
conversation.index = index;
|
||||
// conversation.index = index;
|
||||
|
||||
// Add Open Group to list as soon as the name has been set
|
||||
if (conversation.isPublic && (!conversation.name || conversation.name === 'Unknown group')) {
|
||||
|
|
|
@ -12,4 +12,7 @@ export const getOurNumber = createSelector(
|
|||
(state: UserStateType): string => state.ourNumber
|
||||
);
|
||||
|
||||
export const getIntl = createSelector(getUser, (state: UserStateType): LocalizerType => state.i18n);
|
||||
export const getIntl = createSelector(
|
||||
getUser,
|
||||
(state: UserStateType): LocalizerType => window.i18n
|
||||
);
|
||||
|
|
|
@ -6,7 +6,6 @@ import * as MIME from './MIME';
|
|||
import { saveURLAsFile } from '../util/saveURLAsFile';
|
||||
import { SignalService } from '../protobuf';
|
||||
import { isImageTypeSupported, isVideoTypeSupported } from '../util/GoogleChrome';
|
||||
import { LocalizerType } from './Util';
|
||||
import { fromHexToArray } from '../session/utils/String';
|
||||
import { getSodium } from '../session/crypto';
|
||||
|
||||
|
@ -225,8 +224,10 @@ export function getGridDimensions(attachments?: Array<AttachmentType>): null | D
|
|||
};
|
||||
}
|
||||
|
||||
export function getAlt(attachment: AttachmentType, i18n: LocalizerType): string {
|
||||
return isVideoAttachment(attachment) ? i18n('videoAttachmentAlt') : i18n('imageAttachmentAlt');
|
||||
export function getAlt(attachment: AttachmentType): string {
|
||||
return isVideoAttachment(attachment)
|
||||
? window.i18n('videoAttachmentAlt')
|
||||
: window.i18n('imageAttachmentAlt');
|
||||
}
|
||||
|
||||
// Migration-related attachment stuff
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
import moment from 'moment';
|
||||
import { LocalizerType } from '../types/Util';
|
||||
|
||||
const getExtendedFormats = (i18n: LocalizerType) => ({
|
||||
const getExtendedFormats = () => ({
|
||||
y: 'lll',
|
||||
M: `${i18n('timestampFormat_M') || 'MMM D'} LT`,
|
||||
M: `${window.i18n('timestampFormat_M') || 'MMM D'} LT`,
|
||||
d: 'ddd LT',
|
||||
});
|
||||
const getShortFormats = (i18n: LocalizerType) => ({
|
||||
const getShortFormats = () => ({
|
||||
y: 'll',
|
||||
M: i18n('timestampFormat_M') || 'MMM D',
|
||||
M: window.i18n('timestampFormat_M') || 'MMM D',
|
||||
d: 'ddd',
|
||||
});
|
||||
|
||||
|
@ -19,13 +18,9 @@ function isYear(timestamp: moment.Moment) {
|
|||
return year === targetYear;
|
||||
}
|
||||
|
||||
export function formatRelativeTime(
|
||||
rawTimestamp: number | Date,
|
||||
options: { extended?: boolean; i18n: LocalizerType }
|
||||
) {
|
||||
const { extended, i18n } = options;
|
||||
|
||||
const formats = extended ? getExtendedFormats(i18n) : getShortFormats(i18n);
|
||||
export function formatRelativeTime(rawTimestamp: number | Date, options: { extended?: boolean }) {
|
||||
const { extended } = options;
|
||||
const formats = extended ? getExtendedFormats() : getShortFormats();
|
||||
const timestamp = moment(rawTimestamp);
|
||||
const now = moment();
|
||||
const diff = moment.duration(now.diff(timestamp));
|
||||
|
|
|
@ -19,24 +19,24 @@ export const generateHash = (phrase: string) => phrase && sha512(phrase.trim());
|
|||
export const matchesHash = (phrase: string | null, hash: string) =>
|
||||
phrase && sha512(phrase.trim()) === hash.trim();
|
||||
|
||||
export const validatePassword = (phrase: string, i18n?: LocalizerType) => {
|
||||
export const validatePassword = (phrase: string) => {
|
||||
if (typeof phrase !== 'string') {
|
||||
return i18n ? i18n('passwordTypeError') : ERRORS.TYPE;
|
||||
return window?.i18n ? window?.i18n('passwordTypeError') : ERRORS.TYPE;
|
||||
}
|
||||
|
||||
const trimmed = phrase.trim();
|
||||
if (trimmed.length === 0) {
|
||||
return i18n ? i18n('noGivenPassword') : ERRORS.LENGTH;
|
||||
return window?.i18n ? window?.i18n('noGivenPassword') : ERRORS.LENGTH;
|
||||
}
|
||||
|
||||
if (trimmed.length < 6 || trimmed.length > MAX_PASSWORD_LENGTH) {
|
||||
return i18n ? i18n('passwordLengthError') : ERRORS.LENGTH;
|
||||
return window?.i18n ? window?.i18n('passwordLengthError') : ERRORS.LENGTH;
|
||||
}
|
||||
|
||||
// Restrict characters to letters, numbers and symbols
|
||||
const characterRegex = /^[a-zA-Z0-9-!()._`~@#$%^&*+=[\]{}|<>,;: ]+$/;
|
||||
if (!characterRegex.test(trimmed)) {
|
||||
return i18n ? i18n('passwordCharacterError') : ERRORS.CHARACTER;
|
||||
return window?.i18n ? window?.i18n('passwordCharacterError') : ERRORS.CHARACTER;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
Loading…
Reference in New Issue