Add RTL Support (#1135)
This commit is contained in:
parent
32c7b083c8
commit
b2242f7fe4
@ -74,6 +74,7 @@
|
|||||||
align-self: center;
|
align-self: center;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
text-align: initial;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content-row {
|
.content-row {
|
||||||
|
|||||||
@ -237,7 +237,7 @@ const Audio: FC<OwnProps & StateProps> = ({
|
|||||||
<>
|
<>
|
||||||
<div className={contentClassName}>
|
<div className={contentClassName}>
|
||||||
<div className="content-row">
|
<div className="content-row">
|
||||||
<p className="title">{renderText(getFirstLine())}</p>
|
<p className="title" dir="auto">{renderText(getFirstLine())}</p>
|
||||||
|
|
||||||
<div className="message-date">
|
<div className="message-date">
|
||||||
{date && (
|
{date && (
|
||||||
@ -253,7 +253,7 @@ const Audio: FC<OwnProps & StateProps> = ({
|
|||||||
|
|
||||||
{showSeekline && renderSeekline(playProgress, bufferedProgress, seekHandlers)}
|
{showSeekline && renderSeekline(playProgress, bufferedProgress, seekHandlers)}
|
||||||
{!showSeekline && (
|
{!showSeekline && (
|
||||||
<p className="duration">
|
<p className="duration" dir="auto">
|
||||||
{playProgress > 0 ? `${formatMediaDuration(duration * playProgress)} / ` : undefined}
|
{playProgress > 0 ? `${formatMediaDuration(duration * playProgress)} / ` : undefined}
|
||||||
{getSecondLine()}
|
{getSecondLine()}
|
||||||
</p>
|
</p>
|
||||||
@ -318,10 +318,10 @@ function renderAudio(
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="content">
|
<div className="content">
|
||||||
<p className="title">{renderText(title || fileName)}</p>
|
<p className="title" dir="auto">{renderText(title || fileName)}</p>
|
||||||
{showSeekline && renderSeekline(playProgress, bufferedProgress, seekHandlers)}
|
{showSeekline && renderSeekline(playProgress, bufferedProgress, seekHandlers)}
|
||||||
{!showSeekline && (
|
{!showSeekline && (
|
||||||
<div className="meta">
|
<div className="meta" dir="auto">
|
||||||
<span className="performer">{renderText(performer || 'Unknown')}</span>
|
<span className="performer">{renderText(performer || 'Unknown')}</span>
|
||||||
{date && (
|
{date && (
|
||||||
<>
|
<>
|
||||||
@ -333,7 +333,7 @@ function renderAudio(
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<p className="duration">
|
<p className="duration" dir="auto">
|
||||||
{playProgress > 0 ? `${formatMediaDuration(duration * playProgress)} / ` : undefined}
|
{playProgress > 0 ? `${formatMediaDuration(duration * playProgress)} / ` : undefined}
|
||||||
{formatMediaDuration(duration)}
|
{formatMediaDuration(duration)}
|
||||||
</p>
|
</p>
|
||||||
@ -345,7 +345,7 @@ function renderVoice(voice: ApiVoice, renderedWaveform: any, isMediaUnread?: boo
|
|||||||
return (
|
return (
|
||||||
<div className="content">
|
<div className="content">
|
||||||
{renderedWaveform}
|
{renderedWaveform}
|
||||||
<p className="voice-duration">
|
<p className="voice-duration" dir="auto">
|
||||||
{formatMediaDuration(voice.duration)}
|
{formatMediaDuration(voice.duration)}
|
||||||
{isMediaUnread && <span>•</span>}
|
{isMediaUnread && <span>•</span>}
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@ -63,8 +63,8 @@ const EmbeddedMessage: FC<OwnProps> = ({
|
|||||||
>
|
>
|
||||||
{mediaThumbnail && renderPictogram(pictogramId, mediaThumbnail, mediaBlobUrl, isRoundVideo)}
|
{mediaThumbnail && renderPictogram(pictogramId, mediaThumbnail, mediaBlobUrl, isRoundVideo)}
|
||||||
<div className="message-text">
|
<div className="message-text">
|
||||||
<div className="message-title">{renderText(senderTitle || title || NBSP)}</div>
|
<div className="message-title" dir="auto">{renderText(senderTitle || title || NBSP)}</div>
|
||||||
<p>
|
<p dir="auto">
|
||||||
{!message ? (
|
{!message ? (
|
||||||
customText || NBSP
|
customText || NBSP
|
||||||
) : isActionMessage(message) ? (
|
) : isActionMessage(message) ? (
|
||||||
|
|||||||
@ -113,7 +113,7 @@ const File: FC<OwnProps> = ({
|
|||||||
) : (
|
) : (
|
||||||
<div className={`file-icon ${color}`}>
|
<div className={`file-icon ${color}`}>
|
||||||
{extension.length <= 4 && (
|
{extension.length <= 4 && (
|
||||||
<span className="file-ext">{extension}</span>
|
<span className="file-ext" dir="auto">{extension}</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -129,8 +129,8 @@ const File: FC<OwnProps> = ({
|
|||||||
{onClick && <i className={buildClassName('icon-download', shouldSpinnerRender && 'hidden')} />}
|
{onClick && <i className={buildClassName('icon-download', shouldSpinnerRender && 'hidden')} />}
|
||||||
</div>
|
</div>
|
||||||
<div className="file-info">
|
<div className="file-info">
|
||||||
<div className="file-title">{renderText(name)}</div>
|
<div className="file-title" dir="auto">{renderText(name)}</div>
|
||||||
<div className="file-subtitle">
|
<div className="file-subtitle" dir="auto">
|
||||||
<span>
|
<span>
|
||||||
{isTransferring && transferProgress ? `${Math.round(transferProgress * 100)}%` : sizeString}
|
{isTransferring && transferProgress ? `${Math.round(transferProgress * 100)}%` : sizeString}
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@ -84,7 +84,7 @@ const GroupChatInfo: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
function renderStatusOrTyping() {
|
function renderStatusOrTyping() {
|
||||||
if (withUpdatingStatus && !areMessagesLoaded && !isRestricted) {
|
if (withUpdatingStatus && !areMessagesLoaded && !isRestricted) {
|
||||||
return (
|
return (
|
||||||
<span className="status">{lang('Updating')}</span>
|
<span className="status" dir="auto">{lang('Updating')}</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,7 +98,7 @@ const GroupChatInfo: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
|
|
||||||
if (withChatType) {
|
if (withChatType) {
|
||||||
return (
|
return (
|
||||||
<div className="status">{lang(getChatTypeString(chat))}</div>
|
<div className="status" dir="auto">{lang(getChatTypeString(chat))}</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,7 +125,7 @@ const GroupChatInfo: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
/>
|
/>
|
||||||
<div className="info">
|
<div className="info">
|
||||||
<div className="title">
|
<div className="title">
|
||||||
<h3>{renderText(getChatTitle(lang, chat))}</h3>
|
<h3 dir="auto">{renderText(getChatTitle(lang, chat))}</h3>
|
||||||
{chat.isVerified && <VerifiedIcon />}
|
{chat.isVerified && <VerifiedIcon />}
|
||||||
</div>
|
</div>
|
||||||
{renderStatusOrTyping()}
|
{renderStatusOrTyping()}
|
||||||
|
|||||||
@ -85,7 +85,7 @@ const PickerSelectedItem: FC<OwnProps & StateProps> = ({
|
|||||||
>
|
>
|
||||||
{iconElement}
|
{iconElement}
|
||||||
{!isMinimized && (
|
{!isMinimized && (
|
||||||
<div className="item-name">
|
<div className="item-name" dir="auto">
|
||||||
{titleText}
|
{titleText}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -83,13 +83,13 @@ const PrivateChatInfo: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
function renderStatusOrTyping() {
|
function renderStatusOrTyping() {
|
||||||
if (status) {
|
if (status) {
|
||||||
return (
|
return (
|
||||||
<span className="status">{status}</span>
|
<span className="status" dir="auto">{status}</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (withUpdatingStatus && !areMessagesLoaded) {
|
if (withUpdatingStatus && !areMessagesLoaded) {
|
||||||
return (
|
return (
|
||||||
<span className="status">{lang('Updating')}</span>
|
<span className="status" dir="auto">{lang('Updating')}</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +104,7 @@ const PrivateChatInfo: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
return (
|
return (
|
||||||
<div className={`status ${isUserOnline(user) ? 'online' : ''}`}>
|
<div className={`status ${isUserOnline(user) ? 'online' : ''}`}>
|
||||||
{withUsername && user.username && <span className="handle">{user.username}</span>}
|
{withUsername && user.username && <span className="handle">{user.username}</span>}
|
||||||
<span className="user-status">{getUserStatus(lang, user)}</span>
|
<span className="user-status" dir="auto">{getUserStatus(lang, user)}</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -125,7 +125,7 @@ const PrivateChatInfo: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="title">
|
<div className="title">
|
||||||
<h3>{fullName && renderText(fullName)}</h3>
|
<h3 dir="auto">{fullName && renderText(fullName)}</h3>
|
||||||
{user && user.isVerified && <VerifiedIcon />}
|
{user && user.isVerified && <VerifiedIcon />}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -23,7 +23,7 @@ const TypingStatus: FC<OwnProps & StateProps> = ({ typingStatus, typingUser }) =
|
|||||||
return (
|
return (
|
||||||
<p className="typing-status">
|
<p className="typing-status">
|
||||||
{typingUserName && (
|
{typingUserName && (
|
||||||
<span className="sender-name">{renderText(typingUserName)}</span>
|
<span className="sender-name" dir="auto">{renderText(typingUserName)}</span>
|
||||||
)}
|
)}
|
||||||
{typingStatus.action}
|
{typingStatus.action}
|
||||||
<span className="ellipsis" />
|
<span className="ellipsis" />
|
||||||
|
|||||||
@ -229,6 +229,7 @@ function processEntity(
|
|||||||
<a
|
<a
|
||||||
onClick={handleBotCommandClick}
|
onClick={handleBotCommandClick}
|
||||||
className="text-entity-link"
|
className="text-entity-link"
|
||||||
|
dir="auto"
|
||||||
>
|
>
|
||||||
{renderMessagePart(renderedContent)}
|
{renderMessagePart(renderedContent)}
|
||||||
</a>
|
</a>
|
||||||
@ -238,6 +239,7 @@ function processEntity(
|
|||||||
<a
|
<a
|
||||||
onClick={handleHashtagClick}
|
onClick={handleHashtagClick}
|
||||||
className="text-entity-link"
|
className="text-entity-link"
|
||||||
|
dir="auto"
|
||||||
>
|
>
|
||||||
{renderMessagePart(renderedContent)}
|
{renderMessagePart(renderedContent)}
|
||||||
</a>
|
</a>
|
||||||
@ -247,6 +249,7 @@ function processEntity(
|
|||||||
<a
|
<a
|
||||||
onClick={handleHashtagClick}
|
onClick={handleHashtagClick}
|
||||||
className="text-entity-link"
|
className="text-entity-link"
|
||||||
|
dir="auto"
|
||||||
>
|
>
|
||||||
{renderMessagePart(renderedContent)}
|
{renderMessagePart(renderedContent)}
|
||||||
</a>
|
</a>
|
||||||
@ -260,6 +263,7 @@ function processEntity(
|
|||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
className="text-entity-link"
|
className="text-entity-link"
|
||||||
|
dir="auto"
|
||||||
>
|
>
|
||||||
{renderMessagePart(renderedContent)}
|
{renderMessagePart(renderedContent)}
|
||||||
</a>
|
</a>
|
||||||
@ -385,6 +389,7 @@ function processEntityAsHtml(
|
|||||||
data-entity-type="${ApiMessageEntityTypes.MentionName}"
|
data-entity-type="${ApiMessageEntityTypes.MentionName}"
|
||||||
data-user-id="${entity.userId}"
|
data-user-id="${entity.userId}"
|
||||||
contenteditable="false"
|
contenteditable="false"
|
||||||
|
dir="auto"
|
||||||
>${renderedContent}</a>`;
|
>${renderedContent}</a>`;
|
||||||
case ApiMessageEntityTypes.Url:
|
case ApiMessageEntityTypes.Url:
|
||||||
case ApiMessageEntityTypes.TextUrl:
|
case ApiMessageEntityTypes.TextUrl:
|
||||||
@ -392,6 +397,7 @@ function processEntityAsHtml(
|
|||||||
class="text-entity-link"
|
class="text-entity-link"
|
||||||
href=${getLinkUrl(rawEntityText, entity)}
|
href=${getLinkUrl(rawEntityText, entity)}
|
||||||
data-entity-type="${entity.type}"
|
data-entity-type="${entity.type}"
|
||||||
|
dir="auto"
|
||||||
>${renderedContent}</a>`;
|
>${renderedContent}</a>`;
|
||||||
default:
|
default:
|
||||||
return renderedContent;
|
return renderedContent;
|
||||||
|
|||||||
@ -82,6 +82,7 @@
|
|||||||
padding-right: 0.25rem;
|
padding-right: 0.25rem;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
color: var(--color-text-secondary);
|
color: var(--color-text-secondary);
|
||||||
|
unicode-bidi: plaintext;
|
||||||
|
|
||||||
.sender-name {
|
.sender-name {
|
||||||
color: var(--color-text);
|
color: var(--color-text);
|
||||||
|
|||||||
@ -193,7 +193,7 @@ const Chat: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
|
|
||||||
if (draft && draft.text.length) {
|
if (draft && draft.text.length) {
|
||||||
return (
|
return (
|
||||||
<p className="last-message">
|
<p className="last-message" dir="auto">
|
||||||
<span className="draft">{lang('Draft')}</span>
|
<span className="draft">{lang('Draft')}</span>
|
||||||
{renderText(draft.text)}
|
{renderText(draft.text)}
|
||||||
</p>
|
</p>
|
||||||
@ -210,7 +210,7 @@ const Chat: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
: lastMessageSender;
|
: lastMessageSender;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<p className="last-message">
|
<p className="last-message" dir="auto">
|
||||||
{renderText(renderActionMessageText(
|
{renderText(renderActionMessageText(
|
||||||
lang,
|
lang,
|
||||||
lastMessage,
|
lastMessage,
|
||||||
@ -227,7 +227,7 @@ const Chat: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
const senderName = getMessageSenderName(lang, chatId, lastMessageSender);
|
const senderName = getMessageSenderName(lang, chatId, lastMessageSender);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<p className="last-message">
|
<p className="last-message" dir="auto">
|
||||||
{senderName && (
|
{senderName && (
|
||||||
<span className="sender-name">{renderText(senderName)}</span>
|
<span className="sender-name">{renderText(senderName)}</span>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -82,7 +82,7 @@ const ContactList: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
</ListItem>
|
</ListItem>
|
||||||
))
|
))
|
||||||
) : viewportIds && !viewportIds.length ? (
|
) : viewportIds && !viewportIds.length ? (
|
||||||
<p className="no-results" key="no-results">
|
<p className="no-results" key="no-results" dir="auto">
|
||||||
{filter.length ? 'No contacts matched your search.' : 'Contact list is empty.'}
|
{filter.length ? 'No contacts matched your search.' : 'Contact list is empty.'}
|
||||||
</p>
|
</p>
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
@ -86,7 +86,7 @@ const ChatMessage: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
<div className="info">
|
<div className="info">
|
||||||
<div className="info-row">
|
<div className="info-row">
|
||||||
<div className="title">
|
<div className="title">
|
||||||
<h3>{renderText(getChatTitle(lang, chat, privateChatUser))}</h3>
|
<h3 dir="auto">{renderText(getChatTitle(lang, chat, privateChatUser))}</h3>
|
||||||
{chat.isVerified && <VerifiedIcon />}
|
{chat.isVerified && <VerifiedIcon />}
|
||||||
</div>
|
</div>
|
||||||
<div className="message-date">
|
<div className="message-date">
|
||||||
@ -97,7 +97,7 @@ const ChatMessage: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div className="subtitle">
|
<div className="subtitle">
|
||||||
<div className="message">
|
<div className="message" dir="auto">
|
||||||
{renderMessageSummary(lang, message, mediaBlobUrl || mediaThumbnail, searchQuery, isRoundVideo)}
|
{renderMessageSummary(lang, message, mediaBlobUrl || mediaThumbnail, searchQuery, isRoundVideo)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -95,15 +95,24 @@
|
|||||||
.ListItem.search-result {
|
.ListItem.search-result {
|
||||||
.ChatInfo {
|
.ChatInfo {
|
||||||
.handle {
|
.handle {
|
||||||
|
unicode-bidi: plaintext;
|
||||||
color: var(--color-primary);
|
color: var(--color-primary);
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
content: '@';
|
content: '@';
|
||||||
|
html[lang=ar] & {
|
||||||
|
content: ' ،@';
|
||||||
|
margin-inline-end: .25rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&::after {
|
&::after {
|
||||||
content: ', ';
|
content: ', ';
|
||||||
color: var(--color-text-secondary);
|
color: var(--color-text-secondary);
|
||||||
|
|
||||||
|
html[lang=ar] & {
|
||||||
|
content: '';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -74,7 +74,7 @@ const SettingsPrivacy: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
<div className="multiline-menu-item">
|
<div className="multiline-menu-item">
|
||||||
<span className="title">{lang('BlockedUsers')}</span>
|
<span className="title">{lang('BlockedUsers')}</span>
|
||||||
{blockedCount > 0 && (
|
{blockedCount > 0 && (
|
||||||
<span className="subtitle">
|
<span className="subtitle" dir="auto">
|
||||||
{lang('Users', blockedCount)}
|
{lang('Users', blockedCount)}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
@ -89,7 +89,9 @@ const SettingsPrivacy: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
>
|
>
|
||||||
<div className="multiline-menu-item">
|
<div className="multiline-menu-item">
|
||||||
<span className="title">{lang('TwoStepVerification')}</span>
|
<span className="title">{lang('TwoStepVerification')}</span>
|
||||||
<span className="subtitle">{lang(hasPassword ? 'PasswordOn' : 'PasswordOff')}</span>
|
<span className="subtitle" dir="auto">
|
||||||
|
{lang(hasPassword ? 'PasswordOn' : 'PasswordOff')}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem
|
<ListItem
|
||||||
@ -100,7 +102,7 @@ const SettingsPrivacy: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
<div className="multiline-menu-item">
|
<div className="multiline-menu-item">
|
||||||
<span className="title">{lang('SessionsTitle')}</span>
|
<span className="title">{lang('SessionsTitle')}</span>
|
||||||
{sessionsCount > 0 && (
|
{sessionsCount > 0 && (
|
||||||
<span className="subtitle">
|
<span className="subtitle" dir="auto">
|
||||||
{sessionsCount === 1 ? '1 session' : `${sessionsCount} sessions`}
|
{sessionsCount === 1 ? '1 session' : `${sessionsCount} sessions`}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
@ -117,7 +119,9 @@ const SettingsPrivacy: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
>
|
>
|
||||||
<div className="multiline-menu-item">
|
<div className="multiline-menu-item">
|
||||||
<span className="title">{lang('PrivacyPhoneTitle')}</span>
|
<span className="title">{lang('PrivacyPhoneTitle')}</span>
|
||||||
<span className="subtitle">{getVisibilityValue(visibilityPrivacyPhoneNumber)}</span>
|
<span className="subtitle" dir="auto">
|
||||||
|
{getVisibilityValue(visibilityPrivacyPhoneNumber)}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem
|
<ListItem
|
||||||
@ -126,7 +130,9 @@ const SettingsPrivacy: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
>
|
>
|
||||||
<div className="multiline-menu-item">
|
<div className="multiline-menu-item">
|
||||||
<span className="title">{lang('LastSeenTitle')}</span>
|
<span className="title">{lang('LastSeenTitle')}</span>
|
||||||
<span className="subtitle">{getVisibilityValue(visibilityPrivacyLastSeen)}</span>
|
<span className="subtitle" dir="auto">
|
||||||
|
{getVisibilityValue(visibilityPrivacyLastSeen)}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem
|
<ListItem
|
||||||
@ -135,7 +141,9 @@ const SettingsPrivacy: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
>
|
>
|
||||||
<div className="multiline-menu-item">
|
<div className="multiline-menu-item">
|
||||||
<span className="title">{lang('PrivacyProfilePhotoTitle')}</span>
|
<span className="title">{lang('PrivacyProfilePhotoTitle')}</span>
|
||||||
<span className="subtitle">{getVisibilityValue(visibilityPrivacyProfilePhoto)}</span>
|
<span className="subtitle" dir="auto">
|
||||||
|
{getVisibilityValue(visibilityPrivacyProfilePhoto)}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem
|
<ListItem
|
||||||
@ -144,7 +152,9 @@ const SettingsPrivacy: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
>
|
>
|
||||||
<div className="multiline-menu-item">
|
<div className="multiline-menu-item">
|
||||||
<span className="title">{lang('PrivacyForwardsTitle')}</span>
|
<span className="title">{lang('PrivacyForwardsTitle')}</span>
|
||||||
<span className="subtitle">{getVisibilityValue(visibilityPrivacyForwarding)}</span>
|
<span className="subtitle" dir="auto">
|
||||||
|
{getVisibilityValue(visibilityPrivacyForwarding)}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem
|
<ListItem
|
||||||
@ -153,7 +163,9 @@ const SettingsPrivacy: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
>
|
>
|
||||||
<div className="multiline-menu-item">
|
<div className="multiline-menu-item">
|
||||||
<span className="title">{lang('WhoCanAddMe')}</span>
|
<span className="title">{lang('WhoCanAddMe')}</span>
|
||||||
<span className="subtitle">{getVisibilityValue(visibilityPrivacyGroupChats)}</span>
|
<span className="subtitle" dir="auto">
|
||||||
|
{getVisibilityValue(visibilityPrivacyGroupChats)}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -67,13 +67,13 @@ const SettingsPrivacyBlockedUsers: FC<StateProps & DispatchProps> = ({
|
|||||||
style={`top: ${(viewportOffset + i) * CHAT_HEIGHT_PX}px;`}
|
style={`top: ${(viewportOffset + i) * CHAT_HEIGHT_PX}px;`}
|
||||||
>
|
>
|
||||||
<Avatar size="medium" user={user} chat={chat} />
|
<Avatar size="medium" user={user} chat={chat} />
|
||||||
<div className="contact-info">
|
<div className="contact-info" dir="auto">
|
||||||
<h3>{renderText((isPrivate ? getUserFullName(user) : getChatTitle(lang, chat!)) || '')}</h3>
|
<h3 dir="auto">{renderText((isPrivate ? getUserFullName(user) : getChatTitle(lang, chat!)) || '')}</h3>
|
||||||
{user && user.phoneNumber && (
|
{user && user.phoneNumber && (
|
||||||
<div className="contact-phone">{formatPhoneNumberWithCode(user.phoneNumber)}</div>
|
<div className="contact-phone" dir="auto">{formatPhoneNumberWithCode(user.phoneNumber)}</div>
|
||||||
)}
|
)}
|
||||||
{user && !user.phoneNumber && user.username && (
|
{user && !user.phoneNumber && user.username && (
|
||||||
<div className="contact-username">@{user.username}</div>
|
<div className="contact-username" dir="auto">@{user.username}</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
|
|||||||
@ -121,7 +121,7 @@ const SettingsFoldersChatsPicker: FC<OwnProps> = ({
|
|||||||
ripple
|
ripple
|
||||||
>
|
>
|
||||||
<i className={`icon-${type.icon}`} />
|
<i className={`icon-${type.icon}`} />
|
||||||
<h3 className="chat-type">{lang(type.title)}</h3>
|
<h3 className="chat-type" dir="auto">{lang(type.title)}</h3>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
label=""
|
label=""
|
||||||
checked={selectedChatTypes.includes(type.key)}
|
checked={selectedChatTypes.includes(type.key)}
|
||||||
@ -179,7 +179,9 @@ const SettingsFoldersChatsPicker: FC<OwnProps> = ({
|
|||||||
placeholder={lang('Search')}
|
placeholder={lang('Search')}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<p className="max-items-reached">{`Sorry, you can't add more than ${MAX_CHATS} chats.`}</p>
|
<p className="max-items-reached" dir="auto">
|
||||||
|
{`Sorry, you can't add more than ${MAX_CHATS} chats.`}
|
||||||
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<InfiniteScroll
|
<InfiniteScroll
|
||||||
|
|||||||
@ -139,7 +139,7 @@ const SettingsFoldersMain: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p className="settings-item-description mb-3">
|
<p className="settings-item-description mb-3" dir="auto">
|
||||||
{lang('CreateNewFilterInfo')}
|
{lang('CreateNewFilterInfo')}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|||||||
@ -32,7 +32,7 @@ const SettingsTwoFaCongratulations: FC<OwnProps & StateProps> = ({
|
|||||||
<div className="settings-content-header">
|
<div className="settings-content-header">
|
||||||
<AnimatedEmoji sticker={animatedEmoji} />
|
<AnimatedEmoji sticker={animatedEmoji} />
|
||||||
|
|
||||||
<p className="settings-item-description mb-3">
|
<p className="settings-item-description mb-3" dir="auto">
|
||||||
{lang('TwoStepVerificationPasswordSetInfo')}
|
{lang('TwoStepVerificationPasswordSetInfo')}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -29,7 +29,7 @@ const SettingsTwoFaEnabled: FC<OwnProps & StateProps> = ({
|
|||||||
<div className="settings-content-header">
|
<div className="settings-content-header">
|
||||||
<AnimatedEmoji sticker={animatedEmoji} />
|
<AnimatedEmoji sticker={animatedEmoji} />
|
||||||
|
|
||||||
<p className="settings-item-description mb-3">
|
<p className="settings-item-description mb-3" dir="auto">
|
||||||
{renderText(lang('EnabledPasswordText'), ['br'])}
|
{renderText(lang('EnabledPasswordText'), ['br'])}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -25,7 +25,7 @@ const SettingsTwoFaStart: FC<OwnProps & StateProps> = ({ animatedEmoji, onStart
|
|||||||
<div className="settings-content-header">
|
<div className="settings-content-header">
|
||||||
<AnimatedEmoji sticker={animatedEmoji} />
|
<AnimatedEmoji sticker={animatedEmoji} />
|
||||||
|
|
||||||
<p className="settings-item-description mb-3">
|
<p className="settings-item-description mb-3" dir="auto">
|
||||||
{lang('SetAdditionalPasswordInfo')}
|
{lang('SetAdditionalPasswordInfo')}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -31,6 +31,7 @@
|
|||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
font-size: 1.25rem;
|
font-size: 1.25rem;
|
||||||
line-height: 1.75rem;
|
line-height: 1.75rem;
|
||||||
|
unicode-bidi: plaintext;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -46,7 +46,7 @@ const MediaViewerFooter: FC<OwnProps> = ({ text = '', isHideable, onClick }) =>
|
|||||||
<div className={`MediaViewerFooter ${isHideable ? 'hideable' : ''}`} onClick={stopEvent}>
|
<div className={`MediaViewerFooter ${isHideable ? 'hideable' : ''}`} onClick={stopEvent}>
|
||||||
{text && (
|
{text && (
|
||||||
<div className="media-viewer-footer-content" onClick={onClick}>
|
<div className="media-viewer-footer-content" onClick={onClick}>
|
||||||
<p className={`media-text custom-scroll ${isMultiline ? 'multiline' : ''}`}>{text}</p>
|
<p className={`media-text custom-scroll ${isMultiline ? 'multiline' : ''}`} dir="auto">{text}</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -58,10 +58,10 @@ const SenderInfo: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
<Avatar key={sender.id} size="medium" user={sender as ApiUser} />
|
<Avatar key={sender.id} size="medium" user={sender as ApiUser} />
|
||||||
)}
|
)}
|
||||||
<div className="meta">
|
<div className="meta">
|
||||||
<div className="title">
|
<div className="title" dir="auto">
|
||||||
{senderTitle && renderText(senderTitle)}
|
{senderTitle && renderText(senderTitle)}
|
||||||
</div>
|
</div>
|
||||||
<div className="date">
|
<div className="date" dir="auto">
|
||||||
{isAvatar ? lang('lng_mediaview_profile_photo') : formatMediaDateTime(lang, message!.date * 1000)}
|
{isAvatar ? lang('lng_mediaview_profile_photo') : formatMediaDateTime(lang, message!.date * 1000)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -102,9 +102,9 @@ function renderAudio(audio: ApiAudio) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="title">{renderText(title || fileName)}</div>
|
<div className="title" dir="auto">{renderText(title || fileName)}</div>
|
||||||
{performer && (
|
{performer && (
|
||||||
<div className="subtitle">{renderText(performer)}</div>
|
<div className="subtitle" dir="auto">{renderText(performer)}</div>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
@ -113,8 +113,8 @@ function renderAudio(audio: ApiAudio) {
|
|||||||
function renderVoice(subtitle: string, senderName?: string) {
|
function renderVoice(subtitle: string, senderName?: string) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="title">{senderName && renderText(senderName)}</div>
|
<div className="title" dir="auto">{senderName && renderText(senderName)}</div>
|
||||||
<div className="subtitle">{subtitle}</div>
|
<div className="subtitle" dir="auto">{subtitle}</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -86,10 +86,10 @@ const HeaderPinnedMessage: FC<OwnProps> = ({
|
|||||||
/>
|
/>
|
||||||
{mediaThumbnail && renderPictogram(mediaThumbnail, mediaBlobUrl)}
|
{mediaThumbnail && renderPictogram(mediaThumbnail, mediaBlobUrl)}
|
||||||
<div className="message-text">
|
<div className="message-text">
|
||||||
<div className="title">
|
<div className="title" dir="auto">
|
||||||
{customTitle || `${lang('PinnedMessage')} ${index > 0 ? `#${count - index}` : ''}`}
|
{customTitle || `${lang('PinnedMessage')} ${index > 0 ? `#${count - index}` : ''}`}
|
||||||
</div>
|
</div>
|
||||||
<p>{renderText(text)}</p>
|
<p dir="auto">{renderText(text)}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<RippleEffect />
|
<RippleEffect />
|
||||||
|
|||||||
@ -702,7 +702,7 @@ function renderMessages(
|
|||||||
teactFastList
|
teactFastList
|
||||||
>
|
>
|
||||||
<div className="sticky-date" key="date-header">
|
<div className="sticky-date" key="date-header">
|
||||||
<span>
|
<span dir="auto">
|
||||||
{isSchedule && dateGroup.originalDate === SCHEDULED_WHEN_ONLINE && (
|
{isSchedule && dateGroup.originalDate === SCHEDULED_WHEN_ONLINE && (
|
||||||
lang('MessageScheduledUntilOnline')
|
lang('MessageScheduledUntilOnline')
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -226,6 +226,7 @@
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
unicode-bidi: plaintext;
|
||||||
|
|
||||||
@media (max-width: 600px) {
|
@media (max-width: 600px) {
|
||||||
display: block;
|
display: block;
|
||||||
@ -264,6 +265,10 @@
|
|||||||
margin-top: 0.05rem;
|
margin-top: 0.05rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.user-status, .status {
|
||||||
|
unicode-bidi: plaintext;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.Avatar {
|
.Avatar {
|
||||||
|
|||||||
@ -256,6 +256,8 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
line-height: 1.375rem;
|
line-height: 1.375rem;
|
||||||
font-family: Roboto, -apple-system, "Apple Color Emoji", "Helvetica Neue", sans-serif;
|
font-family: Roboto, -apple-system, "Apple Color Emoji", "Helvetica Neue", sans-serif;
|
||||||
|
unicode-bidi: plaintext;
|
||||||
|
text-align: initial;
|
||||||
|
|
||||||
&.overflown {
|
&.overflown {
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
@ -278,6 +280,8 @@
|
|||||||
bottom: .9375rem;
|
bottom: .9375rem;
|
||||||
color: var(--color-placeholders);
|
color: var(--color-placeholders);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
unicode-bidi: plaintext;
|
||||||
|
text-align: initial;
|
||||||
|
|
||||||
@media (max-width: 600px) {
|
@media (max-width: 600px) {
|
||||||
bottom: 0.6875rem;
|
bottom: 0.6875rem;
|
||||||
@ -301,6 +305,8 @@
|
|||||||
opacity: 0;
|
opacity: 0;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
z-index: -10;
|
z-index: -10;
|
||||||
|
unicode-bidi: plaintext;
|
||||||
|
text-align: initial;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -47,7 +47,9 @@ const EmojiCategory: FC<OwnProps> = ({
|
|||||||
id={`emoji-category-${index}`}
|
id={`emoji-category-${index}`}
|
||||||
className="symbol-set"
|
className="symbol-set"
|
||||||
>
|
>
|
||||||
<p className="symbol-set-name">{lang(category.id === 'recent' ? 'RecentStickers' : `Emoji${index}`)}</p>
|
<p className="symbol-set-name" dir="auto">
|
||||||
|
{lang(category.id === 'recent' ? 'RecentStickers' : `Emoji${index}`)}
|
||||||
|
</p>
|
||||||
<div
|
<div
|
||||||
className={buildClassName('symbol-set-container', transitionClassNames)}
|
className={buildClassName('symbol-set-container', transitionClassNames)}
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
|||||||
@ -356,6 +356,7 @@ const MessageInput: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
id={editableInputId || EDITABLE_INPUT_ID}
|
id={editableInputId || EDITABLE_INPUT_ID}
|
||||||
className={className}
|
className={className}
|
||||||
|
dir="auto"
|
||||||
contentEditable
|
contentEditable
|
||||||
onClick={focusInput}
|
onClick={focusInput}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
@ -364,8 +365,8 @@ const MessageInput: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
onContextMenu={stopEvent}
|
onContextMenu={stopEvent}
|
||||||
onTouchCancel={handleTouchSelection}
|
onTouchCancel={handleTouchSelection}
|
||||||
/>
|
/>
|
||||||
<div ref={cloneRef} className={buildClassName(className, 'clone')} />
|
<div ref={cloneRef} className={buildClassName(className, 'clone')} dir="auto" />
|
||||||
<span className="placeholder-text">{placeholder}</span>
|
<span className="placeholder-text" dir="auto">{placeholder}</span>
|
||||||
<TextFormatter
|
<TextFormatter
|
||||||
isOpen={isTextFormatterOpen}
|
isOpen={isTextFormatterOpen}
|
||||||
anchorPosition={textFormatterAnchorPosition}
|
anchorPosition={textFormatterAnchorPosition}
|
||||||
|
|||||||
@ -44,6 +44,10 @@
|
|||||||
.option-wrapper {
|
.option-wrapper {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
|
.form-control {
|
||||||
|
padding-right: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
.option-remove-button {
|
.option-remove-button {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0.3125rem;
|
top: 0.3125rem;
|
||||||
|
|||||||
@ -337,6 +337,7 @@ const PollModal: FC<OwnProps> = ({ isOpen, onSend, onClear }) => {
|
|||||||
ref={solutionRef}
|
ref={solutionRef}
|
||||||
className="form-control"
|
className="form-control"
|
||||||
contentEditable
|
contentEditable
|
||||||
|
dir="auto"
|
||||||
onChange={(e) => setSolution(e.currentTarget.innerHTML)}
|
onChange={(e) => setSolution(e.currentTarget.innerHTML)}
|
||||||
/>
|
/>
|
||||||
<div className="note">{lang('CreatePoll.ExplanationInfo')}</div>
|
<div className="note">{lang('CreatePoll.ExplanationInfo')}</div>
|
||||||
|
|||||||
@ -122,6 +122,12 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
text-align: initial;
|
||||||
|
unicode-bidi: plaintext;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-container {
|
||||||
|
text-align: initial;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-button {
|
&-button {
|
||||||
|
|||||||
@ -258,7 +258,7 @@ const TextFormatter: FC<OwnProps> = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const text = getSelectedText();
|
const text = getSelectedText();
|
||||||
document.execCommand('insertHTML', false, `<code class="text-entity-code">${text}</code>`);
|
document.execCommand('insertHTML', false, `<code class="text-entity-code" dir="auto">${text}</code>`);
|
||||||
onClose();
|
onClose();
|
||||||
}, [
|
}, [
|
||||||
getSelectedElement, getSelectedText, onClose,
|
getSelectedElement, getSelectedText, onClose,
|
||||||
@ -282,7 +282,11 @@ const TextFormatter: FC<OwnProps> = ({
|
|||||||
|
|
||||||
const text = getSelectedText();
|
const text = getSelectedText();
|
||||||
restoreSelection();
|
restoreSelection();
|
||||||
document.execCommand('insertHTML', false, `<a href=${formattedLinkUrl} class="text-entity-link">${text}</a>`);
|
document.execCommand(
|
||||||
|
'insertHTML',
|
||||||
|
false,
|
||||||
|
`<a href=${formattedLinkUrl} class="text-entity-link" dir="auto">${text}</a>`,
|
||||||
|
);
|
||||||
onClose();
|
onClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -424,6 +428,7 @@ const TextFormatter: FC<OwnProps> = ({
|
|||||||
placeholder="Enter URL..."
|
placeholder="Enter URL..."
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
inputMode="url"
|
inputMode="url"
|
||||||
|
dir="auto"
|
||||||
onChange={handleLinkUrlChange}
|
onChange={handleLinkUrlChange}
|
||||||
onScroll={updateInputStyles}
|
onScroll={updateInputStyles}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -73,6 +73,7 @@ export default function useMentionTooltip(
|
|||||||
data-entity-type="${ApiMessageEntityTypes.MentionName}"
|
data-entity-type="${ApiMessageEntityTypes.MentionName}"
|
||||||
data-user-id="${user.id}"
|
data-user-id="${user.id}"
|
||||||
contenteditable="false"
|
contenteditable="false"
|
||||||
|
dir="auto"
|
||||||
>${getUserFirstOrLastName(user)}</a>`;
|
>${getUserFirstOrLastName(user)}</a>`;
|
||||||
|
|
||||||
const atIndex = html.lastIndexOf('@');
|
const atIndex = html.lastIndexOf('@');
|
||||||
|
|||||||
@ -78,7 +78,7 @@ const CommentButton: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
<i className="icon-comments-sticker" />
|
<i className="icon-comments-sticker" />
|
||||||
{(!recentRepliers || recentRepliers.length === 0) && <i className="icon-comments" />}
|
{(!recentRepliers || recentRepliers.length === 0) && <i className="icon-comments" />}
|
||||||
{renderRecentRepliers()}
|
{renderRecentRepliers()}
|
||||||
<div className="label">
|
<div className="label" dir="auto">
|
||||||
{messagesCount ? lang('Comments', messagesCount, 'i') : lang('LeaveAComment')}
|
{messagesCount ? lang('Comments', messagesCount, 'i') : lang('LeaveAComment')}
|
||||||
</div>
|
</div>
|
||||||
<i className="icon-next" />
|
<i className="icon-next" />
|
||||||
|
|||||||
@ -35,7 +35,7 @@ const MentionLink: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<a onClick={handleClick} className="text-entity-link">
|
<a onClick={handleClick} className="text-entity-link" dir="auto">
|
||||||
{children}
|
{children}
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -503,9 +503,10 @@ const Message: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
noMediaCorners && 'no-media-corners',
|
noMediaCorners && 'no-media-corners',
|
||||||
);
|
);
|
||||||
const hasCustomAppendix = isLastInGroup && !textParts && !asForwarded && !hasThread;
|
const hasCustomAppendix = isLastInGroup && !textParts && !asForwarded && !hasThread;
|
||||||
|
const shouldInlineMeta = !webPage && !animatedEmoji && textParts;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={className} onDoubleClick={handleContentDoubleClick}>
|
<div className={className} onDoubleClick={handleContentDoubleClick} dir="auto">
|
||||||
{renderSenderName()}
|
{renderSenderName()}
|
||||||
{hasReply && (
|
{hasReply && (
|
||||||
<EmbeddedMessage
|
<EmbeddedMessage
|
||||||
@ -605,7 +606,19 @@ const Message: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
{poll && (
|
{poll && (
|
||||||
<Poll message={message} poll={poll} onSendVote={handleVoteSend} />
|
<Poll message={message} poll={poll} onSendVote={handleVoteSend} />
|
||||||
)}
|
)}
|
||||||
{!animatedEmoji && textParts && <p className="text-content">{textParts}</p>}
|
{!animatedEmoji && textParts && (
|
||||||
|
<p className={`text-content ${shouldInlineMeta ? 'with-meta' : ''}`} dir="auto">
|
||||||
|
{textParts}
|
||||||
|
{shouldInlineMeta && (
|
||||||
|
<MessageMeta
|
||||||
|
message={message}
|
||||||
|
outgoingStatus={outgoingStatus}
|
||||||
|
signature={signature}
|
||||||
|
onClick={handleMessageSelect}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
{webPage && (
|
{webPage && (
|
||||||
<WebPage
|
<WebPage
|
||||||
message={message}
|
message={message}
|
||||||
@ -737,13 +750,14 @@ const Message: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
className={contentClassName}
|
className={contentClassName}
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
style={style}
|
style={style}
|
||||||
|
dir="auto"
|
||||||
>
|
>
|
||||||
{withAppendix && (<div className="svg-appendix" ref={appendixRef} />)}
|
{withAppendix && (<div className="svg-appendix" ref={appendixRef} />)}
|
||||||
{asForwarded && !customShape && (!isInDocumentGroup || isFirstInDocumentGroup) && (
|
{asForwarded && !customShape && (!isInDocumentGroup || isFirstInDocumentGroup) && (
|
||||||
<div className="message-title">{lang('ForwardedMessage')}</div>
|
<div className="message-title">{lang('ForwardedMessage')}</div>
|
||||||
)}
|
)}
|
||||||
{renderContent()}
|
{renderContent()}
|
||||||
{(!isInDocumentGroup || isLastInDocumentGroup) && (
|
{(!isInDocumentGroup || isLastInDocumentGroup) && !(!webPage && !animatedEmoji && textParts) && (
|
||||||
<MessageMeta
|
<MessageMeta
|
||||||
message={message}
|
message={message}
|
||||||
outgoingStatus={outgoingStatus}
|
outgoingStatus={outgoingStatus}
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background: rgba(#999999, 0.6);
|
background: rgba(#999999, 0.6);
|
||||||
border-radius: .65rem;
|
border-radius: .625rem;
|
||||||
padding: 0 .25rem;
|
padding: 0 .25rem;
|
||||||
color: white;
|
color: white;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@ -64,9 +64,21 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.media:not(.text):dir(rtl) &,
|
||||||
|
.Message .custom-shape:dir(rtl) & {
|
||||||
|
right: auto !important;
|
||||||
|
left: .25rem;
|
||||||
|
padding: 0 .375rem 0 .3125rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-forwarded.media:not(.text):dir(rtl) &,
|
||||||
|
.Message .is-forwarded.custom-shape:dir(rtl) & {
|
||||||
|
left: .8125rem;
|
||||||
|
}
|
||||||
|
|
||||||
.is-forwarded.media:not(.text) & {
|
.is-forwarded.media:not(.text) & {
|
||||||
bottom: 0.9rem;
|
bottom: 0.935rem;
|
||||||
right: 0.8rem;
|
right: 0.8125rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.emoji-only & {
|
.emoji-only & {
|
||||||
@ -80,6 +92,8 @@
|
|||||||
.MessageOutgoingStatus {
|
.MessageOutgoingStatus {
|
||||||
margin-left: -.1875rem;
|
margin-left: -.1875rem;
|
||||||
font-size: 1.1875rem;
|
font-size: 1.1875rem;
|
||||||
|
border-radius: .625rem;
|
||||||
|
|
||||||
.Message.own & {
|
.Message.own & {
|
||||||
color: var(--color-accent-own);
|
color: var(--color-accent-own);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
.Poll {
|
.Poll {
|
||||||
min-width: 15rem;
|
min-width: 15rem;
|
||||||
|
text-align: initial;
|
||||||
|
|
||||||
@media (max-width: 600px) {
|
@media (max-width: 600px) {
|
||||||
min-width: 50vw;
|
min-width: 50vw;
|
||||||
|
|||||||
@ -256,7 +256,7 @@ const Poll: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="Poll">
|
<div className="Poll" dir="auto">
|
||||||
{renderSolution()}
|
{renderSolution()}
|
||||||
<div className="poll-question">{renderText(summary.question)}</div>
|
<div className="poll-question">{renderText(summary.question)}</div>
|
||||||
<div className="poll-type">
|
<div className="poll-type">
|
||||||
|
|||||||
@ -72,6 +72,7 @@ const WebPage: FC<OwnProps> = ({
|
|||||||
<div
|
<div
|
||||||
className={className}
|
className={className}
|
||||||
data-initial={(siteName || displayUrl)[0]}
|
data-initial={(siteName || displayUrl)[0]}
|
||||||
|
dir="auto"
|
||||||
>
|
>
|
||||||
{photo && (
|
{photo && (
|
||||||
<Photo
|
<Photo
|
||||||
|
|||||||
@ -10,6 +10,34 @@
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
line-height: 1.3125;
|
line-height: 1.3125;
|
||||||
|
text-align: initial;
|
||||||
|
display: flow-root;
|
||||||
|
unicode-bidi: plaintext;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-entity-link {
|
||||||
|
unicode-bidi: plaintext;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-content,
|
||||||
|
&.document {
|
||||||
|
& > .MessageMeta {
|
||||||
|
position: relative;
|
||||||
|
top: .4375rem;
|
||||||
|
bottom: auto !important;
|
||||||
|
float: right;
|
||||||
|
line-height: 1;
|
||||||
|
margin-left: .4375rem;
|
||||||
|
margin-right: -.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:dir(rtl) {
|
||||||
|
& > .MessageMeta {
|
||||||
|
float: left;
|
||||||
|
margin-left: -.25rem;
|
||||||
|
margin-right: .4375rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.theme-dark .Message.own & {
|
.theme-dark .Message.own & {
|
||||||
@ -24,6 +52,10 @@
|
|||||||
|
|
||||||
&:not(.custom-shape) {
|
&:not(.custom-shape) {
|
||||||
font-size: var(--message-text-size, 1rem);
|
font-size: var(--message-text-size, 1rem);
|
||||||
|
|
||||||
|
& > .content-inner {
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.matching-text-highlight {
|
.matching-text-highlight {
|
||||||
@ -40,6 +72,7 @@
|
|||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
line-height: 1.25rem;
|
line-height: 1.25rem;
|
||||||
color: var(--accent-color);
|
color: var(--accent-color);
|
||||||
|
unicode-bidi: plaintext;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
& > .interactive {
|
& > .interactive {
|
||||||
@ -94,8 +127,8 @@
|
|||||||
|
|
||||||
.admin-title {
|
.admin-title {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
margin-left: 1rem;
|
margin-inline-start: 1rem;
|
||||||
text-align: right;
|
text-align: end;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
margin-top: -0.1rem;
|
margin-top: -0.1rem;
|
||||||
@ -118,7 +151,7 @@
|
|||||||
&.has-solid-background {
|
&.has-solid-background {
|
||||||
padding: .3125rem .5rem .375rem;
|
padding: .3125rem .5rem .375rem;
|
||||||
|
|
||||||
.text-content:last-child::after {
|
.forwarded-message > .text-content:not(.with-meta):last-child::after {
|
||||||
content: '';
|
content: '';
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: var(--meta-safe-area-size);
|
width: var(--meta-safe-area-size);
|
||||||
@ -210,7 +243,7 @@
|
|||||||
width: 1.25rem;
|
width: 1.25rem;
|
||||||
background-size: 1.25rem;
|
background-size: 1.25rem;
|
||||||
color: transparent;
|
color: transparent;
|
||||||
margin-right: 1px;
|
margin-inline-end: 1px;
|
||||||
vertical-align: text-bottom;
|
vertical-align: text-bottom;
|
||||||
|
|
||||||
&::selection {
|
&::selection {
|
||||||
@ -531,8 +564,9 @@
|
|||||||
.text-entity-link {
|
.text-entity-link {
|
||||||
color: var(--color-links) !important;
|
color: var(--color-links) !important;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
word-break: none;
|
word-break: break-word;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
unicode-bidi: initial;
|
||||||
|
|
||||||
&:hover, &:active, &:visited {
|
&:hover, &:active, &:visited {
|
||||||
color: var(--color-links-hover) !important;
|
color: var(--color-links-hover) !important;
|
||||||
|
|||||||
@ -86,7 +86,7 @@ const ChatExtra: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
<div className="ChatExtra">
|
<div className="ChatExtra">
|
||||||
{formattedNumber && !!formattedNumber.length && (
|
{formattedNumber && !!formattedNumber.length && (
|
||||||
<ListItem icon="phone" multiline narrow ripple onClick={() => copy(formattedNumber, lang('Phone'))}>
|
<ListItem icon="phone" multiline narrow ripple onClick={() => copy(formattedNumber, lang('Phone'))}>
|
||||||
<span className="title">{formattedNumber}</span>
|
<span className="title" dir="auto">{formattedNumber}</span>
|
||||||
<span className="subtitle">{lang('Phone')}</span>
|
<span className="subtitle">{lang('Phone')}</span>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
)}
|
)}
|
||||||
@ -98,7 +98,7 @@ const ChatExtra: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
ripple
|
ripple
|
||||||
onClick={() => copy(`@${printedUsername}`, lang('Username'))}
|
onClick={() => copy(`@${printedUsername}`, lang('Username'))}
|
||||||
>
|
>
|
||||||
<span className="title">{renderText(printedUsername)}</span>
|
<span className="title" dir="auto">{renderText(printedUsername)}</span>
|
||||||
<span className="subtitle">{lang('Username')}</span>
|
<span className="subtitle">{lang('Username')}</span>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
)}
|
)}
|
||||||
@ -109,7 +109,9 @@ const ChatExtra: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
narrow
|
narrow
|
||||||
isStatic
|
isStatic
|
||||||
>
|
>
|
||||||
<span className="title">{renderText(description, ['br', 'links', 'emoji'])}</span>
|
<span className="title" dir="auto">
|
||||||
|
{renderText(description, ['br', 'links', 'emoji'])}
|
||||||
|
</span>
|
||||||
<span className="subtitle">{lang(userId ? 'UserBio' : 'Info')}</span>
|
<span className="subtitle">{lang(userId ? 'UserBio' : 'Info')}</span>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -80,7 +80,7 @@ const GifSearch: FC<StateProps & DispatchProps> = ({
|
|||||||
|
|
||||||
if (!results.length) {
|
if (!results.length) {
|
||||||
return (
|
return (
|
||||||
<p className="helper-text">{lang('NoGIFsFound')}</p>
|
<p className="helper-text" dir="auto">{lang('NoGIFsFound')}</p>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -116,7 +116,7 @@ const PollAnswerResults: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
{voters && renderViewMoreButton()}
|
{voters && renderViewMoreButton()}
|
||||||
</div>
|
</div>
|
||||||
<div className="answer-head">
|
<div className="answer-head">
|
||||||
<span className="answer-title">{text}</span>
|
<span className="answer-title" dir="auto">{text}</span>
|
||||||
<span className="answer-percent">{getPercentage(answerVote.votersCount, totalVoters)}%</span>
|
<span className="answer-percent">{getPercentage(answerVote.votersCount, totalVoters)}%</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -35,7 +35,7 @@ const PollResults: FC<StateProps> = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="PollResults">
|
<div className="PollResults">
|
||||||
<h3 className="poll-question">{summary.question}</h3>
|
<h3 className="poll-question" dir="auto">{summary.question}</h3>
|
||||||
<div className="poll-results-list custom-scroll">
|
<div className="poll-results-list custom-scroll">
|
||||||
{lastSyncTime && summary.answers.map((answer) => (
|
{lastSyncTime && summary.answers.map((answer) => (
|
||||||
<PollAnswerResults
|
<PollAnswerResults
|
||||||
|
|||||||
@ -157,13 +157,13 @@ const PrivateChatInfo: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
if (user) {
|
if (user) {
|
||||||
return (
|
return (
|
||||||
<div className={`status ${isUserOnline(user) ? 'online' : ''}`}>
|
<div className={`status ${isUserOnline(user) ? 'online' : ''}`}>
|
||||||
<span className="user-status">{getUserStatus(lang, user)}</span>
|
<span className="user-status" dir="auto">{getUserStatus(lang, user)}</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span className="status">{
|
<span className="status" dir="auto">{
|
||||||
isChatChannel(chat!)
|
isChatChannel(chat!)
|
||||||
? lang('Subscribers', chat!.membersCount, 'i')
|
? lang('Subscribers', chat!.membersCount, 'i')
|
||||||
: lang('Members', chat!.membersCount, 'i')
|
: lang('Members', chat!.membersCount, 'i')
|
||||||
@ -203,11 +203,11 @@ const PrivateChatInfo: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
<div className="info">
|
<div className="info">
|
||||||
{isSavedMessages ? (
|
{isSavedMessages ? (
|
||||||
<div className="title">
|
<div className="title">
|
||||||
<h3>{lang('SavedMessages')}</h3>
|
<h3 dir="auto">{lang('SavedMessages')}</h3>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="title">
|
<div className="title">
|
||||||
<h3>{fullName && renderText(fullName)}</h3>
|
<h3 dir="auto">{fullName && renderText(fullName)}</h3>
|
||||||
{isVerifiedIconShown && <VerifiedIcon />}
|
{isVerifiedIconShown && <VerifiedIcon />}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -8,5 +8,7 @@
|
|||||||
margin-bottom: 0.125rem;
|
margin-bottom: 0.125rem;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: var(--color-text-secondary);
|
color: var(--color-text-secondary);
|
||||||
|
unicode-bidi: plaintext;
|
||||||
|
text-align: initial;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -108,10 +108,10 @@ const RightSearch: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
<Avatar chat={senderChat} user={senderUser} />
|
<Avatar chat={senderChat} user={senderUser} />
|
||||||
<div className="info">
|
<div className="info">
|
||||||
<div className="title">
|
<div className="title">
|
||||||
<h3>{title && renderText(title)}</h3>
|
<h3 dir="auto">{title && renderText(title)}</h3>
|
||||||
<LastMessageMeta message={message} />
|
<LastMessageMeta message={message} />
|
||||||
</div>
|
</div>
|
||||||
<div className="subtitle">
|
<div className="subtitle" dir="auto">
|
||||||
{renderText(text, ['emoji', 'highlight'], { highlight: query })}
|
{renderText(text, ['emoji', 'highlight'], { highlight: query })}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -127,13 +127,15 @@ const RightSearch: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
onLoadMore={searchTextMessagesLocal}
|
onLoadMore={searchTextMessagesLocal}
|
||||||
noFastList
|
noFastList
|
||||||
>
|
>
|
||||||
<p className="helper-text">
|
<p className="helper-text" dir="auto">
|
||||||
{!query ? (
|
{!query ? (
|
||||||
'Search messages'
|
lang('lng_dlg_search_for_messages')
|
||||||
|
) : (totalCount === 0 || !foundResults.length) ? (
|
||||||
|
lang('lng_search_no_results')
|
||||||
) : totalCount === 1 ? (
|
) : totalCount === 1 ? (
|
||||||
'1 message found'
|
'1 message found'
|
||||||
) : (
|
) : (
|
||||||
`${(foundResults.length && (totalCount || foundResults.length)) || 'No'} messages found`
|
`${(foundResults.length && (totalCount || foundResults.length))} messages found`
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
{foundResults.map(renderSearchResult)}
|
{foundResults.map(renderSearchResult)}
|
||||||
|
|||||||
@ -80,8 +80,8 @@ const StickerSetResult: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
<div key={set.id} className="sticker-set">
|
<div key={set.id} className="sticker-set">
|
||||||
<div className="sticker-set-header">
|
<div className="sticker-set-header">
|
||||||
<div className="title-wrapper">
|
<div className="title-wrapper">
|
||||||
<h3 className="title">{set.title}</h3>
|
<h3 className="title" dir="auto">{set.title}</h3>
|
||||||
<p className="count">{lang('Stickers', set.count, 'i')}</p>
|
<p className="count" dir="auto">{lang('Stickers', set.count, 'i')}</p>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
className={isAdded ? 'is-added' : undefined}
|
className={isAdded ? 'is-added' : undefined}
|
||||||
|
|||||||
@ -200,8 +200,8 @@ const ManageChannel: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
<div className="section">
|
<div className="section">
|
||||||
<ListItem icon="group" multiline ripple onClick={handleClickSubscribers}>
|
<ListItem icon="group" multiline ripple onClick={handleClickSubscribers}>
|
||||||
<span className="title">{lang('ChannelSubscribers')}</span>
|
<span className="title" dir="auto">{lang('ChannelSubscribers')}</span>
|
||||||
<span className="subtitle">{lang('Subscribers', chat.membersCount!, 'i')}</span>
|
<span className="subtitle" dir="auto">{lang('Subscribers', chat.membersCount!, 'i')}</span>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
</div>
|
</div>
|
||||||
<div className="section">
|
<div className="section">
|
||||||
|
|||||||
@ -86,7 +86,7 @@ const ManageChatAdministrators: FC<OwnProps & StateProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="section">
|
<div className="section">
|
||||||
<p className="text-muted">
|
<p className="text-muted" dir="auto">
|
||||||
{isChannel
|
{isChannel
|
||||||
? 'You can add administrators to help you manage your channel.'
|
? 'You can add administrators to help you manage your channel.'
|
||||||
: 'You can add administrators to help you manage your group.'}
|
: 'You can add administrators to help you manage your group.'}
|
||||||
|
|||||||
@ -135,7 +135,7 @@ const ManageChatPrivacyType: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
checkUsername={checkPublicLink}
|
checkUsername={checkPublicLink}
|
||||||
onChange={setUsername}
|
onChange={setUsername}
|
||||||
/>
|
/>
|
||||||
<p className="section-info">
|
<p className="section-info" dir="auto">
|
||||||
{lang(`${langPrefix2}.Username.CreatePublicLinkHelp`)}
|
{lang(`${langPrefix2}.Username.CreatePublicLinkHelp`)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -185,7 +185,7 @@ const ManageDiscussion: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
function renderDiscussionGroups() {
|
function renderDiscussionGroups() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<p className="section-help">{lang('DiscussionChannelHelp')}</p>
|
<p className="section-help" dir="auto">{lang('DiscussionChannelHelp')}</p>
|
||||||
|
|
||||||
<div teactFastList>
|
<div teactFastList>
|
||||||
<ListItem
|
<ListItem
|
||||||
@ -212,7 +212,7 @@ const ManageDiscussion: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
<NothingFound key="nothing-found" teactOrderKey={0} text="No discussion groups found" />
|
<NothingFound key="nothing-found" teactOrderKey={0} text="No discussion groups found" />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<p className="mt-4 mb-0 section-help">{lang('DiscussionChannelHelp2')}</p>
|
<p className="mt-4 mb-0 section-help" dir="auto">{lang('DiscussionChannelHelp2')}</p>
|
||||||
<ConfirmDialog
|
<ConfirmDialog
|
||||||
isOpen={isConfirmLinkGroupDialogOpen}
|
isOpen={isConfirmLinkGroupDialogOpen}
|
||||||
onClose={closeConfirmLinkGroupDialog}
|
onClose={closeConfirmLinkGroupDialog}
|
||||||
|
|||||||
@ -67,8 +67,8 @@ const Checkbox: FC<OwnProps> = ({
|
|||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
/>
|
/>
|
||||||
<div className="Checkbox-main">
|
<div className="Checkbox-main">
|
||||||
<span className="label">{label}</span>
|
<span className="label" dir="auto">{label}</span>
|
||||||
{subLabel && <span className="subLabel">{subLabel}</span>}
|
{subLabel && <span className="subLabel" dir="auto">{subLabel}</span>}
|
||||||
</div>
|
</div>
|
||||||
{isLoading && <Spinner />}
|
{isLoading && <Spinner />}
|
||||||
</label>
|
</label>
|
||||||
|
|||||||
@ -62,6 +62,7 @@ const InputText: FC<OwnProps> = ({
|
|||||||
className="form-control"
|
className="form-control"
|
||||||
type="text"
|
type="text"
|
||||||
id={id}
|
id={id}
|
||||||
|
dir="auto"
|
||||||
value={value || ''}
|
value={value || ''}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
maxLength={maxLength}
|
maxLength={maxLength}
|
||||||
|
|||||||
@ -20,6 +20,7 @@ const Link: FC<OwnProps> = ({ children, className, onClick }) => {
|
|||||||
<a
|
<a
|
||||||
href="#"
|
href="#"
|
||||||
className={buildClassName('Link', className)}
|
className={buildClassName('Link', className)}
|
||||||
|
dir="auto"
|
||||||
onClick={onClick ? handleClick : undefined}
|
onClick={onClick ? handleClick : undefined}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
|||||||
@ -13,6 +13,7 @@
|
|||||||
color: var(--color-text);
|
color: var(--color-text);
|
||||||
--ripple-color: rgba(0, 0, 0, .08);
|
--ripple-color: rgba(0, 0, 0, .08);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
unicode-bidi: plaintext;
|
||||||
|
|
||||||
&:hover, &:focus {
|
&:hover, &:focus {
|
||||||
background-color: var(--color-chat-hover);
|
background-color: var(--color-chat-hover);
|
||||||
|
|||||||
@ -93,6 +93,7 @@ const SearchInput: FC<OwnProps> = ({
|
|||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
id={inputId}
|
id={inputId}
|
||||||
type="text"
|
type="text"
|
||||||
|
dir="auto"
|
||||||
placeholder={placeholder || lang('Search')}
|
placeholder={placeholder || lang('Search')}
|
||||||
className="form-control"
|
className="form-control"
|
||||||
value={value}
|
value={value}
|
||||||
|
|||||||
@ -22,6 +22,7 @@ type VirtualDomHead = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const FILTERED_ATTRIBUTES = new Set(['key', 'ref', 'teactFastList', 'teactOrderKey']);
|
const FILTERED_ATTRIBUTES = new Set(['key', 'ref', 'teactFastList', 'teactOrderKey']);
|
||||||
|
const HTML_ATTRIBUTES = new Set(['dir']);
|
||||||
const MAPPED_ATTRIBUTES: { [k: string]: string } = {
|
const MAPPED_ATTRIBUTES: { [k: string]: string } = {
|
||||||
autoPlay: 'autoplay',
|
autoPlay: 'autoplay',
|
||||||
autoComplete: 'autocomplete',
|
autoComplete: 'autocomplete',
|
||||||
@ -428,7 +429,7 @@ function addAttribute(element: HTMLElement, key: string, value: any) {
|
|||||||
element.style.cssText = value;
|
element.style.cssText = value;
|
||||||
} else if (key.startsWith('on')) {
|
} else if (key.startsWith('on')) {
|
||||||
addEventListener(element, key, value);
|
addEventListener(element, key, value);
|
||||||
} else if (key.startsWith('data-')) {
|
} else if (key.startsWith('data-') || HTML_ATTRIBUTES.has(key)) {
|
||||||
element.setAttribute(key, value);
|
element.setAttribute(key, value);
|
||||||
} else if (!FILTERED_ATTRIBUTES.has(key)) {
|
} else if (!FILTERED_ATTRIBUTES.has(key)) {
|
||||||
(element as any)[MAPPED_ATTRIBUTES[key] || key] = value;
|
(element as any)[MAPPED_ATTRIBUTES[key] || key] = value;
|
||||||
@ -444,7 +445,7 @@ function removeAttribute(element: HTMLElement, key: string, value: any) {
|
|||||||
element.style.cssText = '';
|
element.style.cssText = '';
|
||||||
} else if (key.startsWith('on')) {
|
} else if (key.startsWith('on')) {
|
||||||
removeEventListener(element, key, value);
|
removeEventListener(element, key, value);
|
||||||
} else if (key.startsWith('data-')) {
|
} else if (key.startsWith('data-') || HTML_ATTRIBUTES.has(key)) {
|
||||||
element.removeAttribute(key);
|
element.removeAttribute(key);
|
||||||
} else if (!FILTERED_ATTRIBUTES.has(key)) {
|
} else if (!FILTERED_ATTRIBUTES.has(key)) {
|
||||||
delete (element as any)[MAPPED_ATTRIBUTES[key] || key];
|
delete (element as any)[MAPPED_ATTRIBUTES[key] || key];
|
||||||
|
|||||||
@ -120,6 +120,12 @@ addReducer('reset', () => {
|
|||||||
cacheApi.clear(CUSTOM_BG_CACHE_NAME);
|
cacheApi.clear(CUSTOM_BG_CACHE_NAME);
|
||||||
cacheApi.clear(LANG_CACHE_NAME);
|
cacheApi.clear(LANG_CACHE_NAME);
|
||||||
|
|
||||||
|
const langChachePrefix = LANG_CACHE_NAME.replace(/\d+$/, '');
|
||||||
|
const langCacheVersion = (LANG_CACHE_NAME.match(/\d+$/) || [0])[0];
|
||||||
|
for (let i = 0; i < langCacheVersion; i++) {
|
||||||
|
cacheApi.clear(`${langChachePrefix}${i === 0 ? '' : i}`);
|
||||||
|
}
|
||||||
|
|
||||||
getDispatch().init();
|
getDispatch().init();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user