Support note for contact (#6413)
This commit is contained in:
parent
28a41a6764
commit
f71b451051
@ -118,6 +118,7 @@ export interface GramJsAppConfig extends LimitsConfig {
|
||||
verify_age_bot_username?: string;
|
||||
verify_age_country?: string;
|
||||
verify_age_min?: number;
|
||||
contact_note_length_limit?: number;
|
||||
}
|
||||
|
||||
function buildEmojiSounds(appConfig: GramJsAppConfig) {
|
||||
@ -187,6 +188,7 @@ export function buildAppConfig(json: GramJs.TypeJSONValue, hash: number): ApiApp
|
||||
maxReactions: getLimit(appConfig, 'reactions_user_max', 'maxReactions'),
|
||||
moreAccounts: DEFAULT_LIMITS.moreAccounts,
|
||||
},
|
||||
contactNoteLimit: appConfig.contact_note_length_limit,
|
||||
hash,
|
||||
storyViewersExpirePeriod: appConfig.story_viewers_expire_period,
|
||||
storyChangelogUserId: appConfig.stories_changelog_user_id?.toString(),
|
||||
|
||||
@ -14,7 +14,7 @@ import { toJSNumber } from '../../../util/numbers';
|
||||
import { buildApiBotInfo } from './bots';
|
||||
import { buildApiBusinessIntro, buildApiBusinessLocation, buildApiBusinessWorkHours } from './business';
|
||||
import {
|
||||
buildApiPhoto, buildApiUsernames,
|
||||
buildApiFormattedText, buildApiPhoto, buildApiUsernames,
|
||||
} from './common';
|
||||
import { buildApiDisallowedGiftsSettings } from './gifts';
|
||||
import { omitVirtualClassFields } from './helpers';
|
||||
@ -36,7 +36,7 @@ export function buildApiUserFullInfo(mtpUserFull: GramJs.users.UserFull): ApiUse
|
||||
contactRequirePremium, businessWorkHours, businessLocation, businessIntro,
|
||||
birthday, personalChannelId, personalChannelMessage, sponsoredEnabled, stargiftsCount, botVerification,
|
||||
botCanManageEmojiStatus, settings, sendPaidMessagesStars, displayGiftsButton, disallowedGifts,
|
||||
starsRating, starsMyPendingRating, starsMyPendingRatingDate, mainTab,
|
||||
starsRating, starsMyPendingRating, starsMyPendingRatingDate, mainTab, note,
|
||||
},
|
||||
users,
|
||||
} = mtpUserFull;
|
||||
@ -76,6 +76,7 @@ export function buildApiUserFullInfo(mtpUserFull: GramJs.users.UserFull): ApiUse
|
||||
paidMessagesStars: toJSNumber(sendPaidMessagesStars),
|
||||
settings: buildApiPeerSettings(settings),
|
||||
mainTab: mainTab && buildApiProfileTab(mainTab),
|
||||
note: note && buildApiFormattedText(note),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { Api as GramJs } from '../../../lib/gramjs';
|
||||
|
||||
import type { ApiEmojiStatusType, ApiPeer, ApiUser,
|
||||
import type {
|
||||
ApiEmojiStatusType, ApiFormattedText, ApiPeer, ApiUser,
|
||||
} from '../../types';
|
||||
|
||||
import { toJSNumber } from '../../../util/numbers';
|
||||
@ -12,6 +13,7 @@ import {
|
||||
buildInputContact,
|
||||
buildInputEmojiStatus,
|
||||
buildInputPeer,
|
||||
buildInputTextWithEntities,
|
||||
buildInputUser,
|
||||
buildMtpPeerId,
|
||||
DEFAULT_PRIMITIVES,
|
||||
@ -212,6 +214,7 @@ export function updateContact({
|
||||
firstName = DEFAULT_PRIMITIVES.STRING,
|
||||
lastName = DEFAULT_PRIMITIVES.STRING,
|
||||
shouldSharePhoneNumber = false,
|
||||
note,
|
||||
}: {
|
||||
id: string;
|
||||
accessHash?: string;
|
||||
@ -219,6 +222,7 @@ export function updateContact({
|
||||
firstName?: string;
|
||||
lastName?: string;
|
||||
shouldSharePhoneNumber?: boolean;
|
||||
note?: ApiFormattedText;
|
||||
}) {
|
||||
return invokeRequest(new GramJs.contacts.AddContact({
|
||||
id: buildInputUser(id, accessHash),
|
||||
@ -226,6 +230,7 @@ export function updateContact({
|
||||
lastName,
|
||||
phone: phoneNumber,
|
||||
addPhonePrivacyException: shouldSharePhoneNumber || undefined,
|
||||
note: note ? buildInputTextWithEntities(note) : undefined,
|
||||
}), {
|
||||
shouldReturnTrue: true,
|
||||
});
|
||||
@ -364,3 +369,14 @@ export function saveCloseFriends(userIds: string[]) {
|
||||
shouldReturnTrue: true,
|
||||
});
|
||||
}
|
||||
|
||||
export function updateContactNote(user: ApiUser, note: ApiFormattedText) {
|
||||
const { id, accessHash } = user;
|
||||
|
||||
return invokeRequest(new GramJs.contacts.UpdateContactNote({
|
||||
id: buildInputUser(id, accessHash),
|
||||
note: buildInputTextWithEntities(note),
|
||||
}), {
|
||||
shouldReturnTrue: true,
|
||||
});
|
||||
}
|
||||
|
||||
@ -274,6 +274,7 @@ export interface ApiAppConfig {
|
||||
verifyAgeBotUsername?: string;
|
||||
verifyAgeCountry?: string;
|
||||
verifyAgeMin?: number;
|
||||
contactNoteLimit?: number;
|
||||
}
|
||||
|
||||
export interface ApiConfig {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import type { API_CHAT_TYPES } from '../../config';
|
||||
import type { ApiBotInfo } from './bots';
|
||||
import type { ApiBusinessIntro, ApiBusinessLocation, ApiBusinessWorkHours } from './business';
|
||||
import type { ApiDocument, ApiPhoto } from './messages';
|
||||
import type { ApiDocument, ApiFormattedText, ApiPhoto } from './messages';
|
||||
import type {
|
||||
ApiBotVerification,
|
||||
ApiEmojiStatusType,
|
||||
@ -82,6 +82,7 @@ export interface ApiUserFullInfo {
|
||||
paidMessagesStars?: number;
|
||||
settings?: ApiPeerSettings;
|
||||
mainTab?: ApiProfileTab;
|
||||
note?: ApiFormattedText;
|
||||
}
|
||||
|
||||
export type ApiUserType = 'userTypeBot' | 'userTypeRegular' | 'userTypeDeleted' | 'userTypeUnknown';
|
||||
|
||||
1
src/assets/font-icons/note.svg
Normal file
1
src/assets/font-icons/note.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path d="M20 0H8.6C5.5 0 2.9 2.6 2.9 5.7v20.5c0 3.2 2.6 5.7 5.7 5.7h14.7c3.2 0 5.7-2.6 5.7-5.7V9.1q0-.9-.6-1.5L21.6.7c-.4-.4-1-.6-1.5-.6Zm-.1 2.5 6.7 6.7h-3.5c-1.8 0-3.2-1.4-3.2-3.2zm3.5 27H8.7c-1.8 0-3.2-1.4-3.2-3.2V5.7c0-1.8 1.4-3.2 3.2-3.2h8.7V6c0 3.2 2.6 5.7 5.7 5.7h3.5v14.5c0 1.8-1.4 3.2-3.2 3.2Z" class="st0"/><path d="M8.9 18.7H23v2.5H8.9zM8.9 23.6H21v2.5H8.9zM8.9 13.7H23v2.5H8.9z" class="st0"/></svg>
|
||||
|
After Width: | Height: | Size: 470 B |
@ -2293,3 +2293,7 @@
|
||||
"TitleGiftLocked" = "Gift Locked";
|
||||
"GiftLockedMessage" = "This gift is currently only available to earlier Telegram users. It will unlock for your account in about **{relativeDate}**.";
|
||||
"QuickPreview" = "Quick Preview";
|
||||
"UserNoteTitle" = "Notes";
|
||||
"UserNoteHint" = "only visible to you";
|
||||
"EditUserNoteHint" = "Notes are only visible to you.";
|
||||
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
@use '../../../styles/mixins';
|
||||
|
||||
.businessLocation {
|
||||
flex-shrink: 0;
|
||||
|
||||
@ -68,3 +70,44 @@
|
||||
margin-top: 0.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.noteSubtitle {
|
||||
display: flex !important;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.noteListItemIcon {
|
||||
align-self: flex-start;
|
||||
padding-top: 1rem;
|
||||
}
|
||||
|
||||
.noteHint {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.noteText {
|
||||
overflow: hidden;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
/* stylelint-disable-next-line plugin/no-low-performance-animation-properties */
|
||||
transition: max-height 0.3s ease;
|
||||
}
|
||||
|
||||
.noteTextCollapsed {
|
||||
@include mixins.gradient-border-bottom(1rem);
|
||||
}
|
||||
|
||||
.noteCollapseIcon {
|
||||
margin-inline-start: 0.125rem;
|
||||
font-size: 0.9375rem;
|
||||
line-height: 0.9375rem;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.expandedIcon {
|
||||
transform: rotate(-180deg);
|
||||
}
|
||||
|
||||
.clickable {
|
||||
cursor: var(--custom-cursor, pointer);
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import {
|
||||
memo, useMemo,
|
||||
memo, useMemo, useRef,
|
||||
} from '../../../lib/teact/teact';
|
||||
import { getActions, getGlobal, withGlobal } from '../../../global';
|
||||
|
||||
@ -46,7 +46,9 @@ import { extractCurrentThemeParams } from '../../../util/themeStyle';
|
||||
import { ChatAnimationTypes } from '../../left/main/hooks';
|
||||
import formatUsername from '../helpers/formatUsername';
|
||||
import renderText from '../helpers/renderText';
|
||||
import { renderTextWithEntities } from '../helpers/renderTextWithEntities';
|
||||
|
||||
import useCollapsibleLines from '../../../hooks/element/useCollapsibleLines';
|
||||
import useEffectWithPrevDeps from '../../../hooks/useEffectWithPrevDeps';
|
||||
import useLang from '../../../hooks/useLang';
|
||||
import useLastCallback from '../../../hooks/useLastCallback';
|
||||
@ -60,6 +62,7 @@ import ListItem from '../../ui/ListItem';
|
||||
import Skeleton from '../../ui/placeholder/Skeleton';
|
||||
import Switcher from '../../ui/Switcher';
|
||||
import CustomEmoji from '../CustomEmoji';
|
||||
import Icon from '../icons/Icon';
|
||||
import SafeLink from '../SafeLink';
|
||||
import BusinessHours from './BusinessHours';
|
||||
import UserBirthday from './UserBirthday';
|
||||
@ -102,6 +105,7 @@ const DEFAULT_MAP_CONFIG = {
|
||||
};
|
||||
|
||||
const BOT_VERIFICATION_ICON_SIZE = 16;
|
||||
const MAX_LINES = 3;
|
||||
|
||||
const ChatExtra = ({
|
||||
chatOrUserId,
|
||||
@ -154,10 +158,19 @@ const ChatExtra = ({
|
||||
businessWorkHours,
|
||||
personalChannelMessageId,
|
||||
birthday,
|
||||
note,
|
||||
} = userFullInfo || {};
|
||||
const oldLang = useOldLang();
|
||||
const lang = useLang();
|
||||
|
||||
const noteTextRef = useRef<HTMLDivElement>();
|
||||
|
||||
const {
|
||||
isCollapsed: isNoteCollapsed,
|
||||
isCollapsible: isNoteCollapsible,
|
||||
setIsCollapsed: setIsNoteCollapsed,
|
||||
} = useCollapsibleLines(noteTextRef, MAX_LINES, undefined);
|
||||
|
||||
useEffectWithPrevDeps(([prevPeerId]) => {
|
||||
if (!peerId || prevPeerId === peerId) return;
|
||||
if (user || (chat && isChatChannel(chat))) {
|
||||
@ -241,6 +254,16 @@ const ChatExtra = ({
|
||||
openSavedDialog({ chatId: chatOrUserId });
|
||||
});
|
||||
|
||||
const canExpandNote = isNoteCollapsible && isNoteCollapsed;
|
||||
|
||||
const handleExpandNote = useLastCallback(() => {
|
||||
setIsNoteCollapsed(false);
|
||||
});
|
||||
|
||||
const handleToggleNote = useLastCallback(() => {
|
||||
setIsNoteCollapsed((prev) => !prev);
|
||||
});
|
||||
|
||||
function copy(text: string, entity: string) {
|
||||
copyTextToClipboard(text);
|
||||
showNotification({ message: `${entity} was copied` });
|
||||
@ -458,6 +481,50 @@ const ChatExtra = ({
|
||||
<span className="subtitle">{oldLang('BusinessProfileLocation')}</span>
|
||||
</ListItem>
|
||||
)}
|
||||
{note && (
|
||||
<ListItem
|
||||
icon="note"
|
||||
iconClassName={styles.noteListItemIcon}
|
||||
multiline
|
||||
narrow
|
||||
isStatic
|
||||
allowSelection
|
||||
>
|
||||
<div
|
||||
ref={noteTextRef}
|
||||
className={buildClassName(
|
||||
'title',
|
||||
'word-break',
|
||||
'allow-selection',
|
||||
styles.noteText,
|
||||
isNoteCollapsed && styles.noteTextCollapsed,
|
||||
)}
|
||||
dir={lang.isRtl ? 'rtl' : undefined}
|
||||
onClick={canExpandNote ? handleExpandNote : undefined}
|
||||
>
|
||||
{renderTextWithEntities({
|
||||
text: note.text,
|
||||
entities: note.entities,
|
||||
})}
|
||||
</div>
|
||||
<div className={buildClassName('subtitle', styles.noteSubtitle)}>
|
||||
<span>{lang('UserNoteTitle')}</span>
|
||||
|
||||
<span className={styles.noteHint}>{lang('UserNoteHint')}</span>
|
||||
{isNoteCollapsible && (
|
||||
<Icon
|
||||
className={buildClassName(
|
||||
styles.noteCollapseIcon,
|
||||
styles.clickable,
|
||||
!isNoteCollapsed && styles.expandedIcon,
|
||||
)}
|
||||
onClick={handleToggleNote}
|
||||
name="down"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</ListItem>
|
||||
)}
|
||||
{hasSavedMessages && !isOwnProfile && !isInSettings && (
|
||||
<ListItem icon="saved-messages" narrow ripple onClick={handleOpenSavedDialog}>
|
||||
<span>{oldLang('SavedMessagesTab')}</span>
|
||||
|
||||
@ -40,6 +40,7 @@
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
&__note-description,
|
||||
&__help-text {
|
||||
font-size: 0.9375rem;
|
||||
color: var(--color-text-secondary);
|
||||
@ -47,5 +48,9 @@
|
||||
&__negative {
|
||||
margin-top: -1rem;
|
||||
}
|
||||
|
||||
&__edit {
|
||||
margin-top: -0.875rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,13 +8,15 @@ import { getActions, withGlobal } from '../../global';
|
||||
import type { ApiCountryCode, ApiUser, ApiUserStatus } from '../../api/types';
|
||||
|
||||
import { getUserStatus } from '../../global/helpers';
|
||||
import { selectUser, selectUserStatus } from '../../global/selectors';
|
||||
import { selectUser, selectUserFullInfo, selectUserStatus } from '../../global/selectors';
|
||||
import { IS_TOUCH_ENV } from '../../util/browser/windowEnvironment';
|
||||
import { formatPhoneNumberWithCode } from '../../util/phoneNumber';
|
||||
import { DEFAULT_MAX_NOTE_LENGTH } from '../../limits';
|
||||
import renderText from '../common/helpers/renderText';
|
||||
|
||||
import useCurrentOrPrev from '../../hooks/useCurrentOrPrev';
|
||||
import useFlag from '../../hooks/useFlag';
|
||||
import useLang from '../../hooks/useLang';
|
||||
import useOldLang from '../../hooks/useOldLang';
|
||||
|
||||
import Avatar from '../common/Avatar';
|
||||
@ -22,6 +24,7 @@ import Button from '../ui/Button';
|
||||
import Checkbox from '../ui/Checkbox';
|
||||
import InputText from '../ui/InputText';
|
||||
import Modal from '../ui/Modal';
|
||||
import TextArea from '../ui/TextArea';
|
||||
|
||||
import './NewContactModal.scss';
|
||||
|
||||
@ -37,6 +40,8 @@ type StateProps = {
|
||||
user?: ApiUser;
|
||||
userStatus?: ApiUserStatus;
|
||||
phoneCodeList: ApiCountryCode[];
|
||||
contactNoteLimit: number;
|
||||
noteText?: string;
|
||||
};
|
||||
|
||||
const NewContactModal: FC<OwnProps & StateProps> = ({
|
||||
@ -46,10 +51,13 @@ const NewContactModal: FC<OwnProps & StateProps> = ({
|
||||
user,
|
||||
userStatus,
|
||||
phoneCodeList,
|
||||
contactNoteLimit,
|
||||
noteText,
|
||||
}) => {
|
||||
const { updateContact, importContact, closeNewContactDialog } = getActions();
|
||||
|
||||
const lang = useOldLang();
|
||||
const oldLang = useOldLang();
|
||||
const lang = useLang();
|
||||
const renderingUser = useCurrentOrPrev(user);
|
||||
const renderingIsByPhoneNumber = useCurrentOrPrev(isByPhoneNumber);
|
||||
const inputRef = useRef<HTMLInputElement>();
|
||||
@ -58,18 +66,23 @@ const NewContactModal: FC<OwnProps & StateProps> = ({
|
||||
const [firstName, setFirstName] = useState<string>(renderingUser?.firstName ?? '');
|
||||
const [lastName, setLastName] = useState<string>(renderingUser?.lastName ?? '');
|
||||
const [phone, setPhone] = useState<string>(renderingUser?.phoneNumber ?? '');
|
||||
const [note, setNote] = useState<string>('');
|
||||
const [shouldSharePhoneNumber, setShouldSharePhoneNumber] = useState<boolean>(true);
|
||||
const canBeSubmitted = Boolean(firstName && (!isByPhoneNumber || phone));
|
||||
|
||||
const noteSymbolsLeft = contactNoteLimit - note.length;
|
||||
const noteRef = useRef<HTMLTextAreaElement>();
|
||||
|
||||
useEffect(() => {
|
||||
if (isOpen) {
|
||||
markIsShown();
|
||||
setFirstName(renderingUser?.firstName ?? '');
|
||||
setLastName(renderingUser?.lastName ?? '');
|
||||
setPhone(renderingUser?.phoneNumber ?? '');
|
||||
setNote(noteText ?? '');
|
||||
setShouldSharePhoneNumber(true);
|
||||
}
|
||||
}, [isOpen, markIsShown, renderingUser?.firstName, renderingUser?.lastName, renderingUser?.phoneNumber]);
|
||||
}, [isOpen, markIsShown, noteText, renderingUser?.firstName, renderingUser?.lastName, renderingUser?.phoneNumber]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!IS_TOUCH_ENV && isShown) {
|
||||
@ -91,14 +104,21 @@ const NewContactModal: FC<OwnProps & StateProps> = ({
|
||||
setLastName(e.target.value);
|
||||
}, []);
|
||||
|
||||
const handleNoteChange = useCallback((e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
||||
setNote(e.target.value);
|
||||
}, []);
|
||||
|
||||
const handleClose = useCallback(() => {
|
||||
closeNewContactDialog();
|
||||
setFirstName('');
|
||||
setLastName('');
|
||||
setPhone('');
|
||||
setNote('');
|
||||
}, [closeNewContactDialog]);
|
||||
|
||||
const handleSubmit = useCallback(() => {
|
||||
const noteToSend = note.trim() ? { text: note, entities: [] } : undefined;
|
||||
|
||||
if (isByPhoneNumber || !userId) {
|
||||
importContact({
|
||||
firstName,
|
||||
@ -111,9 +131,10 @@ const NewContactModal: FC<OwnProps & StateProps> = ({
|
||||
firstName,
|
||||
lastName,
|
||||
shouldSharePhoneNumber,
|
||||
note: noteToSend,
|
||||
});
|
||||
}
|
||||
}, [firstName, importContact, isByPhoneNumber, lastName, phone, shouldSharePhoneNumber, updateContact, userId]);
|
||||
}, [firstName, importContact, isByPhoneNumber, lastName, note, phone, shouldSharePhoneNumber, updateContact, userId]);
|
||||
|
||||
if (!isOpen && !isShown) {
|
||||
return undefined;
|
||||
@ -122,7 +143,7 @@ const NewContactModal: FC<OwnProps & StateProps> = ({
|
||||
function renderAddContact() {
|
||||
return (
|
||||
<>
|
||||
<div className="NewContactModal__profile" dir={lang.isRtl ? 'rtl' : undefined}>
|
||||
<div className="NewContactModal__profile" dir={oldLang.isRtl ? 'rtl' : undefined}>
|
||||
<Avatar
|
||||
size="jumbo"
|
||||
peer={renderingUser}
|
||||
@ -132,29 +153,42 @@ const NewContactModal: FC<OwnProps & StateProps> = ({
|
||||
<p className="NewContactModal__phone-number">
|
||||
{renderingUser?.phoneNumber
|
||||
? formatPhoneNumberWithCode(phoneCodeList, renderingUser.phoneNumber)
|
||||
: lang('MobileHidden')}
|
||||
: oldLang('MobileHidden')}
|
||||
</p>
|
||||
<span className="NewContactModal__user-status" dir="auto">
|
||||
{getUserStatus(lang, renderingUser!, userStatus)}
|
||||
{getUserStatus(oldLang, renderingUser!, userStatus)}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<InputText
|
||||
ref={inputRef}
|
||||
value={firstName}
|
||||
label={lang('FirstName')}
|
||||
label={oldLang('FirstName')}
|
||||
tabIndex={0}
|
||||
onChange={handleFirstNameChange}
|
||||
/>
|
||||
<InputText
|
||||
value={lastName}
|
||||
label={lang('LastName')}
|
||||
label={oldLang('LastName')}
|
||||
tabIndex={0}
|
||||
onChange={handleLastNameChange}
|
||||
/>
|
||||
<TextArea
|
||||
ref={noteRef}
|
||||
id="user-note"
|
||||
label={lang('UserNoteTitle')}
|
||||
onChange={handleNoteChange}
|
||||
value={note}
|
||||
maxLength={contactNoteLimit}
|
||||
maxLengthIndicator={noteSymbolsLeft.toString()}
|
||||
noReplaceNewlines
|
||||
/>
|
||||
<p className="NewContactModal__help-text NewContactModal__help-text__edit">
|
||||
{lang('EditUserNoteHint')}
|
||||
</p>
|
||||
<p className="NewContactModal__help-text">
|
||||
{renderText(
|
||||
lang('NewContact.Phone.Hidden.Text', renderingUser?.firstName || ''),
|
||||
oldLang('NewContact.Phone.Hidden.Text', renderingUser?.firstName || ''),
|
||||
['emoji', 'simple_markdown'],
|
||||
)}
|
||||
</p>
|
||||
@ -163,10 +197,10 @@ const NewContactModal: FC<OwnProps & StateProps> = ({
|
||||
checked={shouldSharePhoneNumber}
|
||||
tabIndex={0}
|
||||
onCheck={setShouldSharePhoneNumber}
|
||||
label={lang('lng_new_contact_share')}
|
||||
label={oldLang('lng_new_contact_share')}
|
||||
/>
|
||||
<p className="NewContactModal__help-text NewContactModal__help-text__negative">
|
||||
{renderText(lang('AddContact.SharedContactExceptionInfo', renderingUser?.firstName))}
|
||||
{renderText(oldLang('AddContact.SharedContactExceptionInfo', renderingUser?.firstName))}
|
||||
</p>
|
||||
</>
|
||||
);
|
||||
@ -181,19 +215,19 @@ const NewContactModal: FC<OwnProps & StateProps> = ({
|
||||
ref={inputRef}
|
||||
value={phone}
|
||||
inputMode="tel"
|
||||
label={lang('lng_contact_phone')}
|
||||
label={oldLang('lng_contact_phone')}
|
||||
tabIndex={0}
|
||||
onChange={handlePhoneChange}
|
||||
/>
|
||||
<InputText
|
||||
value={firstName}
|
||||
label={lang('FirstName')}
|
||||
label={oldLang('FirstName')}
|
||||
tabIndex={0}
|
||||
onChange={handleFirstNameChange}
|
||||
/>
|
||||
<InputText
|
||||
value={lastName}
|
||||
label={lang('LastName')}
|
||||
label={oldLang('LastName')}
|
||||
tabIndex={0}
|
||||
onChange={handleLastNameChange}
|
||||
/>
|
||||
@ -205,7 +239,7 @@ const NewContactModal: FC<OwnProps & StateProps> = ({
|
||||
return (
|
||||
<Modal
|
||||
className="NewContactModal"
|
||||
title={lang('NewContact')}
|
||||
title={oldLang('NewContact')}
|
||||
isOpen={isOpen}
|
||||
onClose={handleClose}
|
||||
onCloseAnimationEnd={unmarkIsShown}
|
||||
@ -219,14 +253,14 @@ const NewContactModal: FC<OwnProps & StateProps> = ({
|
||||
disabled={!canBeSubmitted}
|
||||
onClick={handleSubmit}
|
||||
>
|
||||
{lang('Done')}
|
||||
{oldLang('Done')}
|
||||
</Button>
|
||||
<Button
|
||||
isText
|
||||
className="confirm-dialog-button"
|
||||
onClick={handleClose}
|
||||
>
|
||||
{lang('Cancel')}
|
||||
{oldLang('Cancel')}
|
||||
</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
@ -236,10 +270,15 @@ const NewContactModal: FC<OwnProps & StateProps> = ({
|
||||
export default memo(withGlobal<OwnProps>(
|
||||
(global, { userId }): Complete<StateProps> => {
|
||||
const user = userId ? selectUser(global, userId) : undefined;
|
||||
const userFullInfo = userId ? selectUserFullInfo(global, userId) : undefined;
|
||||
const contactNoteLimit = global.appConfig?.contactNoteLimit || DEFAULT_MAX_NOTE_LENGTH;
|
||||
|
||||
return {
|
||||
user,
|
||||
userStatus: userId ? selectUserStatus(global, userId) : undefined,
|
||||
phoneCodeList: global.countryList.phoneCodes,
|
||||
contactNoteLimit,
|
||||
noteText: userFullInfo?.note?.text,
|
||||
};
|
||||
},
|
||||
)(NewContactModal));
|
||||
|
||||
@ -19,9 +19,11 @@ import {
|
||||
selectUser,
|
||||
selectUserFullInfo,
|
||||
} from '../../../global/selectors';
|
||||
import { DEFAULT_MAX_NOTE_LENGTH } from '../../../limits';
|
||||
|
||||
import useFlag from '../../../hooks/useFlag';
|
||||
import useHistoryBack from '../../../hooks/useHistoryBack';
|
||||
import useLang from '../../../hooks/useLang';
|
||||
import useOldLang from '../../../hooks/useOldLang';
|
||||
|
||||
import Avatar from '../../common/Avatar';
|
||||
@ -34,6 +36,7 @@ import InputText from '../../ui/InputText';
|
||||
import ListItem from '../../ui/ListItem';
|
||||
import SelectAvatar from '../../ui/SelectAvatar';
|
||||
import Spinner from '../../ui/Spinner';
|
||||
import TextArea from '../../ui/TextArea';
|
||||
|
||||
import './Management.scss';
|
||||
|
||||
@ -49,6 +52,8 @@ type StateProps = {
|
||||
isMuted?: boolean;
|
||||
personalPhoto?: ApiPhoto;
|
||||
notPersonalPhoto?: ApiPhoto;
|
||||
noteText?: string;
|
||||
contactNoteLimit: number;
|
||||
};
|
||||
|
||||
const ERROR_FIRST_NAME_MISSING = 'Please provide first name';
|
||||
@ -62,9 +67,12 @@ const ManageUser: FC<OwnProps & StateProps> = ({
|
||||
isActive,
|
||||
personalPhoto,
|
||||
notPersonalPhoto,
|
||||
noteText,
|
||||
contactNoteLimit,
|
||||
}) => {
|
||||
const {
|
||||
updateContact,
|
||||
updateContactNote,
|
||||
deleteContact,
|
||||
closeManagement,
|
||||
uploadContactProfilePhoto,
|
||||
@ -76,7 +84,8 @@ const ManageUser: FC<OwnProps & StateProps> = ({
|
||||
const [isProfileFieldsTouched, markProfileFieldsTouched, unmarkProfileFieldsTouched] = useFlag();
|
||||
const [error, setError] = useState<string | undefined>();
|
||||
const [isNotificationsTouched, markNotificationsTouched, unmarkNotificationsTouched] = useFlag();
|
||||
const lang = useOldLang();
|
||||
const oldLang = useOldLang();
|
||||
const lang = useLang();
|
||||
|
||||
useHistoryBack({
|
||||
isActive,
|
||||
@ -85,9 +94,11 @@ const ManageUser: FC<OwnProps & StateProps> = ({
|
||||
|
||||
const currentFirstName = user ? (user.firstName || '') : '';
|
||||
const currentLastName = user ? (user.lastName || '') : '';
|
||||
const currentNote = noteText || '';
|
||||
|
||||
const [firstName, setFirstName] = useState(currentFirstName);
|
||||
const [lastName, setLastName] = useState(currentLastName);
|
||||
const [note, setNote] = useState(currentNote);
|
||||
const [isNotificationsEnabled, setIsNotificationsEnabled] = useState(!isMuted);
|
||||
|
||||
useEffect(() => {
|
||||
@ -103,7 +114,8 @@ const ManageUser: FC<OwnProps & StateProps> = ({
|
||||
useEffect(() => {
|
||||
setFirstName(currentFirstName);
|
||||
setLastName(currentLastName);
|
||||
}, [currentFirstName, currentLastName, user]);
|
||||
setNote(currentNote);
|
||||
}, [currentFirstName, currentLastName, currentNote]);
|
||||
|
||||
useEffect(() => {
|
||||
if (progress === ManagementProgress.Complete) {
|
||||
@ -127,6 +139,11 @@ const ManageUser: FC<OwnProps & StateProps> = ({
|
||||
markProfileFieldsTouched();
|
||||
}, []);
|
||||
|
||||
const handleNoteChange = useCallback((e: ChangeEvent<HTMLTextAreaElement>) => {
|
||||
setNote(e.target.value);
|
||||
markProfileFieldsTouched();
|
||||
}, []);
|
||||
|
||||
const handleNotificationChange = useCallback((e: ChangeEvent<HTMLInputElement>) => {
|
||||
setIsNotificationsEnabled(e.target.checked);
|
||||
markNotificationsTouched();
|
||||
@ -136,24 +153,36 @@ const ManageUser: FC<OwnProps & StateProps> = ({
|
||||
const handleProfileSave = useCallback(() => {
|
||||
const trimmedFirstName = firstName.trim();
|
||||
const trimmedLastName = lastName.trim();
|
||||
const trimmedNote = note.trim();
|
||||
|
||||
if (!trimmedFirstName.length) {
|
||||
setError(ERROR_FIRST_NAME_MISSING);
|
||||
return;
|
||||
}
|
||||
|
||||
firstNameRef.current?.blur();
|
||||
lastNameRef.current?.blur();
|
||||
noteRef.current?.blur();
|
||||
|
||||
updateContact({
|
||||
userId,
|
||||
firstName: trimmedFirstName,
|
||||
lastName: trimmedLastName,
|
||||
});
|
||||
|
||||
if (trimmedNote !== currentNote) {
|
||||
updateContactNote({
|
||||
userId,
|
||||
note: { text: trimmedNote, entities: [] },
|
||||
});
|
||||
}
|
||||
|
||||
if (isNotificationsTouched) {
|
||||
updateChatMutedState({
|
||||
chatId: userId, mutedUntil: isNotificationsEnabled ? UNMUTE_TIMESTAMP : MUTE_INDEFINITE_TIMESTAMP,
|
||||
});
|
||||
}
|
||||
}, [firstName, isNotificationsEnabled, isNotificationsTouched, lastName, userId]);
|
||||
}, [currentNote, firstName, isNotificationsEnabled, isNotificationsTouched, lastName, note, userId]);
|
||||
|
||||
const handleDeleteContact = useCallback(() => {
|
||||
deleteContact({ userId });
|
||||
@ -161,6 +190,10 @@ const ManageUser: FC<OwnProps & StateProps> = ({
|
||||
closeManagement();
|
||||
}, [closeDeleteDialog, closeManagement, deleteContact, userId]);
|
||||
|
||||
const firstNameRef = useRef<HTMLInputElement>();
|
||||
const lastNameRef = useRef<HTMLInputElement>();
|
||||
const noteRef = useRef<HTMLTextAreaElement>();
|
||||
|
||||
const inputRef = useRef<HTMLInputElement>();
|
||||
const isSuggestRef = useRef(false);
|
||||
|
||||
@ -191,6 +224,7 @@ const ManageUser: FC<OwnProps & StateProps> = ({
|
||||
|
||||
const canSetPersonalPhoto = !isUserBot(user) && user.id !== SERVICE_NOTIFICATIONS_USER_ID;
|
||||
const isLoading = progress === ManagementProgress.InProgress;
|
||||
const noteSymbolsLeft = contactNoteLimit - note.length;
|
||||
|
||||
return (
|
||||
<div className="Management">
|
||||
@ -205,24 +239,37 @@ const ManageUser: FC<OwnProps & StateProps> = ({
|
||||
/>
|
||||
<div className="settings-edit">
|
||||
<InputText
|
||||
ref={firstNameRef}
|
||||
id="user-first-name"
|
||||
label={lang('UserInfo.FirstNamePlaceholder')}
|
||||
label={oldLang('UserInfo.FirstNamePlaceholder')}
|
||||
onChange={handleFirstNameChange}
|
||||
value={firstName}
|
||||
error={error === ERROR_FIRST_NAME_MISSING ? error : undefined}
|
||||
/>
|
||||
<InputText
|
||||
ref={lastNameRef}
|
||||
id="user-last-name"
|
||||
label={lang('UserInfo.LastNamePlaceholder')}
|
||||
label={oldLang('UserInfo.LastNamePlaceholder')}
|
||||
onChange={handleLastNameChange}
|
||||
value={lastName}
|
||||
/>
|
||||
<TextArea
|
||||
ref={noteRef}
|
||||
id="user-note"
|
||||
label={lang('UserNoteTitle')}
|
||||
onChange={handleNoteChange}
|
||||
value={note}
|
||||
maxLength={contactNoteLimit}
|
||||
maxLengthIndicator={noteSymbolsLeft.toString()}
|
||||
noReplaceNewlines
|
||||
/>
|
||||
</div>
|
||||
<p className="section-edit-info" dir="auto">{lang('EditUserNoteHint')}</p>
|
||||
<div className="ListItem narrow">
|
||||
<Checkbox
|
||||
checked={isNotificationsEnabled}
|
||||
label={lang('Notifications')}
|
||||
subLabel={lang(isNotificationsEnabled
|
||||
label={oldLang('Notifications')}
|
||||
subLabel={oldLang(isNotificationsEnabled
|
||||
? 'UserInfo.NotificationsEnabled'
|
||||
: 'UserInfo.NotificationsDisabled')}
|
||||
onChange={handleNotificationChange}
|
||||
@ -232,10 +279,10 @@ const ManageUser: FC<OwnProps & StateProps> = ({
|
||||
{canSetPersonalPhoto && (
|
||||
<div className="section">
|
||||
<ListItem icon="camera-add" ripple onClick={handleSuggestPhoto}>
|
||||
<span className="list-item-ellipsis">{lang('UserInfo.SuggestPhoto', user.firstName)}</span>
|
||||
<span className="list-item-ellipsis">{oldLang('UserInfo.SuggestPhoto', user.firstName)}</span>
|
||||
</ListItem>
|
||||
<ListItem icon="camera-add" ripple onClick={handleSetPersonalPhoto}>
|
||||
<span className="list-item-ellipsis">{lang('UserInfo.SetCustomPhoto', user.firstName)}</span>
|
||||
<span className="list-item-ellipsis">{oldLang('UserInfo.SetCustomPhoto', user.firstName)}</span>
|
||||
</ListItem>
|
||||
{personalPhoto && (
|
||||
<ListItem
|
||||
@ -251,15 +298,15 @@ const ManageUser: FC<OwnProps & StateProps> = ({
|
||||
ripple
|
||||
onClick={openResetPersonalPhotoDialog}
|
||||
>
|
||||
{lang('UserInfo.ResetCustomPhoto')}
|
||||
{oldLang('UserInfo.ResetCustomPhoto')}
|
||||
</ListItem>
|
||||
)}
|
||||
<p className="section-help" dir="auto">{lang('UserInfo.CustomPhotoInfo', user.firstName)}</p>
|
||||
<p className="section-help" dir="auto">{oldLang('UserInfo.CustomPhotoInfo', user.firstName)}</p>
|
||||
</div>
|
||||
)}
|
||||
<div className="section">
|
||||
<ListItem icon="delete" ripple destructive onClick={openDeleteDialog}>
|
||||
{lang('DeleteContact')}
|
||||
{oldLang('DeleteContact')}
|
||||
</ListItem>
|
||||
</div>
|
||||
</div>
|
||||
@ -267,7 +314,7 @@ const ManageUser: FC<OwnProps & StateProps> = ({
|
||||
isShown={isProfileFieldsTouched}
|
||||
onClick={handleProfileSave}
|
||||
disabled={isLoading}
|
||||
ariaLabel={lang('Save')}
|
||||
ariaLabel={oldLang('Save')}
|
||||
>
|
||||
{isLoading ? (
|
||||
<Spinner color="white" />
|
||||
@ -278,16 +325,16 @@ const ManageUser: FC<OwnProps & StateProps> = ({
|
||||
<ConfirmDialog
|
||||
isOpen={isDeleteDialogOpen}
|
||||
onClose={closeDeleteDialog}
|
||||
text={lang('AreYouSureDeleteContact')}
|
||||
confirmLabel={lang('DeleteContact')}
|
||||
text={oldLang('AreYouSureDeleteContact')}
|
||||
confirmLabel={oldLang('DeleteContact')}
|
||||
confirmHandler={handleDeleteContact}
|
||||
confirmIsDestructive
|
||||
/>
|
||||
<ConfirmDialog
|
||||
isOpen={isResetPersonalPhotoDialogOpen}
|
||||
onClose={closeResetPersonalPhotoDialog}
|
||||
text={lang('UserInfo.ResetToOriginalAlertText', user.firstName)}
|
||||
confirmLabel={lang('Reset')}
|
||||
text={oldLang('UserInfo.ResetToOriginalAlertText', user.firstName)}
|
||||
confirmLabel={oldLang('Reset')}
|
||||
confirmHandler={handleResetPersonalAvatar}
|
||||
confirmIsDestructive
|
||||
/>
|
||||
@ -308,9 +355,11 @@ export default memo(withGlobal<OwnProps>(
|
||||
const isMuted = chat && getIsChatMuted(chat, selectNotifyDefaults(global), selectNotifyException(global, chat.id));
|
||||
const personalPhoto = userFullInfo?.personalPhoto;
|
||||
const notPersonalPhoto = userFullInfo?.profilePhoto || userFullInfo?.fallbackPhoto;
|
||||
const noteText = userFullInfo?.note?.text;
|
||||
const contactNoteLimit = global.appConfig?.contactNoteLimit || DEFAULT_MAX_NOTE_LENGTH;
|
||||
|
||||
return {
|
||||
user, progress, isMuted, personalPhoto, notPersonalPhoto,
|
||||
user, progress, isMuted, personalPhoto, notPersonalPhoto, noteText, contactNoteLimit,
|
||||
};
|
||||
},
|
||||
)(ManageUser));
|
||||
|
||||
@ -97,12 +97,17 @@
|
||||
}
|
||||
}
|
||||
|
||||
.section-edit-info,
|
||||
.section-info {
|
||||
padding: 0 1rem;
|
||||
font-size: 0.875rem;
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
|
||||
.section-edit-info {
|
||||
margin-top: -0.875rem;
|
||||
}
|
||||
|
||||
.invite-link {
|
||||
padding: 0 1rem;
|
||||
}
|
||||
|
||||
@ -239,7 +239,7 @@ addActionHandler('openChatRefundModal', async (global, actions, payload): Promis
|
||||
|
||||
addActionHandler('updateContact', async (global, actions, payload): Promise<void> => {
|
||||
const {
|
||||
userId, firstName, lastName, shouldSharePhoneNumber,
|
||||
userId, firstName, lastName, shouldSharePhoneNumber, note,
|
||||
tabId = getCurrentTabId(),
|
||||
} = payload;
|
||||
|
||||
@ -253,7 +253,7 @@ addActionHandler('updateContact', async (global, actions, payload): Promise<void
|
||||
setGlobal(global);
|
||||
|
||||
let result;
|
||||
if (!user.isContact && user.phoneNumber) {
|
||||
if (!user.isContact && user.phoneNumber && !note) {
|
||||
result = await callApi('importContact', { phone: user.phoneNumber, firstName, lastName });
|
||||
} else {
|
||||
const { id, accessHash } = user;
|
||||
@ -264,6 +264,7 @@ addActionHandler('updateContact', async (global, actions, payload): Promise<void
|
||||
firstName,
|
||||
lastName,
|
||||
shouldSharePhoneNumber,
|
||||
note,
|
||||
});
|
||||
}
|
||||
|
||||
@ -289,6 +290,29 @@ addActionHandler('updateContact', async (global, actions, payload): Promise<void
|
||||
setGlobal(global);
|
||||
});
|
||||
|
||||
addActionHandler('updateContactNote', async (global, actions, payload): Promise<void> => {
|
||||
const {
|
||||
userId, note,
|
||||
tabId = getCurrentTabId(),
|
||||
} = payload;
|
||||
|
||||
const user = selectUser(global, userId);
|
||||
if (!user) {
|
||||
return;
|
||||
}
|
||||
|
||||
global = getGlobal();
|
||||
global = updateManagementProgress(global, ManagementProgress.InProgress, tabId);
|
||||
setGlobal(global);
|
||||
|
||||
const result = await callApi('updateContactNote', user, note);
|
||||
|
||||
global = getGlobal();
|
||||
if (result) global = updateUserFullInfo(global, userId, { note });
|
||||
global = updateManagementProgress(global, ManagementProgress.Complete, tabId);
|
||||
setGlobal(global);
|
||||
});
|
||||
|
||||
addActionHandler('deleteContact', async (global, actions, payload): Promise<void> => {
|
||||
const { userId } = payload;
|
||||
|
||||
|
||||
@ -1867,6 +1867,11 @@ export interface ActionPayloads {
|
||||
firstName: string;
|
||||
lastName?: string;
|
||||
shouldSharePhoneNumber?: boolean;
|
||||
note?: ApiFormattedText;
|
||||
} & WithTabId;
|
||||
updateContactNote: {
|
||||
userId: string;
|
||||
note: ApiFormattedText;
|
||||
} & WithTabId;
|
||||
toggleNoPaidMessagesException: {
|
||||
userId: string;
|
||||
|
||||
@ -20,15 +20,19 @@ export default function useCollapsibleLines<T extends HTMLElement, C extends HTM
|
||||
) {
|
||||
const isFirstRenderRef = useRef(true);
|
||||
const cutoutHeightRef = useRef<number | undefined>();
|
||||
const fullHeightRef = useRef<number | undefined>();
|
||||
const [isCollapsible, setIsCollapsible] = useState(!isDisabled);
|
||||
const [isCollapsed, setIsCollapsed] = useState(isCollapsible);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
const element = (cutoutRef || ref).current;
|
||||
const shouldUseStyleInExpand = !cutoutRef;
|
||||
|
||||
if (isDisabled || !element || isFirstRenderRef.current) return;
|
||||
|
||||
requestMutation(() => {
|
||||
element.style.maxHeight = isCollapsed ? `${cutoutHeightRef.current}px` : '';
|
||||
element.style.maxHeight = isCollapsed ? `${cutoutHeightRef.current}px` :
|
||||
shouldUseStyleInExpand ? `${fullHeightRef.current}px` : ``;
|
||||
});
|
||||
}, [cutoutRef, isCollapsed, isDisabled, ref]);
|
||||
|
||||
@ -39,6 +43,7 @@ export default function useCollapsibleLines<T extends HTMLElement, C extends HTM
|
||||
const element = ref.current;
|
||||
|
||||
const { lineHeight, totalLines } = calcTextLineHeightAndCount(element);
|
||||
fullHeightRef.current = element.scrollHeight;
|
||||
if (totalLines > maxLinesBeforeCollapse) {
|
||||
cutoutHeightRef.current = lineHeight * maxLinesBeforeCollapse;
|
||||
setIsCollapsible(true);
|
||||
@ -63,7 +68,9 @@ export default function useCollapsibleLines<T extends HTMLElement, C extends HTM
|
||||
isFirstRenderRef.current = false;
|
||||
const element = (cutoutRef || ref).current;
|
||||
if (!element) return;
|
||||
element.style.maxHeight = cutoutHeightRef.current ? `${cutoutHeightRef.current}px` : '';
|
||||
element.style.maxHeight = cutoutHeightRef.current ?
|
||||
`${cutoutHeightRef.current}px` :
|
||||
`${fullHeightRef.current}px`;
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
@ -1569,6 +1569,7 @@ contacts.addContact#d9ba2e54 flags:# add_phone_privacy_exception:flags.0?true id
|
||||
contacts.resolvePhone#8af94344 phone:string = contacts.ResolvedPeer;
|
||||
contacts.editCloseFriends#ba6705f0 id:Vector<long> = Bool;
|
||||
contacts.getSponsoredPeers#b6c8c393 q:string = contacts.SponsoredPeers;
|
||||
contacts.updateContactNote#139f63fb id:InputUser note:TextWithEntities = Bool;
|
||||
messages.getMessages#63c66506 id:Vector<InputMessage> = messages.Messages;
|
||||
messages.getDialogs#a0f4cb4f flags:# exclude_pinned:flags.0?true folder_id:flags.1?int offset_date:int offset_id:int offset_peer:InputPeer limit:int hash:long = messages.Dialogs;
|
||||
messages.getHistory#4423e6c5 peer:InputPeer offset_id:int offset_date:int add_offset:int limit:int max_id:int min_id:int hash:long = messages.Messages;
|
||||
|
||||
@ -79,6 +79,7 @@
|
||||
"contacts.resolveUsername",
|
||||
"contacts.getTopPeers",
|
||||
"contacts.addContact",
|
||||
"contacts.updateContactNote",
|
||||
"contacts.resolvePhone",
|
||||
"contacts.editCloseFriends",
|
||||
"contacts.getSponsoredPeers",
|
||||
|
||||
@ -37,6 +37,7 @@ export const DEFAULT_LIMITS: Record<ApiLimitType, readonly [number, number]> = {
|
||||
};
|
||||
|
||||
export const DEFAULT_MAX_MESSAGE_LENGTH = 4096;
|
||||
export const DEFAULT_MAX_NOTE_LENGTH = 128;
|
||||
|
||||
export const DEFAULT_APP_CONFIG: ApiAppConfig = {
|
||||
hash: 0,
|
||||
|
||||
@ -3,8 +3,8 @@
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: block;
|
||||
src: url("./icons.woff2?c4762f96fd2b9a4edb1c0206e3cf5af6") format("woff2"),
|
||||
url("./icons.woff?c4762f96fd2b9a4edb1c0206e3cf5af6") format("woff");
|
||||
src: url("./icons.woff2?ef047748945945a49b46209abb54795c") format("woff2"),
|
||||
url("./icons.woff?ef047748945945a49b46209abb54795c") format("woff");
|
||||
}
|
||||
|
||||
.icon-char::before {
|
||||
@ -471,435 +471,438 @@ url("./icons.woff?c4762f96fd2b9a4edb1c0206e3cf5af6") format("woff");
|
||||
.icon-non-contacts::before {
|
||||
content: "\f196";
|
||||
}
|
||||
.icon-one-filled::before {
|
||||
.icon-note::before {
|
||||
content: "\f197";
|
||||
}
|
||||
.icon-open-in-new-tab::before {
|
||||
.icon-one-filled::before {
|
||||
content: "\f198";
|
||||
}
|
||||
.icon-password-off::before {
|
||||
.icon-open-in-new-tab::before {
|
||||
content: "\f199";
|
||||
}
|
||||
.icon-pause::before {
|
||||
.icon-password-off::before {
|
||||
content: "\f19a";
|
||||
}
|
||||
.icon-permissions::before {
|
||||
.icon-pause::before {
|
||||
content: "\f19b";
|
||||
}
|
||||
.icon-phone-discard-outline::before {
|
||||
.icon-permissions::before {
|
||||
content: "\f19c";
|
||||
}
|
||||
.icon-phone-discard::before {
|
||||
.icon-phone-discard-outline::before {
|
||||
content: "\f19d";
|
||||
}
|
||||
.icon-phone::before {
|
||||
.icon-phone-discard::before {
|
||||
content: "\f19e";
|
||||
}
|
||||
.icon-photo::before {
|
||||
.icon-phone::before {
|
||||
content: "\f19f";
|
||||
}
|
||||
.icon-pin-badge::before {
|
||||
.icon-photo::before {
|
||||
content: "\f1a0";
|
||||
}
|
||||
.icon-pin-list::before {
|
||||
.icon-pin-badge::before {
|
||||
content: "\f1a1";
|
||||
}
|
||||
.icon-pin::before {
|
||||
.icon-pin-list::before {
|
||||
content: "\f1a2";
|
||||
}
|
||||
.icon-pinned-chat::before {
|
||||
.icon-pin::before {
|
||||
content: "\f1a3";
|
||||
}
|
||||
.icon-pinned-message::before {
|
||||
.icon-pinned-chat::before {
|
||||
content: "\f1a4";
|
||||
}
|
||||
.icon-pip::before {
|
||||
.icon-pinned-message::before {
|
||||
content: "\f1a5";
|
||||
}
|
||||
.icon-play-story::before {
|
||||
.icon-pip::before {
|
||||
content: "\f1a6";
|
||||
}
|
||||
.icon-play::before {
|
||||
.icon-play-story::before {
|
||||
content: "\f1a7";
|
||||
}
|
||||
.icon-poll::before {
|
||||
.icon-play::before {
|
||||
content: "\f1a8";
|
||||
}
|
||||
.icon-previous::before {
|
||||
.icon-poll::before {
|
||||
content: "\f1a9";
|
||||
}
|
||||
.icon-privacy-policy::before {
|
||||
.icon-previous::before {
|
||||
content: "\f1aa";
|
||||
}
|
||||
.icon-proof-of-ownership::before {
|
||||
.icon-privacy-policy::before {
|
||||
content: "\f1ab";
|
||||
}
|
||||
.icon-quote-text::before {
|
||||
.icon-proof-of-ownership::before {
|
||||
content: "\f1ac";
|
||||
}
|
||||
.icon-quote::before {
|
||||
.icon-quote-text::before {
|
||||
content: "\f1ad";
|
||||
}
|
||||
.icon-radial-badge::before {
|
||||
.icon-quote::before {
|
||||
content: "\f1ae";
|
||||
}
|
||||
.icon-rating-icons-level1::before {
|
||||
.icon-radial-badge::before {
|
||||
content: "\f1af";
|
||||
}
|
||||
.icon-rating-icons-level10::before {
|
||||
.icon-rating-icons-level1::before {
|
||||
content: "\f1b0";
|
||||
}
|
||||
.icon-rating-icons-level2::before {
|
||||
.icon-rating-icons-level10::before {
|
||||
content: "\f1b1";
|
||||
}
|
||||
.icon-rating-icons-level20::before {
|
||||
.icon-rating-icons-level2::before {
|
||||
content: "\f1b2";
|
||||
}
|
||||
.icon-rating-icons-level3::before {
|
||||
.icon-rating-icons-level20::before {
|
||||
content: "\f1b3";
|
||||
}
|
||||
.icon-rating-icons-level30::before {
|
||||
.icon-rating-icons-level3::before {
|
||||
content: "\f1b4";
|
||||
}
|
||||
.icon-rating-icons-level4::before {
|
||||
.icon-rating-icons-level30::before {
|
||||
content: "\f1b5";
|
||||
}
|
||||
.icon-rating-icons-level40::before {
|
||||
.icon-rating-icons-level4::before {
|
||||
content: "\f1b6";
|
||||
}
|
||||
.icon-rating-icons-level5::before {
|
||||
.icon-rating-icons-level40::before {
|
||||
content: "\f1b7";
|
||||
}
|
||||
.icon-rating-icons-level50::before {
|
||||
.icon-rating-icons-level5::before {
|
||||
content: "\f1b8";
|
||||
}
|
||||
.icon-rating-icons-level6::before {
|
||||
.icon-rating-icons-level50::before {
|
||||
content: "\f1b9";
|
||||
}
|
||||
.icon-rating-icons-level60::before {
|
||||
.icon-rating-icons-level6::before {
|
||||
content: "\f1ba";
|
||||
}
|
||||
.icon-rating-icons-level7::before {
|
||||
.icon-rating-icons-level60::before {
|
||||
content: "\f1bb";
|
||||
}
|
||||
.icon-rating-icons-level70::before {
|
||||
.icon-rating-icons-level7::before {
|
||||
content: "\f1bc";
|
||||
}
|
||||
.icon-rating-icons-level8::before {
|
||||
.icon-rating-icons-level70::before {
|
||||
content: "\f1bd";
|
||||
}
|
||||
.icon-rating-icons-level80::before {
|
||||
.icon-rating-icons-level8::before {
|
||||
content: "\f1be";
|
||||
}
|
||||
.icon-rating-icons-level9::before {
|
||||
.icon-rating-icons-level80::before {
|
||||
content: "\f1bf";
|
||||
}
|
||||
.icon-rating-icons-level90::before {
|
||||
.icon-rating-icons-level9::before {
|
||||
content: "\f1c0";
|
||||
}
|
||||
.icon-rating-icons-negative::before {
|
||||
.icon-rating-icons-level90::before {
|
||||
content: "\f1c1";
|
||||
}
|
||||
.icon-readchats::before {
|
||||
.icon-rating-icons-negative::before {
|
||||
content: "\f1c2";
|
||||
}
|
||||
.icon-recent::before {
|
||||
.icon-readchats::before {
|
||||
content: "\f1c3";
|
||||
}
|
||||
.icon-refund::before {
|
||||
.icon-recent::before {
|
||||
content: "\f1c4";
|
||||
}
|
||||
.icon-reload::before {
|
||||
.icon-refund::before {
|
||||
content: "\f1c5";
|
||||
}
|
||||
.icon-remove-quote::before {
|
||||
.icon-reload::before {
|
||||
content: "\f1c6";
|
||||
}
|
||||
.icon-remove::before {
|
||||
.icon-remove-quote::before {
|
||||
content: "\f1c7";
|
||||
}
|
||||
.icon-reopen-topic::before {
|
||||
.icon-remove::before {
|
||||
content: "\f1c8";
|
||||
}
|
||||
.icon-replace::before {
|
||||
.icon-reopen-topic::before {
|
||||
content: "\f1c9";
|
||||
}
|
||||
.icon-replies::before {
|
||||
.icon-replace::before {
|
||||
content: "\f1ca";
|
||||
}
|
||||
.icon-reply-filled::before {
|
||||
.icon-replies::before {
|
||||
content: "\f1cb";
|
||||
}
|
||||
.icon-reply::before {
|
||||
.icon-reply-filled::before {
|
||||
content: "\f1cc";
|
||||
}
|
||||
.icon-revenue-split::before {
|
||||
.icon-reply::before {
|
||||
content: "\f1cd";
|
||||
}
|
||||
.icon-revote::before {
|
||||
.icon-revenue-split::before {
|
||||
content: "\f1ce";
|
||||
}
|
||||
.icon-save-story::before {
|
||||
.icon-revote::before {
|
||||
content: "\f1cf";
|
||||
}
|
||||
.icon-saved-messages::before {
|
||||
.icon-save-story::before {
|
||||
content: "\f1d0";
|
||||
}
|
||||
.icon-schedule::before {
|
||||
.icon-saved-messages::before {
|
||||
content: "\f1d1";
|
||||
}
|
||||
.icon-scheduled::before {
|
||||
.icon-schedule::before {
|
||||
content: "\f1d2";
|
||||
}
|
||||
.icon-sd-photo::before {
|
||||
.icon-scheduled::before {
|
||||
content: "\f1d3";
|
||||
}
|
||||
.icon-search::before {
|
||||
.icon-sd-photo::before {
|
||||
content: "\f1d4";
|
||||
}
|
||||
.icon-select::before {
|
||||
.icon-search::before {
|
||||
content: "\f1d5";
|
||||
}
|
||||
.icon-sell-outline::before {
|
||||
.icon-select::before {
|
||||
content: "\f1d6";
|
||||
}
|
||||
.icon-sell::before {
|
||||
.icon-sell-outline::before {
|
||||
content: "\f1d7";
|
||||
}
|
||||
.icon-send-outline::before {
|
||||
.icon-sell::before {
|
||||
content: "\f1d8";
|
||||
}
|
||||
.icon-send::before {
|
||||
.icon-send-outline::before {
|
||||
content: "\f1d9";
|
||||
}
|
||||
.icon-settings-filled::before {
|
||||
.icon-send::before {
|
||||
content: "\f1da";
|
||||
}
|
||||
.icon-settings::before {
|
||||
.icon-settings-filled::before {
|
||||
content: "\f1db";
|
||||
}
|
||||
.icon-share-filled::before {
|
||||
.icon-settings::before {
|
||||
content: "\f1dc";
|
||||
}
|
||||
.icon-share-screen-outlined::before {
|
||||
.icon-share-filled::before {
|
||||
content: "\f1dd";
|
||||
}
|
||||
.icon-share-screen-stop::before {
|
||||
.icon-share-screen-outlined::before {
|
||||
content: "\f1de";
|
||||
}
|
||||
.icon-share-screen::before {
|
||||
.icon-share-screen-stop::before {
|
||||
content: "\f1df";
|
||||
}
|
||||
.icon-show-message::before {
|
||||
.icon-share-screen::before {
|
||||
content: "\f1e0";
|
||||
}
|
||||
.icon-sidebar::before {
|
||||
.icon-show-message::before {
|
||||
content: "\f1e1";
|
||||
}
|
||||
.icon-skip-next::before {
|
||||
.icon-sidebar::before {
|
||||
content: "\f1e2";
|
||||
}
|
||||
.icon-skip-previous::before {
|
||||
.icon-skip-next::before {
|
||||
content: "\f1e3";
|
||||
}
|
||||
.icon-smallscreen::before {
|
||||
.icon-skip-previous::before {
|
||||
content: "\f1e4";
|
||||
}
|
||||
.icon-smile::before {
|
||||
.icon-smallscreen::before {
|
||||
content: "\f1e5";
|
||||
}
|
||||
.icon-sort-by-date::before {
|
||||
.icon-smile::before {
|
||||
content: "\f1e6";
|
||||
}
|
||||
.icon-sort-by-number::before {
|
||||
.icon-sort-by-date::before {
|
||||
content: "\f1e7";
|
||||
}
|
||||
.icon-sort-by-price::before {
|
||||
.icon-sort-by-number::before {
|
||||
content: "\f1e8";
|
||||
}
|
||||
.icon-sort::before {
|
||||
.icon-sort-by-price::before {
|
||||
content: "\f1e9";
|
||||
}
|
||||
.icon-speaker-muted-story::before {
|
||||
.icon-sort::before {
|
||||
content: "\f1ea";
|
||||
}
|
||||
.icon-speaker-outline::before {
|
||||
.icon-speaker-muted-story::before {
|
||||
content: "\f1eb";
|
||||
}
|
||||
.icon-speaker-story::before {
|
||||
.icon-speaker-outline::before {
|
||||
content: "\f1ec";
|
||||
}
|
||||
.icon-speaker::before {
|
||||
.icon-speaker-story::before {
|
||||
content: "\f1ed";
|
||||
}
|
||||
.icon-spoiler-disable::before {
|
||||
.icon-speaker::before {
|
||||
content: "\f1ee";
|
||||
}
|
||||
.icon-spoiler::before {
|
||||
.icon-spoiler-disable::before {
|
||||
content: "\f1ef";
|
||||
}
|
||||
.icon-sport::before {
|
||||
.icon-spoiler::before {
|
||||
content: "\f1f0";
|
||||
}
|
||||
.icon-star::before {
|
||||
.icon-sport::before {
|
||||
content: "\f1f1";
|
||||
}
|
||||
.icon-stars-lock::before {
|
||||
.icon-star::before {
|
||||
content: "\f1f2";
|
||||
}
|
||||
.icon-stars-refund::before {
|
||||
.icon-stars-lock::before {
|
||||
content: "\f1f3";
|
||||
}
|
||||
.icon-stats::before {
|
||||
.icon-stars-refund::before {
|
||||
content: "\f1f4";
|
||||
}
|
||||
.icon-stealth-future::before {
|
||||
.icon-stats::before {
|
||||
content: "\f1f5";
|
||||
}
|
||||
.icon-stealth-past::before {
|
||||
.icon-stealth-future::before {
|
||||
content: "\f1f6";
|
||||
}
|
||||
.icon-stickers::before {
|
||||
.icon-stealth-past::before {
|
||||
content: "\f1f7";
|
||||
}
|
||||
.icon-stop-raising-hand::before {
|
||||
.icon-stickers::before {
|
||||
content: "\f1f8";
|
||||
}
|
||||
.icon-stop::before {
|
||||
.icon-stop-raising-hand::before {
|
||||
content: "\f1f9";
|
||||
}
|
||||
.icon-story-caption::before {
|
||||
.icon-stop::before {
|
||||
content: "\f1fa";
|
||||
}
|
||||
.icon-story-expired::before {
|
||||
.icon-story-caption::before {
|
||||
content: "\f1fb";
|
||||
}
|
||||
.icon-story-priority::before {
|
||||
.icon-story-expired::before {
|
||||
content: "\f1fc";
|
||||
}
|
||||
.icon-story-reply::before {
|
||||
.icon-story-priority::before {
|
||||
content: "\f1fd";
|
||||
}
|
||||
.icon-strikethrough::before {
|
||||
.icon-story-reply::before {
|
||||
content: "\f1fe";
|
||||
}
|
||||
.icon-tag-add::before {
|
||||
.icon-strikethrough::before {
|
||||
content: "\f1ff";
|
||||
}
|
||||
.icon-tag-crossed::before {
|
||||
.icon-tag-add::before {
|
||||
content: "\f200";
|
||||
}
|
||||
.icon-tag-filter::before {
|
||||
.icon-tag-crossed::before {
|
||||
content: "\f201";
|
||||
}
|
||||
.icon-tag-name::before {
|
||||
.icon-tag-filter::before {
|
||||
content: "\f202";
|
||||
}
|
||||
.icon-tag::before {
|
||||
.icon-tag-name::before {
|
||||
content: "\f203";
|
||||
}
|
||||
.icon-timer::before {
|
||||
.icon-tag::before {
|
||||
content: "\f204";
|
||||
}
|
||||
.icon-toncoin::before {
|
||||
.icon-timer::before {
|
||||
content: "\f205";
|
||||
}
|
||||
.icon-trade::before {
|
||||
.icon-toncoin::before {
|
||||
content: "\f206";
|
||||
}
|
||||
.icon-transcribe::before {
|
||||
.icon-trade::before {
|
||||
content: "\f207";
|
||||
}
|
||||
.icon-truck::before {
|
||||
.icon-transcribe::before {
|
||||
content: "\f208";
|
||||
}
|
||||
.icon-unarchive::before {
|
||||
.icon-truck::before {
|
||||
content: "\f209";
|
||||
}
|
||||
.icon-underlined::before {
|
||||
.icon-unarchive::before {
|
||||
content: "\f20a";
|
||||
}
|
||||
.icon-understood::before {
|
||||
.icon-underlined::before {
|
||||
content: "\f20b";
|
||||
}
|
||||
.icon-unique-profile::before {
|
||||
.icon-understood::before {
|
||||
content: "\f20c";
|
||||
}
|
||||
.icon-unlist-outline::before {
|
||||
.icon-unique-profile::before {
|
||||
content: "\f20d";
|
||||
}
|
||||
.icon-unlist::before {
|
||||
.icon-unlist-outline::before {
|
||||
content: "\f20e";
|
||||
}
|
||||
.icon-unlock-badge::before {
|
||||
.icon-unlist::before {
|
||||
content: "\f20f";
|
||||
}
|
||||
.icon-unlock::before {
|
||||
.icon-unlock-badge::before {
|
||||
content: "\f210";
|
||||
}
|
||||
.icon-unmute::before {
|
||||
.icon-unlock::before {
|
||||
content: "\f211";
|
||||
}
|
||||
.icon-unpin::before {
|
||||
.icon-unmute::before {
|
||||
content: "\f212";
|
||||
}
|
||||
.icon-unread::before {
|
||||
.icon-unpin::before {
|
||||
content: "\f213";
|
||||
}
|
||||
.icon-up::before {
|
||||
.icon-unread::before {
|
||||
content: "\f214";
|
||||
}
|
||||
.icon-user-filled::before {
|
||||
.icon-up::before {
|
||||
content: "\f215";
|
||||
}
|
||||
.icon-user-online::before {
|
||||
.icon-user-filled::before {
|
||||
content: "\f216";
|
||||
}
|
||||
.icon-user-stars::before {
|
||||
.icon-user-online::before {
|
||||
content: "\f217";
|
||||
}
|
||||
.icon-user::before {
|
||||
.icon-user-stars::before {
|
||||
content: "\f218";
|
||||
}
|
||||
.icon-video-outlined::before {
|
||||
.icon-user::before {
|
||||
content: "\f219";
|
||||
}
|
||||
.icon-video-stop::before {
|
||||
.icon-video-outlined::before {
|
||||
content: "\f21a";
|
||||
}
|
||||
.icon-video::before {
|
||||
.icon-video-stop::before {
|
||||
content: "\f21b";
|
||||
}
|
||||
.icon-view-once::before {
|
||||
.icon-video::before {
|
||||
content: "\f21c";
|
||||
}
|
||||
.icon-voice-chat::before {
|
||||
.icon-view-once::before {
|
||||
content: "\f21d";
|
||||
}
|
||||
.icon-volume-1::before {
|
||||
.icon-voice-chat::before {
|
||||
content: "\f21e";
|
||||
}
|
||||
.icon-volume-2::before {
|
||||
.icon-volume-1::before {
|
||||
content: "\f21f";
|
||||
}
|
||||
.icon-volume-3::before {
|
||||
.icon-volume-2::before {
|
||||
content: "\f220";
|
||||
}
|
||||
.icon-warning::before {
|
||||
.icon-volume-3::before {
|
||||
content: "\f221";
|
||||
}
|
||||
.icon-web::before {
|
||||
.icon-warning::before {
|
||||
content: "\f222";
|
||||
}
|
||||
.icon-webapp::before {
|
||||
.icon-web::before {
|
||||
content: "\f223";
|
||||
}
|
||||
.icon-word-wrap::before {
|
||||
.icon-webapp::before {
|
||||
content: "\f224";
|
||||
}
|
||||
.icon-zoom-in::before {
|
||||
.icon-word-wrap::before {
|
||||
content: "\f225";
|
||||
}
|
||||
.icon-zoom-out::before {
|
||||
.icon-zoom-in::before {
|
||||
content: "\f226";
|
||||
}
|
||||
.icon-zoom-out::before {
|
||||
content: "\f227";
|
||||
}
|
||||
|
||||
@ -166,148 +166,149 @@ $icons-map: (
|
||||
"nochannel": "\f194",
|
||||
"noise-suppression": "\f195",
|
||||
"non-contacts": "\f196",
|
||||
"one-filled": "\f197",
|
||||
"open-in-new-tab": "\f198",
|
||||
"password-off": "\f199",
|
||||
"pause": "\f19a",
|
||||
"permissions": "\f19b",
|
||||
"phone-discard-outline": "\f19c",
|
||||
"phone-discard": "\f19d",
|
||||
"phone": "\f19e",
|
||||
"photo": "\f19f",
|
||||
"pin-badge": "\f1a0",
|
||||
"pin-list": "\f1a1",
|
||||
"pin": "\f1a2",
|
||||
"pinned-chat": "\f1a3",
|
||||
"pinned-message": "\f1a4",
|
||||
"pip": "\f1a5",
|
||||
"play-story": "\f1a6",
|
||||
"play": "\f1a7",
|
||||
"poll": "\f1a8",
|
||||
"previous": "\f1a9",
|
||||
"privacy-policy": "\f1aa",
|
||||
"proof-of-ownership": "\f1ab",
|
||||
"quote-text": "\f1ac",
|
||||
"quote": "\f1ad",
|
||||
"radial-badge": "\f1ae",
|
||||
"rating-icons-level1": "\f1af",
|
||||
"rating-icons-level10": "\f1b0",
|
||||
"rating-icons-level2": "\f1b1",
|
||||
"rating-icons-level20": "\f1b2",
|
||||
"rating-icons-level3": "\f1b3",
|
||||
"rating-icons-level30": "\f1b4",
|
||||
"rating-icons-level4": "\f1b5",
|
||||
"rating-icons-level40": "\f1b6",
|
||||
"rating-icons-level5": "\f1b7",
|
||||
"rating-icons-level50": "\f1b8",
|
||||
"rating-icons-level6": "\f1b9",
|
||||
"rating-icons-level60": "\f1ba",
|
||||
"rating-icons-level7": "\f1bb",
|
||||
"rating-icons-level70": "\f1bc",
|
||||
"rating-icons-level8": "\f1bd",
|
||||
"rating-icons-level80": "\f1be",
|
||||
"rating-icons-level9": "\f1bf",
|
||||
"rating-icons-level90": "\f1c0",
|
||||
"rating-icons-negative": "\f1c1",
|
||||
"readchats": "\f1c2",
|
||||
"recent": "\f1c3",
|
||||
"refund": "\f1c4",
|
||||
"reload": "\f1c5",
|
||||
"remove-quote": "\f1c6",
|
||||
"remove": "\f1c7",
|
||||
"reopen-topic": "\f1c8",
|
||||
"replace": "\f1c9",
|
||||
"replies": "\f1ca",
|
||||
"reply-filled": "\f1cb",
|
||||
"reply": "\f1cc",
|
||||
"revenue-split": "\f1cd",
|
||||
"revote": "\f1ce",
|
||||
"save-story": "\f1cf",
|
||||
"saved-messages": "\f1d0",
|
||||
"schedule": "\f1d1",
|
||||
"scheduled": "\f1d2",
|
||||
"sd-photo": "\f1d3",
|
||||
"search": "\f1d4",
|
||||
"select": "\f1d5",
|
||||
"sell-outline": "\f1d6",
|
||||
"sell": "\f1d7",
|
||||
"send-outline": "\f1d8",
|
||||
"send": "\f1d9",
|
||||
"settings-filled": "\f1da",
|
||||
"settings": "\f1db",
|
||||
"share-filled": "\f1dc",
|
||||
"share-screen-outlined": "\f1dd",
|
||||
"share-screen-stop": "\f1de",
|
||||
"share-screen": "\f1df",
|
||||
"show-message": "\f1e0",
|
||||
"sidebar": "\f1e1",
|
||||
"skip-next": "\f1e2",
|
||||
"skip-previous": "\f1e3",
|
||||
"smallscreen": "\f1e4",
|
||||
"smile": "\f1e5",
|
||||
"sort-by-date": "\f1e6",
|
||||
"sort-by-number": "\f1e7",
|
||||
"sort-by-price": "\f1e8",
|
||||
"sort": "\f1e9",
|
||||
"speaker-muted-story": "\f1ea",
|
||||
"speaker-outline": "\f1eb",
|
||||
"speaker-story": "\f1ec",
|
||||
"speaker": "\f1ed",
|
||||
"spoiler-disable": "\f1ee",
|
||||
"spoiler": "\f1ef",
|
||||
"sport": "\f1f0",
|
||||
"star": "\f1f1",
|
||||
"stars-lock": "\f1f2",
|
||||
"stars-refund": "\f1f3",
|
||||
"stats": "\f1f4",
|
||||
"stealth-future": "\f1f5",
|
||||
"stealth-past": "\f1f6",
|
||||
"stickers": "\f1f7",
|
||||
"stop-raising-hand": "\f1f8",
|
||||
"stop": "\f1f9",
|
||||
"story-caption": "\f1fa",
|
||||
"story-expired": "\f1fb",
|
||||
"story-priority": "\f1fc",
|
||||
"story-reply": "\f1fd",
|
||||
"strikethrough": "\f1fe",
|
||||
"tag-add": "\f1ff",
|
||||
"tag-crossed": "\f200",
|
||||
"tag-filter": "\f201",
|
||||
"tag-name": "\f202",
|
||||
"tag": "\f203",
|
||||
"timer": "\f204",
|
||||
"toncoin": "\f205",
|
||||
"trade": "\f206",
|
||||
"transcribe": "\f207",
|
||||
"truck": "\f208",
|
||||
"unarchive": "\f209",
|
||||
"underlined": "\f20a",
|
||||
"understood": "\f20b",
|
||||
"unique-profile": "\f20c",
|
||||
"unlist-outline": "\f20d",
|
||||
"unlist": "\f20e",
|
||||
"unlock-badge": "\f20f",
|
||||
"unlock": "\f210",
|
||||
"unmute": "\f211",
|
||||
"unpin": "\f212",
|
||||
"unread": "\f213",
|
||||
"up": "\f214",
|
||||
"user-filled": "\f215",
|
||||
"user-online": "\f216",
|
||||
"user-stars": "\f217",
|
||||
"user": "\f218",
|
||||
"video-outlined": "\f219",
|
||||
"video-stop": "\f21a",
|
||||
"video": "\f21b",
|
||||
"view-once": "\f21c",
|
||||
"voice-chat": "\f21d",
|
||||
"volume-1": "\f21e",
|
||||
"volume-2": "\f21f",
|
||||
"volume-3": "\f220",
|
||||
"warning": "\f221",
|
||||
"web": "\f222",
|
||||
"webapp": "\f223",
|
||||
"word-wrap": "\f224",
|
||||
"zoom-in": "\f225",
|
||||
"zoom-out": "\f226",
|
||||
"note": "\f197",
|
||||
"one-filled": "\f198",
|
||||
"open-in-new-tab": "\f199",
|
||||
"password-off": "\f19a",
|
||||
"pause": "\f19b",
|
||||
"permissions": "\f19c",
|
||||
"phone-discard-outline": "\f19d",
|
||||
"phone-discard": "\f19e",
|
||||
"phone": "\f19f",
|
||||
"photo": "\f1a0",
|
||||
"pin-badge": "\f1a1",
|
||||
"pin-list": "\f1a2",
|
||||
"pin": "\f1a3",
|
||||
"pinned-chat": "\f1a4",
|
||||
"pinned-message": "\f1a5",
|
||||
"pip": "\f1a6",
|
||||
"play-story": "\f1a7",
|
||||
"play": "\f1a8",
|
||||
"poll": "\f1a9",
|
||||
"previous": "\f1aa",
|
||||
"privacy-policy": "\f1ab",
|
||||
"proof-of-ownership": "\f1ac",
|
||||
"quote-text": "\f1ad",
|
||||
"quote": "\f1ae",
|
||||
"radial-badge": "\f1af",
|
||||
"rating-icons-level1": "\f1b0",
|
||||
"rating-icons-level10": "\f1b1",
|
||||
"rating-icons-level2": "\f1b2",
|
||||
"rating-icons-level20": "\f1b3",
|
||||
"rating-icons-level3": "\f1b4",
|
||||
"rating-icons-level30": "\f1b5",
|
||||
"rating-icons-level4": "\f1b6",
|
||||
"rating-icons-level40": "\f1b7",
|
||||
"rating-icons-level5": "\f1b8",
|
||||
"rating-icons-level50": "\f1b9",
|
||||
"rating-icons-level6": "\f1ba",
|
||||
"rating-icons-level60": "\f1bb",
|
||||
"rating-icons-level7": "\f1bc",
|
||||
"rating-icons-level70": "\f1bd",
|
||||
"rating-icons-level8": "\f1be",
|
||||
"rating-icons-level80": "\f1bf",
|
||||
"rating-icons-level9": "\f1c0",
|
||||
"rating-icons-level90": "\f1c1",
|
||||
"rating-icons-negative": "\f1c2",
|
||||
"readchats": "\f1c3",
|
||||
"recent": "\f1c4",
|
||||
"refund": "\f1c5",
|
||||
"reload": "\f1c6",
|
||||
"remove-quote": "\f1c7",
|
||||
"remove": "\f1c8",
|
||||
"reopen-topic": "\f1c9",
|
||||
"replace": "\f1ca",
|
||||
"replies": "\f1cb",
|
||||
"reply-filled": "\f1cc",
|
||||
"reply": "\f1cd",
|
||||
"revenue-split": "\f1ce",
|
||||
"revote": "\f1cf",
|
||||
"save-story": "\f1d0",
|
||||
"saved-messages": "\f1d1",
|
||||
"schedule": "\f1d2",
|
||||
"scheduled": "\f1d3",
|
||||
"sd-photo": "\f1d4",
|
||||
"search": "\f1d5",
|
||||
"select": "\f1d6",
|
||||
"sell-outline": "\f1d7",
|
||||
"sell": "\f1d8",
|
||||
"send-outline": "\f1d9",
|
||||
"send": "\f1da",
|
||||
"settings-filled": "\f1db",
|
||||
"settings": "\f1dc",
|
||||
"share-filled": "\f1dd",
|
||||
"share-screen-outlined": "\f1de",
|
||||
"share-screen-stop": "\f1df",
|
||||
"share-screen": "\f1e0",
|
||||
"show-message": "\f1e1",
|
||||
"sidebar": "\f1e2",
|
||||
"skip-next": "\f1e3",
|
||||
"skip-previous": "\f1e4",
|
||||
"smallscreen": "\f1e5",
|
||||
"smile": "\f1e6",
|
||||
"sort-by-date": "\f1e7",
|
||||
"sort-by-number": "\f1e8",
|
||||
"sort-by-price": "\f1e9",
|
||||
"sort": "\f1ea",
|
||||
"speaker-muted-story": "\f1eb",
|
||||
"speaker-outline": "\f1ec",
|
||||
"speaker-story": "\f1ed",
|
||||
"speaker": "\f1ee",
|
||||
"spoiler-disable": "\f1ef",
|
||||
"spoiler": "\f1f0",
|
||||
"sport": "\f1f1",
|
||||
"star": "\f1f2",
|
||||
"stars-lock": "\f1f3",
|
||||
"stars-refund": "\f1f4",
|
||||
"stats": "\f1f5",
|
||||
"stealth-future": "\f1f6",
|
||||
"stealth-past": "\f1f7",
|
||||
"stickers": "\f1f8",
|
||||
"stop-raising-hand": "\f1f9",
|
||||
"stop": "\f1fa",
|
||||
"story-caption": "\f1fb",
|
||||
"story-expired": "\f1fc",
|
||||
"story-priority": "\f1fd",
|
||||
"story-reply": "\f1fe",
|
||||
"strikethrough": "\f1ff",
|
||||
"tag-add": "\f200",
|
||||
"tag-crossed": "\f201",
|
||||
"tag-filter": "\f202",
|
||||
"tag-name": "\f203",
|
||||
"tag": "\f204",
|
||||
"timer": "\f205",
|
||||
"toncoin": "\f206",
|
||||
"trade": "\f207",
|
||||
"transcribe": "\f208",
|
||||
"truck": "\f209",
|
||||
"unarchive": "\f20a",
|
||||
"underlined": "\f20b",
|
||||
"understood": "\f20c",
|
||||
"unique-profile": "\f20d",
|
||||
"unlist-outline": "\f20e",
|
||||
"unlist": "\f20f",
|
||||
"unlock-badge": "\f210",
|
||||
"unlock": "\f211",
|
||||
"unmute": "\f212",
|
||||
"unpin": "\f213",
|
||||
"unread": "\f214",
|
||||
"up": "\f215",
|
||||
"user-filled": "\f216",
|
||||
"user-online": "\f217",
|
||||
"user-stars": "\f218",
|
||||
"user": "\f219",
|
||||
"video-outlined": "\f21a",
|
||||
"video-stop": "\f21b",
|
||||
"video": "\f21c",
|
||||
"view-once": "\f21d",
|
||||
"voice-chat": "\f21e",
|
||||
"volume-1": "\f21f",
|
||||
"volume-2": "\f220",
|
||||
"volume-3": "\f221",
|
||||
"warning": "\f222",
|
||||
"web": "\f223",
|
||||
"webapp": "\f224",
|
||||
"word-wrap": "\f225",
|
||||
"zoom-in": "\f226",
|
||||
"zoom-out": "\f227",
|
||||
);
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@ -149,6 +149,7 @@ export type FontIconName =
|
||||
| 'nochannel'
|
||||
| 'noise-suppression'
|
||||
| 'non-contacts'
|
||||
| 'note'
|
||||
| 'one-filled'
|
||||
| 'open-in-new-tab'
|
||||
| 'password-off'
|
||||
|
||||
3
src/types/language.d.ts
vendored
3
src/types/language.d.ts
vendored
@ -1716,6 +1716,9 @@ export interface LangPair {
|
||||
'ConfirmBuyGiftForTonDescription': undefined;
|
||||
'TitleGiftLocked': undefined;
|
||||
'QuickPreview': undefined;
|
||||
'UserNoteTitle': undefined;
|
||||
'UserNoteHint': undefined;
|
||||
'EditUserNoteHint': undefined;
|
||||
}
|
||||
|
||||
export interface LangPairWithVariables<V = LangVariable> {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user