TelegramPWA/src/components/common/PrivateChatInfo.tsx
2021-11-05 22:03:02 +03:00

155 lines
4.4 KiB
TypeScript

import { MouseEvent as ReactMouseEvent } from 'react';
import React, {
FC, useEffect, useCallback, memo,
} from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn';
import { ApiUser, ApiTypingStatus } from '../../api/types';
import { GlobalActions, GlobalState } from '../../global/types';
import { MediaViewerOrigin } from '../../types';
import { selectChatMessages, selectUser } from '../../modules/selectors';
import { getUserFullName, getUserStatus, isUserOnline } from '../../modules/helpers';
import renderText from './helpers/renderText';
import { pick } from '../../util/iteratees';
import useLang from '../../hooks/useLang';
import Avatar from './Avatar';
import VerifiedIcon from './VerifiedIcon';
import TypingStatus from './TypingStatus';
type OwnProps = {
userId: string;
typingStatus?: ApiTypingStatus;
avatarSize?: 'tiny' | 'small' | 'medium' | 'large' | 'jumbo';
forceShowSelf?: boolean;
status?: string;
withMediaViewer?: boolean;
withUsername?: boolean;
withFullInfo?: boolean;
withUpdatingStatus?: boolean;
noStatusOrTyping?: boolean;
noRtl?: boolean;
};
type StateProps = {
user?: ApiUser;
isSavedMessages?: boolean;
areMessagesLoaded: boolean;
serverTimeOffset: number;
} & Pick<GlobalState, 'lastSyncTime'>;
type DispatchProps = Pick<GlobalActions, 'loadFullUser' | 'openMediaViewer'>;
const PrivateChatInfo: FC<OwnProps & StateProps & DispatchProps> = ({
typingStatus,
avatarSize = 'medium',
status,
withMediaViewer,
withUsername,
withFullInfo,
withUpdatingStatus,
noStatusOrTyping,
noRtl,
user,
isSavedMessages,
areMessagesLoaded,
lastSyncTime,
serverTimeOffset,
loadFullUser,
openMediaViewer,
}) => {
const { id: userId } = user || {};
const fullName = getUserFullName(user);
useEffect(() => {
if (withFullInfo && lastSyncTime && userId) {
loadFullUser({ userId });
}
}, [userId, loadFullUser, lastSyncTime, withFullInfo]);
const handleAvatarViewerOpen = useCallback((e: ReactMouseEvent<HTMLDivElement, MouseEvent>, hasPhoto: boolean) => {
if (user && hasPhoto) {
e.stopPropagation();
openMediaViewer({
avatarOwnerId: user.id,
origin: avatarSize === 'jumbo' ? MediaViewerOrigin.ProfileAvatar : MediaViewerOrigin.MiddleHeaderAvatar,
});
}
}, [user, avatarSize, openMediaViewer]);
const lang = useLang();
if (!user) {
return undefined;
}
function renderStatusOrTyping() {
if (status) {
return (
<span className="status" dir="auto">{status}</span>
);
}
if (withUpdatingStatus && !areMessagesLoaded) {
return (
<span className="status" dir="auto">{lang('Updating')}</span>
);
}
if (!user) {
return undefined;
}
if (typingStatus) {
return <TypingStatus typingStatus={typingStatus} />;
}
return (
<div className={`status ${isUserOnline(user) ? 'online' : ''}`}>
{withUsername && user.username && <span className="handle">{user.username}</span>}
<span className="user-status" dir="auto">{getUserStatus(lang, user, serverTimeOffset)}</span>
</div>
);
}
return (
<div className="ChatInfo" dir={!noRtl && lang.isRtl ? 'rtl' : undefined}>
<Avatar
key={user.id}
size={avatarSize}
user={user}
isSavedMessages={isSavedMessages}
onClick={withMediaViewer ? handleAvatarViewerOpen : undefined}
/>
<div className="info">
{isSavedMessages ? (
<div className="title">
<h3>{lang('SavedMessages')}</h3>
</div>
) : (
<div className="title">
<h3 dir="auto">{fullName && renderText(fullName)}</h3>
{user?.isVerified && <VerifiedIcon />}
</div>
)}
{(status || (!isSavedMessages && !noStatusOrTyping)) && renderStatusOrTyping()}
</div>
</div>
);
};
export default memo(withGlobal<OwnProps>(
(global, { userId, forceShowSelf }): StateProps => {
const { lastSyncTime, serverTimeOffset } = global;
const user = selectUser(global, userId);
const isSavedMessages = !forceShowSelf && user && user.isSelf;
const areMessagesLoaded = Boolean(selectChatMessages(global, userId));
return {
lastSyncTime, user, isSavedMessages, areMessagesLoaded, serverTimeOffset,
};
},
(setGlobal, actions): DispatchProps => pick(actions, ['loadFullUser', 'openMediaViewer']),
)(PrivateChatInfo));