Avatar: Finally remove animated avatars (#3061)

This commit is contained in:
Alexander Zinchuk 2023-04-25 17:24:08 +04:00
parent 920b046d2e
commit 27203e9976
34 changed files with 76 additions and 274 deletions

View File

@ -4,10 +4,10 @@ import type { FC } from '../../../lib/teact/teact';
import React, { memo, useMemo, useRef } from '../../../lib/teact/teact';
import { withGlobal } from '../../../global';
import type { ApiChat, ApiPhoto, ApiUser } from '../../../api/types';
import type { ApiChat, ApiUser } from '../../../api/types';
import buildClassName from '../../../util/buildClassName';
import { selectChat, selectUser, selectUserPhotoFromFullInfo } from '../../../global/selectors';
import { selectChat, selectUser } from '../../../global/selectors';
import useLang from '../../../hooks/useLang';
import { GROUP_CALL_DEFAULT_VOLUME, GROUP_CALL_VOLUME_MULTIPLIER } from '../../../config';
@ -23,7 +23,6 @@ type OwnProps = {
type StateProps = {
user?: ApiUser;
userProfilePhoto?: ApiPhoto;
chat?: ApiChat;
};
@ -31,7 +30,6 @@ const GroupCallParticipant: FC<OwnProps & StateProps> = ({
openParticipantMenu,
participant,
user,
userProfilePhoto,
chat,
}) => {
// eslint-disable-next-line no-null/no-null
@ -81,7 +79,7 @@ const GroupCallParticipant: FC<OwnProps & StateProps> = ({
onClick={handleOnClick}
ref={anchorRef}
>
<Avatar user={user} chat={chat} userProfilePhoto={userProfilePhoto} size="medium" />
<Avatar user={user} chat={chat} size="medium" />
<div className="info">
<span className="name">{name}</span>
<span className={buildClassName('about', aboutColor)}>{aboutText}</span>
@ -98,7 +96,6 @@ export default memo(withGlobal<OwnProps>(
return {
user: participant.isUser ? selectUser(global, participant.id) : undefined,
chat: !participant.isUser ? selectChat(global, participant.id) : undefined,
userProfilePhoto: participant.isUser ? selectUserPhotoFromFullInfo(global, participant.id) : undefined,
};
},
)(GroupCallParticipant));

View File

@ -4,11 +4,11 @@ import type { FC } from '../../../lib/teact/teact';
import React, { memo, useCallback } from '../../../lib/teact/teact';
import { withGlobal } from '../../../global';
import type { ApiChat, ApiPhoto, ApiUser } from '../../../api/types';
import type { ApiChat, ApiUser } from '../../../api/types';
import { GROUP_CALL_THUMB_VIDEO_DISABLED } from '../../../config';
import buildClassName from '../../../util/buildClassName';
import { selectChat, selectUser, selectUserPhotoFromFullInfo } from '../../../global/selectors';
import { selectChat, selectUser } from '../../../global/selectors';
import useLang from '../../../hooks/useLang';
import Avatar from '../../common/Avatar';
@ -25,7 +25,6 @@ type OwnProps = {
type StateProps = {
user?: ApiUser;
chat?: ApiChat;
userProfilePhoto?: ApiPhoto;
currentUserId?: string;
isActive?: boolean;
};
@ -35,7 +34,6 @@ const GroupCallParticipantVideo: FC<OwnProps & StateProps> = ({
onClick,
user,
chat,
userProfilePhoto,
isActive,
isFullscreen,
}) => {
@ -62,7 +60,7 @@ const GroupCallParticipantVideo: FC<OwnProps & StateProps> = ({
{lang('Back')}
</button>
)}
<Avatar user={user} chat={chat} userProfilePhoto={userProfilePhoto} className="thumbnail-avatar" />
<Avatar user={user} chat={chat} className="thumbnail-avatar" />
{!GROUP_CALL_THUMB_VIDEO_DISABLED && (
<div className="thumbnail-wrapper">
<video className="thumbnail" muted autoPlay playsInline srcObject={streams?.[type]} />
@ -84,7 +82,6 @@ export default memo(withGlobal<OwnProps>(
currentUserId: global.currentUserId,
user: participant.isUser ? selectUser(global, participant.id) : undefined,
chat: !participant.isUser ? selectChat(global, participant.id) : undefined,
userProfilePhoto: participant.isUser ? selectUserPhotoFromFullInfo(global, participant.id) : undefined,
isActive: (participant.amplitude || 0) > THRESHOLD,
};
},

View File

@ -14,7 +14,6 @@ import useLang from '../../../hooks/useLang';
import Button from '../../ui/Button';
import Avatar from '../../common/Avatar';
import UserAvatar from '../../common/UserAvatar';
import './GroupCallTopPane.scss';
@ -113,11 +112,14 @@ const GroupCallTopPane: FC<OwnProps & StateProps> = ({
<div className="avatars">
{fetchedParticipants.map((p) => {
if (!p) return undefined;
if (p.user) {
return <UserAvatar key={p.user.id} user={p.user} />;
} else {
return <Avatar key={p.chat.id} chat={p.chat} animationLevel={animationLevel} />;
}
return (
<Avatar
key={p.user ? p.user.id : p.chat.id}
chat={p.chat}
user={p.user}
animationLevel={animationLevel}
/>
);
})}
</div>
<Button round className="join">

View File

@ -5,7 +5,7 @@ import React, {
import { getActions, withGlobal } from '../../../global';
import '../../../global/actions/calls';
import type { ApiPhoneCall, ApiPhoto, ApiUser } from '../../../api/types';
import type { ApiPhoneCall, ApiUser } from '../../../api/types';
import type { AnimationLevel } from '../../../types';
import {
@ -14,7 +14,7 @@ import {
IS_REQUEST_FULLSCREEN_SUPPORTED,
} from '../../../util/windowEnvironment';
import { LOCAL_TGS_URLS } from '../../common/helpers/animatedAssets';
import { selectTabState, selectUserPhotoFromFullInfo } from '../../../global/selectors';
import { selectTabState } from '../../../global/selectors';
import buildClassName from '../../../util/buildClassName';
import { selectPhoneCallUser } from '../../../global/selectors/calls';
import useLang from '../../../hooks/useLang';
@ -39,7 +39,6 @@ import styles from './PhoneCall.module.scss';
type StateProps = {
user?: ApiUser;
phoneCall?: ApiPhoneCall;
userProfilePhoto?: ApiPhoto;
isOutgoing: boolean;
isCallPanelVisible?: boolean;
animationLevel: AnimationLevel;
@ -47,7 +46,6 @@ type StateProps = {
const PhoneCall: FC<StateProps> = ({
user,
userProfilePhoto,
isOutgoing,
phoneCall,
isCallPanelVisible,
@ -240,7 +238,6 @@ const PhoneCall: FC<StateProps> = ({
>
<Avatar
user={user}
userProfilePhoto={userProfilePhoto}
size="jumbo"
className={hasVideo || hasPresentation ? styles.blurred : ''}
withVideo
@ -376,12 +373,10 @@ export default memo(withGlobal(
const { phoneCall, currentUserId } = global;
const { isCallPanelVisible, isMasterTab } = selectTabState(global);
const user = selectPhoneCallUser(global);
const userProfilePhoto = user ? selectUserPhotoFromFullInfo(global, user.id) : undefined;
return {
isCallPanelVisible: Boolean(isCallPanelVisible),
user,
userProfilePhoto,
isOutgoing: phoneCall?.adminId === currentUserId,
phoneCall: isMasterTab ? phoneCall : undefined,
animationLevel: global.settings.byKey.animationLevel,

View File

@ -1,8 +1,7 @@
import type { MouseEvent as ReactMouseEvent } from 'react';
import React, {
memo, useCallback, useEffect, useMemo, useRef,
memo, useCallback, useMemo, useRef,
} from '../../lib/teact/teact';
import { getActions } from '../../global';
import type { FC, TeactNode } from '../../lib/teact/teact';
import type {
@ -49,7 +48,6 @@ type OwnProps = {
chat?: ApiChat;
user?: ApiUser;
photo?: ApiPhoto;
userProfilePhoto?: ApiPhoto;
userStatus?: ApiUserStatus;
text?: string;
isSavedMessages?: boolean;
@ -70,7 +68,6 @@ const Avatar: FC<OwnProps> = ({
chat,
user,
photo,
userProfilePhoto,
userStatus,
text,
isSavedMessages,
@ -84,7 +81,6 @@ const Avatar: FC<OwnProps> = ({
observeIntersection,
onClick,
}) => {
const { loadFullUser } = getActions();
// eslint-disable-next-line no-null/no-null
const ref = useRef<HTMLDivElement>(null);
const videoLoopCountRef = useRef(0);
@ -98,9 +94,8 @@ const Avatar: FC<OwnProps> = ({
withVideo && !VIDEO_AVATARS_DISABLED && animationLevel === ANIMATION_LEVEL_MAX
&& user?.isPremium && user?.hasVideoAvatar
);
const hasProfileVideo = userProfilePhoto?.isVideo;
const isIntersectingForVideo = useIsIntersecting(
ref, canShowVideo && hasProfileVideo ? observeIntersection : undefined,
ref, canShowVideo ? observeIntersection : undefined,
);
const shouldLoadVideo = isIntersectingForVideo && (canShowVideo || (forceVideo && photo?.isVideo));
@ -116,10 +111,6 @@ const Avatar: FC<OwnProps> = ({
videoHash = `videoAvatar${photo.id}?size=u`;
}
}
if (hasProfileVideo) {
videoHash = getChatAvatarHash(user!, undefined, 'video', undefined, userProfilePhoto);
}
}
const imgBlobUrl = useMedia(imageHash, false, ApiMediaFormat.BlobUrl, lastSyncTime);
@ -148,13 +139,6 @@ const Avatar: FC<OwnProps> = ({
}
}, [loopIndefinitely, noLoop, videoBlobUrl]);
const userId = user?.id;
useEffect(() => {
if (userId && canShowVideo && !userProfilePhoto) {
loadFullUser({ userId });
}
}, [loadFullUser, userProfilePhoto, userId, canShowVideo]);
const lang = useLang();
let content: TeactNode | undefined;

View File

@ -2,9 +2,9 @@ import React, { memo } from '../../lib/teact/teact';
import { withGlobal } from '../../global';
import type { FC, TeactNode } from '../../lib/teact/teact';
import type { ApiChat, ApiPhoto, ApiUser } from '../../api/types';
import type { ApiChat, ApiUser } from '../../api/types';
import { selectChat, selectUser, selectUserPhotoFromFullInfo } from '../../global/selectors';
import { selectChat, selectUser } from '../../global/selectors';
import { getChatTitle, getUserFirstOrLastName, isUserId } from '../../global/helpers';
import renderText from './helpers/renderText';
import buildClassName from '../../util/buildClassName';
@ -28,7 +28,6 @@ type OwnProps = {
type StateProps = {
chat?: ApiChat;
user?: ApiUser;
userProfilePhoto?: ApiPhoto;
currentUserId?: string;
};
@ -40,7 +39,6 @@ const PickerSelectedItem: FC<OwnProps & StateProps> = ({
clickArg,
chat,
user,
userProfilePhoto,
className,
currentUserId,
onClick,
@ -63,7 +61,6 @@ const PickerSelectedItem: FC<OwnProps & StateProps> = ({
<Avatar
chat={chat}
user={user}
userProfilePhoto={userProfilePhoto}
size="small"
isSavedMessages={user?.isSelf}
/>
@ -114,12 +111,10 @@ export default memo(withGlobal<OwnProps>(
const chat = chatOrUserId ? selectChat(global, chatOrUserId) : undefined;
const user = isUserId(chatOrUserId) ? selectUser(global, chatOrUserId) : undefined;
const userProfilePhoto = user ? selectUserPhotoFromFullInfo(global, user.id) : undefined;
return {
chat,
user,
userProfilePhoto,
currentUserId: global.currentUserId,
};
},

View File

@ -5,15 +5,13 @@ import { getActions, withGlobal } from '../../global';
import type { FC } from '../../lib/teact/teact';
import type {
ApiUser, ApiTypingStatus, ApiUserStatus, ApiChatMember, ApiPhoto,
ApiUser, ApiTypingStatus, ApiUserStatus, ApiChatMember,
} from '../../api/types';
import type { GlobalState } from '../../global/types';
import type { AnimationLevel } from '../../types';
import { MediaViewerOrigin } from '../../types';
import {
selectChatMessages, selectUser, selectUserPhotoFromFullInfo, selectUserStatus,
} from '../../global/selectors';
import { selectChatMessages, selectUser, selectUserStatus } from '../../global/selectors';
import { getMainUsername, getUserStatus, isUserOnline } from '../../global/helpers';
import buildClassName from '../../util/buildClassName';
import renderText from './helpers/renderText';
@ -47,7 +45,6 @@ type StateProps =
{
user?: ApiUser;
userStatus?: ApiUserStatus;
userProfilePhoto?: ApiPhoto;
isSavedMessages?: boolean;
animationLevel: AnimationLevel;
areMessagesLoaded: boolean;
@ -69,7 +66,6 @@ const PrivateChatInfo: FC<OwnProps & StateProps> = ({
noRtl,
user,
userStatus,
userProfilePhoto,
isSavedMessages,
areMessagesLoaded,
animationLevel,
@ -175,7 +171,6 @@ const PrivateChatInfo: FC<OwnProps & StateProps> = ({
key={user.id}
size={avatarSize}
user={user}
userProfilePhoto={userProfilePhoto}
isSavedMessages={isSavedMessages}
onClick={withMediaViewer ? handleAvatarViewerOpen : undefined}
withVideo={withVideoAvatar}
@ -196,13 +191,11 @@ export default memo(withGlobal<OwnProps>(
const userStatus = selectUserStatus(global, userId);
const isSavedMessages = !forceShowSelf && user && user.isSelf;
const areMessagesLoaded = Boolean(selectChatMessages(global, userId));
const userProfilePhoto = user ? selectUserPhotoFromFullInfo(global, user.id) : undefined;
return {
lastSyncTime,
user,
userStatus,
userProfilePhoto,
isSavedMessages,
areMessagesLoaded,
animationLevel: global.settings.byKey.animationLevel,

View File

@ -59,7 +59,7 @@ const ProfilePhoto: FC<OwnProps> = ({
const canHaveMedia = userOrChat && !isSavedMessages && !isDeleted && !isRepliesChat;
const { isVideo } = photo || {};
const avatarHash = canHaveMedia && getChatAvatarHash(userOrChat, 'normal', 'photo');
const avatarHash = canHaveMedia && getChatAvatarHash(userOrChat, 'normal');
const avatarBlobUrl = useMedia(avatarHash, undefined, undefined, lastSyncTime);
const photoHash = canHaveMedia && photo && !isVideo && `photo${photo.id}?size=c`;

View File

@ -1,51 +0,0 @@
import React, { memo } from '../../lib/teact/teact';
import { withGlobal } from '../../global';
import type { FC } from '../../lib/teact/teact';
import type { ApiPhoto, ApiUser } from '../../api/types';
import type { AnimationLevel } from '../../types';
import { selectUserPhotoFromFullInfo } from '../../global/selectors';
import Avatar from './Avatar';
type OwnProps = {
user?: ApiUser;
withVideo?: boolean;
className?: string;
size?: 'micro' | 'tiny' | 'small' | 'medium' | 'large';
};
interface StateProps {
profilePhoto?: ApiPhoto;
animationLevel?: AnimationLevel;
}
const UserAvatar: FC<OwnProps & StateProps> = ({
user,
profilePhoto,
className,
animationLevel,
withVideo,
size,
}) => {
return (
<Avatar
user={user}
className={className}
userProfilePhoto={profilePhoto}
animationLevel={animationLevel}
withVideo={withVideo}
size={size}
/>
);
};
export default memo(withGlobal<OwnProps>(
(global, { user }): StateProps => {
return {
profilePhoto: user ? selectUserPhotoFromFullInfo(global, user.id) : undefined,
animationLevel: global.settings.byKey.animationLevel,
};
},
)(UserAvatar));

View File

@ -8,7 +8,6 @@ import type {
ApiFormattedText,
ApiMessage,
ApiMessageOutgoingStatus,
ApiPhoto,
ApiTopic,
ApiTypingStatus,
ApiUser,
@ -37,7 +36,6 @@ import {
selectThreadParam,
selectTopicFromMessage,
selectUser,
selectUserPhotoFromFullInfo,
selectUserStatus,
} from '../../../global/selectors';
import buildClassName from '../../../util/buildClassName';
@ -78,7 +76,6 @@ type StateProps = {
isMuted?: boolean;
user?: ApiUser;
userStatus?: ApiUserStatus;
userProfilePhoto?: ApiPhoto;
actionTargetUserIds?: string[];
actionTargetMessage?: ApiMessage;
actionTargetChatId?: string;
@ -106,7 +103,6 @@ const Chat: FC<OwnProps & StateProps> = ({
isMuted,
user,
userStatus,
userProfilePhoto,
actionTargetUserIds,
lastMessageSender,
lastMessageOutgoingStatus,
@ -240,7 +236,6 @@ const Chat: FC<OwnProps & StateProps> = ({
<Avatar
chat={chat}
user={user}
userProfilePhoto={userProfilePhoto}
userStatus={userStatus}
isSavedMessages={user?.isSelf}
lastSyncTime={lastSyncTime}
@ -330,7 +325,6 @@ export default memo(withGlobal<OwnProps>(
const user = privateChatUserId ? selectUser(global, privateChatUserId) : undefined;
const userStatus = privateChatUserId ? selectUserStatus(global, privateChatUserId) : undefined;
const userProfilePhoto = user ? selectUserPhotoFromFullInfo(global, user.id) : undefined;
const lastMessageTopic = chat.lastMessage && selectTopicFromMessage(global, chat.lastMessage);
const typingStatus = selectThreadParam(global, chatId, MAIN_THREAD_ID, 'typingStatus');
@ -354,7 +348,6 @@ export default memo(withGlobal<OwnProps>(
}),
user,
userStatus,
userProfilePhoto,
lastMessageTopic,
typingStatus,
};

View File

@ -3,7 +3,7 @@ import React, { memo, useCallback } from '../../../lib/teact/teact';
import { getActions, withGlobal } from '../../../global';
import type {
ApiChat, ApiUser, ApiMessage, ApiMessageOutgoingStatus, ApiPhoto,
ApiChat, ApiUser, ApiMessage, ApiMessageOutgoingStatus,
} from '../../../api/types';
import type { AnimationLevel } from '../../../types';
import type { LangFn } from '../../../hooks/useLang';
@ -17,7 +17,7 @@ import {
getMessageSticker,
getMessageIsSpoiler,
} from '../../../global/helpers';
import { selectChat, selectUser, selectUserPhotoFromFullInfo } from '../../../global/selectors';
import { selectChat, selectUser } from '../../../global/selectors';
import buildClassName from '../../../util/buildClassName';
import { formatPastTimeShort } from '../../../util/dateFormat';
import { renderMessageSummary } from '../../common/helpers/renderMessageText';
@ -43,7 +43,6 @@ type OwnProps = {
type StateProps = {
chat?: ApiChat;
privateChatUser?: ApiUser;
userProfilePhoto?: ApiPhoto;
lastMessageOutgoingStatus?: ApiMessageOutgoingStatus;
lastSyncTime?: number;
animationLevel?: AnimationLevel;
@ -55,7 +54,6 @@ const ChatMessage: FC<OwnProps & StateProps> = ({
chatId,
chat,
privateChatUser,
userProfilePhoto,
animationLevel,
lastSyncTime,
}) => {
@ -88,7 +86,6 @@ const ChatMessage: FC<OwnProps & StateProps> = ({
<Avatar
chat={chat}
user={privateChatUser}
userProfilePhoto={userProfilePhoto}
isSavedMessages={privateChatUser?.isSelf}
lastSyncTime={lastSyncTime}
withVideo
@ -151,16 +148,12 @@ export default memo(withGlobal<OwnProps>(
const privateChatUserId = getPrivateChatUserId(chat);
const privateChatUser = privateChatUserId ? selectUser(global, privateChatUserId) : undefined;
const userProfilePhoto = privateChatUser ? selectUserPhotoFromFullInfo(global, privateChatUser.id) : undefined;
return {
chat,
lastSyncTime: global.lastSyncTime,
animationLevel: global.settings.byKey.animationLevel,
...(privateChatUserId && {
privateChatUser,
userProfilePhoto,
}),
...(privateChatUserId && { privateChatUser }),
};
},
)(ChatMessage));

View File

@ -5,6 +5,7 @@ import React, {
import { getActions, withGlobal } from '../../../global';
import type { ApiUser } from '../../../api/types';
import type { AnimationLevel } from '../../../types';
import { getUserFirstOrLastName } from '../../../global/helpers';
import renderText from '../../common/helpers/renderText';
@ -14,7 +15,7 @@ import useLang from '../../../hooks/useLang';
import Button from '../../ui/Button';
import LeftSearchResultChat from './LeftSearchResultChat';
import UserAvatar from '../../common/UserAvatar';
import Avatar from '../../common/Avatar';
import './RecentContacts.scss';
@ -26,6 +27,7 @@ type StateProps = {
topUserIds?: string[];
usersById: Record<string, ApiUser>;
recentlyFoundChatIds?: string[];
animationLevel: AnimationLevel;
};
const SEARCH_CLOSE_TIMEOUT_MS = 250;
@ -37,6 +39,7 @@ const RecentContacts: FC<OwnProps & StateProps> = ({
topUserIds,
usersById,
recentlyFoundChatIds,
animationLevel,
onReset,
}) => {
const {
@ -83,7 +86,7 @@ const RecentContacts: FC<OwnProps & StateProps> = ({
onClick={() => handleClick(userId)}
dir={lang.isRtl ? 'rtl' : undefined}
>
<UserAvatar user={usersById[userId]} withVideo />
<Avatar user={usersById[userId]} animationLevel={animationLevel} withVideo />
<div className="top-peer-name">{renderText(getUserFirstOrLastName(usersById[userId]) || NBSP)}</div>
</div>
))}
@ -123,11 +126,13 @@ export default memo(withGlobal<OwnProps>(
const { userIds: topUserIds } = global.topPeers;
const usersById = global.users.byId;
const { recentlyFoundChatIds } = global;
const { animationLevel } = global.settings.byKey;
return {
topUserIds,
usersById,
recentlyFoundChatIds,
animationLevel,
};
},
)(RecentContacts));

View File

@ -3,10 +3,9 @@ import { getActions, withGlobal } from '../../../global';
import type { FC } from '../../../lib/teact/teact';
import type { AnimationLevel } from '../../../types';
import type { ApiPhoto, ApiUser, ApiWebSession } from '../../../api/types';
import type { ApiUser, ApiWebSession } from '../../../api/types';
import buildClassName from '../../../util/buildClassName';
import { selectUserPhotoFromFullInfo } from '../../../global/selectors';
import useLang from '../../../hooks/useLang';
import useCurrentOrPrev from '../../../hooks/useCurrentOrPrev';
@ -27,7 +26,6 @@ type OwnProps = {
type StateProps = {
session?: ApiWebSession;
bot?: ApiUser;
botProfilePhoto?: ApiPhoto;
animationLevel: AnimationLevel;
};
@ -35,7 +33,6 @@ const SettingsActiveWebsite: FC<OwnProps & StateProps> = ({
isOpen,
session,
bot,
botProfilePhoto,
animationLevel,
onClose,
}) => {
@ -44,7 +41,6 @@ const SettingsActiveWebsite: FC<OwnProps & StateProps> = ({
const renderingSession = useCurrentOrPrev(session, true);
const renderingBot = useCurrentOrPrev(bot, true);
const renderingBotProfilePhoto = useCurrentOrPrev(botProfilePhoto, true);
const handleTerminateSessionClick = useCallback(() => {
terminateWebAuthorization({ hash: session!.hash });
@ -83,7 +79,6 @@ const SettingsActiveWebsite: FC<OwnProps & StateProps> = ({
<Avatar
className={styles.avatar}
user={renderingBot}
userProfilePhoto={renderingBotProfilePhoto}
size="large"
animationLevel={animationLevel}
withVideo
@ -113,12 +108,10 @@ const SettingsActiveWebsite: FC<OwnProps & StateProps> = ({
export default memo(withGlobal<OwnProps>((global, { hash }): StateProps => {
const session = hash ? global.activeWebSessions.byHash[hash] : undefined;
const bot = session ? global.users.byId[session.botId] : undefined;
const botProfilePhoto = bot ? selectUserPhotoFromFullInfo(global, bot.id) : undefined;
return {
session,
bot,
botProfilePhoto,
animationLevel: global.settings.byKey.animationLevel,
};
})(SettingsActiveWebsite));

View File

@ -5,6 +5,7 @@ import { getActions, getGlobal, withGlobal } from '../../../global';
import type { FC } from '../../../lib/teact/teact';
import type { ApiWebSession } from '../../../api/types';
import type { AnimationLevel } from '../../../types';
import { formatPastTimeShort } from '../../../util/dateFormat';
import buildClassName from '../../../util/buildClassName';
@ -16,7 +17,7 @@ import useHistoryBack from '../../../hooks/useHistoryBack';
import ListItem from '../../ui/ListItem';
import ConfirmDialog from '../../ui/ConfirmDialog';
import SettingsActiveWebsite from './SettingsActiveWebsite';
import UserAvatar from '../../common/UserAvatar';
import Avatar from '../../common/Avatar';
import FullNameTitle from '../../common/FullNameTitle';
import styles from './SettingsActiveWebsites.module.scss';
@ -29,12 +30,14 @@ type OwnProps = {
type StateProps = {
byHash: Record<string, ApiWebSession>;
orderedHashes: string[];
animationLevel: AnimationLevel;
};
const SettingsActiveWebsites: FC<OwnProps & StateProps> = ({
isActive,
byHash,
orderedHashes,
animationLevel,
onReset,
}) => {
const {
@ -110,7 +113,7 @@ const SettingsActiveWebsites: FC<OwnProps & StateProps> = ({
// eslint-disable-next-line react/jsx-no-bind
onClick={() => handleOpenSessionModal(session.hash)}
>
<UserAvatar className={styles.avatar} user={bot} size="tiny" withVideo />
<Avatar className={styles.avatar} user={bot} size="tiny" withVideo animationLevel={animationLevel} />
<div className="multiline-menu-item full-size" dir="auto">
<span className="date">{formatPastTimeShort(lang, session.dateActive * 1000)}</span>
{bot && <FullNameTitle className={styles.title} peer={bot} />}
@ -161,6 +164,7 @@ export default memo(withGlobal<OwnProps>(
return {
byHash,
orderedHashes,
animationLevel: global.settings.byKey.animationLevel,
};
},
)(SettingsActiveWebsites));

View File

@ -1,13 +1,12 @@
import type { FC } from '../../../lib/teact/teact';
import React, { memo, useCallback, useMemo } from '../../../lib/teact/teact';
import { getActions, getGlobal, withGlobal } from '../../../global';
import { getActions, withGlobal } from '../../../global';
import type { ApiChat, ApiCountryCode, ApiUser } from '../../../api/types';
import { CHAT_HEIGHT_PX } from '../../../config';
import { formatPhoneNumberWithCode } from '../../../util/phoneNumber';
import { getMainUsername, isUserId } from '../../../global/helpers';
import { selectUserPhotoFromFullInfo } from '../../../global/selectors';
import buildClassName from '../../../util/buildClassName';
import useLang from '../../../hooks/useLang';
import useHistoryBack from '../../../hooks/useHistoryBack';
@ -99,7 +98,6 @@ const SettingsPrivacyBlockedUsers: FC<OwnProps & StateProps> = ({
size="medium"
user={user}
chat={chat}
userProfilePhoto={user ? selectUserPhotoFromFullInfo(getGlobal(), user.id) : undefined}
/>
<div className="contact-info" dir="auto">
{userOrChat && <FullNameTitle peer={userOrChat} />}

View File

@ -4,13 +4,11 @@ import React, {
} from '../../lib/teact/teact';
import { getActions, withGlobal } from '../../global';
import type {
ApiCountryCode, ApiPhoto, ApiUser, ApiUserStatus,
} from '../../api/types';
import type { ApiCountryCode, ApiUser, ApiUserStatus } from '../../api/types';
import { IS_TOUCH_ENV } from '../../util/windowEnvironment';
import { getUserStatus } from '../../global/helpers';
import { selectUser, selectUserPhotoFromFullInfo, selectUserStatus } from '../../global/selectors';
import { selectUser, selectUserStatus } from '../../global/selectors';
import renderText from '../common/helpers/renderText';
import { formatPhoneNumberWithCode } from '../../util/phoneNumber';
import useLang from '../../hooks/useLang';
@ -36,7 +34,6 @@ export type OwnProps = {
type StateProps = {
user?: ApiUser;
userStatus?: ApiUserStatus;
userProfilePhoto?: ApiPhoto;
phoneCodeList: ApiCountryCode[];
};
@ -46,14 +43,12 @@ const NewContactModal: FC<OwnProps & StateProps> = ({
isByPhoneNumber,
user,
userStatus,
userProfilePhoto,
phoneCodeList,
}) => {
const { updateContact, importContact, closeNewContactDialog } = getActions();
const lang = useLang();
const renderingUser = useCurrentOrPrev(user);
const renderingUserProfilePhoto = useCurrentOrPrev(userProfilePhoto);
const renderingIsByPhoneNumber = useCurrentOrPrev(isByPhoneNumber);
// eslint-disable-next-line no-null/no-null
const inputRef = useRef<HTMLInputElement>(null);
@ -128,7 +123,6 @@ const NewContactModal: FC<OwnProps & StateProps> = ({
<Avatar
size="jumbo"
user={renderingUser}
userProfilePhoto={renderingUserProfilePhoto}
text={`${firstName} ${lastName}`}
/>
<div className="NewContactModal__profile-info">
@ -241,7 +235,6 @@ export default memo(withGlobal<OwnProps>(
return {
user,
userStatus: userId ? selectUserStatus(global, userId) : undefined,
userProfilePhoto: user ? selectUserPhotoFromFullInfo(global, user.id) : undefined,
phoneCodeList: global.countryList.phoneCodes,
};
},

View File

@ -4,7 +4,7 @@ import React, {
import { getActions, withGlobal } from '../../../global';
import type { FC } from '../../../lib/teact/teact';
import type { ApiPhoto, ApiPremiumGiftOption, ApiUser } from '../../../api/types';
import type { ApiPremiumGiftOption, ApiUser } from '../../../api/types';
import type { AnimationLevel } from '../../../types';
import { formatCurrency } from '../../../util/formatCurrency';
@ -14,7 +14,6 @@ import {
selectTabState,
selectUser,
selectUserFullInfo,
selectUserPhotoFromFullInfo,
} from '../../../global/selectors';
import useCurrentOrPrev from '../../../hooks/useCurrentOrPrev';
@ -34,7 +33,6 @@ export type OwnProps = {
type StateProps = {
user?: ApiUser;
userProfilePhoto?: ApiPhoto;
gifts?: ApiPremiumGiftOption[];
monthlyCurrency?: string;
monthlyAmount?: number;
@ -44,7 +42,6 @@ type StateProps = {
const GiftPremiumModal: FC<OwnProps & StateProps> = ({
isOpen,
user,
userProfilePhoto,
gifts,
monthlyCurrency,
monthlyAmount,
@ -54,7 +51,6 @@ const GiftPremiumModal: FC<OwnProps & StateProps> = ({
const lang = useLang();
const renderedUser = useCurrentOrPrev(user, true);
const renderedUserProfilePhoto = useCurrentOrPrev(userProfilePhoto, true);
const renderedGifts = useCurrentOrPrev(gifts, true);
const [selectedOption, setSelectedOption] = useState<number | undefined>();
const firstGift = renderedGifts?.[0];
@ -133,7 +129,6 @@ const GiftPremiumModal: FC<OwnProps & StateProps> = ({
</Button>
<Avatar
user={renderedUser}
userProfilePhoto={renderedUserProfilePhoto}
size="jumbo"
className={styles.avatar}
animationLevel={animationLevel}
@ -177,12 +172,10 @@ const GiftPremiumModal: FC<OwnProps & StateProps> = ({
export default memo(withGlobal<OwnProps>((global): StateProps => {
const { forUserId, monthlyCurrency, monthlyAmount } = selectTabState(global).giftPremiumModal || {};
const user = forUserId ? selectUser(global, forUserId) : undefined;
const userProfilePhoto = user ? selectUserPhotoFromFullInfo(global, user.id) : undefined;
const gifts = user ? selectUserFullInfo(global, user.id)?.premiumGifts : undefined;
return {
user,
userProfilePhoto,
gifts,
monthlyCurrency,
monthlyAmount: monthlyAmount ? Number(monthlyAmount) : undefined,

View File

@ -18,7 +18,6 @@ import useLang from '../../hooks/useLang';
import useAppLayout from '../../hooks/useAppLayout';
import Avatar from '../common/Avatar';
import UserAvatar from '../common/UserAvatar';
import './SenderInfo.scss';
@ -80,7 +79,7 @@ const SenderInfo: FC<OwnProps & StateProps> = ({
return (
<div className="SenderInfo" onClick={handleFocusMessage}>
{isUserId(sender.id) ? (
<UserAvatar key={sender.id} size="medium" user={sender as ApiUser} withVideo />
<Avatar key={sender.id} size="medium" user={sender as ApiUser} animationLevel={animationLevel} withVideo />
) : (
<Avatar key={sender.id} size="medium" chat={sender as ApiChat} animationLevel={animationLevel} withVideo />
)}

View File

@ -2,7 +2,7 @@ import type { FC } from '../../lib/teact/teact';
import React, {
memo, useEffect, useMemo, useRef,
} from '../../lib/teact/teact';
import { getActions, getGlobal, withGlobal } from '../../global';
import { getActions, withGlobal } from '../../global';
import type {
ApiUser, ApiMessage, ApiChat, ApiSticker, ApiTopic,
@ -53,6 +53,7 @@ type OwnProps = {
};
type StateProps = {
usersById: Record<string, ApiUser>;
senderUser?: ApiUser;
senderChat?: ApiChat;
targetUserIds?: string[];
@ -73,6 +74,7 @@ const ActionMessage: FC<OwnProps & StateProps> = ({
appearanceOrder = 0,
isJustAdded,
isLastInList,
usersById,
senderUser,
senderChat,
targetUserIds,
@ -138,8 +140,6 @@ const ActionMessage: FC<OwnProps & StateProps> = ({
const { transitionClassNames } = useShowTransition(isShown, undefined, noAppearanceAnimation, false);
// No need for expensive global updates on users and chats, so we avoid them
const usersById = getGlobal().users.byId;
const targetUsers = useMemo(() => {
return targetUserIds
? targetUserIds.map((userId) => usersById?.[userId]).filter(Boolean)
@ -256,6 +256,7 @@ export default memo(withGlobal<OwnProps>(
chatId, senderId, replyToMessageId, content,
} = message;
const { byId: usersById } = global.users;
const userId = senderId;
const { targetUserIds, targetChatId } = content.action || {};
const targetMessageId = replyToMessageId;
@ -277,6 +278,7 @@ export default memo(withGlobal<OwnProps>(
const topic = selectTopicFromMessage(global, message);
return {
usersById,
senderUser,
senderChat,
targetChatId,

View File

@ -5,6 +5,7 @@ import React, {
import { getActions, getGlobal, withGlobal } from '../../global';
import type { ApiAvailableReaction, ApiMessage, ApiReaction } from '../../api/types';
import type { AnimationLevel } from '../../types';
import { LoadMoreDirection } from '../../types';
import { selectChatMessage, selectTabState } from '../../global/selectors';
@ -20,7 +21,7 @@ import useFlag from '../../hooks/useFlag';
import InfiniteScroll from '../ui/InfiniteScroll';
import Modal from '../ui/Modal';
import Button from '../ui/Button';
import UserAvatar from '../common/UserAvatar';
import Avatar from '../common/Avatar';
import ListItem from '../ui/ListItem';
import ReactionStaticEmoji from '../common/ReactionStaticEmoji';
import Loading from '../ui/Loading';
@ -38,6 +39,7 @@ export type StateProps = Pick<ApiMessage, 'reactors' | 'reactions' | 'seenByUser
chatId?: string;
messageId?: number;
availableReactions?: ApiAvailableReaction[];
animationLevel?: AnimationLevel;
};
const ReactorListModal: FC<OwnProps & StateProps> = ({
@ -48,6 +50,7 @@ const ReactorListModal: FC<OwnProps & StateProps> = ({
messageId,
seenByUserIds,
availableReactions,
animationLevel,
}) => {
const {
loadReactors,
@ -191,7 +194,7 @@ const ReactorListModal: FC<OwnProps & StateProps> = ({
// eslint-disable-next-line react/jsx-no-bind
onClick={() => handleClick(userId)}
>
<UserAvatar user={user} size="small" withVideo />
<Avatar user={user} size="small" withVideo animationLevel={animationLevel} />
<FullNameTitle peer={user} withEmojiStatus />
{r.reaction && (
<ReactionStaticEmoji
@ -232,6 +235,7 @@ export default memo(withGlobal<OwnProps>(
reactors: message?.reactors,
seenByUserIds: message?.seenByUserIds,
availableReactions: global.availableReactions,
animationLevel: global.settings.byKey.animationLevel,
};
},
)(ReactorListModal));

View File

@ -24,7 +24,6 @@ import type {
ApiBotMenuButton,
ApiAttachMenuPeerType,
ApiChatFullInfo,
ApiPhoto,
} from '../../../api/types';
import type { InlineBotSettings, ISettings } from '../../../types';
@ -63,7 +62,7 @@ import {
selectTabState,
selectTheme,
selectUser,
selectUserFullInfo, selectUserPhotoFromFullInfo,
selectUserFullInfo,
} from '../../../global/selectors';
import {
getAllowedAttachmentOptions,
@ -190,7 +189,6 @@ type StateProps =
chatBotCommands?: ApiBotCommand[];
sendAsUser?: ApiUser;
sendAsChat?: ApiChat;
sendAsUserProfilePhoto?: ApiPhoto;
sendAsId?: string;
editingDraft?: ApiFormattedText;
requestedDraftText?: string;
@ -277,7 +275,6 @@ const Composer: FC<OwnProps & StateProps> = ({
chatBotCommands,
sendAsUser,
sendAsChat,
sendAsUserProfilePhoto,
sendAsId,
editingDraft,
replyingToId,
@ -1373,7 +1370,6 @@ const Composer: FC<OwnProps & StateProps> = ({
<Avatar
user={sendAsUser}
chat={sendAsChat}
userProfilePhoto={sendAsUserProfilePhoto}
size="tiny"
/>
</Button>
@ -1586,7 +1582,6 @@ export default memo(withGlobal<OwnProps>(
);
const sendAsUser = sendAsId ? selectUser(global, sendAsId) : undefined;
const sendAsChat = !sendAsUser && sendAsId ? selectChat(global, sendAsId) : undefined;
const sendAsUserProfilePhoto = sendAsUser ? selectUserPhotoFromFullInfo(global, sendAsUser.id) : undefined;
const requestedDraftText = selectRequestedDraftText(global, chatId);
const requestedDraftFiles = selectRequestedDraftFiles(global, chatId);
const currentMessageList = selectCurrentMessageList(global);
@ -1647,7 +1642,6 @@ export default memo(withGlobal<OwnProps>(
botMenuButton: chatBotFullInfo?.botInfo?.menuButton,
sendAsUser,
sendAsChat,
sendAsUserProfilePhoto,
sendAsId,
editingDraft,
requestedDraftText,

View File

@ -16,7 +16,6 @@ import useLang from '../../../hooks/useLang';
import ListItem from '../../ui/ListItem';
import Avatar from '../../common/Avatar';
import UserAvatar from '../../common/UserAvatar';
import Menu from '../../ui/Menu';
import FullNameTitle from '../../common/FullNameTitle';
@ -127,19 +126,12 @@ const SendAsMenu: FC<OwnProps> = ({
rightElement={!isCurrentUserPremium && isPremium
&& <i className="icon icon-lock-badge send-as-icon-locked" />}
>
{user ? (
<UserAvatar
user={user}
size="small"
className={avatarClassName}
/>
) : (
<Avatar
size="small"
chat={chat}
className={avatarClassName}
/>
)}
<Avatar
size="small"
chat={chat}
user={user}
className={avatarClassName}
/>
<div className="info">
{userOrChat && <FullNameTitle peer={userOrChat} noFake />}
<span className="subtitle">{user

View File

@ -9,7 +9,6 @@ import type {
import { isUserId } from '../../../global/helpers';
import { formatIntegerCompact } from '../../../util/textFormat';
import buildClassName from '../../../util/buildClassName';
import { selectUserPhotoFromFullInfo } from '../../../global/selectors';
import useLang from '../../../hooks/useLang';
import Avatar from '../../common/Avatar';
@ -63,7 +62,6 @@ const CommentButton: FC<OwnProps> = ({
key={user.id}
size="small"
user={isUserId(user.id) ? user as ApiUser : undefined}
userProfilePhoto={isUserId(user.id) ? selectUserPhotoFromFullInfo(getGlobal(), user.id) : undefined}
chat={!isUserId(user.id) ? user as ApiChat : undefined}
/>
))}

View File

@ -2,12 +2,10 @@ import type { FC } from '../../../lib/teact/teact';
import React, { useCallback } from '../../../lib/teact/teact';
import { getActions, withGlobal } from '../../../global';
import type {
ApiUser, ApiContact, ApiCountryCode, ApiPhoto,
} from '../../../api/types';
import type { ApiUser, ApiContact, ApiCountryCode } from '../../../api/types';
import type { AnimationLevel } from '../../../types';
import { selectUser, selectUserPhotoFromFullInfo } from '../../../global/selectors';
import { selectUser } from '../../../global/selectors';
import { formatPhoneNumberWithCode } from '../../../util/phoneNumber';
import buildClassName from '../../../util/buildClassName';
@ -21,7 +19,6 @@ type OwnProps = {
type StateProps = {
user?: ApiUser;
userProfilePhoto?: ApiPhoto;
phoneCodeList: ApiCountryCode[];
animationLevel: AnimationLevel;
};
@ -29,7 +26,7 @@ type StateProps = {
const UNREGISTERED_CONTACT_ID = '0';
const Contact: FC<OwnProps & StateProps> = ({
contact, user, userProfilePhoto, phoneCodeList, animationLevel,
contact, user, phoneCodeList, animationLevel,
}) => {
const { openChat } = getActions();
@ -53,7 +50,6 @@ const Contact: FC<OwnProps & StateProps> = ({
<Avatar
size="large"
user={user}
userProfilePhoto={userProfilePhoto}
text={firstName || lastName}
animationLevel={animationLevel}
withVideo
@ -70,11 +66,9 @@ export default withGlobal<OwnProps>(
(global, { contact }): StateProps => {
const { countryList: { phoneCodes: phoneCodeList } } = global;
const user = selectUser(global, contact.userId);
const userProfilePhoto = user ? selectUserPhotoFromFullInfo(global, user.id) : undefined;
return {
user,
userProfilePhoto,
phoneCodeList,
animationLevel: global.settings.byKey.animationLevel,
};

View File

@ -5,9 +5,7 @@ import { requestMutation } from '../../../lib/fasterdom/fasterdom';
import { getActions } from '../../../global';
import type { FC } from '../../../lib/teact/teact';
import type {
ApiChat, ApiMessage, ApiPhoto, ApiUser,
} from '../../../api/types';
import type { ApiChat, ApiMessage, ApiUser } from '../../../api/types';
import type { ISettings } from '../../../types';
import { CUSTOM_APPENDIX_ATTRIBUTE, MESSAGE_CONTENT_SELECTOR } from '../../../config';
@ -55,7 +53,6 @@ const SVG_PIN = { __html: '<svg version="1.1" class="round-pin" xmlns="http://ww
type OwnProps = {
message: ApiMessage;
peer?: ApiUser | ApiChat;
peerProfilePhoto?: ApiPhoto;
lastSyncTime?: number;
isInSelectMode?: boolean;
isSelected?: boolean;
@ -65,7 +62,6 @@ type OwnProps = {
const Location: FC<OwnProps> = ({
message,
peer,
peerProfilePhoto,
lastSyncTime,
isInSelectMode,
isSelected,
@ -247,7 +243,7 @@ const Location: FC<OwnProps> = ({
if (type === 'geoLive') {
return (
<div className={pinClassName} dangerouslySetInnerHTML={SVG_PIN}>
<Avatar chat={avatarChat} user={avatarUser} userProfilePhoto={peerProfilePhoto} className="location-avatar" />
<Avatar chat={avatarChat} user={avatarUser} className="location-avatar" />
{location.heading !== undefined && (
<div className="direction" style={`--direction: ${location.heading}deg`} />
)}

View File

@ -24,7 +24,6 @@ import type {
ApiTopic,
ApiReaction,
ApiStickerSet,
ApiPhoto,
} from '../../../api/types';
import type {
AnimationLevel, FocusDirection, IAlbum, ISettings,
@ -70,7 +69,6 @@ import {
selectChatTranslations,
selectRequestedTranslationLanguage,
selectChatFullInfo,
selectUserPhotoFromFullInfo,
} from '../../../global/selectors';
import {
getMessageContent,
@ -203,8 +201,6 @@ type StateProps = {
canShowSender: boolean;
originSender?: ApiUser | ApiChat;
botSender?: ApiUser;
senderUserProfilePhoto?: ApiPhoto;
originSenderUserProfilePhoto?: ApiPhoto;
isThreadTop?: boolean;
shouldHideReply?: boolean;
replyMessage?: ApiMessage;
@ -313,8 +309,6 @@ const Message: FC<OwnProps & StateProps> = ({
canShowSender,
originSender,
botSender,
senderUserProfilePhoto,
originSenderUserProfilePhoto,
isThreadTop,
shouldHideReply,
replyMessage,
@ -487,7 +481,6 @@ const Message: FC<OwnProps & StateProps> = ({
const shouldPreferOriginSender = forwardInfo && (isChatWithSelf || isRepliesChat || !messageSender);
const avatarPeer = shouldPreferOriginSender ? originSender : messageSender;
const senderPeer = forwardInfo ? originSender : messageSender;
const avatarUserProfilePhoto = shouldPreferOriginSender ? originSenderUserProfilePhoto : senderUserProfilePhoto;
const {
handleMouseDown,
@ -790,7 +783,6 @@ const Message: FC<OwnProps & StateProps> = ({
user={avatarUser}
chat={avatarChat}
text={hiddenName}
userProfilePhoto={avatarUserProfilePhoto}
lastSyncTime={lastSyncTime}
onClick={(avatarUser || avatarChat) ? handleAvatarClick : undefined}
observeIntersection={observeIntersectionForLoading}
@ -1137,7 +1129,6 @@ const Message: FC<OwnProps & StateProps> = ({
isSelected={isSelected}
theme={theme}
peer={sender}
peerProfilePhoto={senderUserProfilePhoto}
/>
)}
</div>
@ -1373,10 +1364,6 @@ export default memo(withGlobal<OwnProps>(
const senderAdminMember = sender?.id && isGroup
? chatFullInfo?.adminMembersById?.[sender?.id]
: undefined;
const senderUserProfilePhoto = canShowSender && sender && isUserId(sender.id)
? selectUserPhotoFromFullInfo(global, sender.id) : undefined;
const originSenderUserProfilePhoto = originSender && isUserId(originSender.id)
? selectUserPhotoFromFullInfo(global, originSender.id) : undefined;
const threadTopMessageId = threadId ? selectThreadTopMessageId(global, chatId, threadId) : undefined;
const isThreadTop = message.id === threadTopMessageId;
@ -1443,8 +1430,6 @@ export default memo(withGlobal<OwnProps>(
canShowSender,
originSender,
botSender,
senderUserProfilePhoto,
originSenderUserProfilePhoto,
shouldHideReply: shouldHideReply || isReplyToTopicStart,
isThreadTop,
replyMessage,

View File

@ -1,7 +1,7 @@
import React, {
memo, useCallback, useEffect, useRef,
} from '../../../lib/teact/teact';
import { getActions, getGlobal } from '../../../global';
import { getActions } from '../../../global';
import type { FC } from '../../../lib/teact/teact';
import type {
@ -21,7 +21,6 @@ import { getMessageCopyOptions } from './helpers/copyOptions';
import { disableScrolling, enableScrolling } from '../../../util/scrollLock';
import { getUserFullName } from '../../../global/helpers';
import buildClassName from '../../../util/buildClassName';
import { selectUserPhotoFromFullInfo } from '../../../global/selectors';
import renderText from '../../common/helpers/renderText';
import useFlag from '../../../hooks/useFlag';
@ -406,7 +405,6 @@ const MessageContextMenu: FC<OwnProps> = ({
<Avatar
size="micro"
user={user}
userProfilePhoto={selectUserPhotoFromFullInfo(getGlobal(), user.id)}
/>
))}
</div>

View File

@ -7,7 +7,7 @@ import React, {
useMemo,
useRef,
} from '../../../lib/teact/teact';
import { getActions, getGlobal, withGlobal } from '../../../global';
import { getActions, withGlobal } from '../../../global';
import type {
ApiMessage, ApiPoll, ApiUser, ApiPollAnswer,
@ -19,7 +19,6 @@ import { formatMediaDuration } from '../../../util/dateFormat';
import type { LangFn } from '../../../hooks/useLang';
import useLang from '../../../hooks/useLang';
import { getServerTimeOffset } from '../../../util/serverTime';
import { selectUserPhotoFromFullInfo } from '../../../global/selectors';
import CheckboxGroup from '../../ui/CheckboxGroup';
import RadioGroup from '../../ui/RadioGroup';
@ -235,7 +234,6 @@ const Poll: FC<OwnProps & StateProps> = ({
key={user.id}
size="micro"
user={user}
userProfilePhoto={selectUserPhotoFromFullInfo(getGlobal(), user.id)}
/>
))}
</div>

View File

@ -11,7 +11,6 @@ import type { ActiveReaction } from '../../../global/types';
import buildClassName from '../../../util/buildClassName';
import { formatIntegerCompact } from '../../../util/textFormat';
import { isSameReaction, isReactionChosen } from '../../../global/helpers';
import { selectUserPhotoFromFullInfo } from '../../../global/selectors';
import Button from '../../ui/Button';
import Avatar from '../../common/Avatar';
@ -81,7 +80,6 @@ const ReactionButton: FC<{
<Avatar
key={user.id}
user={user}
userProfilePhoto={selectUserPhotoFromFullInfo(getGlobal(), user.id)}
size="micro"
/>
))}

View File

@ -4,9 +4,7 @@ import React, {
import { getActions, getGlobal, withGlobal } from '../../global';
import type { FC } from '../../lib/teact/teact';
import type {
ApiMessage, ApiUser, ApiChat, ApiPhoto,
} from '../../api/types';
import type { ApiMessage, ApiUser, ApiChat } from '../../api/types';
import type { AnimationLevel } from '../../types';
import { MEMO_EMPTY_ARRAY } from '../../util/memo';
@ -15,11 +13,8 @@ import {
selectChatMessages,
selectChat,
selectCurrentTextSearch,
selectUserPhotoFromFullInfo,
} from '../../global/selectors';
import {
isChatChannel,
} from '../../global/helpers';
import { isChatChannel } from '../../global/helpers';
import { disableDirectTextInput, enableDirectTextInput } from '../../util/directInputManager';
import { renderMessageSummary } from '../common/helpers/renderMessageText';
import useLang from '../../hooks/useLang';
@ -105,7 +100,6 @@ const RightSearch: FC<OwnProps & StateProps> = ({
}
const senderUser = message.senderId ? selectUser(getGlobal(), message.senderId) : undefined;
const senderUserProfilePhoto = senderUser ? selectUserPhotoFromFullInfo(getGlobal(), senderUser.id) : undefined;
let senderChat;
if (chat && isChatChannel(chat)) {
@ -120,7 +114,6 @@ const RightSearch: FC<OwnProps & StateProps> = ({
return {
message,
senderUser,
senderUserProfilePhoto,
senderChat,
onClick: () => focusMessage({ chatId, threadId, messageId: id }),
};
@ -135,12 +128,11 @@ const RightSearch: FC<OwnProps & StateProps> = ({
}, '.ListItem-button', true);
const renderSearchResult = ({
message, senderUser, senderChat, senderUserProfilePhoto, onClick,
message, senderUser, senderChat, onClick,
}: {
message: ApiMessage;
senderUser?: ApiUser;
senderChat?: ApiChat;
senderUserProfilePhoto?: ApiPhoto;
onClick: NoneToVoidFunction;
}) => {
const text = renderMessageSummary(lang, message, undefined, query);
@ -155,7 +147,6 @@ const RightSearch: FC<OwnProps & StateProps> = ({
<Avatar
chat={senderChat}
user={senderUser}
userProfilePhoto={senderUserProfilePhoto}
animationLevel={animationLevel}
withVideo
/>

View File

@ -3,11 +3,11 @@ import React, { memo, useCallback } from '../../../lib/teact/teact';
import { getActions, withGlobal } from '../../../global';
import type { AnimationLevel } from '../../../types';
import type { ApiPhoto, ApiUser } from '../../../api/types';
import type { ApiUser } from '../../../api/types';
import useLang from '../../../hooks/useLang';
import { getUserFullName } from '../../../global/helpers';
import { selectUser, selectUserPhotoFromFullInfo } from '../../../global/selectors';
import { selectUser } from '../../../global/selectors';
import { formatHumanDate, formatTime, isToday } from '../../../util/dateFormat';
import { getServerTime } from '../../../util/serverTime';
import { createClassNameBuilder } from '../../../util/buildClassName';
@ -27,7 +27,6 @@ type OwnProps = {
type StateProps = {
user?: ApiUser;
userProfilePhoto?: ApiPhoto;
isSavedMessages?: boolean;
animationLevel: AnimationLevel;
};
@ -39,7 +38,6 @@ const JoinRequest: FC<OwnProps & StateProps> = ({
date,
isChannel,
user,
userProfilePhoto,
animationLevel,
}) => {
const { openChat, hideChatJoinRequest } = getActions();
@ -73,7 +71,6 @@ const JoinRequest: FC<OwnProps & StateProps> = ({
key={userId}
size="medium"
user={user}
userProfilePhoto={userProfilePhoto}
animationLevel={animationLevel}
withVideo
/>
@ -102,7 +99,6 @@ export default memo(withGlobal<OwnProps>(
return {
user,
userProfilePhoto: user ? selectUserPhotoFromFullInfo(global, userId) : undefined,
animationLevel: global.settings.byKey.animationLevel,
};
},

View File

@ -16,7 +16,6 @@ import {
selectTabState,
selectUser,
selectUserFullInfo,
selectUserPhotoFromFullInfo,
} from '../../../global/selectors';
import { isUserBot, selectIsChatMuted } from '../../../global/helpers';
import useFlag from '../../../hooks/useFlag';
@ -43,7 +42,6 @@ type OwnProps = {
type StateProps = {
user?: ApiUser;
userProfilePhoto?: ApiPhoto;
progress?: ManagementProgress;
isMuted?: boolean;
personalPhoto?: ApiPhoto;
@ -55,7 +53,6 @@ const ERROR_FIRST_NAME_MISSING = 'Please provide first name';
const ManageUser: FC<OwnProps & StateProps> = ({
userId,
user,
userProfilePhoto,
progress,
isMuted,
onClose,
@ -233,7 +230,6 @@ const ManageUser: FC<OwnProps & StateProps> = ({
photo={notPersonalPhoto}
noPersonalPhoto
user={user}
userProfilePhoto={userProfilePhoto}
size="mini"
className="personal-photo"
/>
@ -298,10 +294,9 @@ export default memo(withGlobal<OwnProps>(
const isMuted = chat && selectIsChatMuted(chat, selectNotifySettings(global), selectNotifyExceptions(global));
const personalPhoto = userFullInfo?.personalPhoto;
const notPersonalPhoto = userFullInfo?.profilePhoto || userFullInfo?.fallbackPhoto;
const userProfilePhoto = user ? selectUserPhotoFromFullInfo(global, user.id) : undefined;
return {
user, progress, isMuted, personalPhoto, notPersonalPhoto, userProfilePhoto,
user, progress, isMuted, personalPhoto, notPersonalPhoto,
};
},
)(ManageUser));

View File

@ -5,7 +5,6 @@ import type {
ApiChatAdminRights,
ApiChatFolder,
ApiTopic,
ApiPhoto,
} from '../../api/types';
import {
MAIN_THREAD_ID,
@ -21,7 +20,6 @@ import { orderBy } from '../../util/iteratees';
import { getUserFirstOrLastName } from './users';
import { formatDateToString, formatTime } from '../../util/dateFormat';
import { prepareSearchWordsForNeedle } from '../../util/searchWords';
import { getVideoAvatarMediaHash } from './media';
const FOREVER_BANNED_DATE = Date.now() / 1000 + 31622400; // 366 days
@ -109,18 +107,12 @@ export function getTopicLink(chatId: string, chatUsername?: string, topicId?: nu
export function getChatAvatarHash(
owner: ApiChat | ApiUser,
size: 'normal' | 'big' = 'normal',
type: 'photo' | 'video' = 'photo',
avatarHash = owner.avatarHash,
profilePhoto?: ApiPhoto,
) {
if (!avatarHash) {
return undefined;
}
if (type === 'video') {
return profilePhoto?.isVideo ? getVideoAvatarMediaHash(profilePhoto) : undefined;
}
switch (size) {
case 'big':
return `profile${owner.id}?${avatarHash}`;

View File

@ -16,12 +16,6 @@ export function selectUserFullInfo<T extends GlobalState>(global: T, userId: str
return global.users.fullInfoById[userId];
}
export function selectUserPhotoFromFullInfo<T extends GlobalState>(global: T, userId: string) {
const fullInfo = selectUserFullInfo(global, userId);
return fullInfo?.personalPhoto || fullInfo?.profilePhoto || fullInfo?.fallbackPhoto;
}
export function selectIsUserBlocked<T extends GlobalState>(global: T, userId: string) {
return selectUserFullInfo(global, userId)?.isBlocked;
}
@ -36,14 +30,6 @@ export function selectIsPremiumPurchaseBlocked<T extends GlobalState>(global: T)
return global.appConfig?.isPremiumPurchaseBlocked ?? true;
}
// Slow, not to be used in `withGlobal`
export function selectUserByUsername<T extends GlobalState>(global: T, username: string) {
const usernameLowered = username.toLowerCase();
return Object.values(global.users.byId).find(
(user) => user.usernames?.some((u) => u.username.toLowerCase() === usernameLowered),
);
}
// Slow, not to be used in `withGlobal`
export function selectUserByPhoneNumber<T extends GlobalState>(global: T, phoneNumber: string) {
const phoneNumberCleaned = phoneNumber.replace(/[^0-9]/g, '');