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