mirror of
https://github.com/danog/telegram-tt.git
synced 2024-11-30 04:39:00 +01:00
Avatar: Loop video 3 times and only with max animation level, refactoring (#2026)
This commit is contained in:
parent
f6477b2f03
commit
76d10d7212
@ -79,7 +79,7 @@ const GroupCallParticipant: FC<OwnProps & StateProps> = ({
|
||||
onClick={handleOnClick}
|
||||
ref={anchorRef}
|
||||
>
|
||||
<Avatar user={user} chat={chat} size="medium" noVideo />
|
||||
<Avatar user={user} chat={chat} size="medium" />
|
||||
<div className="info">
|
||||
<span className="name">{name}</span>
|
||||
<span className={buildClassName('about', aboutColor)}>{aboutText}</span>
|
||||
|
@ -60,7 +60,7 @@ const GroupCallParticipantVideo: FC<OwnProps & StateProps> = ({
|
||||
{lang('Back')}
|
||||
</button>
|
||||
)}
|
||||
<Avatar user={user} chat={chat} className="thumbnail-avatar" noVideo />
|
||||
<Avatar user={user} chat={chat} className="thumbnail-avatar" />
|
||||
{ENABLE_THUMBNAIL_VIDEO && (
|
||||
<div className="thumbnail-wrapper">
|
||||
<video className="thumbnail" muted autoPlay playsInline srcObject={streams?.[type]} />
|
||||
|
@ -5,6 +5,7 @@ import React, {
|
||||
import { getActions, withGlobal } from '../../../global';
|
||||
|
||||
import type { ApiChat, ApiGroupCall, ApiUser } from '../../../api/types';
|
||||
import type { AnimationLevel } from '../../../types';
|
||||
|
||||
import { selectChatGroupCall } from '../../../global/selectors/calls';
|
||||
import buildClassName from '../../../util/buildClassName';
|
||||
@ -26,6 +27,7 @@ type StateProps = {
|
||||
isActive: boolean;
|
||||
usersById: Record<string, ApiUser>;
|
||||
chatsById: Record<string, ApiChat>;
|
||||
animationLevel: AnimationLevel;
|
||||
};
|
||||
|
||||
const GroupCallTopPane: FC<OwnProps & StateProps> = ({
|
||||
@ -35,6 +37,7 @@ const GroupCallTopPane: FC<OwnProps & StateProps> = ({
|
||||
hasPinnedOffset,
|
||||
usersById,
|
||||
chatsById,
|
||||
animationLevel,
|
||||
}) => {
|
||||
const {
|
||||
joinGroupCall,
|
||||
@ -105,9 +108,9 @@ const GroupCallTopPane: FC<OwnProps & StateProps> = ({
|
||||
{fetchedParticipants.map((p) => {
|
||||
if (!p) return undefined;
|
||||
if (p.user) {
|
||||
return <Avatar key={p.user.id} user={p.user} />;
|
||||
return <Avatar key={p.user.id} user={p.user} animationLevel={animationLevel} />;
|
||||
} else {
|
||||
return <Avatar key={p.chat.id} chat={p.chat} />;
|
||||
return <Avatar key={p.chat.id} chat={p.chat} animationLevel={animationLevel} />;
|
||||
}
|
||||
})}
|
||||
</div>
|
||||
@ -130,6 +133,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
isActive: ((!groupCall ? (chat && chat.isCallNotEmpty && chat.isCallActive)
|
||||
: (groupCall.participantsCount > 0 && groupCall.isLoaded)))
|
||||
&& (global.groupCalls.activeGroupCallId !== groupCall?.id),
|
||||
animationLevel: global.settings.byKey.animationLevel,
|
||||
};
|
||||
},
|
||||
)(GroupCallTopPane));
|
||||
|
@ -6,6 +6,7 @@ import { getActions, withGlobal } from '../../../global';
|
||||
import '../../../global/actions/calls';
|
||||
|
||||
import type { ApiPhoneCall, ApiUser } from '../../../api/types';
|
||||
import type { AnimationLevel } from '../../../types';
|
||||
|
||||
import {
|
||||
IS_ANDROID,
|
||||
@ -39,6 +40,7 @@ type StateProps = {
|
||||
phoneCall?: ApiPhoneCall;
|
||||
isOutgoing: boolean;
|
||||
isCallPanelVisible?: boolean;
|
||||
animationLevel: AnimationLevel;
|
||||
};
|
||||
|
||||
const PhoneCall: FC<StateProps> = ({
|
||||
@ -46,6 +48,7 @@ const PhoneCall: FC<StateProps> = ({
|
||||
isOutgoing,
|
||||
phoneCall,
|
||||
isCallPanelVisible,
|
||||
animationLevel,
|
||||
}) => {
|
||||
const lang = useLang();
|
||||
const {
|
||||
@ -235,7 +238,9 @@ const PhoneCall: FC<StateProps> = ({
|
||||
user={user}
|
||||
size="jumbo"
|
||||
className={hasVideo || hasPresentation ? styles.blurred : ''}
|
||||
withVideo
|
||||
noLoop={phoneCall?.state !== 'requesting'}
|
||||
animationLevel={animationLevel}
|
||||
/>
|
||||
{phoneCall?.screencastState === 'active' && streams?.presentation
|
||||
&& <video className={styles.mainVideo} muted autoPlay playsInline srcObject={streams.presentation} />}
|
||||
@ -370,6 +375,7 @@ export default memo(withGlobal(
|
||||
user: selectPhoneCallUser(global),
|
||||
isOutgoing: phoneCall?.adminId === currentUserId,
|
||||
phoneCall,
|
||||
animationLevel: global.settings.byKey.animationLevel,
|
||||
};
|
||||
},
|
||||
)(PhoneCall));
|
||||
|
@ -9,9 +9,10 @@ import type {
|
||||
ApiChat, ApiPhoto, ApiUser, ApiUserStatus,
|
||||
} from '../../api/types';
|
||||
import type { ObserveFn } from '../../hooks/useIntersectionObserver';
|
||||
import type { AnimationLevel } from '../../types';
|
||||
import { ApiMediaFormat } from '../../api/types';
|
||||
|
||||
import { IS_TEST } from '../../config';
|
||||
import { ANIMATION_LEVEL_MAX, IS_TEST } from '../../config';
|
||||
import {
|
||||
getChatAvatarHash,
|
||||
getChatTitle,
|
||||
@ -35,6 +36,8 @@ import useVideoCleanup from '../../hooks/useVideoCleanup';
|
||||
|
||||
import './Avatar.scss';
|
||||
|
||||
const LOOP_COUNT = 3;
|
||||
|
||||
const cn = createClassNameBuilder('Avatar');
|
||||
cn.media = cn('media');
|
||||
cn.icon = cn('icon');
|
||||
@ -48,8 +51,9 @@ type OwnProps = {
|
||||
userStatus?: ApiUserStatus;
|
||||
text?: string;
|
||||
isSavedMessages?: boolean;
|
||||
noVideo?: boolean;
|
||||
withVideo?: boolean;
|
||||
noLoop?: boolean;
|
||||
animationLevel?: AnimationLevel;
|
||||
lastSyncTime?: number;
|
||||
observeIntersection?: ObserveFn;
|
||||
onClick?: (e: ReactMouseEvent<HTMLDivElement, MouseEvent>, hasMedia: boolean) => void;
|
||||
@ -64,9 +68,10 @@ const Avatar: FC<OwnProps> = ({
|
||||
userStatus,
|
||||
text,
|
||||
isSavedMessages,
|
||||
noVideo,
|
||||
withVideo,
|
||||
noLoop,
|
||||
lastSyncTime,
|
||||
animationLevel,
|
||||
observeIntersection,
|
||||
onClick,
|
||||
}) => {
|
||||
@ -75,15 +80,17 @@ const Avatar: FC<OwnProps> = ({
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
// eslint-disable-next-line no-null/no-null
|
||||
const videoRef = useRef<HTMLVideoElement>(null);
|
||||
const videoLoopCountRef = useRef(0);
|
||||
const isIntersecting = useIsIntersecting(ref, observeIntersection);
|
||||
const isDeleted = user && isDeletedUser(user);
|
||||
const isReplies = user && isChatWithRepliesBot(user.id);
|
||||
let imageHash: string | undefined;
|
||||
let videoHash: string | undefined;
|
||||
|
||||
const withVideo = isIntersecting && !noVideo && user?.isPremium && user?.hasVideoAvatar;
|
||||
const shouldShowVideo = isIntersecting && animationLevel === ANIMATION_LEVEL_MAX && withVideo && user?.isPremium
|
||||
&& user?.hasVideoAvatar;
|
||||
const profilePhoto = user?.fullInfo?.profilePhoto;
|
||||
const shouldLoadVideo = withVideo && profilePhoto?.isVideo;
|
||||
const shouldLoadVideo = shouldShowVideo && profilePhoto?.isVideo;
|
||||
|
||||
const shouldFetchBig = size === 'jumbo';
|
||||
if (!isSavedMessages && !isDeleted) {
|
||||
@ -112,22 +119,27 @@ const Avatar: FC<OwnProps> = ({
|
||||
|
||||
useEffect(() => {
|
||||
const video = videoRef.current;
|
||||
if (!video || !noLoop) return undefined;
|
||||
if (!video || !videoBlobUrl) return undefined;
|
||||
|
||||
const returnToStart = () => {
|
||||
video.currentTime = 0;
|
||||
videoLoopCountRef.current += 1;
|
||||
if (videoLoopCountRef.current >= LOOP_COUNT || noLoop) {
|
||||
video.style.display = 'none';
|
||||
} else {
|
||||
video.play();
|
||||
}
|
||||
};
|
||||
|
||||
video.addEventListener('ended', returnToStart);
|
||||
return () => video.removeEventListener('ended', returnToStart);
|
||||
}, [noLoop]);
|
||||
}, [noLoop, videoBlobUrl]);
|
||||
|
||||
const userId = user?.id;
|
||||
useEffect(() => {
|
||||
if (withVideo && !profilePhoto) {
|
||||
if (shouldShowVideo && !profilePhoto) {
|
||||
loadFullUser({ userId });
|
||||
}
|
||||
}, [loadFullUser, profilePhoto, userId, withVideo]);
|
||||
}, [loadFullUser, profilePhoto, userId, shouldShowVideo]);
|
||||
|
||||
const lang = useLang();
|
||||
|
||||
@ -157,7 +169,6 @@ const Avatar: FC<OwnProps> = ({
|
||||
muted
|
||||
autoPlay
|
||||
disablePictureInPicture
|
||||
loop={!noLoop}
|
||||
playsInline
|
||||
/>
|
||||
)}
|
||||
|
@ -3,6 +3,7 @@ import React, { useCallback, memo } from '../../lib/teact/teact';
|
||||
import { getActions, withGlobal } from '../../global';
|
||||
|
||||
import type { ApiChat } from '../../api/types';
|
||||
import type { AnimationLevel } from '../../types';
|
||||
|
||||
import { selectIsChatWithSelf, selectUser } from '../../global/selectors';
|
||||
import {
|
||||
@ -41,6 +42,7 @@ type StateProps = {
|
||||
currentUserId: string | undefined;
|
||||
canDeleteForAll?: boolean;
|
||||
contactName?: string;
|
||||
animationLevel: AnimationLevel;
|
||||
};
|
||||
|
||||
const DeleteChatModal: FC<OwnProps & StateProps> = ({
|
||||
@ -55,6 +57,7 @@ const DeleteChatModal: FC<OwnProps & StateProps> = ({
|
||||
currentUserId,
|
||||
canDeleteForAll,
|
||||
contactName,
|
||||
animationLevel,
|
||||
onClose,
|
||||
onCloseAnimationEnd,
|
||||
}) => {
|
||||
@ -125,6 +128,8 @@ const DeleteChatModal: FC<OwnProps & StateProps> = ({
|
||||
size="tiny"
|
||||
chat={chat}
|
||||
isSavedMessages={isChatWithSelf}
|
||||
animationLevel={animationLevel}
|
||||
withVideo
|
||||
/>
|
||||
<h3 className="modal-title">{lang(renderTitle())}</h3>
|
||||
</div>
|
||||
@ -236,6 +241,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
currentUserId: global.currentUserId,
|
||||
canDeleteForAll,
|
||||
contactName,
|
||||
animationLevel: global.settings.byKey.animationLevel,
|
||||
};
|
||||
},
|
||||
)(DeleteChatModal));
|
||||
|
@ -5,6 +5,7 @@ import { getActions, withGlobal } from '../../global';
|
||||
|
||||
import type { ApiChat, ApiTypingStatus } from '../../api/types';
|
||||
import type { GlobalState } from '../../global/types';
|
||||
import type { AnimationLevel } from '../../types';
|
||||
import { MediaViewerOrigin } from '../../types';
|
||||
|
||||
import {
|
||||
@ -43,6 +44,7 @@ type StateProps =
|
||||
chat?: ApiChat;
|
||||
onlineCount?: number;
|
||||
areMessagesLoaded: boolean;
|
||||
animationLevel: AnimationLevel;
|
||||
}
|
||||
& Pick<GlobalState, 'lastSyncTime'>;
|
||||
|
||||
@ -61,6 +63,7 @@ const GroupChatInfo: FC<OwnProps & StateProps> = ({
|
||||
chat,
|
||||
onlineCount,
|
||||
areMessagesLoaded,
|
||||
animationLevel,
|
||||
lastSyncTime,
|
||||
}) => {
|
||||
const {
|
||||
@ -145,7 +148,8 @@ const GroupChatInfo: FC<OwnProps & StateProps> = ({
|
||||
size={avatarSize}
|
||||
chat={chat}
|
||||
onClick={withMediaViewer ? handleAvatarViewerOpen : undefined}
|
||||
noVideo={!withVideoAvatar}
|
||||
withVideo={withVideoAvatar}
|
||||
animationLevel={animationLevel}
|
||||
/>
|
||||
<div className="info">
|
||||
<div className="title">
|
||||
@ -184,7 +188,11 @@ export default memo(withGlobal<OwnProps>(
|
||||
const areMessagesLoaded = Boolean(selectChatMessages(global, chatId));
|
||||
|
||||
return {
|
||||
lastSyncTime, chat, onlineCount, areMessagesLoaded,
|
||||
lastSyncTime,
|
||||
chat,
|
||||
onlineCount,
|
||||
areMessagesLoaded,
|
||||
animationLevel: global.settings.byKey.animationLevel,
|
||||
};
|
||||
},
|
||||
)(GroupChatInfo));
|
||||
|
@ -61,7 +61,6 @@ const PickerSelectedItem: FC<OwnProps & StateProps> = ({
|
||||
user={user}
|
||||
size="small"
|
||||
isSavedMessages={user?.isSelf}
|
||||
noVideo
|
||||
/>
|
||||
);
|
||||
|
||||
|
@ -5,6 +5,7 @@ import { getActions, withGlobal } from '../../global';
|
||||
|
||||
import type { ApiUser, ApiTypingStatus, ApiUserStatus } from '../../api/types';
|
||||
import type { GlobalState } from '../../global/types';
|
||||
import type { AnimationLevel } from '../../types';
|
||||
import { MediaViewerOrigin } from '../../types';
|
||||
|
||||
import { selectChatMessages, selectUser, selectUserStatus } from '../../global/selectors';
|
||||
@ -40,6 +41,7 @@ type StateProps =
|
||||
user?: ApiUser;
|
||||
userStatus?: ApiUserStatus;
|
||||
isSavedMessages?: boolean;
|
||||
animationLevel: AnimationLevel;
|
||||
areMessagesLoaded: boolean;
|
||||
serverTimeOffset: number;
|
||||
}
|
||||
@ -61,6 +63,7 @@ const PrivateChatInfo: FC<OwnProps & StateProps> = ({
|
||||
userStatus,
|
||||
isSavedMessages,
|
||||
areMessagesLoaded,
|
||||
animationLevel,
|
||||
lastSyncTime,
|
||||
serverTimeOffset,
|
||||
}) => {
|
||||
@ -136,7 +139,8 @@ const PrivateChatInfo: FC<OwnProps & StateProps> = ({
|
||||
user={user}
|
||||
isSavedMessages={isSavedMessages}
|
||||
onClick={withMediaViewer ? handleAvatarViewerOpen : undefined}
|
||||
noVideo={!withVideoAvatar}
|
||||
withVideo={withVideoAvatar}
|
||||
animationLevel={animationLevel}
|
||||
/>
|
||||
<div className="info">
|
||||
{isSavedMessages ? (
|
||||
@ -166,7 +170,13 @@ export default memo(withGlobal<OwnProps>(
|
||||
const areMessagesLoaded = Boolean(selectChatMessages(global, userId));
|
||||
|
||||
return {
|
||||
lastSyncTime, user, userStatus, isSavedMessages, areMessagesLoaded, serverTimeOffset,
|
||||
lastSyncTime,
|
||||
user,
|
||||
userStatus,
|
||||
isSavedMessages,
|
||||
areMessagesLoaded,
|
||||
serverTimeOffset,
|
||||
animationLevel: global.settings.byKey.animationLevel,
|
||||
};
|
||||
},
|
||||
)(PrivateChatInfo));
|
||||
|
@ -6,6 +6,7 @@ import { getActions, withGlobal } from '../../global';
|
||||
|
||||
import type { ApiUser, ApiChat, ApiUserStatus } from '../../api/types';
|
||||
import type { GlobalState } from '../../global/types';
|
||||
import type { AnimationLevel } from '../../types';
|
||||
import { MediaViewerOrigin } from '../../types';
|
||||
|
||||
import { IS_TOUCH_ENV } from '../../util/environment';
|
||||
@ -40,7 +41,7 @@ type StateProps =
|
||||
userStatus?: ApiUserStatus;
|
||||
chat?: ApiChat;
|
||||
isSavedMessages?: boolean;
|
||||
animationLevel: 0 | 1 | 2;
|
||||
animationLevel: AnimationLevel;
|
||||
serverTimeOffset: number;
|
||||
mediaId?: number;
|
||||
avatarOwnerId?: string;
|
||||
|
@ -9,6 +9,7 @@ import type { ObserveFn } from '../../../hooks/useIntersectionObserver';
|
||||
import type {
|
||||
ApiChat, ApiUser, ApiMessage, ApiMessageOutgoingStatus, ApiFormattedText, ApiUserStatus,
|
||||
} from '../../../api/types';
|
||||
import type { AnimationLevel } from '../../../types';
|
||||
import { MAIN_THREAD_ID } from '../../../api/types';
|
||||
|
||||
import { ANIMATION_END_DELAY } from '../../../config';
|
||||
@ -82,7 +83,7 @@ type StateProps = {
|
||||
lastMessageSender?: ApiUser;
|
||||
lastMessageOutgoingStatus?: ApiMessageOutgoingStatus;
|
||||
draft?: ApiFormattedText;
|
||||
animationLevel?: number;
|
||||
animationLevel?: AnimationLevel;
|
||||
isSelected?: boolean;
|
||||
canScrollDown?: boolean;
|
||||
canChangeFolder?: boolean;
|
||||
@ -315,6 +316,8 @@ const Chat: FC<OwnProps & StateProps> = ({
|
||||
userStatus={userStatus}
|
||||
isSavedMessages={user?.isSelf}
|
||||
lastSyncTime={lastSyncTime}
|
||||
animationLevel={animationLevel}
|
||||
withVideo
|
||||
observeIntersection={observeIntersection}
|
||||
/>
|
||||
{chat.isCallActive && chat.isCallNotEmpty && (
|
||||
|
@ -4,7 +4,7 @@ import React, {
|
||||
} from '../../../lib/teact/teact';
|
||||
import { getActions, withGlobal } from '../../../global';
|
||||
|
||||
import type { ISettings } from '../../../types';
|
||||
import type { AnimationLevel, ISettings } from '../../../types';
|
||||
import { LeftColumnContent, SettingsScreens } from '../../../types';
|
||||
import type { ApiChat } from '../../../api/types';
|
||||
import type { GlobalState } from '../../../global/types';
|
||||
@ -63,7 +63,7 @@ type StateProps =
|
||||
globalSearchChatId?: string;
|
||||
searchDate?: number;
|
||||
theme: ISettings['theme'];
|
||||
animationLevel: 0 | 1 | 2;
|
||||
animationLevel: AnimationLevel;
|
||||
chatsById?: Record<string, ApiChat>;
|
||||
isMessageListOpen: boolean;
|
||||
isConnectionStatusMinimized: ISettings['isConnectionStatusMinimized'];
|
||||
|
@ -5,6 +5,7 @@ import { getActions, withGlobal } from '../../../global';
|
||||
import type {
|
||||
ApiChat, ApiUser, ApiMessage, ApiMessageOutgoingStatus,
|
||||
} from '../../../api/types';
|
||||
import type { AnimationLevel } from '../../../types';
|
||||
|
||||
import { IS_SINGLE_COLUMN_LAYOUT } from '../../../util/environment';
|
||||
import {
|
||||
@ -47,6 +48,7 @@ type StateProps = {
|
||||
privateChatUser?: ApiUser;
|
||||
lastMessageOutgoingStatus?: ApiMessageOutgoingStatus;
|
||||
lastSyncTime?: number;
|
||||
animationLevel?: AnimationLevel;
|
||||
};
|
||||
|
||||
const ChatMessage: FC<OwnProps & StateProps> = ({
|
||||
@ -55,6 +57,7 @@ const ChatMessage: FC<OwnProps & StateProps> = ({
|
||||
chatId,
|
||||
chat,
|
||||
privateChatUser,
|
||||
animationLevel,
|
||||
lastSyncTime,
|
||||
}) => {
|
||||
const { focusMessage } = getActions();
|
||||
@ -87,6 +90,8 @@ const ChatMessage: FC<OwnProps & StateProps> = ({
|
||||
user={privateChatUser}
|
||||
isSavedMessages={privateChatUser?.isSelf}
|
||||
lastSyncTime={lastSyncTime}
|
||||
withVideo
|
||||
animationLevel={animationLevel}
|
||||
/>
|
||||
<div className="info">
|
||||
<div className="info-row">
|
||||
@ -141,6 +146,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
return {
|
||||
chat,
|
||||
lastSyncTime: global.lastSyncTime,
|
||||
animationLevel: global.settings.byKey.animationLevel,
|
||||
...(privateChatUserId && { privateChatUser: selectUser(global, privateChatUserId) }),
|
||||
};
|
||||
},
|
||||
|
@ -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';
|
||||
@ -26,6 +27,7 @@ type StateProps = {
|
||||
topUserIds?: string[];
|
||||
usersById: Record<string, ApiUser>;
|
||||
recentlyFoundChatIds?: string[];
|
||||
animationLevel: AnimationLevel;
|
||||
};
|
||||
|
||||
const SEARCH_CLOSE_TIMEOUT_MS = 250;
|
||||
@ -34,7 +36,10 @@ const NBSP = '\u00A0';
|
||||
const runThrottled = throttle((cb) => cb(), 60000, true);
|
||||
|
||||
const RecentContacts: FC<OwnProps & StateProps> = ({
|
||||
topUserIds, usersById, recentlyFoundChatIds,
|
||||
topUserIds,
|
||||
usersById,
|
||||
recentlyFoundChatIds,
|
||||
animationLevel,
|
||||
onReset,
|
||||
}) => {
|
||||
const {
|
||||
@ -72,7 +77,7 @@ const RecentContacts: FC<OwnProps & StateProps> = ({
|
||||
<div ref={topUsersRef} className="top-peers no-selection">
|
||||
{topUserIds.map((userId) => (
|
||||
<div className="top-peer-item" onClick={() => handleClick(userId)} dir={lang.isRtl ? 'rtl' : undefined}>
|
||||
<Avatar user={usersById[userId]} />
|
||||
<Avatar user={usersById[userId]} animationLevel={animationLevel} withVideo />
|
||||
<div className="top-peer-name">{renderText(getUserFirstOrLastName(usersById[userId]) || NBSP)}</div>
|
||||
</div>
|
||||
))}
|
||||
@ -112,11 +117,13 @@ export default memo(withGlobal<OwnProps>(
|
||||
const { userIds: topUserIds } = global.topPeers;
|
||||
const usersById = global.users.byId;
|
||||
const { recentlyFoundChatIds } = global.globalSearch;
|
||||
const { animationLevel } = global.settings.byKey;
|
||||
|
||||
return {
|
||||
topUserIds,
|
||||
usersById,
|
||||
recentlyFoundChatIds,
|
||||
animationLevel,
|
||||
};
|
||||
},
|
||||
)(RecentContacts));
|
||||
|
@ -3,6 +3,7 @@ import { getActions, withGlobal } from '../../../global';
|
||||
|
||||
import type { FC } from '../../../lib/teact/teact';
|
||||
import type { ApiUser, ApiWebSession } from '../../../api/types';
|
||||
import type { AnimationLevel } from '../../../types';
|
||||
|
||||
import { getUserFullName } from '../../../global/helpers';
|
||||
import buildClassName from '../../../util/buildClassName';
|
||||
@ -25,10 +26,15 @@ type OwnProps = {
|
||||
type StateProps = {
|
||||
session?: ApiWebSession;
|
||||
bot?: ApiUser;
|
||||
animationLevel: AnimationLevel;
|
||||
};
|
||||
|
||||
const SettingsActiveWebsite: FC<OwnProps & StateProps> = ({
|
||||
isOpen, session, bot, onClose,
|
||||
isOpen,
|
||||
session,
|
||||
bot,
|
||||
animationLevel,
|
||||
onClose,
|
||||
}) => {
|
||||
const { terminateWebAuthorization } = getActions();
|
||||
const lang = useLang();
|
||||
@ -70,7 +76,7 @@ const SettingsActiveWebsite: FC<OwnProps & StateProps> = ({
|
||||
onClose={onClose}
|
||||
className={styles.root}
|
||||
>
|
||||
<Avatar className={styles.avatar} user={renderingBot} size="large" />
|
||||
<Avatar className={styles.avatar} user={renderingBot} size="large" animationLevel={animationLevel} withVideo />
|
||||
<h3 className={styles.title} dir="auto">{getUserFullName(renderingBot)}</h3>
|
||||
<div className={styles.date} aria-label={lang('PrivacySettings.LastSeen')}>
|
||||
{renderingSession?.domain}
|
||||
@ -99,5 +105,6 @@ export default memo(withGlobal<OwnProps>((global, { hash }) => {
|
||||
return {
|
||||
session,
|
||||
bot,
|
||||
animationLevel: global.settings.byKey.animationLevel,
|
||||
};
|
||||
})(SettingsActiveWebsite));
|
||||
|
@ -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 { getUserFullName } from '../../../global/helpers';
|
||||
@ -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)}
|
||||
>
|
||||
<Avatar className={styles.avatar} user={bot} size="tiny" />
|
||||
<Avatar className={styles.avatar} user={bot} size="tiny" animationLevel={animationLevel} withVideo />
|
||||
<div className="multiline-menu-item full-size" dir="auto">
|
||||
<span className="date">{formatPastTimeShort(lang, session.dateActive * 1000)}</span>
|
||||
<span className="title">{getUserFullName(bot)}</span>
|
||||
@ -161,6 +164,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
return {
|
||||
byHash,
|
||||
orderedHashes,
|
||||
animationLevel: global.settings.byKey.animationLevel,
|
||||
};
|
||||
},
|
||||
)(SettingsActiveWebsites));
|
||||
|
@ -79,7 +79,7 @@ const SettingsPrivacyBlockedUsers: FC<OwnProps & StateProps> = ({
|
||||
}]}
|
||||
style={`top: ${(viewportOffset + i) * CHAT_HEIGHT_PX}px;`}
|
||||
>
|
||||
<Avatar size="medium" user={user} chat={chat} noVideo />
|
||||
<Avatar size="medium" user={user} chat={chat} />
|
||||
<div className="contact-info" dir="auto">
|
||||
<h3 dir="auto">{renderText((isPrivate ? getUserFullName(user) : getChatTitle(lang, chat!)) || '')}</h3>
|
||||
{user?.phoneNumber && (
|
||||
|
@ -5,6 +5,7 @@ import { getActions, withGlobal } from '../../global';
|
||||
import type {
|
||||
ApiContact, ApiError, ApiInviteInfo, ApiPhoto,
|
||||
} from '../../api/types';
|
||||
import type { AnimationLevel } from '../../types';
|
||||
|
||||
import getReadableErrorText from '../../util/getReadableErrorText';
|
||||
import { pick } from '../../util/iteratees';
|
||||
@ -20,9 +21,10 @@ import './Dialogs.scss';
|
||||
|
||||
type StateProps = {
|
||||
dialogs: (ApiError | ApiInviteInfo)[];
|
||||
animationLevel: AnimationLevel;
|
||||
};
|
||||
|
||||
const Dialogs: FC<StateProps> = ({ dialogs }) => {
|
||||
const Dialogs: FC<StateProps> = ({ dialogs, animationLevel }) => {
|
||||
const {
|
||||
dismissDialog,
|
||||
acceptInviteConfirmation,
|
||||
@ -46,7 +48,7 @@ const Dialogs: FC<StateProps> = ({ dialogs }) => {
|
||||
function renderInviteHeader(title: string, photo?: ApiPhoto) {
|
||||
return (
|
||||
<div className="modal-header">
|
||||
{photo && <Avatar size="small" photo={photo} />}
|
||||
{photo && <Avatar size="small" photo={photo} animationLevel={animationLevel} withVideo />}
|
||||
<div className="modal-title">
|
||||
{renderText(title)}
|
||||
</div>
|
||||
@ -194,5 +196,10 @@ function getErrorHeader(error: ApiError) {
|
||||
}
|
||||
|
||||
export default memo(withGlobal(
|
||||
(global): StateProps => pick(global, ['dialogs']),
|
||||
(global): StateProps => {
|
||||
return {
|
||||
dialogs: global.dialogs,
|
||||
animationLevel: global.settings.byKey.animationLevel,
|
||||
};
|
||||
},
|
||||
)(Dialogs));
|
||||
|
@ -4,7 +4,7 @@ import React, {
|
||||
} from '../../lib/teact/teact';
|
||||
import { getActions, getGlobal, withGlobal } from '../../global';
|
||||
|
||||
import type { LangCode } from '../../types';
|
||||
import type { AnimationLevel, LangCode } from '../../types';
|
||||
import type {
|
||||
ApiChat, ApiMessage, ApiUpdateAuthorizationStateType, ApiUpdateConnectionStateType, ApiUser,
|
||||
} from '../../api/types';
|
||||
@ -94,7 +94,7 @@ type StateProps = {
|
||||
openedCustomEmojiSetIds?: string[];
|
||||
activeGroupCallId?: string;
|
||||
isServiceChatReady?: boolean;
|
||||
animationLevel: number;
|
||||
animationLevel: AnimationLevel;
|
||||
language?: LangCode;
|
||||
wasTimeFormatSetManually?: boolean;
|
||||
isPhoneCallActive?: boolean;
|
||||
|
@ -5,6 +5,7 @@ import { getActions, withGlobal } from '../../../global';
|
||||
|
||||
import type { FC } from '../../../lib/teact/teact';
|
||||
import type { ApiPremiumGiftOption, ApiUser } from '../../../api/types';
|
||||
import type { AnimationLevel } from '../../../types';
|
||||
|
||||
import { formatCurrency } from '../../../util/formatCurrency';
|
||||
import renderText from '../../common/helpers/renderText';
|
||||
@ -31,10 +32,16 @@ type StateProps = {
|
||||
gifts?: ApiPremiumGiftOption[];
|
||||
monthlyCurrency?: string;
|
||||
monthlyAmount?: number;
|
||||
animationLevel: AnimationLevel;
|
||||
};
|
||||
|
||||
const GiftPremiumModal: FC<OwnProps & StateProps> = ({
|
||||
isOpen, user, gifts, monthlyCurrency, monthlyAmount,
|
||||
isOpen,
|
||||
user,
|
||||
gifts,
|
||||
monthlyCurrency,
|
||||
monthlyAmount,
|
||||
animationLevel,
|
||||
}) => {
|
||||
const { openPremiumModal, closeGiftPremiumModal, openUrl } = getActions();
|
||||
|
||||
@ -116,7 +123,7 @@ const GiftPremiumModal: FC<OwnProps & StateProps> = ({
|
||||
>
|
||||
<i className="icon-close" />
|
||||
</Button>
|
||||
<Avatar user={renderedUser} size="jumbo" className={styles.avatar} />
|
||||
<Avatar user={renderedUser} size="jumbo" className={styles.avatar} animationLevel={animationLevel} withVideo />
|
||||
<h2 className={styles.headerText}>
|
||||
{lang('GiftTelegramPremiumTitle')}
|
||||
</h2>
|
||||
@ -162,5 +169,6 @@ export default memo(withGlobal<OwnProps>((global): StateProps => {
|
||||
gifts,
|
||||
monthlyCurrency,
|
||||
monthlyAmount: monthlyAmount ? Number(monthlyAmount) : undefined,
|
||||
animationLevel: global.settings.byKey.animationLevel,
|
||||
};
|
||||
})(GiftPremiumModal));
|
||||
|
@ -6,6 +6,7 @@ import React, {
|
||||
import type {
|
||||
ApiChat, ApiMessage, ApiUser,
|
||||
} from '../../api/types';
|
||||
import type { AnimationLevel } from '../../types';
|
||||
import { MediaViewerOrigin } from '../../types';
|
||||
|
||||
import { getActions, withGlobal } from '../../global';
|
||||
@ -62,7 +63,7 @@ type StateProps = {
|
||||
message?: ApiMessage;
|
||||
chatMessages?: Record<number, ApiMessage>;
|
||||
collectionIds?: number[];
|
||||
animationLevel: 0 | 1 | 2;
|
||||
animationLevel: AnimationLevel;
|
||||
};
|
||||
|
||||
const ANIMATION_DURATION = 350;
|
||||
|
@ -5,6 +5,7 @@ import { withGlobal } from '../../global';
|
||||
import type {
|
||||
ApiChat, ApiDimensions, ApiMessage, ApiUser,
|
||||
} from '../../api/types';
|
||||
import type { AnimationLevel } from '../../types';
|
||||
import { MediaViewerOrigin } from '../../types';
|
||||
|
||||
import { IS_SINGLE_COLUMN_LAYOUT, IS_TOUCH_ENV } from '../../util/environment';
|
||||
@ -30,7 +31,7 @@ type OwnProps = {
|
||||
avatarOwnerId?: string;
|
||||
origin?: MediaViewerOrigin;
|
||||
isActive?: boolean;
|
||||
animationLevel: 0 | 1 | 2;
|
||||
animationLevel: AnimationLevel;
|
||||
onClose: () => void;
|
||||
onFooterClick: () => void;
|
||||
setControlsVisible?: (isVisible: boolean) => void;
|
||||
|
@ -3,7 +3,7 @@ import React, {
|
||||
memo, useCallback, useEffect, useRef, useState,
|
||||
} from '../../lib/teact/teact';
|
||||
|
||||
import type { MediaViewerOrigin } from '../../types';
|
||||
import type { AnimationLevel, MediaViewerOrigin } from '../../types';
|
||||
import type { RealTouchEvent } from '../../util/captureEvents';
|
||||
|
||||
import { animateNumber, timingFunctions } from '../../util/animation';
|
||||
@ -38,7 +38,7 @@ type OwnProps = {
|
||||
threadId?: number;
|
||||
avatarOwnerId?: string;
|
||||
origin?: MediaViewerOrigin;
|
||||
animationLevel: 0 | 1 | 2;
|
||||
animationLevel: AnimationLevel;
|
||||
onClose: () => void;
|
||||
hasFooter?: boolean;
|
||||
onFooterClick: () => void;
|
||||
|
@ -3,6 +3,7 @@ import React, { useCallback } from '../../lib/teact/teact';
|
||||
import { getActions, withGlobal } from '../../global';
|
||||
|
||||
import type { ApiChat, ApiMessage, ApiUser } from '../../api/types';
|
||||
import type { AnimationLevel } from '../../types';
|
||||
|
||||
import { IS_SINGLE_COLUMN_LAYOUT } from '../../util/environment';
|
||||
import { getSenderTitle, isUserId } from '../../global/helpers';
|
||||
@ -29,6 +30,7 @@ type OwnProps = {
|
||||
type StateProps = {
|
||||
sender?: ApiUser | ApiChat;
|
||||
message?: ApiMessage;
|
||||
animationLevel: AnimationLevel;
|
||||
};
|
||||
|
||||
const ANIMATION_DURATION = 350;
|
||||
@ -39,6 +41,7 @@ const SenderInfo: FC<OwnProps & StateProps> = ({
|
||||
sender,
|
||||
isAvatar,
|
||||
message,
|
||||
animationLevel,
|
||||
}) => {
|
||||
const {
|
||||
closeMediaViewer,
|
||||
@ -70,9 +73,9 @@ const SenderInfo: FC<OwnProps & StateProps> = ({
|
||||
return (
|
||||
<div className="SenderInfo" onClick={handleFocusMessage}>
|
||||
{isUserId(sender.id) ? (
|
||||
<Avatar key={sender.id} size="medium" user={sender as ApiUser} />
|
||||
<Avatar key={sender.id} size="medium" user={sender as ApiUser} animationLevel={animationLevel} withVideo />
|
||||
) : (
|
||||
<Avatar key={sender.id} size="medium" chat={sender as ApiChat} />
|
||||
<Avatar key={sender.id} size="medium" chat={sender as ApiChat} animationLevel={animationLevel} withVideo />
|
||||
)}
|
||||
<div className="meta">
|
||||
<div className="title" dir="auto">
|
||||
@ -90,14 +93,16 @@ const SenderInfo: FC<OwnProps & StateProps> = ({
|
||||
|
||||
export default withGlobal<OwnProps>(
|
||||
(global, { chatId, messageId, isAvatar }): StateProps => {
|
||||
const { animationLevel } = global.settings.byKey;
|
||||
if (isAvatar && chatId) {
|
||||
return {
|
||||
sender: isUserId(chatId) ? selectUser(global, chatId) : selectChat(global, chatId),
|
||||
animationLevel,
|
||||
};
|
||||
}
|
||||
|
||||
if (!messageId || !chatId) {
|
||||
return {};
|
||||
return { animationLevel };
|
||||
}
|
||||
|
||||
const message = selectChatMessage(global, chatId, messageId);
|
||||
@ -105,6 +110,7 @@ export default withGlobal<OwnProps>(
|
||||
return {
|
||||
message,
|
||||
sender: message && selectSender(global, message),
|
||||
animationLevel,
|
||||
};
|
||||
},
|
||||
)(SenderInfo);
|
||||
|
@ -7,6 +7,7 @@ import { getActions, getGlobal, withGlobal } from '../../global';
|
||||
import type { ApiBotInfo, ApiMessage, ApiRestrictionReason } from '../../api/types';
|
||||
import { MAIN_THREAD_ID } from '../../api/types';
|
||||
import type { MessageListType } from '../../global/types';
|
||||
import type { AnimationLevel } from '../../types';
|
||||
import { LoadMoreDirection } from '../../types';
|
||||
|
||||
import { ANIMATION_END_DELAY, LOCAL_MESSAGE_MIN_ID, MESSAGE_LIST_SLICE } from '../../config';
|
||||
@ -95,7 +96,7 @@ type StateProps = {
|
||||
restrictionReason?: ApiRestrictionReason;
|
||||
focusingId?: number;
|
||||
isSelectModeActive?: boolean;
|
||||
animationLevel?: number;
|
||||
animationLevel?: AnimationLevel;
|
||||
lastMessage?: ApiMessage;
|
||||
isLoadingBotInfo?: boolean;
|
||||
botInfo?: ApiBotInfo;
|
||||
|
@ -10,7 +10,7 @@ import type {
|
||||
MessageListType,
|
||||
ActiveEmojiInteraction,
|
||||
} from '../../global/types';
|
||||
import type { ThemeKey } from '../../types';
|
||||
import type { AnimationLevel, ThemeKey } from '../../types';
|
||||
|
||||
import {
|
||||
MIN_SCREEN_WIDTH_FOR_STATIC_LEFT_COLUMN,
|
||||
@ -100,7 +100,7 @@ type StateProps = {
|
||||
isSeenByModalOpen: boolean;
|
||||
isReactorListModalOpen: boolean;
|
||||
isGiftPremiumModalOpen?: boolean;
|
||||
animationLevel?: number;
|
||||
animationLevel: AnimationLevel;
|
||||
shouldSkipHistoryAnimations?: boolean;
|
||||
currentTransitionKey: number;
|
||||
isChannel?: boolean;
|
||||
|
@ -5,6 +5,7 @@ import React, {
|
||||
import { getActions, getGlobal, withGlobal } from '../../global';
|
||||
|
||||
import type { ApiMessage } from '../../api/types';
|
||||
import type { AnimationLevel } from '../../types';
|
||||
import { LoadMoreDirection } from '../../types';
|
||||
|
||||
import useLang from '../../hooks/useLang';
|
||||
@ -37,6 +38,7 @@ export type OwnProps = {
|
||||
export type StateProps = Pick<ApiMessage, 'reactors' | 'reactions' | 'seenByUserIds'> & {
|
||||
chatId?: string;
|
||||
messageId?: number;
|
||||
animationLevel: AnimationLevel;
|
||||
};
|
||||
|
||||
const ReactorListModal: FC<OwnProps & StateProps> = ({
|
||||
@ -46,6 +48,7 @@ const ReactorListModal: FC<OwnProps & StateProps> = ({
|
||||
chatId,
|
||||
messageId,
|
||||
seenByUserIds,
|
||||
animationLevel,
|
||||
}) => {
|
||||
const {
|
||||
loadReactors,
|
||||
@ -169,7 +172,7 @@ const ReactorListModal: FC<OwnProps & StateProps> = ({
|
||||
// eslint-disable-next-line react/jsx-no-bind
|
||||
onClick={() => handleClick(userId)}
|
||||
>
|
||||
<Avatar user={user} size="small" />
|
||||
<Avatar user={user} size="small" animationLevel={animationLevel} withVideo />
|
||||
<div className="title">
|
||||
<h3 dir="auto">{fullName && renderText(fullName)}</h3>
|
||||
{user.isPremium && <PremiumIcon />}
|
||||
@ -204,6 +207,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
reactions: message?.reactions,
|
||||
reactors: message?.reactors,
|
||||
seenByUserIds: message?.seenByUserIds,
|
||||
animationLevel: global.settings.byKey.animationLevel,
|
||||
};
|
||||
},
|
||||
)(ReactorListModal));
|
||||
|
@ -36,7 +36,7 @@ const BotCommand: FC<OwnProps> = ({
|
||||
focus={focus}
|
||||
>
|
||||
{withAvatar && (
|
||||
<Avatar size="small" user={bot} noVideo />
|
||||
<Avatar size="small" user={bot} />
|
||||
)}
|
||||
<div className="content-inner">
|
||||
<span className="title">/{botCommand.command}</span>
|
||||
|
@ -1128,7 +1128,6 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
user={sendAsUser}
|
||||
chat={sendAsChat}
|
||||
size="tiny"
|
||||
noVideo
|
||||
/>
|
||||
</Button>
|
||||
)}
|
||||
|
@ -285,7 +285,7 @@ const StickerPicker: FC<OwnProps & StateProps> = ({
|
||||
) : stickerSet.id === FAVORITE_SYMBOL_SET_ID ? (
|
||||
<i className="icon-favorite" />
|
||||
) : stickerSet.id === CHAT_STICKER_SET_ID ? (
|
||||
<Avatar chat={chat} size="small" noVideo />
|
||||
<Avatar chat={chat} size="small" />
|
||||
) : stickerSet.isLottie ? (
|
||||
<StickerSetCoverAnimated
|
||||
stickerSet={stickerSet as ApiStickerSet}
|
||||
|
@ -62,7 +62,6 @@ const CommentButton: FC<OwnProps> = ({
|
||||
size="small"
|
||||
user={isUserId(user.id) ? user as ApiUser : undefined}
|
||||
chat={!isUserId(user.id) ? user as ApiChat : undefined}
|
||||
noVideo
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
@ -3,6 +3,7 @@ import React, { useCallback } from '../../../lib/teact/teact';
|
||||
import { getActions, withGlobal } from '../../../global';
|
||||
|
||||
import type { ApiUser, ApiContact, ApiCountryCode } from '../../../api/types';
|
||||
import type { AnimationLevel } from '../../../types';
|
||||
|
||||
import { selectUser } from '../../../global/selectors';
|
||||
import { formatPhoneNumberWithCode } from '../../../util/phoneNumber';
|
||||
@ -19,12 +20,13 @@ type OwnProps = {
|
||||
type StateProps = {
|
||||
user?: ApiUser;
|
||||
phoneCodeList: ApiCountryCode[];
|
||||
animationLevel: AnimationLevel;
|
||||
};
|
||||
|
||||
const UNREGISTERED_CONTACT_ID = '0';
|
||||
|
||||
const Contact: FC<OwnProps & StateProps> = ({
|
||||
contact, user, phoneCodeList,
|
||||
contact, user, phoneCodeList, animationLevel,
|
||||
}) => {
|
||||
const { openChat } = getActions();
|
||||
|
||||
@ -45,7 +47,7 @@ const Contact: FC<OwnProps & StateProps> = ({
|
||||
className={buildClassName('Contact', isRegistered && 'interactive')}
|
||||
onClick={isRegistered ? handleClick : undefined}
|
||||
>
|
||||
<Avatar size="large" user={user} text={firstName || lastName} />
|
||||
<Avatar size="large" user={user} text={firstName || lastName} animationLevel={animationLevel} withVideo />
|
||||
<div className="contact-info">
|
||||
<div className="contact-name">{firstName} {lastName}</div>
|
||||
<div className="contact-phone">{formatPhoneNumberWithCode(phoneCodeList, phoneNumber)}</div>
|
||||
@ -60,6 +62,7 @@ export default withGlobal<OwnProps>(
|
||||
return {
|
||||
user: selectUser(global, contact.userId),
|
||||
phoneCodeList,
|
||||
animationLevel: global.settings.byKey.animationLevel,
|
||||
};
|
||||
},
|
||||
)(Contact);
|
||||
|
@ -18,7 +18,9 @@ import type {
|
||||
ApiThreadInfo,
|
||||
ApiAvailableReaction,
|
||||
} from '../../../api/types';
|
||||
import type { FocusDirection, IAlbum, ISettings } from '../../../types';
|
||||
import type {
|
||||
AnimationLevel, FocusDirection, IAlbum, ISettings,
|
||||
} from '../../../types';
|
||||
import {
|
||||
AudioOrigin,
|
||||
} from '../../../types';
|
||||
@ -198,6 +200,7 @@ type StateProps = {
|
||||
transcribedText?: string;
|
||||
isTranscriptionError?: boolean;
|
||||
isPremium: boolean;
|
||||
animationLevel: AnimationLevel;
|
||||
};
|
||||
|
||||
type MetaPosition =
|
||||
@ -285,6 +288,7 @@ const Message: FC<OwnProps & StateProps> = ({
|
||||
threadInfo,
|
||||
hasUnreadReaction,
|
||||
memoFirstUnreadIdRef,
|
||||
animationLevel,
|
||||
}) => {
|
||||
const {
|
||||
toggleMessageSelection,
|
||||
@ -617,6 +621,8 @@ const Message: FC<OwnProps & StateProps> = ({
|
||||
lastSyncTime={lastSyncTime}
|
||||
onClick={(avatarUser || avatarChat) ? handleAvatarClick : undefined}
|
||||
observeIntersection={observeIntersectionForMedia}
|
||||
animationLevel={animationLevel}
|
||||
withVideo
|
||||
/>
|
||||
{isAvatarPremium && <PremiumIcon className="chat-avatar-premium" />}
|
||||
</>
|
||||
@ -1176,6 +1182,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
isTranscribing: transcriptionId !== undefined && global.transcriptions[transcriptionId]?.isPending,
|
||||
transcribedText: transcriptionId !== undefined ? global.transcriptions[transcriptionId]?.text : undefined,
|
||||
isPremium: selectIsCurrentUserPremium(global),
|
||||
animationLevel: global.settings.byKey.animationLevel,
|
||||
};
|
||||
},
|
||||
)(Message));
|
||||
|
@ -348,7 +348,6 @@ const MessageContextMenu: FC<OwnProps> = ({
|
||||
<Avatar
|
||||
size="micro"
|
||||
user={user}
|
||||
noVideo
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
@ -234,7 +234,6 @@ const Poll: FC<OwnProps & StateProps> = ({
|
||||
<Avatar
|
||||
size="micro"
|
||||
user={user}
|
||||
noVideo
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
@ -68,7 +68,7 @@ const ReactionButton: FC<{
|
||||
/>
|
||||
{recentReactors?.length ? (
|
||||
<div className="avatars">
|
||||
{recentReactors.map((user) => <Avatar user={user} size="micro" noVideo />)}
|
||||
{recentReactors.map((user) => <Avatar user={user} size="micro" />)}
|
||||
</div>
|
||||
) : formatIntegerCompact(reaction.count)}
|
||||
</Button>
|
||||
|
@ -1,8 +1,9 @@
|
||||
import type { FC } from '../../lib/teact/teact';
|
||||
import React, { useMemo, memo, useRef } from '../../lib/teact/teact';
|
||||
import { getActions, getGlobal, withGlobal } from '../../global';
|
||||
|
||||
import type { FC } from '../../lib/teact/teact';
|
||||
import type { ApiMessage, ApiUser, ApiChat } from '../../api/types';
|
||||
import type { AnimationLevel } from '../../types';
|
||||
|
||||
import { MEMO_EMPTY_ARRAY } from '../../util/memo';
|
||||
import {
|
||||
@ -43,18 +44,20 @@ type StateProps = {
|
||||
query?: string;
|
||||
totalCount?: number;
|
||||
foundIds?: number[];
|
||||
animationLevel?: AnimationLevel;
|
||||
};
|
||||
|
||||
const RightSearch: FC<OwnProps & StateProps> = ({
|
||||
chatId,
|
||||
threadId,
|
||||
onClose,
|
||||
isActive,
|
||||
chat,
|
||||
messagesById,
|
||||
query,
|
||||
totalCount,
|
||||
foundIds,
|
||||
animationLevel,
|
||||
onClose,
|
||||
}) => {
|
||||
const {
|
||||
searchTextMessagesLocal,
|
||||
@ -129,7 +132,7 @@ const RightSearch: FC<OwnProps & StateProps> = ({
|
||||
className="chat-item-clickable search-result-message m-0"
|
||||
onClick={onClick}
|
||||
>
|
||||
<Avatar chat={senderChat} user={senderUser} />
|
||||
<Avatar chat={senderChat} user={senderUser} animationLevel={animationLevel} withVideo />
|
||||
<div className="info">
|
||||
<div className="title">
|
||||
<h3 dir="auto">{title && renderText(title)}</h3>
|
||||
@ -189,6 +192,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
query,
|
||||
totalCount,
|
||||
foundIds,
|
||||
animationLevel: global.settings.byKey.animationLevel,
|
||||
};
|
||||
},
|
||||
)(RightSearch));
|
||||
|
@ -2,6 +2,7 @@ import type { FC } from '../../../lib/teact/teact';
|
||||
import React, { memo, useCallback } from '../../../lib/teact/teact';
|
||||
import { getActions, withGlobal } from '../../../global';
|
||||
|
||||
import type { AnimationLevel } from '../../../types';
|
||||
import type { ApiUser } from '../../../api/types';
|
||||
|
||||
import useLang from '../../../hooks/useLang';
|
||||
@ -27,17 +28,19 @@ type OwnProps = {
|
||||
type StateProps = {
|
||||
user?: ApiUser;
|
||||
isSavedMessages?: boolean;
|
||||
animationLevel: AnimationLevel;
|
||||
serverTimeOffset: number;
|
||||
};
|
||||
|
||||
const JoinRequest: FC<OwnProps & StateProps> = ({
|
||||
userId,
|
||||
chatId,
|
||||
about,
|
||||
date,
|
||||
isChannel,
|
||||
user,
|
||||
animationLevel,
|
||||
serverTimeOffset,
|
||||
chatId,
|
||||
}) => {
|
||||
const { openChat, hideChatJoinRequest } = getActions();
|
||||
|
||||
@ -70,6 +73,8 @@ const JoinRequest: FC<OwnProps & StateProps> = ({
|
||||
key={userId}
|
||||
size="medium"
|
||||
user={user}
|
||||
animationLevel={animationLevel}
|
||||
withVideo
|
||||
/>
|
||||
<div className={buildClassName('user-info')}>
|
||||
<div className={buildClassName('user-name')}>{fullName}</div>
|
||||
@ -96,6 +101,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
|
||||
return {
|
||||
user,
|
||||
animationLevel: global.settings.byKey.animationLevel,
|
||||
serverTimeOffset: global.serverTimeOffset,
|
||||
};
|
||||
},
|
||||
|
@ -27,6 +27,7 @@ export interface IAlbum {
|
||||
}
|
||||
|
||||
export type ThemeKey = 'light' | 'dark';
|
||||
export type AnimationLevel = 0 | 1 | 2;
|
||||
|
||||
export interface IThemeSettings {
|
||||
background?: string;
|
||||
@ -59,7 +60,7 @@ export interface ISettings extends NotifySettings, Record<string, any> {
|
||||
theme: ThemeKey;
|
||||
shouldUseSystemTheme: boolean;
|
||||
messageTextSize: number;
|
||||
animationLevel: 0 | 1 | 2;
|
||||
animationLevel: AnimationLevel;
|
||||
messageSendKeyCombo: 'enter' | 'ctrl-enter';
|
||||
canAutoLoadPhotoFromContacts: boolean;
|
||||
canAutoLoadPhotoInPrivateChats: boolean;
|
||||
|
Loading…
Reference in New Issue
Block a user