[Refactoring] Migrate to Icon component (#5485)

This commit is contained in:
zubiden 2025-01-21 18:22:01 +01:00 committed by Alexander Zinchuk
parent aecd1d216f
commit 88f14ab310
126 changed files with 429 additions and 328 deletions

View File

@ -3,11 +3,17 @@
.icon-char::before { .icon-char::before {
font-family: Roboto, "Helvetica Neue", sans-serif; font-family: Roboto, "Helvetica Neue", sans-serif;
content: attr(data-char); content: attr(data-char);
width: 1.5rem; width: 1em;
text-align: center; text-align: center;
display: block; display: block;
} }
.icon-placeholder::before {
content: '';
display: block;
width: 1em;
}
@mixin icon { @mixin icon {
/* use !important to prevent issues with browser extensions that change fonts */ /* use !important to prevent issues with browser extensions that change fonts */
/* stylelint-disable-next-line font-family-no-missing-generic-family-keyword */ /* stylelint-disable-next-line font-family-no-missing-generic-family-keyword */

View File

@ -30,6 +30,7 @@ import useOldLang from '../../../hooks/useOldLang';
import { useFullscreenStatus } from '../../../hooks/window/useFullscreen'; import { useFullscreenStatus } from '../../../hooks/window/useFullscreen';
import useGroupCallVideoLayout from './hooks/useGroupCallVideoLayout'; import useGroupCallVideoLayout from './hooks/useGroupCallVideoLayout';
import Icon from '../../common/icons/Icon';
import Button from '../../ui/Button'; import Button from '../../ui/Button';
import Checkbox from '../../ui/Checkbox'; import Checkbox from '../../ui/Checkbox';
import FloatingActionButton from '../../ui/FloatingActionButton'; import FloatingActionButton from '../../ui/FloatingActionButton';
@ -278,10 +279,7 @@ const GroupCall: FC<OwnProps & StateProps> = ({
className={buildClassName(styles.headerButton, styles.firstButton)} className={buildClassName(styles.headerButton, styles.firstButton)}
ariaLabel={lang(isFullscreen ? 'AccExitFullscreen' : 'AccSwitchToFullscreen')} ariaLabel={lang(isFullscreen ? 'AccExitFullscreen' : 'AccSwitchToFullscreen')}
> >
<i <Icon name={isFullscreen ? 'smallscreen' : 'fullscreen'} />
className={buildClassName('icon', isFullscreen ? 'icon-smallscreen' : 'icon-fullscreen')}
aria-hidden
/>
</Button> </Button>
)} )}
@ -298,7 +296,7 @@ const GroupCall: FC<OwnProps & StateProps> = ({
onClick={handleToggleSidebar} onClick={handleToggleSidebar}
ariaLabel={lang('AccDescrExpandPanel')} ariaLabel={lang('AccDescrExpandPanel')}
> >
<i className="icon icon-sidebar" aria-hidden /> <Icon name="sidebar" />
</Button> </Button>
)} )}
</div> </div>
@ -328,7 +326,7 @@ const GroupCall: FC<OwnProps & StateProps> = ({
onClick={handleToggleFullscreen} onClick={handleToggleFullscreen}
ariaLabel={lang('AccSwitchToFullscreen')} ariaLabel={lang('AccSwitchToFullscreen')}
> >
<i className="icon icon-fullscreen" aria-hidden /> <Icon name="fullscreen" />
</Button> </Button>
)} )}
@ -341,10 +339,7 @@ const GroupCall: FC<OwnProps & StateProps> = ({
className={buildClassName(styles.headerButton, styles.firstButton)} className={buildClassName(styles.headerButton, styles.firstButton)}
ariaLabel={lang('Close')} ariaLabel={lang('Close')}
> >
<i <Icon name="close" />
className={buildClassName('icon', 'icon-close')}
aria-hidden
/>
</Button> </Button>
)} )}
@ -361,7 +356,7 @@ const GroupCall: FC<OwnProps & StateProps> = ({
onClick={handleToggleSidebar} onClick={handleToggleSidebar}
ariaLabel={lang('AccDescrCollapsePanel')} ariaLabel={lang('AccDescrCollapsePanel')}
> >
<i className="icon icon-sidebar" aria-hidden /> <Icon name="sidebar" />
</Button> </Button>
)} )}
@ -389,7 +384,7 @@ const GroupCall: FC<OwnProps & StateProps> = ({
onClick={handleInviteMember} onClick={handleInviteMember}
ariaLabel={lang('VoipGroupInviteMember')} ariaLabel={lang('VoipGroupInviteMember')}
> >
<i className="icon icon-add-user" aria-hidden /> <Icon name="add-user" />
</Button> </Button>
)} )}
</div> </div>
@ -438,7 +433,7 @@ const GroupCall: FC<OwnProps & StateProps> = ({
className={styles.addParticipantButton} className={styles.addParticipantButton}
ariaLabel={lang('VoipGroupInviteMember')} ariaLabel={lang('VoipGroupInviteMember')}
> >
<i className="icon icon-add-user-filled" aria-hidden /> <Icon name="add-user-filled" />
</FloatingActionButton> </FloatingActionButton>
</div> </div>
@ -482,7 +477,7 @@ const GroupCall: FC<OwnProps & StateProps> = ({
ariaLabel={lang(hasVideo ? 'VoipStopVideo' : 'VoipStartVideo')} ariaLabel={lang(hasVideo ? 'VoipStopVideo' : 'VoipStartVideo')}
disabled={isConnecting} disabled={isConnecting}
> >
<i className={buildClassName('icon', !hasVideo ? 'icon-video-stop' : 'icon-video')} aria-hidden /> <Icon name={!hasVideo ? 'video-stop' : 'video'} />
</Button> </Button>
<Button <Button
@ -498,10 +493,7 @@ const GroupCall: FC<OwnProps & StateProps> = ({
ariaLabel={lang(hasPresentation ? 'lng_group_call_screen_share_stop' : 'lng_group_call_tooltip_screen')} ariaLabel={lang(hasPresentation ? 'lng_group_call_screen_share_stop' : 'lng_group_call_tooltip_screen')}
disabled={isConnecting || !IS_SCREENSHARE_SUPPORTED} disabled={isConnecting || !IS_SCREENSHARE_SUPPORTED}
> >
<i <Icon name={!hasPresentation ? 'share-screen-stop' : 'share-screen'} />
className={buildClassName('icon', !hasPresentation ? 'icon-share-screen-stop' : 'icon-share-screen')}
aria-hidden
/>
</Button> </Button>
<MicrophoneButton className={styles.actionButton} /> <MicrophoneButton className={styles.actionButton} />
@ -518,7 +510,7 @@ const GroupCall: FC<OwnProps & StateProps> = ({
ariaLabel={lang('lng_group_call_settings')} ariaLabel={lang('lng_group_call_settings')}
disabled disabled
> >
<i className="icon icon-settings-filled" aria-hidden /> <Icon name="settings-filled" />
</Button> </Button>
<Button <Button
@ -532,7 +524,7 @@ const GroupCall: FC<OwnProps & StateProps> = ({
onClick={handleLeaveGroupCall} onClick={handleLeaveGroupCall}
ariaLabel={lang('lng_group_call_leave')} ariaLabel={lang('lng_group_call_leave')}
> >
<i className="icon icon-close" aria-hidden /> <Icon name="close" />
</Button> </Button>
</div> </div>

View File

@ -19,6 +19,7 @@ import useOldLang from '../../../hooks/useOldLang';
import Avatar from '../../common/Avatar'; import Avatar from '../../common/Avatar';
import FullNameTitle from '../../common/FullNameTitle'; import FullNameTitle from '../../common/FullNameTitle';
import Icon from '../../common/icons/Icon';
import ListItem from '../../ui/ListItem'; import ListItem from '../../ui/ListItem';
import GroupCallParticipantMenu from './GroupCallParticipantMenu'; import GroupCallParticipantMenu from './GroupCallParticipantMenu';
import OutlinedMicrophoneIcon from './OutlinedMicrophoneIcon'; import OutlinedMicrophoneIcon from './OutlinedMicrophoneIcon';
@ -128,9 +129,9 @@ const GroupCallParticipant: FC<OwnProps & StateProps> = ({
> >
<FullNameTitle peer={peer} withEmojiStatus className={styles.title} /> <FullNameTitle peer={peer} withEmojiStatus className={styles.title} />
<span className={buildClassName(styles.subtitle, 'subtitle', aboutColor)}> <span className={buildClassName(styles.subtitle, 'subtitle', aboutColor)}>
{hasPresentationStream && <i className="icon icon-share-screen" aria-hidden />} {hasPresentationStream && <Icon name="share-screen" />}
{hasVideoStream && <i className="icon icon-video" aria-hidden />} {hasVideoStream && <Icon name="video" />}
{hasCustomVolume && <i className="icon icon-speaker" aria-hidden />} {hasCustomVolume && <Icon name="speaker" />}
<span className={styles.subtitleText}>{renderText(aboutText)}</span> <span className={styles.subtitleText}>{renderText(aboutText)}</span>
</span> </span>
<GroupCallParticipantMenu <GroupCallParticipantMenu

View File

@ -25,6 +25,7 @@ import useLastCallback from '../../../hooks/useLastCallback';
import useOldLang from '../../../hooks/useOldLang'; import useOldLang from '../../../hooks/useOldLang';
import FullNameTitle from '../../common/FullNameTitle'; import FullNameTitle from '../../common/FullNameTitle';
import Icon from '../../common/icons/Icon';
import Button from '../../ui/Button'; import Button from '../../ui/Button';
import Skeleton from '../../ui/placeholder/Skeleton'; import Skeleton from '../../ui/placeholder/Skeleton';
import GroupCallParticipantMenu from './GroupCallParticipantMenu'; import GroupCallParticipantMenu from './GroupCallParticipantMenu';
@ -292,7 +293,7 @@ const GroupCallParticipantVideo: FC<OwnProps & StateProps> = ({
ariaLabel={lang(isPinned ? 'lng_group_call_context_unpin_camera' : 'lng_group_call_context_pin_camera')} ariaLabel={lang(isPinned ? 'lng_group_call_context_unpin_camera' : 'lng_group_call_context_pin_camera')}
onClick={handleClickPin} onClick={handleClickPin}
> >
<i className={buildClassName('icon', isPinned ? 'icon-unpin' : 'icon-pin')} /> <Icon name={isPinned ? 'unpin' : 'pin'} />
</Button> </Button>
)} )}
<div className={styles.bottomPanel}> <div className={styles.bottomPanel}>

View File

@ -31,6 +31,7 @@ import useOldLang from '../../../hooks/useOldLang';
import AnimatedIcon from '../../common/AnimatedIcon'; import AnimatedIcon from '../../common/AnimatedIcon';
import Avatar from '../../common/Avatar'; import Avatar from '../../common/Avatar';
import Icon from '../../common/icons/Icon';
import Button from '../../ui/Button'; import Button from '../../ui/Button';
import Modal from '../../ui/Modal'; import Modal from '../../ui/Modal';
import PhoneCallButton from './PhoneCallButton'; import PhoneCallButton from './PhoneCallButton';
@ -273,7 +274,7 @@ const PhoneCall: FC<StateProps> = ({
onClick={handleToggleFullscreen} onClick={handleToggleFullscreen}
ariaLabel={lang(isFullscreen ? 'AccExitFullscreen' : 'AccSwitchToFullscreen')} ariaLabel={lang(isFullscreen ? 'AccExitFullscreen' : 'AccSwitchToFullscreen')}
> >
<i className={buildClassName('icon', isFullscreen ? 'icon-smallscreen' : 'icon-fullscreen')} /> <Icon name={isFullscreen ? 'smallscreen' : 'fullscreen'} />
</Button> </Button>
)} )}
@ -284,7 +285,7 @@ const PhoneCall: FC<StateProps> = ({
onClick={handleClose} onClick={handleClose}
className={styles.closeButton} className={styles.closeButton}
> >
<i className="icon icon-close" /> <Icon name="close" />
</Button> </Button>
</div> </div>
<div <div

View File

@ -5,6 +5,7 @@ import type { IconName } from '../../../types/icons';
import buildClassName from '../../../util/buildClassName'; import buildClassName from '../../../util/buildClassName';
import Icon from '../../common/icons/Icon';
import Button from '../../ui/Button'; import Button from '../../ui/Button';
import styles from './PhoneCallButton.module.scss'; import styles from './PhoneCallButton.module.scss';
@ -38,7 +39,7 @@ const PhoneCallButton: FC<OwnProps> = ({
onClick={onClick} onClick={onClick}
disabled={isDisabled} disabled={isDisabled}
> >
{customIcon || <i className={buildClassName(iconClassName, 'icon', `icon-${icon}`)} />} {customIcon || <Icon name={icon!} className={iconClassName} />}
</Button> </Button>
<div className={styles.buttonText}>{label}</div> <div className={styles.buttonText}>{label}</div>
</div> </div>

View File

@ -8,6 +8,7 @@ import buildClassName from '../../../util/buildClassName';
import useOldLang from '../../../hooks/useOldLang'; import useOldLang from '../../../hooks/useOldLang';
import Icon from '../../common/icons/Icon';
import Button from '../../ui/Button'; import Button from '../../ui/Button';
import InputText from '../../ui/InputText'; import InputText from '../../ui/InputText';
import Modal from '../../ui/Modal'; import Modal from '../../ui/Modal';
@ -54,10 +55,9 @@ const RatePhoneCallModal: FC<OwnProps> = ({
{new Array(5).fill(undefined).map((_, i) => { {new Array(5).fill(undefined).map((_, i) => {
const isFilled = rating !== undefined && rating >= i; const isFilled = rating !== undefined && rating >= i;
return ( return (
<i <Icon
name={isFilled ? 'favorite-filled' : 'favorite'}
className={buildClassName( className={buildClassName(
'icon',
isFilled ? 'icon-favorite-filled' : 'icon-favorite',
isFilled && styles.isFilled, isFilled && styles.isFilled,
styles.star, styles.star,
)} )}

View File

@ -413,7 +413,7 @@ const Audio: FC<OwnProps> = ({
<div className={fullClassName} dir={lang.isRtl ? 'rtl' : 'ltr'}> <div className={fullClassName} dir={lang.isRtl ? 'rtl' : 'ltr'}>
{isSelectable && ( {isSelectable && (
<div className="message-select-control"> <div className="message-select-control">
{isSelected && <i className="icon icon-select" />} {isSelected && <Icon name="select" />}
</div> </div>
)} )}
{renderTooglePlayWrapper()} {renderTooglePlayWrapper()}
@ -448,7 +448,7 @@ const Audio: FC<OwnProps> = ({
ariaLabel={isDownloading ? 'Cancel download' : 'Download'} ariaLabel={isDownloading ? 'Cancel download' : 'Download'}
onClick={handleDownloadClick} onClick={handleDownloadClick}
> >
<i className={buildClassName('icon', isDownloading ? 'icon-close' : 'icon-arrow-down')} /> <Icon name={isDownloading ? 'close' : 'arrow-down'} />
</Button> </Button>
)} )}
{origin === AudioOrigin.Search && renderWithTitle()} {origin === AudioOrigin.Search && renderWithTitle()}
@ -589,12 +589,12 @@ function renderVoice(
} }
}} }}
> >
<i className={buildClassName( <Icon
'transcribe-icon', name={(isTranscribed || isTranscriptionError) ? 'down' : 'transcribe'}
'icon', className={buildClassName(
(isTranscribed || isTranscriptionError) ? 'icon-down' : 'icon-transcribe', 'transcribe-icon',
(isTranscribed || isTranscriptionError) && !isTranscriptionHidden && 'transcribe-shown', (isTranscribed || isTranscriptionError) && !isTranscriptionHidden && 'transcribe-shown',
)} )}
/> />
{isTranscribing && ( {isTranscribing && (
<svg viewBox="0 0 32 24" className="loading-svg"> <svg viewBox="0 0 32 24" className="loading-svg">

View File

@ -15,6 +15,7 @@ import usePreviousDeprecated from '../../hooks/usePreviousDeprecated';
import Button from '../ui/Button'; import Button from '../ui/Button';
import Modal from '../ui/Modal'; import Modal from '../ui/Modal';
import Icon from './icons/Icon';
import './CalendarModal.scss'; import './CalendarModal.scss';
@ -258,7 +259,7 @@ const CalendarModal: FC<OwnProps> = ({
color="translucent" color="translucent"
onClick={onClose} onClick={onClose}
> >
<i className="icon icon-close" /> <Icon name="close" />
</Button> </Button>
<h4> <h4>
@ -274,7 +275,7 @@ const CalendarModal: FC<OwnProps> = ({
disabled={shouldDisablePrevMonth} disabled={shouldDisablePrevMonth}
onClick={!shouldDisablePrevMonth ? handlePrevMonth : undefined} onClick={!shouldDisablePrevMonth ? handlePrevMonth : undefined}
> >
<i className="icon icon-previous" /> <Icon name="previous" />
</Button> </Button>
<Button <Button
@ -284,7 +285,7 @@ const CalendarModal: FC<OwnProps> = ({
disabled={shouldDisableNextMonth} disabled={shouldDisableNextMonth}
onClick={!shouldDisableNextMonth ? handleNextMonth : undefined} onClick={!shouldDisableNextMonth ? handleNextMonth : undefined}
> >
<i className="icon icon-next" /> <Icon name="next" />
</Button> </Button>
</div> </div>
</div> </div>

View File

@ -20,6 +20,7 @@ import useShowTransitionDeprecated from '../../hooks/useShowTransitionDeprecated
import Link from '../ui/Link'; import Link from '../ui/Link';
import ProgressSpinner from '../ui/ProgressSpinner'; import ProgressSpinner from '../ui/ProgressSpinner';
import Icon from './icons/Icon';
import './File.scss'; import './File.scss';
@ -103,7 +104,7 @@ const File: FC<OwnProps> = ({
<div ref={elementRef} className={fullClassName} dir={lang.isRtl ? 'rtl' : undefined}> <div ref={elementRef} className={fullClassName} dir={lang.isRtl ? 'rtl' : undefined}>
{isSelectable && ( {isSelectable && (
<div className="message-select-control"> <div className="message-select-control">
{isSelected && <i className="icon icon-select" />} {isSelected && <Icon name="select" />}
</div> </div>
)} )}
<div className="file-icon-container" onClick={isUploading ? undefined : onClick}> <div className="file-icon-container" onClick={isUploading ? undefined : onClick}>
@ -141,13 +142,9 @@ const File: FC<OwnProps> = ({
</div> </div>
)} )}
{onClick && ( {onClick && (
<i <Icon
className={buildClassName( name={actionIcon || 'download'}
'action-icon', className={buildClassName('action-icon', shouldSpinnerRender && 'hidden')}
'icon',
actionIcon ? `icon-${actionIcon}` : 'icon-download',
shouldSpinnerRender && 'hidden',
)}
/> />
)} )}
</div> </div>

View File

@ -24,6 +24,7 @@ import Menu from '../ui/Menu';
import MenuItem from '../ui/MenuItem'; import MenuItem from '../ui/MenuItem';
import OptimizedVideo from '../ui/OptimizedVideo'; import OptimizedVideo from '../ui/OptimizedVideo';
import Spinner from '../ui/Spinner'; import Spinner from '../ui/Spinner';
import Icon from './icons/Icon';
import './GifButton.scss'; import './GifButton.scss';
@ -141,7 +142,7 @@ const GifButton: FC<OwnProps> = ({
noFastClick noFastClick
onClick={handleUnsaveClick} onClick={handleUnsaveClick}
> >
<i className="icon icon-close gif-unsave-button-icon" /> <Icon name="close" className="gif-unsave-button-icon" />
</Button> </Button>
)} )}
{withThumb && ( {withThumb && (

View File

@ -69,7 +69,7 @@ const InviteLink: FC<OwnProps> = ({
onClick={onTrigger} onClick={onTrigger}
ariaLabel={lang('AccDescrOpenMenu2')} ariaLabel={lang('AccDescrOpenMenu2')}
> >
<i className="icon icon-more" /> <Icon name="more" />
</Button> </Button>
); );
}, [isMobile, lang]); }, [isMobile, lang]);

View File

@ -15,6 +15,7 @@ import useAppLayout from '../../hooks/useAppLayout';
import useOldLang from '../../hooks/useOldLang'; import useOldLang from '../../hooks/useOldLang';
import Button from '../ui/Button'; import Button from '../ui/Button';
import Icon from './icons/Icon';
type OwnProps = { type OwnProps = {
submitLabel?: string; submitLabel?: string;
@ -149,7 +150,7 @@ const PasswordForm: FC<OwnProps> = ({
title="Toggle password visibility" title="Toggle password visibility"
aria-label="Toggle password visibility" aria-label="Toggle password visibility"
> >
<i className={buildClassName('icon', isPasswordVisible ? 'icon-eye' : 'icon-eye-closed')} /> <Icon name={isPasswordVisible ? 'eye' : 'eye-closed'} />
</div> </div>
</div> </div>
{description && <p className="description">{description}</p>} {description && <p className="description">{description}</p>}

View File

@ -5,6 +5,7 @@ import buildClassName from '../../util/buildClassName';
import { IS_TOUCH_ENV } from '../../util/windowEnvironment'; import { IS_TOUCH_ENV } from '../../util/windowEnvironment';
import Button from '../ui/Button'; import Button from '../ui/Button';
import Icon from './icons/Icon';
import styles from './SliderDots.module.scss'; import styles from './SliderDots.module.scss';
@ -46,7 +47,7 @@ const SliderDots: FC<OwnProps> = ({
round round
onClick={handleGoBack} onClick={handleGoBack}
> >
<i className="icon icon-previous" /> <Icon name="previous" />
</Button> </Button>
)} )}
<div className={styles.root} style={`--start-from: ${startFrom}; --length: ${length}; --count: ${count};`}> <div className={styles.root} style={`--start-from: ${startFrom}; --length: ${length}; --count: ${count};`}>
@ -81,7 +82,7 @@ const SliderDots: FC<OwnProps> = ({
disabled={active === length - 1} disabled={active === length - 1}
onClick={handleGoForward} onClick={handleGoForward}
> >
<i className="icon icon-next" /> <Icon name="next" />
</Button> </Button>
)} )}
</div> </div>

View File

@ -37,6 +37,7 @@ import DropdownMenu from '../ui/DropdownMenu';
import Loading from '../ui/Loading'; import Loading from '../ui/Loading';
import MenuItem from '../ui/MenuItem'; import MenuItem from '../ui/MenuItem';
import Modal from '../ui/Modal'; import Modal from '../ui/Modal';
import Icon from './icons/Icon';
import StickerButton from './StickerButton'; import StickerButton from './StickerButton';
import './StickerSetModal.scss'; import './StickerSetModal.scss';
@ -183,7 +184,7 @@ const StickerSetModal: FC<OwnProps & StateProps> = ({
onClick={onTrigger} onClick={onTrigger}
ariaLabel="More actions" ariaLabel="More actions"
> >
<i className="icon icon-more" /> <Icon name="more" />
</Button> </Button>
); );
}, [isMobile]); }, [isMobile]);
@ -194,7 +195,7 @@ const StickerSetModal: FC<OwnProps & StateProps> = ({
return ( return (
<div className={fullClassName} dir={lang.isRtl ? 'rtl' : undefined}> <div className={fullClassName} dir={lang.isRtl ? 'rtl' : undefined}>
<Button round color="translucent" size="smaller" ariaLabel={lang('Close')} onClick={onClose}> <Button round color="translucent" size="smaller" ariaLabel={lang('Close')} onClick={onClose}>
<i className="icon icon-close" /> <Icon name="close" />
</Button> </Button>
<div className="modal-title"> <div className="modal-title">
{renderingStickerSet ? renderText(renderingStickerSet.title, ['emoji', 'links']) : lang('AccDescrStickerSet')} {renderingStickerSet ? renderText(renderingStickerSet.title, ['emoji', 'links']) : lang('AccDescrStickerSet')}

View File

@ -10,6 +10,7 @@ import renderText from './helpers/renderText';
import useOldLang from '../../hooks/useOldLang'; import useOldLang from '../../hooks/useOldLang';
import Icon from './icons/Icon';
import TopicIcon from './TopicIcon'; import TopicIcon from './TopicIcon';
import styles from './TopicChip.module.scss'; import styles from './TopicChip.module.scss';
@ -40,8 +41,8 @@ const TopicChip: FC<OwnProps> = ({
? <TopicIcon topic={topic} size={TOPIC_ICON_SIZE} /> ? <TopicIcon topic={topic} size={TOPIC_ICON_SIZE} />
: <img src={blankSrc} alt="" draggable={false} />} : <img src={blankSrc} alt="" draggable={false} />}
{topic?.title ? renderText(topic.title) : lang('Loading')} {topic?.title ? renderText(topic.title) : lang('Loading')}
{topic?.isClosed && <i className="icon icon-lock" />} {topic?.isClosed && <Icon name="lock" />}
<i className="icon icon-next" /> <Icon name="next" />
</div> </div>
); );
}; };

View File

@ -7,6 +7,8 @@ import { getTopicDefaultIcon } from '../../util/forumColors';
import { getFirstLetters } from '../../util/textFormat'; import { getFirstLetters } from '../../util/textFormat';
import renderText from './helpers/renderText'; import renderText from './helpers/renderText';
import Icon from './icons/Icon';
import styles from './TopicDefaultIcon.module.scss'; import styles from './TopicDefaultIcon.module.scss';
type OwnProps = { type OwnProps = {
@ -30,8 +32,9 @@ const TopicDefaultIcon: FC<OwnProps> = ({
if (topicId === GENERAL_TOPIC_ID) { if (topicId === GENERAL_TOPIC_ID) {
return ( return (
<i <Icon
className={buildClassName(styles.root, className, 'icon', 'icon-hashtag', 'general-forum-icon')} name="hashtag"
className={buildClassName(styles.root, className, 'general-forum-icon')}
onClick={onClick} onClick={onClick}
/> />
); );

View File

@ -11,6 +11,8 @@ import { areLinesWrapping } from '../helpers/renderText';
import useOldLang from '../../../hooks/useOldLang'; import useOldLang from '../../../hooks/useOldLang';
import useWindowSize from '../../../hooks/window/useWindowSize'; import useWindowSize from '../../../hooks/window/useWindowSize';
import Icon from '../icons/Icon';
import styles from './CodeOverlay.module.scss'; import styles from './CodeOverlay.module.scss';
export type OwnProps = { export type OwnProps = {
@ -63,12 +65,12 @@ const CodeOverlay: FC<OwnProps> = ({
<div className={contentClass}> <div className={contentClass}>
{withWordWrapButton && ( {withWordWrapButton && (
<div className={wrapClass} onClick={handleWordWrapClick} title="Word Wrap"> <div className={wrapClass} onClick={handleWordWrapClick} title="Word Wrap">
<i className="icon icon-word-wrap" /> <Icon name="word-wrap" />
</div> </div>
)} )}
{!noCopy && ( {!noCopy && (
<div className={styles.copy} onClick={handleCopy} title={lang('Copy')}> <div className={styles.copy} onClick={handleCopy} title={lang('Copy')}>
<i className="icon icon-copy" /> <Icon name="copy" />
</div> </div>
)} )}
</div> </div>

View File

@ -11,23 +11,29 @@ type OwnProps = {
style?: string; style?: string;
role?: AriaRole; role?: AriaRole;
ariaLabel?: string; ariaLabel?: string;
character?: string;
ref?: React.RefObject<HTMLElement>;
onClick?: (e: React.MouseEvent<HTMLDivElement>) => void; onClick?: (e: React.MouseEvent<HTMLDivElement>) => void;
}; };
const Icon = ({ const Icon = ({
name, name,
ref,
className, className,
style, style,
role, role,
ariaLabel, ariaLabel,
character,
onClick, onClick,
}: OwnProps) => { }: OwnProps) => {
return ( return (
<i <i
ref={ref}
className={buildClassName(`icon icon-${name}`, className)} className={buildClassName(`icon icon-${name}`, className)}
style={style} style={style}
aria-hidden={!ariaLabel} aria-hidden={!ariaLabel}
aria-label={ariaLabel} aria-label={ariaLabel}
data-char={character}
role={role} role={role}
onClick={onClick} onClick={onClick}
/> />

View File

@ -33,6 +33,7 @@ import Modal from '../../ui/Modal';
import Transition from '../../ui/Transition'; import Transition from '../../ui/Transition';
import Avatar from '../Avatar'; import Avatar from '../Avatar';
import FullNameTitle from '../FullNameTitle'; import FullNameTitle from '../FullNameTitle';
import Icon from '../icons/Icon';
import TopicIcon from '../TopicIcon'; import TopicIcon from '../TopicIcon';
import PickerItem from './PickerItem'; import PickerItem from './PickerItem';
@ -231,7 +232,7 @@ const ChatOrUserPicker: FC<OwnProps> = ({
<> <>
<div className="modal-header" dir={lang.isRtl ? 'rtl' : undefined}> <div className="modal-header" dir={lang.isRtl ? 'rtl' : undefined}>
<Button round color="translucent" size="smaller" ariaLabel={lang('Back')} onClick={handleHeaderBackClick}> <Button round color="translucent" size="smaller" ariaLabel={lang('Back')} onClick={handleHeaderBackClick}>
<i className="icon icon-arrow-left" /> <Icon name="arrow-left" />
</Button> </Button>
<InputText <InputText
ref={topicSearchRef} ref={topicSearchRef}
@ -284,7 +285,7 @@ const ChatOrUserPicker: FC<OwnProps> = ({
ariaLabel={lang('Close')} ariaLabel={lang('Close')}
onClick={onClose} onClick={onClose}
> >
<i className="icon icon-close" /> <Icon name="close" />
</Button> </Button>
<InputText <InputText
ref={searchRef} ref={searchRef}

View File

@ -11,6 +11,7 @@ import useMedia from '../../../hooks/useMedia';
import useMediaTransitionDeprecated from '../../../hooks/useMediaTransitionDeprecated'; import useMediaTransitionDeprecated from '../../../hooks/useMediaTransitionDeprecated';
import CustomEmoji from '../CustomEmoji'; import CustomEmoji from '../CustomEmoji';
import Icon from '../icons/Icon';
import './ReactionStaticEmoji.scss'; import './ReactionStaticEmoji.scss';
@ -58,7 +59,7 @@ const ReactionStaticEmoji: FC<OwnProps> = ({
if (shouldReplaceWithHeartIcon) { if (shouldReplaceWithHeartIcon) {
return ( return (
<i className="ReactionStaticEmoji icon icon-heart" style={`font-size: ${size}px; width: ${size}px`} /> <Icon name="heart" className="ReactionStaticEmoji" style={`font-size: ${size}px; width: ${size}px`} />
); );
} }

View File

@ -17,6 +17,7 @@ import useOldLang from '../../hooks/useOldLang';
import useShowTransitionDeprecated from '../../hooks/useShowTransitionDeprecated'; import useShowTransitionDeprecated from '../../hooks/useShowTransitionDeprecated';
import useLeftHeaderButtonRtlForumTransition from './main/hooks/useLeftHeaderButtonRtlForumTransition'; import useLeftHeaderButtonRtlForumTransition from './main/hooks/useLeftHeaderButtonRtlForumTransition';
import Icon from '../common/icons/Icon';
import StoryRibbon from '../story/StoryRibbon'; import StoryRibbon from '../story/StoryRibbon';
import StoryToggler from '../story/StoryToggler'; import StoryToggler from '../story/StoryToggler';
import Button from '../ui/Button'; import Button from '../ui/Button';
@ -103,7 +104,7 @@ const ArchivedChats: FC<OwnProps> = ({
)} )}
onTransitionEnd={handleDropdownMenuTransitionEnd} onTransitionEnd={handleDropdownMenuTransitionEnd}
> >
<i className="icon icon-arrow-left" /> <Icon name="arrow-left" />
</Button> </Button>
{shouldRenderTitle && <h3 className={titleClassNames}>{lang('ArchivedChats')}</h3>} {shouldRenderTitle && <h3 className={titleClassNames}>{lang('ArchivedChats')}</h3>}
<div className="story-toggler-wrapper"> <div className="story-toggler-wrapper">

View File

@ -5,6 +5,7 @@ import type { ConnectionStatus } from '../../hooks/useConnectionStatus';
import useOldLang from '../../hooks/useOldLang'; import useOldLang from '../../hooks/useOldLang';
import Icon from '../common/icons/Icon';
import Button from '../ui/Button'; import Button from '../ui/Button';
import Spinner from '../ui/Spinner'; import Spinner from '../ui/Spinner';
import Transition from '../ui/Transition'; import Transition from '../ui/Transition';
@ -37,7 +38,7 @@ const ConnectionStatusOverlay: FC<OwnProps> = ({
size="tiny" size="tiny"
color="translucent-black" color="translucent-black"
> >
<span className="icon icon-close" /> <Icon name="close" />
</Button> </Button>
</div> </div>
); );

View File

@ -7,6 +7,7 @@ import buildClassName from '../../util/buildClassName';
import useOldLang from '../../hooks/useOldLang'; import useOldLang from '../../hooks/useOldLang';
import Icon from '../common/icons/Icon';
import Button from '../ui/Button'; import Button from '../ui/Button';
import Menu from '../ui/Menu'; import Menu from '../ui/Menu';
import MenuItem from '../ui/MenuItem'; import MenuItem from '../ui/MenuItem';
@ -68,8 +69,8 @@ const NewChatButton: FC<OwnProps> = ({
ariaLabel={lang(isMenuOpen ? 'Close' : 'NewMessageTitle')} ariaLabel={lang(isMenuOpen ? 'Close' : 'NewMessageTitle')}
tabIndex={-1} tabIndex={-1}
> >
<i className="icon icon-new-chat-filled" /> <Icon name="new-chat-filled" />
<i className="icon icon-close" /> <Icon name="close" />
</Button> </Button>
<Menu <Menu
isOpen={isMenuOpen} isOpen={isMenuOpen}

View File

@ -67,6 +67,7 @@ import useChatListEntry from './hooks/useChatListEntry';
import Avatar from '../../common/Avatar'; import Avatar from '../../common/Avatar';
import DeleteChatModal from '../../common/DeleteChatModal'; import DeleteChatModal from '../../common/DeleteChatModal';
import FullNameTitle from '../../common/FullNameTitle'; import FullNameTitle from '../../common/FullNameTitle';
import Icon from '../../common/icons/Icon';
import StarIcon from '../../common/icons/StarIcon'; import StarIcon from '../../common/icons/StarIcon';
import LastMessageMeta from '../../common/LastMessageMeta'; import LastMessageMeta from '../../common/LastMessageMeta';
import ListItem from '../../ui/ListItem'; import ListItem from '../../ui/ListItem';
@ -383,7 +384,7 @@ const Chat: FC<OwnProps & StateProps> = ({
isSavedDialog={isSavedDialog} isSavedDialog={isSavedDialog}
observeIntersection={observeIntersection} observeIntersection={observeIntersection}
/> />
{isMuted && !isSavedDialog && <i className="icon icon-muted" />} {isMuted && !isSavedDialog && <Icon name="muted" />}
<div className="separator" /> <div className="separator" />
{lastMessage && ( {lastMessage && (
<LastMessageMeta <LastMessageMeta

View File

@ -15,6 +15,7 @@ import useLastCallback from '../../../hooks/useLastCallback';
import useOldLang from '../../../hooks/useOldLang'; import useOldLang from '../../../hooks/useOldLang';
import AnimatedCounter from '../../common/AnimatedCounter'; import AnimatedCounter from '../../common/AnimatedCounter';
import Icon from '../../common/icons/Icon';
import Button from '../../ui/Button'; import Button from '../../ui/Button';
import ShowTransition from '../../ui/ShowTransition'; import ShowTransition from '../../ui/ShowTransition';
@ -110,13 +111,13 @@ const ChatBadge: FC<OwnProps> = ({
function renderContent() { function renderContent() {
const unreadReactionsElement = unreadReactionsCount && ( const unreadReactionsElement = unreadReactionsCount && (
<div className={buildClassName('ChatBadge reaction', shouldBeMuted && 'muted')}> <div className={buildClassName('ChatBadge reaction', shouldBeMuted && 'muted')}>
<i className="icon icon-heart" /> <Icon name="heart" />
</div> </div>
); );
const unreadMentionsElement = unreadMentionsCount && ( const unreadMentionsElement = unreadMentionsCount && (
<div className="ChatBadge mention"> <div className="ChatBadge mention">
<i className="icon icon-mention" /> <Icon name="mention" />
</div> </div>
); );
@ -132,7 +133,7 @@ const ChatBadge: FC<OwnProps> = ({
const pinnedElement = isPinned && ( const pinnedElement = isPinned && (
<div className={className}> <div className={className}>
<i className="icon icon-pinned-chat" /> <Icon name="pinned-chat" />
</div> </div>
); );

View File

@ -12,6 +12,7 @@ import useHistoryBack from '../../../hooks/useHistoryBack';
import useInfiniteScroll from '../../../hooks/useInfiniteScroll'; import useInfiniteScroll from '../../../hooks/useInfiniteScroll';
import useOldLang from '../../../hooks/useOldLang'; import useOldLang from '../../../hooks/useOldLang';
import Icon from '../../common/icons/Icon';
import PrivateChatInfo from '../../common/PrivateChatInfo'; import PrivateChatInfo from '../../common/PrivateChatInfo';
import FloatingActionButton from '../../ui/FloatingActionButton'; import FloatingActionButton from '../../ui/FloatingActionButton';
import InfiniteScroll from '../../ui/InfiniteScroll'; import InfiniteScroll from '../../ui/InfiniteScroll';
@ -100,7 +101,7 @@ const ContactList: FC<OwnProps & StateProps> = ({
onClick={openNewContactDialog} onClick={openNewContactDialog}
ariaLabel={lang('CreateNewContact')} ariaLabel={lang('CreateNewContact')}
> >
<i className="icon icon-add-user-filled" /> <Icon name="add-user-filled" />
</FloatingActionButton> </FloatingActionButton>
</InfiniteScroll> </InfiniteScroll>
); );

View File

@ -12,6 +12,7 @@ import useAppLayout from '../../../hooks/useAppLayout';
import useOldLang from '../../../hooks/useOldLang'; import useOldLang from '../../../hooks/useOldLang';
import AnimatedIconFromSticker from '../../common/AnimatedIconFromSticker'; import AnimatedIconFromSticker from '../../common/AnimatedIconFromSticker';
import Icon from '../../common/icons/Icon';
import Button from '../../ui/Button'; import Button from '../../ui/Button';
import styles from './EmptyFolder.module.scss'; import styles from './EmptyFolder.module.scss';
@ -59,7 +60,7 @@ const EmptyFolder: FC<OwnProps & StateProps> = ({
size="smaller" size="smaller"
isRtl={lang.isRtl} isRtl={lang.isRtl}
> >
<i className="icon icon-settings" /> <Icon name="settings" />
<div className={styles.buttonText}> <div className={styles.buttonText}>
{lang('ChatList.EmptyChatListEditFilter')} {lang('ChatList.EmptyChatListEditFilter')}
</div> </div>

View File

@ -39,6 +39,7 @@ import useOrderDiff from './hooks/useOrderDiff';
import GroupCallTopPane from '../../calls/group/GroupCallTopPane'; import GroupCallTopPane from '../../calls/group/GroupCallTopPane';
import GroupChatInfo from '../../common/GroupChatInfo'; import GroupChatInfo from '../../common/GroupChatInfo';
import Icon from '../../common/icons/Icon';
import HeaderActions from '../../middle/HeaderActions'; import HeaderActions from '../../middle/HeaderActions';
import Button from '../../ui/Button'; import Button from '../../ui/Button';
import InfiniteScroll from '../../ui/InfiniteScroll'; import InfiniteScroll from '../../ui/InfiniteScroll';
@ -234,7 +235,7 @@ const ForumPanel: FC<OwnProps & StateProps> = ({
onClick={handleClose} onClick={handleClose}
ariaLabel={lang('Close')} ariaLabel={lang('Close')}
> >
<i className="icon icon-close" /> <Icon name="close" />
</Button> </Button>
{chat && ( {chat && (

View File

@ -36,6 +36,7 @@ import useOldLang from '../../../hooks/useOldLang';
import { useFullscreenStatus } from '../../../hooks/window/useFullscreen'; import { useFullscreenStatus } from '../../../hooks/window/useFullscreen';
import useLeftHeaderButtonRtlForumTransition from './hooks/useLeftHeaderButtonRtlForumTransition'; import useLeftHeaderButtonRtlForumTransition from './hooks/useLeftHeaderButtonRtlForumTransition';
import Icon from '../../common/icons/Icon';
import PeerChip from '../../common/PeerChip'; import PeerChip from '../../common/PeerChip';
import StoryToggler from '../../story/StoryToggler'; import StoryToggler from '../../story/StoryToggler';
import Button from '../../ui/Button'; import Button from '../../ui/Button';
@ -310,7 +311,7 @@ const LeftMainHeader: FC<OwnProps & StateProps> = ({
onClick={handleLockScreen} onClick={handleLockScreen}
className={buildClassName(!isCurrentUserPremium && 'extra-spacing')} className={buildClassName(!isCurrentUserPremium && 'extra-spacing')}
> >
<i className="icon icon-lock" /> <Icon name="lock" />
</Button> </Button>
)} )}
<ShowTransition <ShowTransition

View File

@ -36,6 +36,7 @@ import useOldLang from '../../../hooks/useOldLang';
import useChatListEntry from './hooks/useChatListEntry'; import useChatListEntry from './hooks/useChatListEntry';
import useTopicContextActions from './hooks/useTopicContextActions'; import useTopicContextActions from './hooks/useTopicContextActions';
import Icon from '../../common/icons/Icon';
import LastMessageMeta from '../../common/LastMessageMeta'; import LastMessageMeta from '../../common/LastMessageMeta';
import TopicIcon from '../../common/TopicIcon'; import TopicIcon from '../../common/TopicIcon';
import ConfirmDialog from '../../ui/ConfirmDialog'; import ConfirmDialog from '../../ui/ConfirmDialog';
@ -190,15 +191,10 @@ const Topic: FC<OwnProps & StateProps> = ({
<TopicIcon topic={topic} className={styles.topicIcon} observeIntersection={observeIntersection} /> <TopicIcon topic={topic} className={styles.topicIcon} observeIntersection={observeIntersection} />
<h3 dir="auto" className="fullName">{renderText(topic.title)}</h3> <h3 dir="auto" className="fullName">{renderText(topic.title)}</h3>
</div> </div>
{topic.isMuted && <i className="icon icon-muted" />} {topic.isMuted && <Icon name="muted" />}
<div className="separator" /> <div className="separator" />
{isClosed && ( {isClosed && (
<i className={buildClassName( <Icon name="lock-badge" className={styles.closedIcon} />
'icon',
'icon-lock-badge',
styles.closedIcon,
)}
/>
)} )}
{lastMessage && ( {lastMessage && (
<LastMessageMeta <LastMessageMeta

View File

@ -37,6 +37,7 @@ import useMedia from '../../../../hooks/useMedia';
import useOldLang from '../../../../hooks/useOldLang'; import useOldLang from '../../../../hooks/useOldLang';
import ChatForumLastMessage from '../../../common/ChatForumLastMessage'; import ChatForumLastMessage from '../../../common/ChatForumLastMessage';
import Icon from '../../../common/icons/Icon';
import MessageSummary from '../../../common/MessageSummary'; import MessageSummary from '../../../common/MessageSummary';
import TypingStatus from '../../../common/TypingStatus'; import TypingStatus from '../../../common/TypingStatus';
@ -183,8 +184,8 @@ export default function useChatListEntry({
<span className="colon">:</span> <span className="colon">:</span>
</> </>
)} )}
{!isSavedDialog && lastMessage.forwardInfo && (<i className="icon icon-share-filled chat-prefix-icon" />)} {!isSavedDialog && lastMessage.forwardInfo && (<Icon name="share-filled" className="chat-prefix-icon" />)}
{lastMessage.replyInfo?.type === 'story' && (<i className="icon icon-story-reply chat-prefix-icon" />)} {lastMessage.replyInfo?.type === 'story' && (<Icon name="story-reply" className="chat-prefix-icon" />)}
{renderSummary(lastMessage, observeIntersection, mediaBlobUrl || mediaThumbnail, isRoundVideo)} {renderSummary(lastMessage, observeIntersection, mediaBlobUrl || mediaThumbnail, isRoundVideo)}
</p> </p>
); );
@ -279,7 +280,7 @@ function renderSummary(
} }
draggable={false} draggable={false}
/> />
{getMessageVideo(message) && <i className="icon icon-play" />} {getMessageVideo(message) && <Icon name="play" />}
{messageSummary} {messageSummary}
</span> </span>
); );

View File

@ -10,6 +10,7 @@ import sortChatIds from '../../common/helpers/sortChatIds';
import useHistoryBack from '../../../hooks/useHistoryBack'; import useHistoryBack from '../../../hooks/useHistoryBack';
import useOldLang from '../../../hooks/useOldLang'; import useOldLang from '../../../hooks/useOldLang';
import Icon from '../../common/icons/Icon';
import PeerPicker from '../../common/pickers/PeerPicker'; import PeerPicker from '../../common/pickers/PeerPicker';
import Button from '../../ui/Button'; import Button from '../../ui/Button';
import FloatingActionButton from '../../ui/FloatingActionButton'; import FloatingActionButton from '../../ui/FloatingActionButton';
@ -94,7 +95,7 @@ const NewChatStep1: FC<OwnProps & StateProps> = ({
onClick={onReset} onClick={onReset}
ariaLabel="Return to Chat List" ariaLabel="Return to Chat List"
> >
<i className="icon icon-arrow-left" /> <Icon name="arrow-left" />
</Button> </Button>
<h3>{lang('GroupAddMembers')}</h3> <h3>{lang('GroupAddMembers')}</h3>
</div> </div>
@ -120,7 +121,7 @@ const NewChatStep1: FC<OwnProps & StateProps> = ({
onClick={handleNextStep} onClick={handleNextStep}
ariaLabel={isChannel ? 'Continue To Channel Info' : 'Continue To Group Info'} ariaLabel={isChannel ? 'Continue To Channel Info' : 'Continue To Group Info'}
> >
<i className="icon icon-arrow-right" /> <Icon name="arrow-right" />
</FloatingActionButton> </FloatingActionButton>
</div> </div>
</div> </div>

View File

@ -13,6 +13,7 @@ import { selectTabState } from '../../../global/selectors';
import useHistoryBack from '../../../hooks/useHistoryBack'; import useHistoryBack from '../../../hooks/useHistoryBack';
import useOldLang from '../../../hooks/useOldLang'; import useOldLang from '../../../hooks/useOldLang';
import Icon from '../../common/icons/Icon';
import PrivateChatInfo from '../../common/PrivateChatInfo'; import PrivateChatInfo from '../../common/PrivateChatInfo';
import AvatarEditable from '../../ui/AvatarEditable'; import AvatarEditable from '../../ui/AvatarEditable';
import Button from '../../ui/Button'; import Button from '../../ui/Button';
@ -157,7 +158,7 @@ const NewChatStep2: FC<OwnProps & StateProps > = ({
onClick={() => onReset()} onClick={() => onReset()}
ariaLabel="Return to member selection" ariaLabel="Return to member selection"
> >
<i className="icon icon-arrow-left" /> <Icon name="arrow-left" />
</Button> </Button>
<h3>{lang(isChannel ? 'NewChannel' : 'NewGroup')}</h3> <h3>{lang(isChannel ? 'NewChannel' : 'NewGroup')}</h3>
</div> </div>
@ -211,7 +212,7 @@ const NewChatStep2: FC<OwnProps & StateProps > = ({
{isLoading ? ( {isLoading ? (
<Spinner color="white" /> <Spinner color="white" />
) : ( ) : (
<i className="icon icon-arrow-right" /> <Icon name="arrow-right" />
)} )}
</FloatingActionButton> </FloatingActionButton>
</div> </div>

View File

@ -30,6 +30,7 @@ import useSelectWithEnter from '../../../hooks/useSelectWithEnter';
import Avatar from '../../common/Avatar'; import Avatar from '../../common/Avatar';
import FullNameTitle from '../../common/FullNameTitle'; import FullNameTitle from '../../common/FullNameTitle';
import Icon from '../../common/icons/Icon';
import Link from '../../ui/Link'; import Link from '../../ui/Link';
import ListItem from '../../ui/ListItem'; import ListItem from '../../ui/ListItem';
@ -129,7 +130,7 @@ function renderSummary(
} }
draggable={false} draggable={false}
/> />
{getMessageVideo(message) && <i className="icon icon-play" />} {getMessageVideo(message) && <Icon name="play" />}
{renderMessageSummary(lang, message, true, searchQuery)} {renderMessageSummary(lang, message, true, searchQuery)}
</span> </span>
); );

View File

@ -3,6 +3,8 @@ import React, { memo, useMemo } from '../../../lib/teact/teact';
import { formatDateToString } from '../../../util/dates/dateFormat'; import { formatDateToString } from '../../../util/dates/dateFormat';
import Icon from '../../common/icons/Icon';
import './DateSuggest.scss'; import './DateSuggest.scss';
const SUGGESTION_COUNT = 8; const SUGGESTION_COUNT = 8;
@ -25,7 +27,7 @@ const DateSuggest: FC<OwnProps> = ({
className="date-item" className="date-item"
key={text} key={text}
> >
<i className="icon icon-calendar" /> <Icon name="calendar" />
<span>{text}</span> <span>{text}</span>
</div> </div>
); );

View File

@ -16,6 +16,7 @@ import useHorizontalScroll from '../../../hooks/useHorizontalScroll';
import useOldLang from '../../../hooks/useOldLang'; import useOldLang from '../../../hooks/useOldLang';
import Avatar from '../../common/Avatar'; import Avatar from '../../common/Avatar';
import Icon from '../../common/icons/Icon';
import Button from '../../ui/Button'; import Button from '../../ui/Button';
import LeftSearchResultChat from './LeftSearchResultChat'; import LeftSearchResultChat from './LeftSearchResultChat';
@ -113,7 +114,7 @@ const RecentContacts: FC<OwnProps & StateProps> = ({
onClick={handleClearRecentlyFoundChats} onClick={handleClearRecentlyFoundChats}
isRtl={lang.isRtl} isRtl={lang.isRtl}
> >
<i className="icon icon-close" /> <Icon name="close" />
</Button> </Button>
</h3> </h3>
{recentlyFoundChatIds.map((id) => ( {recentlyFoundChatIds.map((id) => (

View File

@ -11,6 +11,7 @@ import getSessionIcon from './helpers/getSessionIcon';
import useCurrentOrPrev from '../../../hooks/useCurrentOrPrev'; import useCurrentOrPrev from '../../../hooks/useCurrentOrPrev';
import useOldLang from '../../../hooks/useOldLang'; import useOldLang from '../../../hooks/useOldLang';
import Icon from '../../common/icons/Icon';
import Button from '../../ui/Button'; import Button from '../../ui/Button';
import ListItem from '../../ui/ListItem'; import ListItem from '../../ui/ListItem';
import Modal from '../../ui/Modal'; import Modal from '../../ui/Modal';
@ -63,7 +64,7 @@ const SettingsActiveSession: FC<OwnProps & StateProps> = ({
return ( return (
<div className="modal-header-condensed" dir={lang.isRtl ? 'rtl' : undefined}> <div className="modal-header-condensed" dir={lang.isRtl ? 'rtl' : undefined}>
<Button round color="translucent" size="smaller" ariaLabel={lang('Close')} onClick={onClose}> <Button round color="translucent" size="smaller" ariaLabel={lang('Close')} onClick={onClose}>
<i className="icon icon-close" /> <Icon name="close" />
</Button> </Button>
<div className="modal-title">{lang('SessionPreview.Title')}</div> <div className="modal-title">{lang('SessionPreview.Title')}</div>
<Button <Button

View File

@ -11,6 +11,7 @@ import useOldLang from '../../../hooks/useOldLang';
import Avatar from '../../common/Avatar'; import Avatar from '../../common/Avatar';
import FullNameTitle from '../../common/FullNameTitle'; import FullNameTitle from '../../common/FullNameTitle';
import Icon from '../../common/icons/Icon';
import Button from '../../ui/Button'; import Button from '../../ui/Button';
import Modal from '../../ui/Modal'; import Modal from '../../ui/Modal';
@ -52,7 +53,7 @@ const SettingsActiveWebsite: FC<OwnProps & StateProps> = ({
return ( return (
<div className="modal-header-condensed" dir={lang.isRtl ? 'rtl' : undefined}> <div className="modal-header-condensed" dir={lang.isRtl ? 'rtl' : undefined}>
<Button round color="translucent" size="smaller" ariaLabel={lang('Close')} onClick={onClose}> <Button round color="translucent" size="smaller" ariaLabel={lang('Close')} onClick={onClose}>
<i className="icon icon-close" /> <Icon name="close" />
</Button> </Button>
<div className="modal-title">{lang('WebSessionsTitle')}</div> <div className="modal-title">{lang('WebSessionsTitle')}</div>
<Button <Button

View File

@ -22,6 +22,7 @@ import useMedia from '../../../hooks/useMedia';
import useOldLang from '../../../hooks/useOldLang'; import useOldLang from '../../../hooks/useOldLang';
import usePreviousDeprecated from '../../../hooks/usePreviousDeprecated'; import usePreviousDeprecated from '../../../hooks/usePreviousDeprecated';
import Icon from '../../common/icons/Icon';
import ManageUsernames from '../../common/ManageUsernames'; import ManageUsernames from '../../common/ManageUsernames';
import SafeLink from '../../common/SafeLink'; import SafeLink from '../../common/SafeLink';
import UsernameInput from '../../common/UsernameInput'; import UsernameInput from '../../common/UsernameInput';
@ -286,7 +287,7 @@ const SettingsEditProfile: FC<OwnProps & StateProps> = ({
{isLoading ? ( {isLoading ? (
<Spinner color="white" /> <Spinner color="white" />
) : ( ) : (
<i className="icon icon-check" /> <Icon name="check" />
)} )}
</FloatingActionButton> </FloatingActionButton>
</div> </div>

View File

@ -11,6 +11,7 @@ import useLang from '../../../hooks/useLang';
import useMultiClick from '../../../hooks/useMultiClick'; import useMultiClick from '../../../hooks/useMultiClick';
import useOldLang from '../../../hooks/useOldLang'; import useOldLang from '../../../hooks/useOldLang';
import Icon from '../../common/icons/Icon';
import Button from '../../ui/Button'; import Button from '../../ui/Button';
import ConfirmDialog from '../../ui/ConfirmDialog'; import ConfirmDialog from '../../ui/ConfirmDialog';
import DropdownMenu from '../../ui/DropdownMenu'; import DropdownMenu from '../../ui/DropdownMenu';
@ -71,7 +72,7 @@ const SettingsHeader: FC<OwnProps> = ({
onClick={onTrigger} onClick={onTrigger}
ariaLabel="More actions" ariaLabel="More actions"
> >
<i className="icon icon-more" /> <Icon name="more" />
</Button> </Button>
); );
}, [isMobile]); }, [isMobile]);
@ -269,7 +270,7 @@ const SettingsHeader: FC<OwnProps> = ({
onClick={() => onScreenSelect(SettingsScreens.EditProfile)} onClick={() => onScreenSelect(SettingsScreens.EditProfile)}
ariaLabel={oldLang('lng_settings_information')} ariaLabel={oldLang('lng_settings_information')}
> >
<i className="icon icon-edit" /> <Icon name="edit" />
</Button> </Button>
<DropdownMenu <DropdownMenu
className="settings-more-menu" className="settings-more-menu"
@ -292,7 +293,7 @@ const SettingsHeader: FC<OwnProps> = ({
onClick={onReset} onClick={onReset}
ariaLabel={oldLang('AccDescrGoBack')} ariaLabel={oldLang('AccDescrGoBack')}
> >
<i className="icon icon-arrow-left" /> <Icon name="arrow-left" />
</Button> </Button>
{renderHeaderContent()} {renderHeaderContent()}
<ConfirmDialog <ConfirmDialog

View File

@ -15,6 +15,7 @@ import useOldLang from '../../../hooks/useOldLang';
import Avatar from '../../common/Avatar'; import Avatar from '../../common/Avatar';
import FullNameTitle from '../../common/FullNameTitle'; import FullNameTitle from '../../common/FullNameTitle';
import Icon from '../../common/icons/Icon';
import FloatingActionButton from '../../ui/FloatingActionButton'; import FloatingActionButton from '../../ui/FloatingActionButton';
import ListItem from '../../ui/ListItem'; import ListItem from '../../ui/ListItem';
import Loading from '../../ui/Loading'; import Loading from '../../ui/Loading';
@ -138,7 +139,7 @@ const SettingsPrivacyBlockedUsers: FC<OwnProps & StateProps> = ({
onClick={openBlockUserModal} onClick={openBlockUserModal}
ariaLabel={lang('BlockContact')} ariaLabel={lang('BlockContact')}
> >
<i className="icon icon-add" /> <Icon name="add" />
</FloatingActionButton> </FloatingActionButton>
<BlockUserModal <BlockUserModal
isOpen={isBlockUserModalOpen} isOpen={isBlockUserModalOpen}

View File

@ -22,6 +22,7 @@ import useHistoryBack from '../../../hooks/useHistoryBack';
import useLang from '../../../hooks/useLang'; import useLang from '../../../hooks/useLang';
import useOldLang from '../../../hooks/useOldLang'; import useOldLang from '../../../hooks/useOldLang';
import Icon from '../../common/icons/Icon';
import PeerPicker from '../../common/pickers/PeerPicker'; import PeerPicker from '../../common/pickers/PeerPicker';
import FloatingActionButton from '../../ui/FloatingActionButton'; import FloatingActionButton from '../../ui/FloatingActionButton';
@ -200,7 +201,7 @@ const SettingsPrivacyVisibilityExceptionList: FC<OwnProps & StateProps> = ({
onClick={handleSubmit} onClick={handleSubmit}
ariaLabel={isAllowList ? oldLang('AlwaysAllow') : oldLang('NeverAllow')} ariaLabel={isAllowList ? oldLang('AlwaysAllow') : oldLang('NeverAllow')}
> >
<i className="icon icon-check" /> <Icon name="check" />
</FloatingActionButton> </FloatingActionButton>
</div> </div>
); );

View File

@ -25,6 +25,7 @@ import useOldLang from '../../../../hooks/useOldLang';
import AnimatedIcon from '../../../common/AnimatedIcon'; import AnimatedIcon from '../../../common/AnimatedIcon';
import GroupChatInfo from '../../../common/GroupChatInfo'; import GroupChatInfo from '../../../common/GroupChatInfo';
import Icon from '../../../common/icons/Icon';
import PrivateChatInfo from '../../../common/PrivateChatInfo'; import PrivateChatInfo from '../../../common/PrivateChatInfo';
import FloatingActionButton from '../../../ui/FloatingActionButton'; import FloatingActionButton from '../../../ui/FloatingActionButton';
import InputText from '../../../ui/InputText'; import InputText from '../../../ui/InputText';
@ -386,7 +387,7 @@ const SettingsFoldersEdit: FC<OwnProps & StateProps> = ({
{state.isLoading ? ( {state.isLoading ? (
<Spinner color="white" /> <Spinner color="white" />
) : ( ) : (
<i className="icon icon-check" /> <Icon name="check" />
)} )}
</FloatingActionButton> </FloatingActionButton>
</div> </div>

View File

@ -310,10 +310,10 @@ const SettingsFoldersMain: FC<OwnProps & StateProps> = ({
entities: folder.title.entities, entities: folder.title.entities,
noCustomEmojiPlayback: folder.noTitleAnimations, noCustomEmojiPlayback: folder.noTitleAnimations,
})} })}
{isBlocked && <i className="icon icon-lock-badge settings-folders-blocked-icon" />} {isBlocked && <Icon name="lock-badge" className="settings-folders-blocked-icon" />}
</span> </span>
<span className="subtitle"> <span className="subtitle">
{folder.isChatList && <i className="icon icon-link mr-1" />} {folder.isChatList && <Icon name="link" className="mr-1" />}
{folder.subtitle} {folder.subtitle}
</span> </span>
</ListItem> </ListItem>

View File

@ -24,6 +24,7 @@ import useLastCallback from '../../../../hooks/useLastCallback';
import useOldLang from '../../../../hooks/useOldLang'; import useOldLang from '../../../../hooks/useOldLang';
import AnimatedIcon from '../../../common/AnimatedIcon'; import AnimatedIcon from '../../../common/AnimatedIcon';
import Icon from '../../../common/icons/Icon';
import LinkField from '../../../common/LinkField'; import LinkField from '../../../common/LinkField';
import PeerPicker from '../../../common/pickers/PeerPicker'; import PeerPicker from '../../../common/pickers/PeerPicker';
import FloatingActionButton from '../../../ui/FloatingActionButton'; import FloatingActionButton from '../../../ui/FloatingActionButton';
@ -201,7 +202,7 @@ const SettingsShareChatlist: FC<OwnProps & StateProps> = ({
{isLoading ? ( {isLoading ? (
<Spinner color="white" /> <Spinner color="white" />
) : ( ) : (
<i className="icon icon-check" /> <Icon name="check" />
)} )}
</FloatingActionButton> </FloatingActionButton>
</div> </div>

View File

@ -1,25 +1,31 @@
import React, { memo } from '../../../lib/teact/teact'; import React, { memo } from '../../../lib/teact/teact';
import buildClassName from '../../../util/buildClassName'; import type { IconName } from '../../../types/icons';
import { hexToRgb, lerpRgb } from '../../../util/switchTheme'; import { hexToRgb, lerpRgb } from '../../../util/switchTheme';
import renderText from '../../common/helpers/renderText'; import renderText from '../../common/helpers/renderText';
import useLastCallback from '../../../hooks/useLastCallback'; import useLastCallback from '../../../hooks/useLastCallback';
import Icon from '../../common/icons/Icon';
import ListItem from '../../ui/ListItem'; import ListItem from '../../ui/ListItem';
import styles from './PremiumFeatureItem.module.scss'; import styles from './PremiumFeatureItem.module.scss';
type OwnProps<T> = { type OwnProps<T> = {
icon: string;
isFontIcon?: boolean;
title: string; title: string;
text: string; text: string;
index: number; index: number;
count: number; count: number;
section: T; section: T;
onClick?: (section: T) => void; onClick?: (section: T) => void;
}; } & ({
icon: IconName;
isFontIcon: true;
} | {
icon: string;
isFontIcon?: false;
});
const COLORS = [ const COLORS = [
'#F2862D', '#EB7B4D', '#E46D72', '#DD6091', '#CC5FBA', '#B464E7', '#F2862D', '#EB7B4D', '#E46D72', '#DD6091', '#CC5FBA', '#B464E7',
@ -49,11 +55,7 @@ const PremiumFeatureItem = <T,>({
return ( return (
<ListItem buttonClassName={styles.root} onClick={handleClick} inactive={!onClick}> <ListItem buttonClassName={styles.root} onClick={handleClick} inactive={!onClick}>
{isFontIcon ? ( {isFontIcon ? (
<i <Icon name={icon} className={styles.fontIcon} style={`--item-color: rgb(${r},${g},${b})`} />
className={buildClassName(styles.fontIcon, `icon icon-${icon}`)}
aria-hidden
style={`--item-color: rgb(${r},${g},${b})`}
/>
) : ( ) : (
<img src={icon} className={styles.icon} alt="" style={`--item-color: rgb(${r},${g},${b})`} draggable={false} /> <img src={icon} className={styles.icon} alt="" style={`--item-color: rgb(${r},${g},${b})`} draggable={false} />
)} )}

View File

@ -24,6 +24,7 @@ import useLastCallback from '../../../hooks/useLastCallback';
import useOldLang from '../../../hooks/useOldLang'; import useOldLang from '../../../hooks/useOldLang';
import usePreviousDeprecated from '../../../hooks/usePreviousDeprecated'; import usePreviousDeprecated from '../../../hooks/usePreviousDeprecated';
import Icon from '../../common/icons/Icon';
import SliderDots from '../../common/SliderDots'; import SliderDots from '../../common/SliderDots';
import Button from '../../ui/Button'; import Button from '../../ui/Button';
import PremiumLimitPreview from './common/PremiumLimitPreview'; import PremiumLimitPreview from './common/PremiumLimitPreview';
@ -221,7 +222,7 @@ const PremiumFeatureModal: FC<OwnProps> = ({
onClick={onBack} onClick={onBack}
ariaLabel={lang('Back')} ariaLabel={lang('Back')}
> >
<i className="icon icon-arrow-left" /> <Icon name="arrow-left" />
</Button> </Button>
<div className={styles.preview} /> <div className={styles.preview} />

View File

@ -7,6 +7,8 @@ import buildClassName from '../../../../util/buildClassName';
import useOldLang from '../../../../hooks/useOldLang'; import useOldLang from '../../../../hooks/useOldLang';
import Icon from '../../../common/icons/Icon';
import styles from './PremiumLimitsCompare.module.scss'; import styles from './PremiumLimitsCompare.module.scss';
type OwnProps = { type OwnProps = {
@ -30,7 +32,7 @@ const PremiumLimitsCompare: FC<OwnProps> = ({
<div className={buildClassName(styles.root, className)}> <div className={buildClassName(styles.root, className)}>
{floatingBadgeIcon && ( {floatingBadgeIcon && (
<div className={styles.floatingBadge}> <div className={styles.floatingBadge}>
<i className={buildClassName(styles.floatingBadgeIcon, `icon-${floatingBadgeIcon}`, 'icon')} /> <Icon name={floatingBadgeIcon} className={styles.floatingBadgeIcon} />
<div className={styles.floatingBadgeValue} dir={lang.isRtl ? 'rtl' : undefined}>{leftValue}</div> <div className={styles.floatingBadgeValue} dir={lang.isRtl ? 'rtl' : undefined}>{leftValue}</div>
<div className={styles.floatingBadgeTriangle}> <div className={styles.floatingBadgeTriangle}>
<svg width="26" height="9" viewBox="0 0 26 9" fill="none"> <svg width="26" height="9" viewBox="0 0 26 9" fill="none">

View File

@ -2,6 +2,7 @@ import React, { memo, useLayoutEffect, useRef } from '../../../../lib/teact/teac
import { withGlobal } from '../../../../global'; import { withGlobal } from '../../../../global';
import type { ApiUser } from '../../../../api/types'; import type { ApiUser } from '../../../../api/types';
import type { IconName } from '../../../../types/icons';
import { selectUser } from '../../../../global/selectors'; import { selectUser } from '../../../../global/selectors';
import buildClassName from '../../../../util/buildClassName'; import buildClassName from '../../../../util/buildClassName';
@ -41,7 +42,7 @@ const STORY_FEATURE_DESCRIPTIONS = {
stories_link: 'PremiumStoriesFormattingDescription', stories_link: 'PremiumStoriesFormattingDescription',
}; };
const STORY_FEATURE_ICONS = { const STORY_FEATURE_ICONS: Record<string, IconName> = {
stories_order: 'story-priority', stories_order: 'story-priority',
stories_stealth: 'eye-closed-outline', stories_stealth: 'eye-closed-outline',
stories_views: 'eye-outline', stories_views: 'eye-outline',

View File

@ -53,6 +53,7 @@ import usePreviousDeprecated from '../../hooks/usePreviousDeprecated';
import { dispatchPriorityPlaybackEvent } from '../../hooks/usePriorityPlaybackCheck'; import { dispatchPriorityPlaybackEvent } from '../../hooks/usePriorityPlaybackCheck';
import { useMediaProps } from './hooks/useMediaProps'; import { useMediaProps } from './hooks/useMediaProps';
import Icon from '../common/icons/Icon';
import ReportAvatarModal from '../common/ReportAvatarModal'; import ReportAvatarModal from '../common/ReportAvatarModal';
import Button from '../ui/Button'; import Button from '../ui/Button';
import ShowTransition from '../ui/ShowTransition'; import ShowTransition from '../ui/ShowTransition';
@ -426,7 +427,7 @@ const MediaViewer = ({
ariaLabel={lang('Close')} ariaLabel={lang('Close')}
onClick={handleClose} onClick={handleClose}
> >
<i className="icon icon-close" /> <Icon name="close" />
</Button> </Button>
)} )}
<Transition activeKey={animationKey.current!} name={headerAnimation}> <Transition activeKey={animationKey.current!} name={headerAnimation}>

View File

@ -3,6 +3,7 @@ import React, { memo, useMemo } from '../../lib/teact/teact';
import { getActions, withGlobal } from '../../global'; import { getActions, withGlobal } from '../../global';
import type { ActiveDownloads, MediaViewerOrigin, MessageListType } from '../../types'; import type { ActiveDownloads, MediaViewerOrigin, MessageListType } from '../../types';
import type { IconName } from '../../types/icons';
import type { MenuItemProps } from '../ui/MenuItem'; import type { MenuItemProps } from '../ui/MenuItem';
import type { MediaViewerItem } from './helpers/getViewableMedia'; import type { MediaViewerItem } from './helpers/getViewableMedia';
@ -31,6 +32,7 @@ import useOldLang from '../../hooks/useOldLang';
import useZoomChange from './hooks/useZoomChangeSignal'; import useZoomChange from './hooks/useZoomChangeSignal';
import DeleteProfilePhotoModal from '../common/DeleteProfilePhotoModal'; import DeleteProfilePhotoModal from '../common/DeleteProfilePhotoModal';
import Icon from '../common/icons/Icon';
import Button from '../ui/Button'; import Button from '../ui/Button';
import DropdownMenu from '../ui/DropdownMenu'; import DropdownMenu from '../ui/DropdownMenu';
import MenuItem from '../ui/MenuItem'; import MenuItem from '../ui/MenuItem';
@ -158,7 +160,7 @@ const MediaViewerActions: FC<OwnProps & StateProps> = ({
onClick={onTrigger} onClick={onTrigger}
ariaLabel="More actions" ariaLabel="More actions"
> >
<i className="icon icon-more" /> <Icon name="more" />
</Button> </Button>
); );
}, []); }, []);
@ -191,7 +193,7 @@ const MediaViewerActions: FC<OwnProps & StateProps> = ({
{isDownloading ? ( {isDownloading ? (
<ProgressSpinner progress={downloadProgress} size="s" onClick={handleDownloadClick} /> <ProgressSpinner progress={downloadProgress} size="s" onClick={handleDownloadClick} />
) : ( ) : (
<i className="icon icon-download" /> <Icon name="download" />
)} )}
</Button> </Button>
) : ( ) : (
@ -203,7 +205,7 @@ const MediaViewerActions: FC<OwnProps & StateProps> = ({
color="translucent-white" color="translucent-white"
ariaLabel={lang('AccActionDownload')} ariaLabel={lang('AccActionDownload')}
> >
<i className="icon icon-download" /> <Icon name="download" />
</Button> </Button>
)); ));
} }
@ -286,7 +288,7 @@ const MediaViewerActions: FC<OwnProps & StateProps> = ({
}) => ( }) => (
<MenuItem <MenuItem
key={icon} key={icon}
icon={icon} icon={icon as IconName}
href={href} href={href}
download={download} download={download}
onClick={onClick} onClick={onClick}
@ -312,7 +314,7 @@ const MediaViewerActions: FC<OwnProps & StateProps> = ({
ariaLabel={lang('Forward')} ariaLabel={lang('Forward')}
onClick={onForward} onClick={onForward}
> >
<i className="icon icon-forward" /> <Icon name="forward" />
</Button> </Button>
)} )}
{renderDownloadButton()} {renderDownloadButton()}
@ -323,7 +325,7 @@ const MediaViewerActions: FC<OwnProps & StateProps> = ({
ariaLabel={lang('MediaZoomOut')} ariaLabel={lang('MediaZoomOut')}
onClick={handleZoomOut} onClick={handleZoomOut}
> >
<i className="icon icon-zoom-out" /> <Icon name="zoom-out" />
</Button> </Button>
<Button <Button
round round
@ -332,7 +334,7 @@ const MediaViewerActions: FC<OwnProps & StateProps> = ({
ariaLabel={lang('MediaZoomIn')} ariaLabel={lang('MediaZoomIn')}
onClick={handleZoomIn} onClick={handleZoomIn}
> >
<i className="icon icon-zoom-in" /> <Icon name="zoom-in" />
</Button> </Button>
{canReportAvatar && ( {canReportAvatar && (
<Button <Button
@ -342,7 +344,7 @@ const MediaViewerActions: FC<OwnProps & StateProps> = ({
ariaLabel={lang(isVideo ? 'PeerInfo.ReportProfileVideo' : 'PeerInfo.ReportProfilePhoto')} ariaLabel={lang(isVideo ? 'PeerInfo.ReportProfileVideo' : 'PeerInfo.ReportProfilePhoto')}
onClick={onReport} onClick={onReport}
> >
<i className="icon icon-flag" /> <Icon name="flag" />
</Button> </Button>
)} )}
{canUpdate && ( {canUpdate && (
@ -353,7 +355,7 @@ const MediaViewerActions: FC<OwnProps & StateProps> = ({
ariaLabel={lang('ProfilePhoto.SetMainPhoto')} ariaLabel={lang('ProfilePhoto.SetMainPhoto')}
onClick={handleUpdate} onClick={handleUpdate}
> >
<i className="icon icon-copy-media" /> <Icon name="copy-media" />
</Button> </Button>
)} )}
{canDelete && ( {canDelete && (
@ -364,7 +366,7 @@ const MediaViewerActions: FC<OwnProps & StateProps> = ({
ariaLabel={lang('Delete')} ariaLabel={lang('Delete')}
onClick={openDeleteModalHandler} onClick={openDeleteModalHandler}
> >
<i className="icon icon-delete" /> <Icon name="delete" />
</Button> </Button>
)} )}
<Button <Button
@ -374,7 +376,7 @@ const MediaViewerActions: FC<OwnProps & StateProps> = ({
ariaLabel={lang('Close')} ariaLabel={lang('Close')}
onClick={onCloseMediaViewer} onClick={onCloseMediaViewer}
> >
<i className="icon icon-close" /> <Icon name="close" />
</Button> </Button>
{canDelete && renderDeleteModal()} {canDelete && renderDeleteModal()}
</div> </div>

View File

@ -23,6 +23,7 @@ import useFullscreen from '../../hooks/window/useFullscreen';
import useControlsSignal from './hooks/useControlsSignal'; import useControlsSignal from './hooks/useControlsSignal';
import useVideoWaitingSignal from './hooks/useVideoWaitingSignal'; import useVideoWaitingSignal from './hooks/useVideoWaitingSignal';
import Icon from '../common/icons/Icon';
import Button from '../ui/Button'; import Button from '../ui/Button';
import ProgressSpinner from '../ui/ProgressSpinner'; import ProgressSpinner from '../ui/ProgressSpinner';
import VideoPlayerControls from './VideoPlayerControls'; import VideoPlayerControls from './VideoPlayerControls';
@ -327,7 +328,7 @@ const VideoPlayer: FC<OwnProps> = ({
</div> </div>
{shouldRenderPlayButton && ( {shouldRenderPlayButton && (
<Button round className={`play-button ${playButtonClassNames}`} onClick={togglePlayState}> <Button round className={`play-button ${playButtonClassNames}`} onClick={togglePlayState}>
<i className="icon icon-play" /> <Icon name="play" />
</Button> </Button>
)} )}
{shouldRenderSpinner && ( {shouldRenderSpinner && (

View File

@ -7,6 +7,7 @@ import React, {
import type { ApiDimensions } from '../../api/types'; import type { ApiDimensions } from '../../api/types';
import type { BufferedRange } from '../../hooks/useBuffering'; import type { BufferedRange } from '../../hooks/useBuffering';
import type { IconName } from '../../types/icons';
import buildClassName from '../../util/buildClassName'; import buildClassName from '../../util/buildClassName';
import { formatMediaDuration } from '../../util/dates/dateFormat'; import { formatMediaDuration } from '../../util/dates/dateFormat';
@ -21,6 +22,7 @@ import useLastCallback from '../../hooks/useLastCallback';
import useOldLang from '../../hooks/useOldLang'; import useOldLang from '../../hooks/useOldLang';
import useControlsSignal from './hooks/useControlsSignal'; import useControlsSignal from './hooks/useControlsSignal';
import Icon from '../common/icons/Icon';
import Button from '../ui/Button'; import Button from '../ui/Button';
import Menu from '../ui/Menu'; import Menu from '../ui/Menu';
import MenuItem from '../ui/MenuItem'; import MenuItem from '../ui/MenuItem';
@ -147,11 +149,11 @@ const VideoPlayerControls: FC<OwnProps> = ({
setIsSeeking(true); setIsSeeking(true);
}); });
const volumeIcon = useMemo(() => { const volumeIcon: IconName = useMemo(() => {
if (volume === 0 || isMuted) return 'icon-muted'; if (volume === 0 || isMuted) return 'muted';
if (volume < 0.3) return 'icon-volume-1'; if (volume < 0.3) return 'volume-1';
if (volume < 0.6) return 'icon-volume-2'; if (volume < 0.6) return 'volume-2';
return 'icon-volume-3'; return 'volume-3';
}, [volume, isMuted]); }, [volume, isMuted]);
return ( return (
@ -182,7 +184,7 @@ const VideoPlayerControls: FC<OwnProps> = ({
round round
onClick={onPlayPause} onClick={onPlayPause}
> >
<i className={buildClassName('icon', isPlaying ? 'icon-pause' : 'icon-play')} /> <Icon name={isPlaying ? 'pause' : 'play'} />
</Button> </Button>
<Button <Button
ariaLabel="Volume" ariaLabel="Volume"
@ -192,7 +194,7 @@ const VideoPlayerControls: FC<OwnProps> = ({
round round
onClick={onVolumeClick} onClick={onVolumeClick}
> >
<i className={buildClassName('icon', volumeIcon)} /> <Icon name={volumeIcon} />
</Button> </Button>
{!IS_IOS && ( {!IS_IOS && (
<RangeSlider bold className="volume-slider" value={isMuted ? 0 : volume * 100} onChange={onVolumeChange} /> <RangeSlider bold className="volume-slider" value={isMuted ? 0 : volume * 100} onChange={onVolumeChange} />
@ -223,7 +225,7 @@ const VideoPlayerControls: FC<OwnProps> = ({
round round
onClick={onPictureInPictureChange} onClick={onPictureInPictureChange}
> >
<i className="icon icon-pip" /> <Icon name="pip" />
</Button> </Button>
)} )}
{isFullscreenSupported && ( {isFullscreenSupported && (
@ -235,7 +237,7 @@ const VideoPlayerControls: FC<OwnProps> = ({
round round
onClick={onChangeFullscreen} onClick={onChangeFullscreen}
> >
<i className={buildClassName('icon ', isFullscreen ? 'icon-smallscreen' : 'icon-fullscreen')} /> <Icon name={isFullscreen ? 'smallscreen' : 'fullscreen'} />
</Button> </Button>
)} )}
</div> </div>

View File

@ -37,6 +37,7 @@ import { useHotkeys } from '../../hooks/useHotkeys';
import useLastCallback from '../../hooks/useLastCallback'; import useLastCallback from '../../hooks/useLastCallback';
import useOldLang from '../../hooks/useOldLang'; import useOldLang from '../../hooks/useOldLang';
import Icon from '../common/icons/Icon';
import Button from '../ui/Button'; import Button from '../ui/Button';
import DropdownMenu from '../ui/DropdownMenu'; import DropdownMenu from '../ui/DropdownMenu';
import MenuItem from '../ui/MenuItem'; import MenuItem from '../ui/MenuItem';
@ -290,7 +291,7 @@ const HeaderActions: FC<OwnProps & StateProps> = ({
onClick={onTrigger} onClick={onTrigger}
ariaLabel={lang('TranslateMessage')} ariaLabel={lang('TranslateMessage')}
> >
<i className="icon icon-language" aria-hidden /> <Icon name="language" />
</Button> </Button>
); );
}, [isRightColumnShown, lang]); }, [isRightColumnShown, lang]);
@ -376,7 +377,7 @@ const HeaderActions: FC<OwnProps & StateProps> = ({
onClick={handleSearchClick} onClick={handleSearchClick}
ariaLabel={lang('Conversation.SearchPlaceholder')} ariaLabel={lang('Conversation.SearchPlaceholder')}
> >
<i className="icon icon-search" aria-hidden /> <Icon name="search" />
</Button> </Button>
)} )}
{canCall && ( {canCall && (
@ -387,7 +388,7 @@ const HeaderActions: FC<OwnProps & StateProps> = ({
onClick={handleRequestCall} onClick={handleRequestCall}
ariaLabel="Call" ariaLabel="Call"
> >
<i className="icon icon-phone" aria-hidden /> <Icon name="phone" />
</Button> </Button>
)} )}
</> </>
@ -402,7 +403,7 @@ const HeaderActions: FC<OwnProps & StateProps> = ({
onClick={handleJoinRequestsClick} onClick={handleJoinRequestsClick}
ariaLabel={isChannel ? lang('SubscribeRequests') : lang('MemberRequests')} ariaLabel={isChannel ? lang('SubscribeRequests') : lang('MemberRequests')}
> >
<i className="icon icon-user" aria-hidden /> <Icon name="user" />
<div className="badge">{pendingJoinRequests}</div> <div className="badge">{pendingJoinRequests}</div>
</Button> </Button>
)} )}
@ -417,7 +418,7 @@ const HeaderActions: FC<OwnProps & StateProps> = ({
ariaLabel="More actions" ariaLabel="More actions"
onClick={handleHeaderMenuOpen} onClick={handleHeaderMenuOpen}
> >
<i className="icon icon-more" aria-hidden /> <Icon name="more" />
</Button> </Button>
{menuAnchor && ( {menuAnchor && (
<HeaderMenuContainer <HeaderMenuContainer

View File

@ -24,6 +24,7 @@ import useOldLang from '../../hooks/useOldLang';
import usePreviousDeprecated from '../../hooks/usePreviousDeprecated'; import usePreviousDeprecated from '../../hooks/usePreviousDeprecated';
import useCopySelectedMessages from './hooks/useCopySelectedMessages'; import useCopySelectedMessages from './hooks/useCopySelectedMessages';
import Icon from '../common/icons/Icon';
import Button from '../ui/Button'; import Button from '../ui/Button';
import DeleteSelectedMessageModal from './DeleteSelectedMessageModal'; import DeleteSelectedMessageModal from './DeleteSelectedMessageModal';
@ -143,7 +144,7 @@ const MessageSelectToolbar: FC<OwnProps & StateProps> = ({
title={label} title={label}
aria-label={label} aria-label={label}
> >
<i className={buildClassName('icon', `icon-${icon}`)} /> <Icon name={icon} />
</div> </div>
); );
}; };
@ -157,7 +158,7 @@ const MessageSelectToolbar: FC<OwnProps & StateProps> = ({
onClick={handleExitMessageSelectMode} onClick={handleExitMessageSelectMode}
ariaLabel="Exit select mode" ariaLabel="Exit select mode"
> >
<i className="icon icon-close" /> <Icon name="close" />
</Button> </Button>
<span className="MessageSelectToolbar-count" title={formattedMessagesCount}> <span className="MessageSelectToolbar-count" title={formattedMessagesCount}>
{formattedMessagesCount} {formattedMessagesCount}

View File

@ -80,6 +80,7 @@ import useWindowSize from '../../hooks/window/useWindowSize';
import usePinnedMessage from './hooks/usePinnedMessage'; import usePinnedMessage from './hooks/usePinnedMessage';
import Composer from '../common/Composer'; import Composer from '../common/Composer';
import Icon from '../common/icons/Icon';
import PrivacySettingsNoticeModal from '../common/PrivacySettingsNoticeModal.async'; import PrivacySettingsNoticeModal from '../common/PrivacySettingsNoticeModal.async';
import SeenByModal from '../common/SeenByModal.async'; import SeenByModal from '../common/SeenByModal.async';
import UnpinAllMessagesModal from '../common/UnpinAllMessagesModal.async'; import UnpinAllMessagesModal from '../common/UnpinAllMessagesModal.async';
@ -573,7 +574,7 @@ function MiddleColumn({
className="composer-button unpin-all-button" className="composer-button unpin-all-button"
onClick={handleOpenUnpinModal} onClick={handleOpenUnpinModal}
> >
<i className="icon icon-unpin" /> <Icon name="unpin" />
<span>{lang('Chat.Pinned.UnpinAll', pinnedMessagesCount, 'i')}</span> <span>{lang('Chat.Pinned.UnpinAll', pinnedMessagesCount, 'i')}</span>
</Button> </Button>
</div> </div>

View File

@ -10,6 +10,7 @@ import renderText from '../common/helpers/renderText';
import useOldLang from '../../hooks/useOldLang'; import useOldLang from '../../hooks/useOldLang';
import Icon from '../common/icons/Icon';
import TopicIcon from '../common/TopicIcon'; import TopicIcon from '../common/TopicIcon';
import './NoMessages.scss'; import './NoMessages.scss';
@ -79,7 +80,7 @@ function renderSavedMessages(lang: OldLangFn) {
return ( return (
<div className="NoMessages"> <div className="NoMessages">
<div className="wrapper"> <div className="wrapper">
<i className="icon no-messages-icon icon-cloud-download" /> <Icon name="cloud-download" className="no-messages-icon" />
<h3 className="title">{lang('Conversation.CloudStorageInfo.Title')}</h3> <h3 className="title">{lang('Conversation.CloudStorageInfo.Title')}</h3>
<ul className="description"> <ul className="description">
<li>{lang('Conversation.ClousStorageInfo.Description1')}</li> <li>{lang('Conversation.ClousStorageInfo.Description1')}</li>

View File

@ -25,6 +25,7 @@ import useOldLang from '../../hooks/useOldLang';
import Avatar from '../common/Avatar'; import Avatar from '../common/Avatar';
import FullNameTitle from '../common/FullNameTitle'; import FullNameTitle from '../common/FullNameTitle';
import Icon from '../common/icons/Icon';
import PrivateChatInfo from '../common/PrivateChatInfo'; import PrivateChatInfo from '../common/PrivateChatInfo';
import ReactionStaticEmoji from '../common/reactions/ReactionStaticEmoji'; import ReactionStaticEmoji from '../common/reactions/ReactionStaticEmoji';
import Button from '../ui/Button'; import Button from '../ui/Button';
@ -154,7 +155,7 @@ const ReactorListModal: FC<OwnProps & StateProps> = ({
// eslint-disable-next-line react/jsx-no-bind // eslint-disable-next-line react/jsx-no-bind
onClick={() => setChosenTab(undefined)} onClick={() => setChosenTab(undefined)}
> >
<i className="icon icon-heart" /> <Icon name="heart" />
{Boolean(reactors?.count) && formatIntegerCompact(reactors.count)} {Boolean(reactors?.count) && formatIntegerCompact(reactors.count)}
</Button> </Button>
{allReactions.map((reaction) => { {allReactions.map((reaction) => {
@ -210,7 +211,7 @@ const ReactorListModal: FC<OwnProps & StateProps> = ({
<div className="info"> <div className="info">
<FullNameTitle peer={peer} withEmojiStatus /> <FullNameTitle peer={peer} withEmojiStatus />
<span className="status" dir="auto"> <span className="status" dir="auto">
<i className="icon icon-heart-outline status-icon" /> <Icon name="heart-outline" className="status-icon" />
{formatDateAtTime(lang, r.addedDate * 1000)} {formatDateAtTime(lang, r.addedDate * 1000)}
</span> </span>
</div> </div>

View File

@ -9,6 +9,7 @@ import { formatIntegerCompact } from '../../util/textFormat';
import useContextMenuHandlers from '../../hooks/useContextMenuHandlers'; import useContextMenuHandlers from '../../hooks/useContextMenuHandlers';
import useOldLang from '../../hooks/useOldLang'; import useOldLang from '../../hooks/useOldLang';
import Icon from '../common/icons/Icon';
import Button from '../ui/Button'; import Button from '../ui/Button';
import Menu from '../ui/Menu'; import Menu from '../ui/Menu';
import MenuItem from '../ui/MenuItem'; import MenuItem from '../ui/MenuItem';
@ -53,7 +54,7 @@ const ScrollDownButton: FC<OwnProps> = ({
onContextMenu={handleContextMenu} onContextMenu={handleContextMenu}
ariaLabel={lang(ariaLabelLang)} ariaLabel={lang(ariaLabelLang)}
> >
<i className={buildClassName(styles.icon, 'icon', `icon-${icon}`)} /> <Icon name={icon} className={styles.icon} />
</Button> </Button>
{Boolean(unreadCount) && <div className={styles.unreadCount}>{formatIntegerCompact(unreadCount)}</div>} {Boolean(unreadCount) && <div className={styles.unreadCount}>{formatIntegerCompact(unreadCount)}</div>}
{onReadAll && ( {onReadAll && (

View File

@ -45,6 +45,7 @@ import useCustomEmojiTooltip from './hooks/useCustomEmojiTooltip';
import useEmojiTooltip from './hooks/useEmojiTooltip'; import useEmojiTooltip from './hooks/useEmojiTooltip';
import useMentionTooltip from './hooks/useMentionTooltip'; import useMentionTooltip from './hooks/useMentionTooltip';
import Icon from '../../common/icons/Icon';
import Button from '../../ui/Button'; import Button from '../../ui/Button';
import DropdownMenu from '../../ui/DropdownMenu'; import DropdownMenu from '../../ui/DropdownMenu';
import MenuItem from '../../ui/MenuItem'; import MenuItem from '../../ui/MenuItem';
@ -438,7 +439,7 @@ const AttachmentModal: FC<OwnProps & StateProps> = ({
onClick={onTrigger} onClick={onTrigger}
ariaLabel="More actions" ariaLabel="More actions"
> >
<i className="icon icon-more" /> <Icon name="more" />
</Button> </Button>
); );
}, [isMobile]); }, [isMobile]);
@ -498,7 +499,7 @@ const AttachmentModal: FC<OwnProps & StateProps> = ({
return ( return (
<div className="modal-header-condensed" dir={lang.isRtl ? 'rtl' : undefined}> <div className="modal-header-condensed" dir={lang.isRtl ? 'rtl' : undefined}>
<Button round color="translucent" size="smaller" ariaLabel="Cancel attachments" onClick={onClear}> <Button round color="translucent" size="smaller" ariaLabel="Cancel attachments" onClick={onClear}>
<i className="icon icon-close" /> <Icon name="close" />
</Button> </Button>
<div className="modal-title">{title}</div> <div className="modal-title">{title}</div>
{notEditingFile && !isInAlbum {notEditingFile && !isInAlbum

View File

@ -12,6 +12,7 @@ import { REM } from '../../common/helpers/mediaDimensions';
import useLastCallback from '../../../hooks/useLastCallback'; import useLastCallback from '../../../hooks/useLastCallback';
import File from '../../common/File'; import File from '../../common/File';
import Icon from '../../common/icons/Icon';
import MediaSpoiler from '../../common/MediaSpoiler'; import MediaSpoiler from '../../common/MediaSpoiler';
import styles from './AttachmentModalItem.module.scss'; import styles from './AttachmentModalItem.module.scss';
@ -84,8 +85,10 @@ const AttachmentModalItem: FC<OwnProps> = ({
smaller smaller
/> />
{onDelete && ( {onDelete && (
<i <Icon
className={buildClassName('icon', 'icon-delete', styles.actionItem, styles.deleteFile)} name="delete"
className={buildClassName(styles.actionItem, styles.deleteFile)}
// eslint-disable-next-line react/jsx-no-bind
onClick={() => onDelete(index)} onClick={() => onDelete(index)}
/> />
)} )}
@ -113,19 +116,14 @@ const AttachmentModalItem: FC<OwnProps> = ({
/> />
{shouldRenderOverlay && ( {shouldRenderOverlay && (
<div className={styles.overlay}> <div className={styles.overlay}>
<i <Icon
className={buildClassName( name={attachment.shouldSendAsSpoiler ? 'spoiler-disable' : 'spoiler'}
'icon', className={styles.actionItem}
attachment.shouldSendAsSpoiler ? 'icon-spoiler-disable' : 'icon-spoiler',
styles.actionItem,
)}
onClick={handleSpoilerClick} onClick={handleSpoilerClick}
/> />
{onDelete && ( {onDelete && (
<i // eslint-disable-next-line react/jsx-no-bind
className={buildClassName('icon', 'icon-delete', styles.actionItem)} <Icon name="delete" className={styles.actionItem} onClick={() => onDelete(index)} />
onClick={() => onDelete(index)}
/>
)} )}
</div> </div>
)} )}

View File

@ -4,6 +4,7 @@ import React, { memo, useEffect, useRef } from '../../../lib/teact/teact';
import buildClassName from '../../../util/buildClassName'; import buildClassName from '../../../util/buildClassName';
import renderText from '../../common/helpers/renderText'; import renderText from '../../common/helpers/renderText';
import Icon from '../../common/icons/Icon';
import Button from '../../ui/Button'; import Button from '../../ui/Button';
type OwnProps = { type OwnProps = {
@ -52,7 +53,7 @@ const BotMenuButton: FC<OwnProps> = ({
onClick={onClick} onClick={onClick}
ariaLabel="Open bot command keyboard" ariaLabel="Open bot command keyboard"
> >
<i className={buildClassName('bot-menu-icon', 'icon', 'icon-webapp', isOpen && 'open')} /> <Icon name="webapp" className={buildClassName('bot-menu-icon', isOpen && 'open')} />
<span ref={textRef} className="bot-menu-text">{renderText(text)}</span> <span ref={textRef} className="bot-menu-text">{renderText(text)}</span>
</Button> </Button>
); );

View File

@ -59,10 +59,6 @@
.bubble { .bubble {
width: auto; width: auto;
} }
.icon-placeholder {
width: 1.5rem;
}
} }
.quote-reply { .quote-reply {

View File

@ -280,7 +280,7 @@ const ComposerEmbeddedMessage: FC<OwnProps & StateProps> = ({
ariaLabel={oldLang('Cancel')} ariaLabel={oldLang('Cancel')}
onClick={handleClearClick} onClick={handleClearClick}
> >
<i className="icon icon-close" /> <Icon name="close" />
</Button> </Button>
{(isShowingReply || isForwarding) && !isContextMenuDisabled && ( {(isShowingReply || isForwarding) && !isContextMenuDisabled && (
<Menu <Menu
@ -297,7 +297,7 @@ const ComposerEmbeddedMessage: FC<OwnProps & StateProps> = ({
<> <>
<MenuItem <MenuItem
icon={!noAuthors ? 'message-succeeded' : undefined} icon={!noAuthors ? 'message-succeeded' : undefined}
customIcon={noAuthors ? <i className="icon icon-placeholder" /> : undefined} customIcon={noAuthors ? <Icon name="placeholder" /> : undefined}
// eslint-disable-next-line react/jsx-no-bind // eslint-disable-next-line react/jsx-no-bind
onClick={() => setForwardNoAuthors({ onClick={() => setForwardNoAuthors({
noAuthors: false, noAuthors: false,
@ -307,7 +307,7 @@ const ComposerEmbeddedMessage: FC<OwnProps & StateProps> = ({
</MenuItem> </MenuItem>
<MenuItem <MenuItem
icon={noAuthors ? 'message-succeeded' : undefined} icon={noAuthors ? 'message-succeeded' : undefined}
customIcon={!noAuthors ? <i className="icon icon-placeholder" /> : undefined} customIcon={!noAuthors ? <Icon name="placeholder" /> : undefined}
// eslint-disable-next-line react/jsx-no-bind // eslint-disable-next-line react/jsx-no-bind
onClick={() => setForwardNoAuthors({ onClick={() => setForwardNoAuthors({
noAuthors: true, noAuthors: true,
@ -320,7 +320,7 @@ const ComposerEmbeddedMessage: FC<OwnProps & StateProps> = ({
<MenuSeparator /> <MenuSeparator />
<MenuItem <MenuItem
icon={!noCaptions ? 'message-succeeded' : undefined} icon={!noCaptions ? 'message-succeeded' : undefined}
customIcon={noCaptions ? <i className="icon icon-placeholder" /> : undefined} customIcon={noCaptions ? <Icon name="placeholder" /> : undefined}
// eslint-disable-next-line react/jsx-no-bind // eslint-disable-next-line react/jsx-no-bind
onClick={() => setForwardNoCaptions({ onClick={() => setForwardNoCaptions({
noCaptions: false, noCaptions: false,
@ -330,7 +330,7 @@ const ComposerEmbeddedMessage: FC<OwnProps & StateProps> = ({
</MenuItem> </MenuItem>
<MenuItem <MenuItem
icon={noCaptions ? 'message-succeeded' : undefined} icon={noCaptions ? 'message-succeeded' : undefined}
customIcon={!noCaptions ? <i className="icon icon-placeholder" /> : undefined} customIcon={!noCaptions ? <Icon name="placeholder" /> : undefined}
// eslint-disable-next-line react/jsx-no-bind // eslint-disable-next-line react/jsx-no-bind
onClick={() => setForwardNoCaptions({ onClick={() => setForwardNoCaptions({
noCaptions: true, noCaptions: true,

View File

@ -8,6 +8,8 @@ import useFlag from '../../../hooks/useFlag';
import useLastCallback from '../../../hooks/useLastCallback'; import useLastCallback from '../../../hooks/useLastCallback';
import useResizeObserver from '../../../hooks/useResizeObserver'; import useResizeObserver from '../../../hooks/useResizeObserver';
import Icon from '../../common/icons/Icon';
import './DropTarget.scss'; import './DropTarget.scss';
export type OwnProps = { export type OwnProps = {
@ -68,7 +70,7 @@ const DropTarget: FC<OwnProps> = ({ isQuick, isGeneric, onFileSelect }) => {
<rect className="target-outline" x="0" y="0" width="100%" height="100%" rx="8" /> <rect className="target-outline" x="0" y="0" width="100%" height="100%" rx="8" />
</svg> </svg>
<div className="target-content"> <div className="target-content">
<div className={`icon icon-${isQuick ? 'photo' : 'document'}`} /> <Icon name={isQuick ? 'photo' : 'document'} />
<div className="title">Drop files here to send them</div> <div className="title">Drop files here to send them</div>
{!isGeneric && <div className="description">{isQuick ? 'in a quick way' : 'without compression'}</div>} {!isGeneric && <div className="description">{isQuick ? 'in a quick way' : 'without compression'}</div>}
</div> </div>

View File

@ -6,6 +6,7 @@ import React, {
import { withGlobal } from '../../../global'; import { withGlobal } from '../../../global';
import type { GlobalState } from '../../../global/types'; import type { GlobalState } from '../../../global/types';
import type { IconName } from '../../../types/icons';
import type { import type {
EmojiData, EmojiData,
EmojiModule, EmojiModule,
@ -30,6 +31,7 @@ import useOldLang from '../../../hooks/useOldLang';
import useScrolledState from '../../../hooks/useScrolledState'; import useScrolledState from '../../../hooks/useScrolledState';
import useAsyncRendering from '../../right/hooks/useAsyncRendering'; import useAsyncRendering from '../../right/hooks/useAsyncRendering';
import Icon from '../../common/icons/Icon';
import Button from '../../ui/Button'; import Button from '../../ui/Button';
import Loading from '../../ui/Loading'; import Loading from '../../ui/Loading';
import EmojiCategory from './EmojiCategory'; import EmojiCategory from './EmojiCategory';
@ -45,16 +47,16 @@ type StateProps = Pick<GlobalState, 'recentEmojis'>;
type EmojiCategoryData = { id: string; name: string; emojis: string[] }; type EmojiCategoryData = { id: string; name: string; emojis: string[] };
const ICONS_BY_CATEGORY: Record<string, string> = { const ICONS_BY_CATEGORY: Record<string, IconName> = {
recent: 'icon-recent', recent: 'recent',
people: 'icon-smile', people: 'smile',
nature: 'icon-animals', nature: 'animals',
foods: 'icon-eats', foods: 'eats',
activity: 'icon-sport', activity: 'sport',
places: 'icon-car', places: 'car',
objects: 'icon-lamp', objects: 'lamp',
symbols: 'icon-language', symbols: 'language',
flags: 'icon-flag', flags: 'flag',
}; };
const OPEN_ANIMATION_DELAY = 200; const OPEN_ANIMATION_DELAY = 200;
@ -200,7 +202,7 @@ const EmojiPicker: FC<OwnProps & StateProps> = ({
onClick={() => selectCategory(index)} onClick={() => selectCategory(index)}
ariaLabel={category.name} ariaLabel={category.name}
> >
<i className={buildClassName('icon', icon)} /> <Icon name={icon} />
</Button> </Button>
); );
} }

View File

@ -33,6 +33,7 @@ import useLastCallback from '../../../hooks/useLastCallback';
import useOldLang from '../../../hooks/useOldLang'; import useOldLang from '../../../hooks/useOldLang';
import useInputCustomEmojis from './hooks/useInputCustomEmojis'; import useInputCustomEmojis from './hooks/useInputCustomEmojis';
import Icon from '../../common/icons/Icon';
import Button from '../../ui/Button'; import Button from '../../ui/Button';
import TextTimer from '../../ui/TextTimer'; import TextTimer from '../../ui/TextTimer';
import TextFormatter from './TextFormatter.async'; import TextFormatter from './TextFormatter.async';
@ -597,7 +598,7 @@ const MessageInput: FC<OwnProps & StateProps> = ({
dir="auto" dir="auto"
> >
{!isAttachmentModalInput && !canSendPlainText {!isAttachmentModalInput && !canSendPlainText
&& <i className="icon icon-lock-badge placeholder-icon" />} && <Icon name="lock-badge" className="placeholder-icon" />}
{shouldDisplayTimer ? ( {shouldDisplayTimer ? (
<TextTimer langKey={timedPlaceholderLangKey!} endsAt={timedPlaceholderDate!} onEnd={handleTimerEnd} /> <TextTimer langKey={timedPlaceholderLangKey!} endsAt={timedPlaceholderDate!} onEnd={handleTimerEnd} />
) : placeholder} ) : placeholder}

View File

@ -13,6 +13,7 @@ import parseHtmlAsFormattedText from '../../../util/parseHtmlAsFormattedText';
import useLastCallback from '../../../hooks/useLastCallback'; import useLastCallback from '../../../hooks/useLastCallback';
import useOldLang from '../../../hooks/useOldLang'; import useOldLang from '../../../hooks/useOldLang';
import Icon from '../../common/icons/Icon';
import Button from '../../ui/Button'; import Button from '../../ui/Button';
import Checkbox from '../../ui/Checkbox'; import Checkbox from '../../ui/Checkbox';
import InputText from '../../ui/InputText'; import InputText from '../../ui/InputText';
@ -245,7 +246,7 @@ const PollModal: FC<OwnProps> = ({
return ( return (
<div className="modal-header-condensed"> <div className="modal-header-condensed">
<Button round color="translucent" size="smaller" ariaLabel="Cancel poll creation" onClick={onClear}> <Button round color="translucent" size="smaller" ariaLabel="Cancel poll creation" onClick={onClear}>
<i className="icon icon-close" /> <Icon name="close" />
</Button> </Button>
<div className="modal-title">{lang('NewPoll')}</div> <div className="modal-title">{lang('NewPoll')}</div>
<Button <Button
@ -283,7 +284,7 @@ const PollModal: FC<OwnProps> = ({
// eslint-disable-next-line react/jsx-no-bind // eslint-disable-next-line react/jsx-no-bind
onClick={() => removeOption(index)} onClick={() => removeOption(index)}
> >
<i className="icon icon-close" /> <Icon name="close" />
</Button> </Button>
)} )}
</div> </div>

View File

@ -15,6 +15,7 @@ import { useKeyboardNavigation } from './hooks/useKeyboardNavigation';
import Avatar from '../../common/Avatar'; import Avatar from '../../common/Avatar';
import FullNameTitle from '../../common/FullNameTitle'; import FullNameTitle from '../../common/FullNameTitle';
import Icon from '../../common/icons/Icon';
import ListItem from '../../ui/ListItem'; import ListItem from '../../ui/ListItem';
import Menu from '../../ui/Menu'; import Menu from '../../ui/Menu';
@ -123,7 +124,7 @@ const SendAsMenu: FC<OwnProps> = ({
onClick={handleClick} onClick={handleClick}
focus={selectedSendAsIndex === index} focus={selectedSendAsIndex === index}
rightElement={!isCurrentUserPremium && isPremium rightElement={!isCurrentUserPremium && isPremium
&& <i className="icon icon-lock-badge send-as-icon-locked" />} && <Icon name="lock-badge" className="send-as-icon-locked" />}
> >
<Avatar <Avatar
size="small" size="small"

View File

@ -38,6 +38,7 @@ import { useStickerPickerObservers } from '../../common/hooks/useStickerPickerOb
import useAsyncRendering from '../../right/hooks/useAsyncRendering'; import useAsyncRendering from '../../right/hooks/useAsyncRendering';
import Avatar from '../../common/Avatar'; import Avatar from '../../common/Avatar';
import Icon from '../../common/icons/Icon';
import StickerButton from '../../common/StickerButton'; import StickerButton from '../../common/StickerButton';
import StickerSet from '../../common/StickerSet'; import StickerSet from '../../common/StickerSet';
import Button from '../../ui/Button'; import Button from '../../ui/Button';
@ -292,9 +293,9 @@ const StickerPicker: FC<OwnProps & StateProps> = ({
onClick={() => selectStickerSet(index)} onClick={() => selectStickerSet(index)}
> >
{stickerSet.id === RECENT_SYMBOL_SET_ID ? ( {stickerSet.id === RECENT_SYMBOL_SET_ID ? (
<i className="icon icon-recent" /> <Icon name="recent" />
) : stickerSet.id === FAVORITE_SYMBOL_SET_ID ? ( ) : stickerSet.id === FAVORITE_SYMBOL_SET_ID ? (
<i className="icon icon-favorite" /> <Icon name="favorite" />
) : stickerSet.id === CHAT_STICKER_SET_ID ? ( ) : stickerSet.id === CHAT_STICKER_SET_ID ? (
<Avatar peer={chat} size="small" /> <Avatar peer={chat} size="small" />
) : ( ) : (

View File

@ -21,6 +21,7 @@ import useOldLang from '../../../hooks/useOldLang';
import useShowTransitionDeprecated from '../../../hooks/useShowTransitionDeprecated'; import useShowTransitionDeprecated from '../../../hooks/useShowTransitionDeprecated';
import CustomEmojiPicker from '../../common/CustomEmojiPicker'; import CustomEmojiPicker from '../../common/CustomEmojiPicker';
import Icon from '../../common/icons/Icon';
import Button from '../../ui/Button'; import Button from '../../ui/Button';
import Menu from '../../ui/Menu'; import Menu from '../../ui/Menu';
import Portal from '../../ui/Portal'; import Portal from '../../ui/Portal';
@ -270,7 +271,7 @@ const SymbolMenu: FC<OwnProps & StateProps> = ({
size="tiny" size="tiny"
onClick={onClose} onClick={onClose}
> >
<i className="icon icon-close" /> <Icon name="close" />
</Button> </Button>
)} )}
<SymbolMenuFooter <SymbolMenuFooter

View File

@ -11,6 +11,7 @@ import buildClassName from '../../../util/buildClassName';
import useFlag from '../../../hooks/useFlag'; import useFlag from '../../../hooks/useFlag';
import useLastCallback from '../../../hooks/useLastCallback'; import useLastCallback from '../../../hooks/useLastCallback';
import Icon from '../../common/icons/Icon';
import Button from '../../ui/Button'; import Button from '../../ui/Button';
import ResponsiveHoverButton from '../../ui/ResponsiveHoverButton'; import ResponsiveHoverButton from '../../ui/ResponsiveHoverButton';
import Spinner from '../../ui/Spinner'; import Spinner from '../../ui/Spinner';
@ -150,8 +151,8 @@ const SymbolMenuButton: FC<OwnProps> = ({
onClick={isSymbolMenuOpen ? closeSymbolMenu : handleSymbolMenuOpen} onClick={isSymbolMenuOpen ? closeSymbolMenu : handleSymbolMenuOpen}
ariaLabel="Choose emoji, sticker or GIF" ariaLabel="Choose emoji, sticker or GIF"
> >
<i className="icon icon-smile" /> <Icon name="smile" />
<i className="icon icon-keyboard" /> <Icon name="keyboard" />
{isSymbolMenuOpen && !isSymbolMenuLoaded && <Spinner color="gray" />} {isSymbolMenuOpen && !isSymbolMenuLoaded && <Spinner color="gray" />}
</Button> </Button>
) : ( ) : (
@ -163,7 +164,7 @@ const SymbolMenuButton: FC<OwnProps> = ({
ariaLabel="Choose emoji, sticker or GIF" ariaLabel="Choose emoji, sticker or GIF"
> >
<div ref={triggerRef} className="symbol-menu-trigger" /> <div ref={triggerRef} className="symbol-menu-trigger" />
<i className="icon icon-smile" /> <Icon name="smile" />
</ResponsiveHoverButton> </ResponsiveHoverButton>
)} )}

View File

@ -6,6 +6,7 @@ import buildClassName from '../../../util/buildClassName';
import useLastCallback from '../../../hooks/useLastCallback'; import useLastCallback from '../../../hooks/useLastCallback';
import useOldLang from '../../../hooks/useOldLang'; import useOldLang from '../../../hooks/useOldLang';
import Icon from '../../common/icons/Icon';
import Button from '../../ui/Button'; import Button from '../../ui/Button';
type OwnProps = { type OwnProps = {
@ -80,7 +81,7 @@ const SymbolMenuFooter: FC<OwnProps> = ({
color="translucent" color="translucent"
onClick={handleSearchOpen} onClick={handleSearchOpen}
> >
<i className="icon icon-search" /> <Icon name="search" />
</Button> </Button>
)} )}
@ -98,7 +99,7 @@ const SymbolMenuFooter: FC<OwnProps> = ({
faded faded
color="translucent" color="translucent"
> >
<i className="icon icon-delete-left" /> <Icon name="delete-left" />
</Button> </Button>
)} )}
</div> </div>

View File

@ -20,6 +20,7 @@ import useOldLang from '../../../hooks/useOldLang';
import useShowTransitionDeprecated from '../../../hooks/useShowTransitionDeprecated'; import useShowTransitionDeprecated from '../../../hooks/useShowTransitionDeprecated';
import useVirtualBackdrop from '../../../hooks/useVirtualBackdrop'; import useVirtualBackdrop from '../../../hooks/useVirtualBackdrop';
import Icon from '../../common/icons/Icon';
import Button from '../../ui/Button'; import Button from '../../ui/Button';
import './TextFormatter.scss'; import './TextFormatter.scss';
@ -421,7 +422,7 @@ const TextFormatter: FC<OwnProps> = ({
className={getFormatButtonClassName('spoiler')} className={getFormatButtonClassName('spoiler')}
onClick={handleSpoilerText} onClick={handleSpoilerText}
> >
<i className="icon icon-eye-closed" /> <Icon name="eye-closed" />
</Button> </Button>
<div className="TextFormatter-divider" /> <div className="TextFormatter-divider" />
<Button <Button
@ -430,7 +431,7 @@ const TextFormatter: FC<OwnProps> = ({
className={getFormatButtonClassName('bold')} className={getFormatButtonClassName('bold')}
onClick={handleBoldText} onClick={handleBoldText}
> >
<i className="icon icon-bold" /> <Icon name="bold" />
</Button> </Button>
<Button <Button
color="translucent" color="translucent"
@ -438,7 +439,7 @@ const TextFormatter: FC<OwnProps> = ({
className={getFormatButtonClassName('italic')} className={getFormatButtonClassName('italic')}
onClick={handleItalicText} onClick={handleItalicText}
> >
<i className="icon icon-italic" /> <Icon name="italic" />
</Button> </Button>
<Button <Button
color="translucent" color="translucent"
@ -446,7 +447,7 @@ const TextFormatter: FC<OwnProps> = ({
className={getFormatButtonClassName('underline')} className={getFormatButtonClassName('underline')}
onClick={handleUnderlineText} onClick={handleUnderlineText}
> >
<i className="icon icon-underlined" /> <Icon name="underlined" />
</Button> </Button>
<Button <Button
color="translucent" color="translucent"
@ -454,7 +455,7 @@ const TextFormatter: FC<OwnProps> = ({
className={getFormatButtonClassName('strikethrough')} className={getFormatButtonClassName('strikethrough')}
onClick={handleStrikethroughText} onClick={handleStrikethroughText}
> >
<i className="icon icon-strikethrough" /> <Icon name="strikethrough" />
</Button> </Button>
<Button <Button
color="translucent" color="translucent"
@ -462,18 +463,18 @@ const TextFormatter: FC<OwnProps> = ({
className={getFormatButtonClassName('monospace')} className={getFormatButtonClassName('monospace')}
onClick={handleMonospaceText} onClick={handleMonospaceText}
> >
<i className="icon icon-monospace" /> <Icon name="monospace" />
</Button> </Button>
<div className="TextFormatter-divider" /> <div className="TextFormatter-divider" />
<Button color="translucent" ariaLabel={lang('TextFormat.AddLinkTitle')} onClick={openLinkControl}> <Button color="translucent" ariaLabel={lang('TextFormat.AddLinkTitle')} onClick={openLinkControl}>
<i className="icon icon-link" /> <Icon name="link" />
</Button> </Button>
</div> </div>
<div className="TextFormatter-link-control"> <div className="TextFormatter-link-control">
<div className="TextFormatter-buttons"> <div className="TextFormatter-buttons">
<Button color="translucent" ariaLabel={lang('Cancel')} onClick={closeLinkControl}> <Button color="translucent" ariaLabel={lang('Cancel')} onClick={closeLinkControl}>
<i className="icon icon-arrow-left" /> <Icon name="arrow-left" />
</Button> </Button>
<div className="TextFormatter-divider" /> <div className="TextFormatter-divider" />
@ -502,7 +503,7 @@ const TextFormatter: FC<OwnProps> = ({
className="color-primary" className="color-primary"
onClick={handleLinkUrlConfirm} onClick={handleLinkUrlConfirm}
> >
<i className="icon icon-check" /> <Icon name="check" />
</Button> </Button>
</div> </div>
</div> </div>

View File

@ -37,10 +37,6 @@
.bubble { .bubble {
width: auto; width: auto;
} }
.icon-placeholder {
width: 1.5rem;
}
} }
& &-left-icon { & &-left-icon {

View File

@ -25,6 +25,7 @@ import useOldLang from '../../../hooks/useOldLang';
import useShowTransitionDeprecated from '../../../hooks/useShowTransitionDeprecated'; import useShowTransitionDeprecated from '../../../hooks/useShowTransitionDeprecated';
import useSyncEffect from '../../../hooks/useSyncEffect'; import useSyncEffect from '../../../hooks/useSyncEffect';
import Icon from '../../common/icons/Icon';
import Button from '../../ui/Button'; import Button from '../../ui/Button';
import Menu from '../../ui/Menu'; import Menu from '../../ui/Menu';
import MenuItem from '../../ui/MenuItem'; import MenuItem from '../../ui/MenuItem';
@ -219,7 +220,7 @@ const WebPagePreview: FC<OwnProps & StateProps> = ({
<div className={buildClassName('WebPagePreview', transitionClassNames)} ref={ref}> <div className={buildClassName('WebPagePreview', transitionClassNames)} ref={ref}>
<div className="WebPagePreview_inner"> <div className="WebPagePreview_inner">
<div className="WebPagePreview-left-icon" onClick={handlePreviewClick}> <div className="WebPagePreview-left-icon" onClick={handlePreviewClick}>
<i className="icon icon-link" /> <Icon name="link" />
</div> </div>
<WebPage <WebPage
message={messageStub} message={messageStub}
@ -236,7 +237,7 @@ const WebPagePreview: FC<OwnProps & StateProps> = ({
ariaLabel="Clear Webpage Preview" ariaLabel="Clear Webpage Preview"
onClick={handleClearWebpagePreview} onClick={handleClearWebpagePreview}
> >
<i className="icon icon-close" /> <Icon name="close" />
</Button> </Button>
{!isEditing && renderContextMenu()} {!isEditing && renderContextMenu()}
</div> </div>

View File

@ -16,6 +16,7 @@ import useMedia from '../../../hooks/useMedia';
import useOldLang from '../../../hooks/useOldLang'; import useOldLang from '../../../hooks/useOldLang';
import useShowTransitionDeprecated from '../../../hooks/useShowTransitionDeprecated'; import useShowTransitionDeprecated from '../../../hooks/useShowTransitionDeprecated';
import Icon from '../../common/icons/Icon';
import MediaAreaOverlay from '../../story/mediaArea/MediaAreaOverlay'; import MediaAreaOverlay from '../../story/mediaArea/MediaAreaOverlay';
import styles from './BaseStory.module.scss'; import styles from './BaseStory.module.scss';
@ -99,7 +100,7 @@ function BaseStory({
)} )}
{isExpired && ( {isExpired && (
<span> <span>
<i className={buildClassName(styles.expiredIcon, 'icon icon-story-expired')} aria-hidden /> <Icon name="story-expired" className={styles.expiredIcon} />
{lang('StoryExpiredSubtitle')} {lang('StoryExpiredSubtitle')}
</span> </span>
)} )}

View File

@ -14,6 +14,7 @@ import useAsyncRendering from '../../right/hooks/useAsyncRendering';
import AnimatedCounter from '../../common/AnimatedCounter'; import AnimatedCounter from '../../common/AnimatedCounter';
import Avatar from '../../common/Avatar'; import Avatar from '../../common/Avatar';
import Icon from '../../common/icons/Icon';
import Spinner from '../../ui/Spinner'; import Spinner from '../../ui/Spinner';
import './CommentButton.scss'; import './CommentButton.scss';
@ -105,14 +106,14 @@ const CommentButton: FC<OwnProps> = ({
role="button" role="button"
tabIndex={0} tabIndex={0}
> >
<i <Icon
name="comments-sticker"
className={buildClassName( className={buildClassName(
'CommentButton_icon-comments icon icon-comments-sticker', 'CommentButton_icon-comments',
isLoading && shouldRenderLoading && 'CommentButton_hidden', isLoading && shouldRenderLoading && 'CommentButton_hidden',
)} )}
aria-hidden
/> />
{!recentRepliers?.length && <i className="icon icon-comments" aria-hidden />} {!recentRepliers?.length && <Icon name="comments" />}
{renderRecentRepliers()} {renderRecentRepliers()}
<div className="label" dir="auto"> <div className="label" dir="auto">
{messagesCount ? commentsText : lang('LeaveAComment')} {messagesCount ? commentsText : lang('LeaveAComment')}
@ -127,12 +128,12 @@ const CommentButton: FC<OwnProps> = ({
color={isCustomShape ? 'white' : 'blue'} color={isCustomShape ? 'white' : 'blue'}
/> />
) } ) }
<i <Icon
name="next"
className={buildClassName( className={buildClassName(
'CommentButton_icon-open icon icon-next', 'CommentButton_icon-open',
isLoading && shouldRenderLoading && 'CommentButton_hidden', isLoading && shouldRenderLoading && 'CommentButton_hidden',
)} )}
aria-hidden
/> />
</div> </div>
</div> </div>

View File

@ -13,6 +13,7 @@ import useInterval from '../../../hooks/schedulers/useInterval';
import useLastCallback from '../../../hooks/useLastCallback'; import useLastCallback from '../../../hooks/useLastCallback';
import useOldLang from '../../../hooks/useOldLang'; import useOldLang from '../../../hooks/useOldLang';
import Icon from '../../common/icons/Icon';
import MediaSpoiler from '../../common/MediaSpoiler'; import MediaSpoiler from '../../common/MediaSpoiler';
import styles from './InvoiceMediaPreview.module.scss'; import styles from './InvoiceMediaPreview.module.scss';
@ -73,7 +74,7 @@ const InvoiceMediaPreview: FC<OwnProps> = ({
/> />
{Boolean(duration) && <div className={styles.duration}>{formatMediaDuration(duration)}</div>} {Boolean(duration) && <div className={styles.duration}>{formatMediaDuration(duration)}</div>}
<div className={styles.buy}> <div className={styles.buy}>
<i className={buildClassName('icon', 'icon-lock', styles.lock)} /> <Icon name="lock" className={styles.lock} />
{lang('Checkout.PayPrice', formatCurrencyAsString(amount, currency))} {lang('Checkout.PayPrice', formatCurrencyAsString(amount, currency))}
</div> </div>
</div> </div>

View File

@ -11,6 +11,7 @@ import { ARE_CALLS_SUPPORTED } from '../../../util/windowEnvironment';
import useLastCallback from '../../../hooks/useLastCallback'; import useLastCallback from '../../../hooks/useLastCallback';
import useOldLang from '../../../hooks/useOldLang'; import useOldLang from '../../../hooks/useOldLang';
import Icon from '../../common/icons/Icon';
import Button from '../../ui/Button'; import Button from '../../ui/Button';
import styles from './MessagePhoneCall.module.scss'; import styles from './MessagePhoneCall.module.scss';
@ -70,15 +71,14 @@ const MessagePhoneCall: FC<OwnProps> = ({
disabled={!ARE_CALLS_SUPPORTED} disabled={!ARE_CALLS_SUPPORTED}
ariaLabel={lang(isOutgoing ? 'CallAgain' : 'CallBack')} ariaLabel={lang(isOutgoing ? 'CallAgain' : 'CallBack')}
> >
<i className={buildClassName('icon', isVideo ? 'icon-video-outlined' : 'icon-phone')} /> <Icon name={isVideo ? 'video-outlined' : 'phone'} />
</Button> </Button>
<div className={styles.info}> <div className={styles.info}>
<div className={styles.reason}>{lang(reasonText)}</div> <div className={styles.reason}>{lang(reasonText)}</div>
<div className={styles.meta}> <div className={styles.meta}>
<i <Icon
name="arrow-right"
className={buildClassName( className={buildClassName(
'icon',
'icon-arrow-right',
styles.arrow, styles.arrow,
isMissed && styles.missed, isMissed && styles.missed,
isCancelled && styles.canceled, isCancelled && styles.canceled,

View File

@ -25,6 +25,7 @@ import usePreviousDeprecated from '../../../hooks/usePreviousDeprecated';
import useShowTransition from '../../../hooks/useShowTransition'; import useShowTransition from '../../../hooks/useShowTransition';
import useBlurredMediaThumbRef from './hooks/useBlurredMediaThumbRef'; import useBlurredMediaThumbRef from './hooks/useBlurredMediaThumbRef';
import Icon from '../../common/icons/Icon';
import MediaSpoiler from '../../common/MediaSpoiler'; import MediaSpoiler from '../../common/MediaSpoiler';
import ProgressSpinner from '../../ui/ProgressSpinner'; import ProgressSpinner from '../../ui/ProgressSpinner';
@ -242,7 +243,7 @@ const Photo = <T,>({
<ProgressSpinner progress={transferProgress} onClick={isUploading ? handleClick : undefined} /> <ProgressSpinner progress={transferProgress} onClick={isUploading ? handleClick : undefined} />
</div> </div>
)} )}
{shouldRenderDownloadButton && <i ref={downloadButtonRef} className="icon icon-download" />} {shouldRenderDownloadButton && <Icon ref={downloadButtonRef} name="download" />}
<MediaSpoiler <MediaSpoiler
isVisible={isSpoilerShown} isVisible={isSpoilerShown}
withAnimation withAnimation

View File

@ -25,6 +25,7 @@ import useLastCallback from '../../../hooks/useLastCallback';
import useOldLang from '../../../hooks/useOldLang'; import useOldLang from '../../../hooks/useOldLang';
import AvatarList from '../../common/AvatarList'; import AvatarList from '../../common/AvatarList';
import Icon from '../../common/icons/Icon';
import Button from '../../ui/Button'; import Button from '../../ui/Button';
import CheckboxGroup from '../../ui/CheckboxGroup'; import CheckboxGroup from '../../ui/CheckboxGroup';
import RadioGroup from '../../ui/RadioGroup'; import RadioGroup from '../../ui/RadioGroup';
@ -264,7 +265,7 @@ const Poll: FC<OwnProps> = ({
onClick={showSolution} onClick={showSolution}
ariaLabel="Show Solution" ariaLabel="Show Solution"
> >
<i className="icon icon-lamp" /> <Icon name="lamp" />
</Button> </Button>
)} )}
</div> </div>

View File

@ -319,7 +319,7 @@ const RoundVideo: FC<OwnProps> = ({
)} )}
{shouldRenderSpoiler && !shouldRenderSpinner && renderPlayWrapper()} {shouldRenderSpoiler && !shouldRenderSpinner && renderPlayWrapper()}
{!mediaData && !isLoadAllowed && ( {!mediaData && !isLoadAllowed && (
<i className="icon icon-download" /> <Icon name="download" />
)} )}
{!isInOneTimeModal && ( {!isInOneTimeModal && (
<div className="message-media-duration"> <div className="message-media-duration">

View File

@ -183,7 +183,7 @@ function SimilarChannel({ channel }: { channel: ApiChat }) {
<div className={styles.item} onClick={() => openChat({ id: channel.id })}> <div className={styles.item} onClick={() => openChat({ id: channel.id })}>
<Avatar className={styles.avatar} key={channel.id} size="large" peer={channel} /> <Avatar className={styles.avatar} key={channel.id} size="large" peer={channel} />
<div style={`background: ${color}`} className={styles.badge}> <div style={`background: ${color}`} className={styles.badge}>
<i className={buildClassName(styles.icon, 'icon icon-user-filled')} /> <Icon name="user-filled" className={styles.icon} />
<span className={styles.membersCount}>{formatIntegerCompact(channel?.membersCount || 0)} <span className={styles.membersCount}>{formatIntegerCompact(channel?.membersCount || 0)}
</span> </span>
</div> </div>

View File

@ -26,6 +26,7 @@ import usePreviousDeprecated from '../../../hooks/usePreviousDeprecated';
import useShowTransition from '../../../hooks/useShowTransition'; import useShowTransition from '../../../hooks/useShowTransition';
import useBlurredMediaThumbRef from './hooks/useBlurredMediaThumbRef'; import useBlurredMediaThumbRef from './hooks/useBlurredMediaThumbRef';
import Icon from '../../common/icons/Icon';
import MediaSpoiler from '../../common/MediaSpoiler'; import MediaSpoiler from '../../common/MediaSpoiler';
import OptimizedVideo from '../../ui/OptimizedVideo'; import OptimizedVideo from '../../ui/OptimizedVideo';
import ProgressSpinner from '../../ui/ProgressSpinner'; import ProgressSpinner from '../../ui/ProgressSpinner';
@ -271,7 +272,7 @@ const Video = <T,>({
<canvas ref={thumbRef} className="thumbnail" /> <canvas ref={thumbRef} className="thumbnail" />
)} )}
{isProtected && <span className="protector" />} {isProtected && <span className="protector" />}
<i ref={playButtonRef} className="icon icon-large-play" /> <Icon ref={playButtonRef} name="large-play" />
<MediaSpoiler <MediaSpoiler
isVisible={isSpoilerShown} isVisible={isSpoilerShown}
withAnimation withAnimation
@ -289,7 +290,7 @@ const Video = <T,>({
</div> </div>
)} )}
{!isLoadAllowed && !fullMediaData && ( {!isLoadAllowed && !fullMediaData && (
<i className="icon icon-download" /> <Icon name="download" />
)} )}
{isTransferring && (!isUnsupported || isDownloading) ? ( {isTransferring && (!isUnsupported || isDownloading) ? (
<span className="message-transfer-progress"> <span className="message-transfer-progress">
@ -298,7 +299,7 @@ const Video = <T,>({
) : ( ) : (
<div className="message-media-duration"> <div className="message-media-duration">
{!isPaidPreview && video.isGif ? 'GIF' : formatMediaDuration(Math.max(duration - playProgress, 0))} {!isPaidPreview && video.isGif ? 'GIF' : formatMediaDuration(Math.max(duration - playProgress, 0))}
{isUnsupported && <i className="icon icon-message-failed playback-failed" />} {isUnsupported && <Icon name="message-failed" className="playback-failed" />}
</div> </div>
)} )}
</div> </div>

View File

@ -14,6 +14,8 @@ import buildClassName from '../../../../util/buildClassName';
import useLastCallback from '../../../../hooks/useLastCallback'; import useLastCallback from '../../../../hooks/useLastCallback';
import Icon from '../../../common/icons/Icon';
type OwnProps<T> = type OwnProps<T> =
(PhotoProps<T> | VideoProps<T>) & { (PhotoProps<T> | VideoProps<T>) & {
clickArg: number; clickArg: number;
@ -65,7 +67,7 @@ export default function withSelectControl(WrappedComponent: FC) {
{isInSelectMode && ( {isInSelectMode && (
<div className="message-select-control"> <div className="message-select-control">
{isSelected && ( {isSelected && (
<i className="icon icon-select" /> <Icon name="select" />
)} )}
</div> </div>
)} )}

View File

@ -20,6 +20,7 @@ import buildClassName, { createClassNameBuilder } from '../../../../util/buildCl
import useLastCallback from '../../../../hooks/useLastCallback'; import useLastCallback from '../../../../hooks/useLastCallback';
import useOldLang from '../../../../hooks/useOldLang'; import useOldLang from '../../../../hooks/useOldLang';
import Icon from '../../../common/icons/Icon';
import Button from '../../../ui/Button'; import Button from '../../../ui/Button';
import Link from '../../../ui/Link'; import Link from '../../../ui/Link';
import ReactionSelectorCustomReaction from './ReactionSelectorCustomReaction'; import ReactionSelectorCustomReaction from './ReactionSelectorCustomReaction';
@ -228,7 +229,7 @@ const ReactionSelector: FC<OwnProps> = ({
className={cn('show-more')} className={cn('show-more')}
onClick={handleShowMoreClick} onClick={handleShowMoreClick}
> >
<i className="icon icon-down" /> <Icon name="down" />
</Button> </Button>
)} )}
</div> </div>

View File

@ -225,7 +225,6 @@
.icon-check, .icon-placeholder { .icon-check, .icon-placeholder {
margin-left: 0.25rem; margin-left: 0.25rem;
margin-right: 0.25rem; margin-right: 0.25rem;
width: 1.5rem;
} }
} }
} }

View File

@ -6,6 +6,7 @@ import type {
ApiAudio, ApiChat, ApiMessage, ApiPeer, ApiAudio, ApiChat, ApiMessage, ApiPeer,
MediaContent, MediaContent,
} from '../../../api/types'; } from '../../../api/types';
import type { IconName } from '../../../types/icons';
import { PLAYBACK_RATE_FOR_AUDIO_MIN_DURATION } from '../../../config'; import { PLAYBACK_RATE_FOR_AUDIO_MIN_DURATION } from '../../../config';
import { import {
@ -31,6 +32,7 @@ import useOldLang from '../../../hooks/useOldLang';
import useShowTransition from '../../../hooks/useShowTransition'; import useShowTransition from '../../../hooks/useShowTransition';
import useHeaderPane, { type PaneState } from '../hooks/useHeaderPane'; import useHeaderPane, { type PaneState } from '../hooks/useHeaderPane';
import Icon from '../../common/icons/Icon';
import Button from '../../ui/Button'; import Button from '../../ui/Button';
import DropdownMenu from '../../ui/DropdownMenu'; import DropdownMenu from '../../ui/DropdownMenu';
import MenuItem from '../../ui/MenuItem'; import MenuItem from '../../ui/MenuItem';
@ -242,11 +244,11 @@ const AudioPlayer: FC<OwnProps & StateProps> = ({
); );
}); });
const volumeIcon = useMemo(() => { const volumeIcon: IconName = useMemo(() => {
if (volume === 0 || isMuted) return 'icon-muted'; if (volume === 0 || isMuted) return 'muted';
if (volume < 0.3) return 'icon-volume-1'; if (volume < 0.3) return 'volume-1';
if (volume < 0.6) return 'icon-volume-2'; if (volume < 0.6) return 'volume-2';
return 'icon-volume-3'; return 'volume-3';
}, [volume, isMuted]); }, [volume, isMuted]);
if (noUi || !shouldRender) { if (noUi || !shouldRender) {
@ -274,7 +276,7 @@ const AudioPlayer: FC<OwnProps & StateProps> = ({
onClick={requestPreviousTrack} onClick={requestPreviousTrack}
ariaLabel="Previous track" ariaLabel="Previous track"
> >
<i className="icon icon-skip-previous" /> <Icon name="skip-previous" />
</Button> </Button>
<Button <Button
round round
@ -285,8 +287,8 @@ const AudioPlayer: FC<OwnProps & StateProps> = ({
onClick={playPause} onClick={playPause}
ariaLabel={isPlaying ? 'Pause audio' : 'Play audio'} ariaLabel={isPlaying ? 'Pause audio' : 'Play audio'}
> >
<i className="icon icon-play" /> <Icon name="play" />
<i className="icon icon-pause" /> <Icon name="pause" />
</Button> </Button>
<Button <Button
round round
@ -298,7 +300,7 @@ const AudioPlayer: FC<OwnProps & StateProps> = ({
onClick={requestNextTrack} onClick={requestNextTrack}
ariaLabel="Next track" ariaLabel="Next track"
> >
<i className="icon icon-skip-next" /> <Icon name="skip-next" />
</Button> </Button>
<div className="volume-button-wrapper"> <div className="volume-button-wrapper">
@ -311,7 +313,7 @@ const AudioPlayer: FC<OwnProps & StateProps> = ({
onClick={handleVolumeClick} onClick={handleVolumeClick}
ripple={!isMobile} ripple={!isMobile}
> >
<i className={buildClassName('icon', volumeIcon)} /> <Icon name={volumeIcon} />
</Button> </Button>
{!IS_IOS && ( {!IS_IOS && (
@ -349,7 +351,7 @@ const AudioPlayer: FC<OwnProps & StateProps> = ({
onClick={handleClose} onClick={handleClose}
ariaLabel="Close player" ariaLabel="Close player"
> >
<i className="icon icon-close" /> <Icon name="close" />
</Button> </Button>
</div> </div>
); );
@ -389,7 +391,7 @@ function renderPlaybackRateMenuItem(
// eslint-disable-next-line react/jsx-no-bind // eslint-disable-next-line react/jsx-no-bind
onClick={() => onClick(rate)} onClick={() => onClick(rate)}
icon={isSelected ? 'check' : undefined} icon={isSelected ? 'check' : undefined}
customIcon={!isSelected ? <i className="icon icon-placeholder" /> : undefined} customIcon={!isSelected ? <Icon name="placeholder" /> : undefined}
> >
{rate}X {rate}X
</MenuItem> </MenuItem>

View File

@ -19,6 +19,7 @@ import useLastCallback from '../../../hooks/useLastCallback';
import useOldLang from '../../../hooks/useOldLang'; import useOldLang from '../../../hooks/useOldLang';
import AvatarList from '../../common/AvatarList'; import AvatarList from '../../common/AvatarList';
import Icon from '../../common/icons/Icon';
import PeerPicker from '../../common/pickers/PeerPicker'; import PeerPicker from '../../common/pickers/PeerPicker';
import Button from '../../ui/Button'; import Button from '../../ui/Button';
import Modal from '../../ui/Modal'; import Modal from '../../ui/Modal';
@ -133,7 +134,7 @@ const InviteViaLinkModal: FC<OwnProps & StateProps> = ({
ariaLabel={lang('Close')} ariaLabel={lang('Close')}
onClick={handleClose} onClick={handleClose}
> >
<i className="icon icon-close" /> <Icon name="close" />
</Button> </Button>
{premiumSectionText && ( {premiumSectionText && (
<> <>

View File

@ -23,6 +23,7 @@ import useLastCallback from '../../../../hooks/useLastCallback';
import useOldLang from '../../../../hooks/useOldLang'; import useOldLang from '../../../../hooks/useOldLang';
import Avatar from '../../../common/Avatar'; import Avatar from '../../../common/Avatar';
import Icon from '../../../common/icons/Icon';
import SafeLink from '../../../common/SafeLink'; import SafeLink from '../../../common/SafeLink';
import Button from '../../../ui/Button'; import Button from '../../../ui/Button';
import Modal from '../../../ui/Modal'; import Modal from '../../../ui/Modal';
@ -165,7 +166,7 @@ const StarsGiftModal: FC<OwnProps & StateProps> = ({
onClick={() => closeStarsGiftModal()} onClick={() => closeStarsGiftModal()}
ariaLabel={oldLang('Close')} ariaLabel={oldLang('Close')}
> >
<i className="icon icon-close" /> <Icon name="close" />
</Button> </Button>
<div className={buildClassName(styles.header, isHeaderHidden && styles.hiddenHeader)}> <div className={buildClassName(styles.header, isHeaderHidden && styles.hiddenHeader)}>
<h2 className={styles.starHeaderText}> <h2 className={styles.starHeaderText}>

View File

@ -27,6 +27,7 @@ import useLastCallback from '../../hooks/useLastCallback';
import useOldLang from '../../hooks/useOldLang'; import useOldLang from '../../hooks/useOldLang';
import usePreviousDeprecated from '../../hooks/usePreviousDeprecated'; import usePreviousDeprecated from '../../hooks/usePreviousDeprecated';
import Icon from '../common/icons/Icon';
import Button from '../ui/Button'; import Button from '../ui/Button';
import Modal from '../ui/Modal'; import Modal from '../ui/Modal';
import Spinner from '../ui/Spinner'; import Spinner from '../ui/Spinner';
@ -573,10 +574,7 @@ const PaymentModal: FC<OwnProps & StateProps> = ({
onClick={step === PaymentStep.Checkout ? closeModal : handleBackClick} onClick={step === PaymentStep.Checkout ? closeModal : handleBackClick}
ariaLabel="Close" ariaLabel="Close"
> >
<i className={buildClassName( <Icon name={step === PaymentStep.Checkout ? 'close' : 'arrow-left'} />
'icon', step === PaymentStep.Checkout ? 'icon-close' : 'icon-arrow-left',
)}
/>
</Button> </Button>
<h3>{modalHeader}</h3> <h3>{modalHeader}</h3>
</div> </div>

View File

@ -10,6 +10,7 @@ import useFlag from '../../hooks/useFlag';
import useLang from '../../hooks/useLang'; import useLang from '../../hooks/useLang';
import usePrevious from '../../hooks/usePrevious'; import usePrevious from '../../hooks/usePrevious';
import Icon from '../common/icons/Icon';
import Button from '../ui/Button'; import Button from '../ui/Button';
import Modal from '../ui/Modal'; import Modal from '../ui/Modal';
import Checkout from './Checkout'; import Checkout from './Checkout';
@ -66,7 +67,7 @@ const ReceiptModal: FC<OwnProps & StateProps> = ({
onClick={closeModal} onClick={closeModal}
ariaLabel="Close" ariaLabel="Close"
> >
<i className="icon icon-close" /> <Icon name="close" />
</Button> </Button>
<h3> {lang('PaymentReceipt')} </h3> <h3> {lang('PaymentReceipt')} </h3>
</div> </div>

View File

@ -20,6 +20,7 @@ import useHistoryBack from '../../hooks/useHistoryBack';
import useOldLang from '../../hooks/useOldLang'; import useOldLang from '../../hooks/useOldLang';
import usePreviousDeprecated from '../../hooks/usePreviousDeprecated'; import usePreviousDeprecated from '../../hooks/usePreviousDeprecated';
import Icon from '../common/icons/Icon';
import PeerPicker from '../common/pickers/PeerPicker'; import PeerPicker from '../common/pickers/PeerPicker';
import FloatingActionButton from '../ui/FloatingActionButton'; import FloatingActionButton from '../ui/FloatingActionButton';
import Spinner from '../ui/Spinner'; import Spinner from '../ui/Spinner';
@ -142,7 +143,7 @@ const AddChatMembers: FC<OwnProps & StateProps> = ({
{isLoading ? ( {isLoading ? (
<Spinner color="white" /> <Spinner color="white" />
) : ( ) : (
<i className="icon icon-arrow-right" /> <Icon name="arrow-right" />
)} )}
</FloatingActionButton> </FloatingActionButton>
</div> </div>

View File

@ -18,6 +18,7 @@ import useHistoryBack from '../../hooks/useHistoryBack';
import useOldLang from '../../hooks/useOldLang'; import useOldLang from '../../hooks/useOldLang';
import CustomEmojiPicker from '../common/CustomEmojiPicker'; import CustomEmojiPicker from '../common/CustomEmojiPicker';
import Icon from '../common/icons/Icon';
import TopicIcon from '../common/TopicIcon'; import TopicIcon from '../common/TopicIcon';
import FloatingActionButton from '../ui/FloatingActionButton'; import FloatingActionButton from '../ui/FloatingActionButton';
import InputText from '../ui/InputText'; import InputText from '../ui/InputText';
@ -160,7 +161,7 @@ const CreateTopic: FC<OwnProps & StateProps> = ({
{isLoading ? ( {isLoading ? (
<Spinner color="white" /> <Spinner color="white" />
) : ( ) : (
<i className="icon icon-check" /> <Icon name="check" />
)} )}
</FloatingActionButton> </FloatingActionButton>
</div> </div>

View File

@ -18,6 +18,7 @@ import useHistoryBack from '../../hooks/useHistoryBack';
import useOldLang from '../../hooks/useOldLang'; import useOldLang from '../../hooks/useOldLang';
import CustomEmojiPicker from '../common/CustomEmojiPicker'; import CustomEmojiPicker from '../common/CustomEmojiPicker';
import Icon from '../common/icons/Icon';
import TopicIcon from '../common/TopicIcon'; import TopicIcon from '../common/TopicIcon';
import FloatingActionButton from '../ui/FloatingActionButton'; import FloatingActionButton from '../ui/FloatingActionButton';
import InputText from '../ui/InputText'; import InputText from '../ui/InputText';
@ -176,7 +177,7 @@ const EditTopic: FC<OwnProps & StateProps> = ({
{isLoading ? ( {isLoading ? (
<Spinner color="white" /> <Spinner color="white" />
) : ( ) : (
<i className="icon icon-check" /> <Icon name="check" />
)} )}
</FloatingActionButton> </FloatingActionButton>
</div> </div>

View File

@ -83,6 +83,7 @@ import Audio from '../common/Audio';
import Document from '../common/Document'; import Document from '../common/Document';
import UserGift from '../common/gift/UserGift'; import UserGift from '../common/gift/UserGift';
import GroupChatInfo from '../common/GroupChatInfo'; import GroupChatInfo from '../common/GroupChatInfo';
import Icon from '../common/icons/Icon';
import Media from '../common/Media'; import Media from '../common/Media';
import NothingFound from '../common/NothingFound'; import NothingFound from '../common/NothingFound';
import PreviewMedia from '../common/PreviewMedia'; import PreviewMedia from '../common/PreviewMedia';
@ -721,7 +722,7 @@ const Profile: FC<OwnProps & StateProps> = ({
{/* eslint-disable-next-line react/jsx-no-bind */} {/* eslint-disable-next-line react/jsx-no-bind */}
<Button className="show-more-channels" size="smaller" onClick={() => openPremiumModal()}> <Button className="show-more-channels" size="smaller" onClick={() => openPremiumModal()}>
{oldLang('UnlockSimilar')} {oldLang('UnlockSimilar')}
<i className="icon icon-unlock-badge" /> <Icon name="unlock-badge" />
</Button> </Button>
<div className="more-similar"> <div className="more-similar">
{renderText(oldLang('MoreSimilarText', limitSimilarPeers), ['simple_markdown'])} {renderText(oldLang('MoreSimilarText', limitSimilarPeers), ['simple_markdown'])}
@ -760,7 +761,7 @@ const Profile: FC<OwnProps & StateProps> = ({
{/* eslint-disable-next-line react/jsx-no-bind */} {/* eslint-disable-next-line react/jsx-no-bind */}
<Button className="show-more-bots" size="smaller" onClick={() => openPremiumModal()}> <Button className="show-more-bots" size="smaller" onClick={() => openPremiumModal()}>
{lang('UnlockMoreSimilarBots')} {lang('UnlockMoreSimilarBots')}
<i className="icon icon-unlock-badge" /> <Icon name="unlock-badge" />
</Button> </Button>
<div className="more-similar"> <div className="more-similar">
{renderText(lang('MoreSimilarBotsText', { count: limitSimilarPeers }, { {renderText(lang('MoreSimilarBotsText', { count: limitSimilarPeers }, {
@ -829,7 +830,7 @@ const Profile: FC<OwnProps & StateProps> = ({
onClick={handleNewMemberDialogOpen} onClick={handleNewMemberDialogOpen}
ariaLabel={oldLang('lng_channel_add_users')} ariaLabel={oldLang('lng_channel_add_users')}
> >
<i className="icon icon-add-user-filled" /> <Icon name="add-user-filled" />
</FloatingActionButton> </FloatingActionButton>
)} )}
{canDeleteMembers && ( {canDeleteMembers && (

View File

@ -378,7 +378,7 @@ const RightHeader: FC<OwnProps & StateProps> = ({
ariaLabel={lang('Edit')} ariaLabel={lang('Edit')}
onClick={handleEditInviteClick} onClick={handleEditInviteClick}
> >
<i className="icon icon-edit" /> <Icon name="edit" />
</Button> </Button>
)} )}
{currentInviteInfo && currentInviteInfo.isRevoked && ( {currentInviteInfo && currentInviteInfo.isRevoked && (
@ -390,7 +390,7 @@ const RightHeader: FC<OwnProps & StateProps> = ({
ariaLabel={lang('Delete')} ariaLabel={lang('Delete')}
onClick={openDeleteDialog} onClick={openDeleteDialog}
> >
<i className="icon icon-delete" /> <Icon name="delete" />
</Button> </Button>
<ConfirmDialog <ConfirmDialog
isOpen={isDeleteDialogOpen} isOpen={isDeleteDialogOpen}
@ -475,7 +475,7 @@ const RightHeader: FC<OwnProps & StateProps> = ({
ariaLabel={lang('AddContact')} ariaLabel={lang('AddContact')}
onClick={handleAddContact} onClick={handleAddContact}
> >
<i className="icon icon-add-user" aria-hidden /> <Icon name="add-user" />
</Button> </Button>
)} )}
{canManage && !isInsideTopic && ( {canManage && !isInsideTopic && (
@ -486,7 +486,7 @@ const RightHeader: FC<OwnProps & StateProps> = ({
ariaLabel={lang('Edit')} ariaLabel={lang('Edit')}
onClick={handleToggleManagement} onClick={handleToggleManagement}
> >
<i className="icon icon-edit" /> <Icon name="edit" />
</Button> </Button>
)} )}
{canEditBot && ( {canEditBot && (
@ -508,7 +508,7 @@ const RightHeader: FC<OwnProps & StateProps> = ({
ariaLabel={lang('EditTopic')} ariaLabel={lang('EditTopic')}
onClick={toggleEditTopic} onClick={toggleEditTopic}
> >
<i className="icon icon-edit" /> <Icon name="edit" />
</Button> </Button>
)} )}
{canViewStatistics && ( {canViewStatistics && (
@ -519,7 +519,7 @@ const RightHeader: FC<OwnProps & StateProps> = ({
ariaLabel={lang('Statistics')} ariaLabel={lang('Statistics')}
onClick={handleToggleStatistics} onClick={handleToggleStatistics}
> >
<i className="icon icon-stats" /> <Icon name="stats" />
</Button> </Button>
)} )}
</section> </section>

View File

@ -20,6 +20,7 @@ import useHistoryBack from '../../../hooks/useHistoryBack';
import useMedia from '../../../hooks/useMedia'; import useMedia from '../../../hooks/useMedia';
import useOldLang from '../../../hooks/useOldLang'; import useOldLang from '../../../hooks/useOldLang';
import Icon from '../../common/icons/Icon';
import AvatarEditable from '../../ui/AvatarEditable'; import AvatarEditable from '../../ui/AvatarEditable';
import ConfirmDialog from '../../ui/ConfirmDialog'; import ConfirmDialog from '../../ui/ConfirmDialog';
import FloatingActionButton from '../../ui/FloatingActionButton'; import FloatingActionButton from '../../ui/FloatingActionButton';
@ -331,7 +332,7 @@ const ManageChannel: FC<OwnProps & StateProps> = ({
{isLoading ? ( {isLoading ? (
<Spinner color="white" /> <Spinner color="white" />
) : ( ) : (
<i className="icon icon-check" /> <Icon name="check" />
)} )}
</FloatingActionButton> </FloatingActionButton>
<ConfirmDialog <ConfirmDialog

Some files were not shown because too many files have changed in this diff Show More