[Refactoring] User: Extract nested data to a separate path (#4953)
This commit is contained in:
parent
8b76de86ba
commit
25b4aae4cd
@ -5,7 +5,6 @@ import type {
|
|||||||
ApiChat, ApiPeer, ApiSticker, ApiUser,
|
ApiChat, ApiPeer, ApiSticker, ApiUser,
|
||||||
} from '../../types';
|
} from '../../types';
|
||||||
|
|
||||||
import { COMMON_CHATS_LIMIT } from '../../../config';
|
|
||||||
import { buildApiChatFromPreview } from '../apiBuilders/chats';
|
import { buildApiChatFromPreview } from '../apiBuilders/chats';
|
||||||
import { buildApiPhoto } from '../apiBuilders/common';
|
import { buildApiPhoto } from '../apiBuilders/common';
|
||||||
import { buildApiPeerId } from '../apiBuilders/peers';
|
import { buildApiPeerId } from '../apiBuilders/peers';
|
||||||
@ -87,21 +86,21 @@ export async function fetchFullUser({
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchCommonChats(id: string, accessHash?: string, maxId?: string) {
|
export async function fetchCommonChats(user: ApiUser, maxId?: string) {
|
||||||
const commonChats = await invokeRequest(new GramJs.messages.GetCommonChats({
|
const result = await invokeRequest(new GramJs.messages.GetCommonChats({
|
||||||
userId: buildInputEntity(id, accessHash) as GramJs.InputUser,
|
userId: buildInputEntity(user.id, user.accessHash) as GramJs.InputUser,
|
||||||
maxId: maxId ? buildMtpPeerId(maxId, getEntityTypeById(maxId)) : undefined,
|
maxId: maxId ? buildMtpPeerId(maxId, getEntityTypeById(maxId)) : undefined,
|
||||||
limit: COMMON_CHATS_LIMIT,
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
if (!commonChats) {
|
if (!result) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const chats = commonChats.chats.map((c) => buildApiChatFromPreview(c)).filter(Boolean);
|
const chats = result.chats.map((c) => buildApiChatFromPreview(c)).filter(Boolean);
|
||||||
const chatIds = chats.map(({ id: chatId }) => chatId);
|
const chatIds = chats.map(({ id: chatId }) => chatId);
|
||||||
|
const count = 'count' in result ? result.count : chatIds.length;
|
||||||
|
|
||||||
return { chatIds, isFullyLoaded: chatIds.length < COMMON_CHATS_LIMIT };
|
return { chatIds, count };
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchNearestCountry() {
|
export async function fetchNearestCountry() {
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import type { ApiBotCommand } from './bots';
|
|||||||
import type {
|
import type {
|
||||||
ApiChatReactions, ApiFormattedText, ApiPhoto, ApiStickerSet,
|
ApiChatReactions, ApiFormattedText, ApiPhoto, ApiStickerSet,
|
||||||
} from './messages';
|
} from './messages';
|
||||||
import type { ApiChatInviteImporter, ApiPeerPhotos } from './misc';
|
import type { ApiChatInviteImporter } from './misc';
|
||||||
import type {
|
import type {
|
||||||
ApiEmojiStatus, ApiFakeType, ApiUser, ApiUsername,
|
ApiEmojiStatus, ApiFakeType, ApiUser, ApiUsername,
|
||||||
} from './users';
|
} from './users';
|
||||||
@ -41,7 +41,6 @@ export interface ApiChat {
|
|||||||
membersCount?: number;
|
membersCount?: number;
|
||||||
creationDate?: number;
|
creationDate?: number;
|
||||||
isSupport?: true;
|
isSupport?: true;
|
||||||
profilePhotos?: ApiPeerPhotos;
|
|
||||||
draftDate?: number;
|
draftDate?: number;
|
||||||
isProtected?: boolean;
|
isProtected?: boolean;
|
||||||
fakeType?: ApiFakeType;
|
fakeType?: ApiFakeType;
|
||||||
|
|||||||
@ -3,7 +3,6 @@ import type { ApiBotInfo } from './bots';
|
|||||||
import type { ApiBusinessIntro, ApiBusinessLocation, ApiBusinessWorkHours } from './business';
|
import type { ApiBusinessIntro, ApiBusinessLocation, ApiBusinessWorkHours } from './business';
|
||||||
import type { ApiPeerColor } from './chats';
|
import type { ApiPeerColor } from './chats';
|
||||||
import type { ApiDocument, ApiPhoto } from './messages';
|
import type { ApiDocument, ApiPhoto } from './messages';
|
||||||
import type { ApiPeerPhotos } from './misc';
|
|
||||||
|
|
||||||
export interface ApiUser {
|
export interface ApiUser {
|
||||||
id: string;
|
id: string;
|
||||||
@ -23,14 +22,8 @@ export interface ApiUser {
|
|||||||
accessHash?: string;
|
accessHash?: string;
|
||||||
hasVideoAvatar?: boolean;
|
hasVideoAvatar?: boolean;
|
||||||
avatarPhotoId?: string;
|
avatarPhotoId?: string;
|
||||||
profilePhotos?: ApiPeerPhotos;
|
|
||||||
botPlaceholder?: string;
|
botPlaceholder?: string;
|
||||||
canBeInvitedToGroup?: boolean;
|
canBeInvitedToGroup?: boolean;
|
||||||
commonChats?: {
|
|
||||||
ids: string[];
|
|
||||||
maxId: string;
|
|
||||||
isFullyLoaded: boolean;
|
|
||||||
};
|
|
||||||
fakeType?: ApiFakeType;
|
fakeType?: ApiFakeType;
|
||||||
isAttachBot?: boolean;
|
isAttachBot?: boolean;
|
||||||
emojiStatus?: ApiEmojiStatus;
|
emojiStatus?: ApiEmojiStatus;
|
||||||
@ -82,6 +75,12 @@ export interface ApiUserStatus {
|
|||||||
isReadDateRestricted?: boolean;
|
isReadDateRestricted?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ApiUserCommonChats {
|
||||||
|
ids: string[];
|
||||||
|
maxId?: string;
|
||||||
|
isFullyLoaded: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ApiUsername {
|
export interface ApiUsername {
|
||||||
username: string;
|
username: string;
|
||||||
isActive?: boolean;
|
isActive?: boolean;
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import React, { memo, useEffect, useState } from '../../lib/teact/teact';
|
|||||||
import { getActions, withGlobal } from '../../global';
|
import { getActions, withGlobal } from '../../global';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
ApiChat, ApiSticker, ApiTopic, ApiUser, ApiUserStatus,
|
ApiChat, ApiPeerPhotos, ApiSticker, ApiTopic, ApiUser, ApiUserStatus,
|
||||||
} from '../../api/types';
|
} from '../../api/types';
|
||||||
import { MediaViewerOrigin } from '../../types';
|
import { MediaViewerOrigin } from '../../types';
|
||||||
|
|
||||||
@ -13,6 +13,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
selectChat,
|
selectChat,
|
||||||
selectCurrentMessageList,
|
selectCurrentMessageList,
|
||||||
|
selectPeerPhotos,
|
||||||
selectTabState,
|
selectTabState,
|
||||||
selectThreadMessagesCount,
|
selectThreadMessagesCount,
|
||||||
selectUser,
|
selectUser,
|
||||||
@ -54,6 +55,7 @@ type StateProps =
|
|||||||
topic?: ApiTopic;
|
topic?: ApiTopic;
|
||||||
messagesCount?: number;
|
messagesCount?: number;
|
||||||
emojiStatusSticker?: ApiSticker;
|
emojiStatusSticker?: ApiSticker;
|
||||||
|
profilePhotos?: ApiPeerPhotos;
|
||||||
};
|
};
|
||||||
|
|
||||||
const EMOJI_STATUS_SIZE = 24;
|
const EMOJI_STATUS_SIZE = 24;
|
||||||
@ -72,6 +74,7 @@ const ProfileInfo: FC<OwnProps & StateProps> = ({
|
|||||||
topic,
|
topic,
|
||||||
messagesCount,
|
messagesCount,
|
||||||
emojiStatusSticker,
|
emojiStatusSticker,
|
||||||
|
profilePhotos,
|
||||||
peerId,
|
peerId,
|
||||||
}) => {
|
}) => {
|
||||||
const {
|
const {
|
||||||
@ -84,9 +87,7 @@ const ProfileInfo: FC<OwnProps & StateProps> = ({
|
|||||||
|
|
||||||
const lang = useOldLang();
|
const lang = useOldLang();
|
||||||
|
|
||||||
const userProfilePhotos = user?.profilePhotos;
|
const photos = profilePhotos?.photos || MEMO_EMPTY_ARRAY;
|
||||||
const chatProfilePhotos = chat?.profilePhotos;
|
|
||||||
const photos = userProfilePhotos?.photos || chatProfilePhotos?.photos || MEMO_EMPTY_ARRAY;
|
|
||||||
const prevMediaIndex = usePreviousDeprecated(mediaIndex);
|
const prevMediaIndex = usePreviousDeprecated(mediaIndex);
|
||||||
const prevAvatarOwnerId = usePreviousDeprecated(avatarOwnerId);
|
const prevAvatarOwnerId = usePreviousDeprecated(avatarOwnerId);
|
||||||
const [hasSlideAnimation, setHasSlideAnimation] = useState(true);
|
const [hasSlideAnimation, setHasSlideAnimation] = useState(true);
|
||||||
@ -213,7 +214,7 @@ const ProfileInfo: FC<OwnProps & StateProps> = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
function renderPhotoTabs() {
|
function renderPhotoTabs() {
|
||||||
const totalPhotosLength = Math.max(photos.length, userProfilePhotos?.count || 0, chatProfilePhotos?.count || 0);
|
const totalPhotosLength = Math.max(photos.length, profilePhotos?.count || 0);
|
||||||
if (!photos || totalPhotosLength <= 1) {
|
if (!photos || totalPhotosLength <= 1) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
@ -293,18 +294,18 @@ const ProfileInfo: FC<OwnProps & StateProps> = ({
|
|||||||
>
|
>
|
||||||
<div className={styles.photoWrapper}>
|
<div className={styles.photoWrapper}>
|
||||||
{renderPhotoTabs()}
|
{renderPhotoTabs()}
|
||||||
{!forceShowSelf && userProfilePhotos?.personalPhoto && (
|
{!forceShowSelf && profilePhotos?.personalPhoto && (
|
||||||
<div className={buildClassName(
|
<div className={buildClassName(
|
||||||
styles.fallbackPhoto,
|
styles.fallbackPhoto,
|
||||||
isFirst && styles.fallbackPhotoVisible,
|
isFirst && styles.fallbackPhotoVisible,
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className={styles.fallbackPhotoContents}>
|
<div className={styles.fallbackPhotoContents}>
|
||||||
{lang(userProfilePhotos.personalPhoto.isVideo ? 'UserInfo.CustomVideo' : 'UserInfo.CustomPhoto')}
|
{lang(profilePhotos.personalPhoto.isVideo ? 'UserInfo.CustomVideo' : 'UserInfo.CustomPhoto')}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{forceShowSelf && userProfilePhotos?.fallbackPhoto && (
|
{forceShowSelf && profilePhotos?.fallbackPhoto && (
|
||||||
<div className={buildClassName(
|
<div className={buildClassName(
|
||||||
styles.fallbackPhoto,
|
styles.fallbackPhoto,
|
||||||
(isFirst || isLast) && styles.fallbackPhotoVisible,
|
(isFirst || isLast) && styles.fallbackPhotoVisible,
|
||||||
@ -313,12 +314,12 @@ const ProfileInfo: FC<OwnProps & StateProps> = ({
|
|||||||
<div className={styles.fallbackPhotoContents} onClick={handleSelectFallbackPhoto}>
|
<div className={styles.fallbackPhotoContents} onClick={handleSelectFallbackPhoto}>
|
||||||
{!isLast && (
|
{!isLast && (
|
||||||
<Avatar
|
<Avatar
|
||||||
photo={userProfilePhotos.fallbackPhoto}
|
photo={profilePhotos.fallbackPhoto}
|
||||||
className={styles.fallbackPhotoAvatar}
|
className={styles.fallbackPhotoAvatar}
|
||||||
size="mini"
|
size="mini"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{lang(userProfilePhotos.fallbackPhoto.isVideo ? 'UserInfo.PublicVideo' : 'UserInfo.PublicPhoto')}
|
{lang(profilePhotos.fallbackPhoto.isVideo ? 'UserInfo.PublicVideo' : 'UserInfo.PublicPhoto')}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -368,6 +369,7 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
const user = selectUser(global, peerId);
|
const user = selectUser(global, peerId);
|
||||||
const userStatus = selectUserStatus(global, peerId);
|
const userStatus = selectUserStatus(global, peerId);
|
||||||
const chat = selectChat(global, peerId);
|
const chat = selectChat(global, peerId);
|
||||||
|
const profilePhotos = selectPeerPhotos(global, peerId);
|
||||||
const { mediaIndex, chatId: avatarOwnerId } = selectTabState(global).mediaViewer;
|
const { mediaIndex, chatId: avatarOwnerId } = selectTabState(global).mediaViewer;
|
||||||
const isForum = chat?.isForum;
|
const isForum = chat?.isForum;
|
||||||
const { threadId: currentTopicId } = selectCurrentMessageList(global) || {};
|
const { threadId: currentTopicId } = selectCurrentMessageList(global) || {};
|
||||||
@ -383,6 +385,7 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
mediaIndex,
|
mediaIndex,
|
||||||
avatarOwnerId,
|
avatarOwnerId,
|
||||||
emojiStatusSticker,
|
emojiStatusSticker,
|
||||||
|
profilePhotos,
|
||||||
...(topic && {
|
...(topic && {
|
||||||
topic,
|
topic,
|
||||||
messagesCount: selectThreadMessagesCount(global, peerId, currentTopicId!),
|
messagesCount: selectThreadMessagesCount(global, peerId, currentTopicId!),
|
||||||
|
|||||||
@ -6,7 +6,11 @@ import { getActions, withGlobal } from '../../global';
|
|||||||
|
|
||||||
import type {
|
import type {
|
||||||
ApiChat,
|
ApiChat,
|
||||||
ApiMessage, ApiPeer, ApiPhoto, ApiSponsoredMessage,
|
ApiMessage,
|
||||||
|
ApiPeer,
|
||||||
|
ApiPeerPhotos,
|
||||||
|
ApiPhoto,
|
||||||
|
ApiSponsoredMessage,
|
||||||
} from '../../api/types';
|
} from '../../api/types';
|
||||||
import { type MediaViewerMedia, MediaViewerOrigin, type ThreadId } from '../../types';
|
import { type MediaViewerMedia, MediaViewerOrigin, type ThreadId } from '../../types';
|
||||||
|
|
||||||
@ -25,6 +29,7 @@ import {
|
|||||||
selectListedIds,
|
selectListedIds,
|
||||||
selectOutlyingListByMessageId,
|
selectOutlyingListByMessageId,
|
||||||
selectPeer,
|
selectPeer,
|
||||||
|
selectPeerPhotos,
|
||||||
selectPerformanceSettingsValue,
|
selectPerformanceSettingsValue,
|
||||||
selectScheduledMessage, selectSponsoredMessage,
|
selectScheduledMessage, selectSponsoredMessage,
|
||||||
selectTabState,
|
selectTabState,
|
||||||
@ -69,6 +74,7 @@ type StateProps = {
|
|||||||
origin?: MediaViewerOrigin;
|
origin?: MediaViewerOrigin;
|
||||||
avatar?: ApiPhoto;
|
avatar?: ApiPhoto;
|
||||||
avatarOwner?: ApiPeer;
|
avatarOwner?: ApiPeer;
|
||||||
|
profilePhotos?: ApiPeerPhotos;
|
||||||
chatMessages?: Record<number, ApiMessage>;
|
chatMessages?: Record<number, ApiMessage>;
|
||||||
sponsoredMessage?: ApiSponsoredMessage;
|
sponsoredMessage?: ApiSponsoredMessage;
|
||||||
standaloneMedia?: MediaViewerMedia[];
|
standaloneMedia?: MediaViewerMedia[];
|
||||||
@ -95,6 +101,7 @@ const MediaViewer = ({
|
|||||||
origin,
|
origin,
|
||||||
avatar,
|
avatar,
|
||||||
avatarOwner,
|
avatarOwner,
|
||||||
|
profilePhotos,
|
||||||
chatMessages,
|
chatMessages,
|
||||||
sponsoredMessage,
|
sponsoredMessage,
|
||||||
standaloneMedia,
|
standaloneMedia,
|
||||||
@ -132,7 +139,7 @@ const MediaViewer = ({
|
|||||||
const [isReportModalOpen, openReportModal, closeReportModal] = useFlag();
|
const [isReportModalOpen, openReportModal, closeReportModal] = useFlag();
|
||||||
|
|
||||||
const currentItem = getMediaViewerItem({
|
const currentItem = getMediaViewerItem({
|
||||||
message, avatarOwner, standaloneMedia, mediaIndex, sponsoredMessage,
|
message, avatarOwner, standaloneMedia, profilePhotos, mediaIndex, sponsoredMessage,
|
||||||
});
|
});
|
||||||
const { media, isSingle } = getViewableMedia(currentItem) || {};
|
const { media, isSingle } = getViewableMedia(currentItem) || {};
|
||||||
|
|
||||||
@ -275,7 +282,7 @@ const MediaViewer = ({
|
|||||||
if (!item || isLoadingMoreMedia) return;
|
if (!item || isLoadingMoreMedia) return;
|
||||||
|
|
||||||
if (item.type === 'avatar') {
|
if (item.type === 'avatar') {
|
||||||
const isNearEnd = item.mediaIndex >= item.avatarOwner.profilePhotos!.photos.length - AVATAR_LOAD_TRIGGER;
|
const isNearEnd = item.mediaIndex >= item.profilePhotos.photos.length - AVATAR_LOAD_TRIGGER;
|
||||||
if (!isNearEnd) return;
|
if (!isNearEnd) return;
|
||||||
loadMoreProfilePhotos({ peerId: item.avatarOwner.id });
|
loadMoreProfilePhotos({ peerId: item.avatarOwner.id });
|
||||||
}
|
}
|
||||||
@ -299,10 +306,15 @@ const MediaViewer = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (from.type === 'avatar') {
|
if (from.type === 'avatar') {
|
||||||
const { avatarOwner: fromAvatarOwner, mediaIndex: fromMediaIndex } = from;
|
const { avatarOwner: fromAvatarOwner, profilePhotos: fromProfilePhotos, mediaIndex: fromMediaIndex } = from;
|
||||||
const nextIndex = fromMediaIndex + direction;
|
const nextIndex = fromMediaIndex + direction;
|
||||||
if (nextIndex >= 0 && fromAvatarOwner.profilePhotos && nextIndex < fromAvatarOwner.profilePhotos.photos.length) {
|
if (nextIndex >= 0 && fromProfilePhotos && nextIndex < fromProfilePhotos.photos.length) {
|
||||||
return { type: 'avatar', avatarOwner: fromAvatarOwner, mediaIndex: nextIndex };
|
return {
|
||||||
|
type: 'avatar',
|
||||||
|
avatarOwner: fromAvatarOwner,
|
||||||
|
profilePhotos: fromProfilePhotos,
|
||||||
|
mediaIndex: nextIndex,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return undefined;
|
return undefined;
|
||||||
@ -367,7 +379,7 @@ const MediaViewer = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const handleBeforeDelete = useLastCallback(() => {
|
const handleBeforeDelete = useLastCallback(() => {
|
||||||
const mediaCount = avatarOwner?.profilePhotos?.photos.length
|
const mediaCount = profilePhotos?.photos.length
|
||||||
|| standaloneMedia?.length || messageMediaIds?.length || 0;
|
|| standaloneMedia?.length || messageMediaIds?.length || 0;
|
||||||
if (mediaCount <= 1 || !currentItem) {
|
if (mediaCount <= 1 || !currentItem) {
|
||||||
handleClose();
|
handleClose();
|
||||||
@ -489,9 +501,10 @@ export default memo(withGlobal(
|
|||||||
canUpdateMedia = isUserId(peer.id) ? peer.id === currentUserId : isChatAdmin(peer as ApiChat);
|
canUpdateMedia = isUserId(peer.id) ? peer.id === currentUserId : isChatAdmin(peer as ApiChat);
|
||||||
}
|
}
|
||||||
|
|
||||||
const profilePhotos = peer?.profilePhotos;
|
const profilePhotos = selectPeerPhotos(global, chatId!);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
profilePhotos,
|
||||||
avatar: profilePhotos?.photos[mediaIndex!],
|
avatar: profilePhotos?.photos[mediaIndex!],
|
||||||
avatarOwner: peer,
|
avatarOwner: peer,
|
||||||
isLoadingMoreMedia: profilePhotos?.isLoading,
|
isLoadingMoreMedia: profilePhotos?.isLoading,
|
||||||
|
|||||||
@ -128,8 +128,8 @@ const MediaViewerActions: FC<OwnProps & StateProps> = ({
|
|||||||
|
|
||||||
const handleUpdate = useLastCallback(() => {
|
const handleUpdate = useLastCallback(() => {
|
||||||
if (item?.type !== 'avatar') return;
|
if (item?.type !== 'avatar') return;
|
||||||
const { avatarOwner, mediaIndex } = item;
|
const { avatarOwner, profilePhotos, mediaIndex } = item;
|
||||||
const avatarPhoto = avatarOwner.profilePhotos?.photos[mediaIndex]!;
|
const avatarPhoto = profilePhotos?.photos[mediaIndex]!;
|
||||||
if (isUserId(avatarOwner.id)) {
|
if (isUserId(avatarOwner.id)) {
|
||||||
updateProfilePhoto({ photo: avatarPhoto });
|
updateProfilePhoto({ photo: avatarPhoto });
|
||||||
} else {
|
} else {
|
||||||
@ -170,7 +170,7 @@ const MediaViewerActions: FC<OwnProps & StateProps> = ({
|
|||||||
onClose={closeDeleteModal}
|
onClose={closeDeleteModal}
|
||||||
onConfirm={onBeforeDelete}
|
onConfirm={onBeforeDelete}
|
||||||
profileId={item.avatarOwner.id}
|
profileId={item.avatarOwner.id}
|
||||||
photo={item.avatarOwner.profilePhotos!.photos[item.mediaIndex!]}
|
photo={item.profilePhotos.photos[item.mediaIndex!]}
|
||||||
/>
|
/>
|
||||||
) : undefined;
|
) : undefined;
|
||||||
}
|
}
|
||||||
@ -390,7 +390,7 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
|
|
||||||
const message = item?.type === 'message' ? item.message : undefined;
|
const message = item?.type === 'message' ? item.message : undefined;
|
||||||
const avatarOwner = item?.type === 'avatar' ? item.avatarOwner : undefined;
|
const avatarOwner = item?.type === 'avatar' ? item.avatarOwner : undefined;
|
||||||
const avatarPhoto = avatarOwner?.profilePhotos?.photos[item!.mediaIndex!];
|
const avatarPhoto = item?.type === 'avatar' && item.profilePhotos.photos[item.mediaIndex];
|
||||||
|
|
||||||
const currentMessageList = selectCurrentMessageList(global);
|
const currentMessageList = selectCurrentMessageList(global);
|
||||||
const { threadId } = selectCurrentMessageList(global) || {};
|
const { threadId } = selectCurrentMessageList(global) || {};
|
||||||
|
|||||||
@ -68,14 +68,15 @@ const SenderInfo: FC<OwnProps & StateProps> = ({
|
|||||||
if (!item || item.type === 'standalone') return undefined;
|
if (!item || item.type === 'standalone') return undefined;
|
||||||
|
|
||||||
const avatarOwner = item.type === 'avatar' ? item.avatarOwner : undefined;
|
const avatarOwner = item.type === 'avatar' ? item.avatarOwner : undefined;
|
||||||
const avatar = avatarOwner?.profilePhotos?.photos[item.mediaIndex!];
|
const profilePhotos = item.type === 'avatar' ? item.profilePhotos : undefined;
|
||||||
const isFallbackAvatar = avatar?.id === avatarOwner?.profilePhotos?.fallbackPhoto?.id;
|
const avatar = profilePhotos?.photos[item.mediaIndex!];
|
||||||
|
const isFallbackAvatar = avatar?.id === profilePhotos?.fallbackPhoto?.id;
|
||||||
const date = item.type === 'message' ? item.message.date : avatar?.date;
|
const date = item.type === 'message' ? item.message.date : avatar?.date;
|
||||||
if (!date) return undefined;
|
if (!date) return undefined;
|
||||||
|
|
||||||
const formattedDate = formatMediaDateTime(lang, date * 1000, true);
|
const formattedDate = formatMediaDateTime(lang, date * 1000, true);
|
||||||
const count = avatarOwner?.profilePhotos?.count
|
const count = profilePhotos?.count
|
||||||
&& (avatarOwner.profilePhotos.count + (avatarOwner?.profilePhotos?.fallbackPhoto ? 1 : 0));
|
&& (profilePhotos.count + (profilePhotos?.fallbackPhoto ? 1 : 0));
|
||||||
const countText = count && lang('Of', [item.mediaIndex! + 1, count]);
|
const countText = count && lang('Of', [item.mediaIndex! + 1, count]);
|
||||||
|
|
||||||
const parts: string[] = [];
|
const parts: string[] = [];
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
import type { ApiMessage, ApiPeer, ApiSponsoredMessage } from '../../../api/types';
|
import type {
|
||||||
|
ApiMessage, ApiPeer, ApiPeerPhotos, ApiSponsoredMessage,
|
||||||
|
} from '../../../api/types';
|
||||||
import type { MediaViewerMedia } from '../../../types';
|
import type { MediaViewerMedia } from '../../../types';
|
||||||
|
|
||||||
import { getMessageContent, isDocumentPhoto, isDocumentVideo } from '../../../global/helpers';
|
import { getMessageContent, isDocumentPhoto, isDocumentVideo } from '../../../global/helpers';
|
||||||
@ -10,6 +12,7 @@ export type MediaViewerItem = {
|
|||||||
} | {
|
} | {
|
||||||
type: 'avatar';
|
type: 'avatar';
|
||||||
avatarOwner: ApiPeer;
|
avatarOwner: ApiPeer;
|
||||||
|
profilePhotos: ApiPeerPhotos;
|
||||||
mediaIndex: number;
|
mediaIndex: number;
|
||||||
} | {
|
} | {
|
||||||
type: 'standalone';
|
type: 'standalone';
|
||||||
@ -27,18 +30,20 @@ type ViewableMedia = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function getMediaViewerItem({
|
export function getMediaViewerItem({
|
||||||
message, avatarOwner, standaloneMedia, mediaIndex, sponsoredMessage,
|
message, avatarOwner, profilePhotos, standaloneMedia, mediaIndex, sponsoredMessage,
|
||||||
}: {
|
}: {
|
||||||
message?: ApiMessage;
|
message?: ApiMessage;
|
||||||
avatarOwner?: ApiPeer;
|
avatarOwner?: ApiPeer;
|
||||||
|
profilePhotos?: ApiPeerPhotos;
|
||||||
standaloneMedia?: MediaViewerMedia[];
|
standaloneMedia?: MediaViewerMedia[];
|
||||||
sponsoredMessage?: ApiSponsoredMessage;
|
sponsoredMessage?: ApiSponsoredMessage;
|
||||||
mediaIndex?: number;
|
mediaIndex?: number;
|
||||||
}): MediaViewerItem | undefined {
|
}): MediaViewerItem | undefined {
|
||||||
if (avatarOwner) {
|
if (avatarOwner && profilePhotos) {
|
||||||
return {
|
return {
|
||||||
type: 'avatar',
|
type: 'avatar',
|
||||||
avatarOwner,
|
avatarOwner,
|
||||||
|
profilePhotos,
|
||||||
mediaIndex: mediaIndex!,
|
mediaIndex: mediaIndex!,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -81,7 +86,7 @@ export default function getViewableMedia(params?: MediaViewerItem): ViewableMedi
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (params.type === 'avatar') {
|
if (params.type === 'avatar') {
|
||||||
const avatar = params.avatarOwner.profilePhotos?.photos[params.mediaIndex];
|
const avatar = params.profilePhotos?.photos[params.mediaIndex];
|
||||||
if (avatar) {
|
if (avatar) {
|
||||||
return {
|
return {
|
||||||
media: avatar,
|
media: avatar,
|
||||||
|
|||||||
@ -37,7 +37,6 @@ import {
|
|||||||
isChatChannel,
|
isChatChannel,
|
||||||
isChatGroup,
|
isChatGroup,
|
||||||
isUserBot,
|
isUserBot,
|
||||||
isUserId,
|
|
||||||
isUserRightBanned,
|
isUserRightBanned,
|
||||||
} from '../../global/helpers';
|
} from '../../global/helpers';
|
||||||
import {
|
import {
|
||||||
@ -48,12 +47,12 @@ import {
|
|||||||
selectCurrentSharedMediaSearch,
|
selectCurrentSharedMediaSearch,
|
||||||
selectIsCurrentUserPremium,
|
selectIsCurrentUserPremium,
|
||||||
selectIsRightColumnShown,
|
selectIsRightColumnShown,
|
||||||
selectPeerFullInfo,
|
|
||||||
selectPeerStories,
|
selectPeerStories,
|
||||||
selectSimilarChannelIds,
|
selectSimilarChannelIds,
|
||||||
selectTabState,
|
selectTabState,
|
||||||
selectTheme,
|
selectTheme,
|
||||||
selectUser,
|
selectUser,
|
||||||
|
selectUserCommonChats,
|
||||||
selectUserFullInfo,
|
selectUserFullInfo,
|
||||||
} from '../../global/selectors';
|
} from '../../global/selectors';
|
||||||
import { selectPremiumLimit } from '../../global/selectors/limits';
|
import { selectPremiumLimit } from '../../global/selectors/limits';
|
||||||
@ -110,7 +109,6 @@ type StateProps = {
|
|||||||
theme: ISettings['theme'];
|
theme: ISettings['theme'];
|
||||||
isChannel?: boolean;
|
isChannel?: boolean;
|
||||||
currentUserId?: string;
|
currentUserId?: string;
|
||||||
resolvedUserId?: string;
|
|
||||||
messagesById?: Record<number, ApiMessage>;
|
messagesById?: Record<number, ApiMessage>;
|
||||||
foundIds?: number[];
|
foundIds?: number[];
|
||||||
mediaSearchType?: SharedMediaType;
|
mediaSearchType?: SharedMediaType;
|
||||||
@ -166,10 +164,8 @@ const Profile: FC<OwnProps & StateProps> = ({
|
|||||||
chatId,
|
chatId,
|
||||||
threadId,
|
threadId,
|
||||||
profileState,
|
profileState,
|
||||||
onProfileStateChange,
|
|
||||||
theme,
|
theme,
|
||||||
isChannel,
|
isChannel,
|
||||||
resolvedUserId,
|
|
||||||
currentUserId,
|
currentUserId,
|
||||||
messagesById,
|
messagesById,
|
||||||
foundIds,
|
foundIds,
|
||||||
@ -205,6 +201,7 @@ const Profile: FC<OwnProps & StateProps> = ({
|
|||||||
isSavedDialog,
|
isSavedDialog,
|
||||||
forceScrollProfileTab,
|
forceScrollProfileTab,
|
||||||
isSynced,
|
isSynced,
|
||||||
|
onProfileStateChange,
|
||||||
}) => {
|
}) => {
|
||||||
const {
|
const {
|
||||||
setSharedMediaSearchType,
|
setSharedMediaSearchType,
|
||||||
@ -230,7 +227,7 @@ const Profile: FC<OwnProps & StateProps> = ({
|
|||||||
const lang = useOldLang();
|
const lang = useOldLang();
|
||||||
const [deletingUserId, setDeletingUserId] = useState<string | undefined>();
|
const [deletingUserId, setDeletingUserId] = useState<string | undefined>();
|
||||||
|
|
||||||
const profileId = isSavedDialog ? String(threadId) : (resolvedUserId || chatId);
|
const profileId = isSavedDialog ? String(threadId) : chatId;
|
||||||
const isSavedMessages = profileId === currentUserId && !isSavedDialog;
|
const isSavedMessages = profileId === currentUserId && !isSavedDialog;
|
||||||
|
|
||||||
const tabs = useMemo(() => ([
|
const tabs = useMemo(() => ([
|
||||||
@ -303,6 +300,9 @@ const Profile: FC<OwnProps & StateProps> = ({
|
|||||||
|
|
||||||
const renderingActiveTab = activeTab > tabs.length - 1 ? tabs.length - 1 : activeTab;
|
const renderingActiveTab = activeTab > tabs.length - 1 ? tabs.length - 1 : activeTab;
|
||||||
const tabType = tabs[renderingActiveTab].type as ProfileTabType;
|
const tabType = tabs[renderingActiveTab].type as ProfileTabType;
|
||||||
|
const handleLoadCommonChats = useCallback(() => {
|
||||||
|
loadCommonChats({ userId: chatId });
|
||||||
|
}, [chatId]);
|
||||||
const handleLoadPeerStories = useCallback(({ offsetId }: { offsetId: number }) => {
|
const handleLoadPeerStories = useCallback(({ offsetId }: { offsetId: number }) => {
|
||||||
loadPeerProfileStories({ peerId: chatId, offsetId });
|
loadPeerProfileStories({ peerId: chatId, offsetId });
|
||||||
}, [chatId]);
|
}, [chatId]);
|
||||||
@ -312,7 +312,7 @@ const Profile: FC<OwnProps & StateProps> = ({
|
|||||||
|
|
||||||
const [resultType, viewportIds, getMore, noProfileInfo] = useProfileViewportIds(
|
const [resultType, viewportIds, getMore, noProfileInfo] = useProfileViewportIds(
|
||||||
loadMoreMembers,
|
loadMoreMembers,
|
||||||
loadCommonChats,
|
handleLoadCommonChats,
|
||||||
searchSharedMediaMessages,
|
searchSharedMediaMessages,
|
||||||
handleLoadPeerStories,
|
handleLoadPeerStories,
|
||||||
handleLoadStoriesArchive,
|
handleLoadStoriesArchive,
|
||||||
@ -746,9 +746,12 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
(global, {
|
(global, {
|
||||||
chatId, threadId, isMobile,
|
chatId, threadId, isMobile,
|
||||||
}): StateProps => {
|
}): StateProps => {
|
||||||
|
const user = selectUser(global, chatId);
|
||||||
const chat = selectChat(global, chatId);
|
const chat = selectChat(global, chatId);
|
||||||
const chatFullInfo = selectChatFullInfo(global, chatId);
|
const chatFullInfo = selectChatFullInfo(global, chatId);
|
||||||
|
const userFullInfo = selectUserFullInfo(global, chatId);
|
||||||
const messagesById = selectChatMessages(global, chatId);
|
const messagesById = selectChatMessages(global, chatId);
|
||||||
|
|
||||||
const { currentType: mediaSearchType, resultsByType } = selectCurrentSharedMediaSearch(global) || {};
|
const { currentType: mediaSearchType, resultsByType } = selectCurrentSharedMediaSearch(global) || {};
|
||||||
const { foundIds } = (resultsByType && mediaSearchType && resultsByType[mediaSearchType]) || {};
|
const { foundIds } = (resultsByType && mediaSearchType && resultsByType[mediaSearchType]) || {};
|
||||||
|
|
||||||
@ -774,19 +777,13 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
const { similarChannelIds } = selectSimilarChannelIds(global, chatId) || {};
|
const { similarChannelIds } = selectSimilarChannelIds(global, chatId) || {};
|
||||||
const isCurrentUserPremium = selectIsCurrentUserPremium(global);
|
const isCurrentUserPremium = selectIsCurrentUserPremium(global);
|
||||||
|
|
||||||
let hasCommonChatsTab;
|
|
||||||
let resolvedUserId;
|
|
||||||
let user;
|
|
||||||
if (isUserId(chatId)) {
|
|
||||||
resolvedUserId = chatId;
|
|
||||||
user = selectUser(global, resolvedUserId);
|
|
||||||
hasCommonChatsTab = user && !user.isSelf && !isUserBot(user) && !isSavedDialog;
|
|
||||||
}
|
|
||||||
|
|
||||||
const peer = user || chat;
|
const peer = user || chat;
|
||||||
const peerFullInfo = selectPeerFullInfo(global, chatId);
|
const peerFullInfo = userFullInfo || chatFullInfo;
|
||||||
|
|
||||||
|
const hasCommonChatsTab = user && !user.isSelf && !isUserBot(user) && !isSavedDialog
|
||||||
|
&& Boolean(userFullInfo?.commonChatsCount);
|
||||||
|
const commonChats = selectUserCommonChats(global, chatId);
|
||||||
|
|
||||||
const userFullInfo = selectUserFullInfo(global, chatId);
|
|
||||||
const hasPreviewMediaTab = userFullInfo?.botInfo?.hasPreviewMedia;
|
const hasPreviewMediaTab = userFullInfo?.botInfo?.hasPreviewMedia;
|
||||||
const botPreviewMedia = global.users.previewMediaByBotId[chatId];
|
const botPreviewMedia = global.users.previewMediaByBotId[chatId];
|
||||||
|
|
||||||
@ -801,7 +798,6 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
return {
|
return {
|
||||||
theme: selectTheme(global),
|
theme: selectTheme(global),
|
||||||
isChannel,
|
isChannel,
|
||||||
resolvedUserId,
|
|
||||||
messagesById,
|
messagesById,
|
||||||
foundIds,
|
foundIds,
|
||||||
mediaSearchType,
|
mediaSearchType,
|
||||||
@ -835,7 +831,7 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
isSynced: global.isSynced,
|
isSynced: global.isSynced,
|
||||||
limitSimilarChannels: selectPremiumLimit(global, 'recommendedChannels'),
|
limitSimilarChannels: selectPremiumLimit(global, 'recommendedChannels'),
|
||||||
...(hasMembersTab && members && { members, adminMembersById }),
|
...(hasMembersTab && members && { members, adminMembersById }),
|
||||||
...(hasCommonChatsTab && user && { commonChatIds: user.commonChats?.ids }),
|
...(hasCommonChatsTab && user && { commonChatIds: commonChats?.ids }),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
)(Profile));
|
)(Profile));
|
||||||
|
|||||||
@ -86,7 +86,6 @@ export const PINNED_MESSAGES_LIMIT = 50;
|
|||||||
export const BLOCKED_LIST_LIMIT = 100;
|
export const BLOCKED_LIST_LIMIT = 100;
|
||||||
export const PROFILE_SENSITIVE_AREA = 500;
|
export const PROFILE_SENSITIVE_AREA = 500;
|
||||||
export const TOPIC_LIST_SENSITIVE_AREA = 600;
|
export const TOPIC_LIST_SENSITIVE_AREA = 600;
|
||||||
export const COMMON_CHATS_LIMIT = 100;
|
|
||||||
export const GROUP_CALL_PARTICIPANTS_LIMIT = 100;
|
export const GROUP_CALL_PARTICIPANTS_LIMIT = 100;
|
||||||
export const STORY_LIST_LIMIT = 100;
|
export const STORY_LIST_LIMIT = 100;
|
||||||
export const API_GENERAL_ID_LIMIT = 100;
|
export const API_GENERAL_ID_LIMIT = 100;
|
||||||
|
|||||||
@ -23,6 +23,7 @@ import {
|
|||||||
updatePeerPhotos,
|
updatePeerPhotos,
|
||||||
updatePeerPhotosIsLoading,
|
updatePeerPhotosIsLoading,
|
||||||
updateUser,
|
updateUser,
|
||||||
|
updateUserCommonChats,
|
||||||
updateUserFullInfo,
|
updateUserFullInfo,
|
||||||
updateUsers,
|
updateUsers,
|
||||||
updateUserSearch,
|
updateUserSearch,
|
||||||
@ -31,10 +32,11 @@ import {
|
|||||||
import {
|
import {
|
||||||
selectChat,
|
selectChat,
|
||||||
selectChatFullInfo,
|
selectChatFullInfo,
|
||||||
selectCurrentMessageList,
|
|
||||||
selectPeer,
|
selectPeer,
|
||||||
|
selectPeerPhotos,
|
||||||
selectTabState,
|
selectTabState,
|
||||||
selectUser,
|
selectUser,
|
||||||
|
selectUserCommonChats,
|
||||||
selectUserFullInfo,
|
selectUserFullInfo,
|
||||||
} from '../../selectors';
|
} from '../../selectors';
|
||||||
|
|
||||||
@ -56,6 +58,7 @@ addActionHandler('loadFullUser', async (global, actions, payload): Promise<void>
|
|||||||
global = getGlobal();
|
global = getGlobal();
|
||||||
const fullInfo = selectUserFullInfo(global, userId);
|
const fullInfo = selectUserFullInfo(global, userId);
|
||||||
const { user: newUser, fullInfo: newFullInfo } = result;
|
const { user: newUser, fullInfo: newFullInfo } = result;
|
||||||
|
const profilePhotos = selectPeerPhotos(global, userId);
|
||||||
const hasChangedAvatar = user.avatarPhotoId !== newUser.avatarPhotoId;
|
const hasChangedAvatar = user.avatarPhotoId !== newUser.avatarPhotoId;
|
||||||
const hasChangedProfilePhoto = fullInfo?.profilePhoto?.id !== newFullInfo?.profilePhoto?.id;
|
const hasChangedProfilePhoto = fullInfo?.profilePhoto?.id !== newFullInfo?.profilePhoto?.id;
|
||||||
const hasChangedFallbackPhoto = fullInfo?.fallbackPhoto?.id !== newFullInfo?.fallbackPhoto?.id;
|
const hasChangedFallbackPhoto = fullInfo?.fallbackPhoto?.id !== newFullInfo?.fallbackPhoto?.id;
|
||||||
@ -71,7 +74,7 @@ addActionHandler('loadFullUser', async (global, actions, payload): Promise<void>
|
|||||||
global = updateChats(global, buildCollectionByKey(result.chats, 'id'));
|
global = updateChats(global, buildCollectionByKey(result.chats, 'id'));
|
||||||
|
|
||||||
setGlobal(global);
|
setGlobal(global);
|
||||||
if (withPhotos || (user.profilePhotos?.count && hasChangedPhoto)) {
|
if (withPhotos || (profilePhotos?.count && hasChangedPhoto)) {
|
||||||
actions.loadMoreProfilePhotos({ peerId: userId, shouldInvalidateCache: true });
|
actions.loadMoreProfilePhotos({ peerId: userId, shouldInvalidateCache: true });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -156,28 +159,27 @@ addActionHandler('loadCurrentUser', (): ActionReturnType => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
addActionHandler('loadCommonChats', async (global, actions, payload): Promise<void> => {
|
addActionHandler('loadCommonChats', async (global, actions, payload): Promise<void> => {
|
||||||
const { tabId = getCurrentTabId() } = payload || {};
|
const { userId } = payload;
|
||||||
const { chatId } = selectCurrentMessageList(global, tabId) || {};
|
const user = selectUser(global, userId);
|
||||||
const user = chatId ? selectUser(global, chatId) : undefined;
|
const commonChats = selectUserCommonChats(global, userId);
|
||||||
if (!user || isUserBot(user) || user.commonChats?.isFullyLoaded) {
|
if (!user || isUserBot(user) || commonChats?.isFullyLoaded) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const maxId = user.commonChats?.maxId;
|
const result = await callApi('fetchCommonChats', user, commonChats?.maxId);
|
||||||
const result = await callApi('fetchCommonChats', user.id, user.accessHash!, maxId);
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { chatIds, isFullyLoaded } = result;
|
const { chatIds, count } = result;
|
||||||
|
|
||||||
|
const ids = unique((commonChats?.ids || []).concat(chatIds));
|
||||||
|
|
||||||
global = getGlobal();
|
global = getGlobal();
|
||||||
global = updateUser(global, user.id, {
|
global = updateUserCommonChats(global, user.id, {
|
||||||
commonChats: {
|
maxId: chatIds.length ? chatIds[chatIds.length - 1] : undefined,
|
||||||
maxId: chatIds.length ? chatIds[chatIds.length - 1] : '0',
|
ids,
|
||||||
ids: unique((user.commonChats?.ids || []).concat(chatIds)),
|
isFullyLoaded: ids.length >= count,
|
||||||
isFullyLoaded,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
setGlobal(global);
|
setGlobal(global);
|
||||||
@ -258,11 +260,12 @@ addActionHandler('loadMoreProfilePhotos', async (global, actions, payload): Prom
|
|||||||
const user = isPrivate ? selectUser(global, peerId) : undefined;
|
const user = isPrivate ? selectUser(global, peerId) : undefined;
|
||||||
const chat = !isPrivate ? selectChat(global, peerId) : undefined;
|
const chat = !isPrivate ? selectChat(global, peerId) : undefined;
|
||||||
const peer = user || chat;
|
const peer = user || chat;
|
||||||
|
const profilePhotos = selectPeerPhotos(global, peerId);
|
||||||
if (!peer?.avatarPhotoId) {
|
if (!peer?.avatarPhotoId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (peer.profilePhotos && !shouldInvalidateCache && (isPreload || !peer.profilePhotos.nextOffset)) return;
|
if (profilePhotos && !shouldInvalidateCache && (isPreload || !profilePhotos.nextOffset)) return;
|
||||||
|
|
||||||
global = updatePeerPhotosIsLoading(global, peerId, true);
|
global = updatePeerPhotosIsLoading(global, peerId, true);
|
||||||
setGlobal(global);
|
setGlobal(global);
|
||||||
@ -292,7 +295,7 @@ addActionHandler('loadMoreProfilePhotos', async (global, actions, payload): Prom
|
|||||||
const peerFullInfo = userFullInfo || chatFullInfo;
|
const peerFullInfo = userFullInfo || chatFullInfo;
|
||||||
if (!peerFullInfo) return;
|
if (!peerFullInfo) return;
|
||||||
|
|
||||||
const offset = peer.profilePhotos?.nextOffset;
|
const offset = profilePhotos?.nextOffset;
|
||||||
const limit = !offset || isPreload || shouldInvalidateCache ? PROFILE_PHOTOS_FIRST_LOAD_LIMIT : undefined;
|
const limit = !offset || isPreload || shouldInvalidateCache ? PROFILE_PHOTOS_FIRST_LOAD_LIMIT : undefined;
|
||||||
|
|
||||||
const result = await callApi('fetchProfilePhotos', {
|
const result = await callApi('fetchProfilePhotos', {
|
||||||
|
|||||||
@ -16,6 +16,7 @@ import {
|
|||||||
deletePeerPhoto,
|
deletePeerPhoto,
|
||||||
leaveChat,
|
leaveChat,
|
||||||
removeUnreadMentions,
|
removeUnreadMentions,
|
||||||
|
replacePeerPhotos,
|
||||||
replaceThreadParam,
|
replaceThreadParam,
|
||||||
updateChat,
|
updateChat,
|
||||||
updateChatFullInfo,
|
updateChatFullInfo,
|
||||||
@ -548,8 +549,8 @@ addActionHandler('apiUpdate', (global, actions, update): ActionReturnType => {
|
|||||||
if (!photoId || peer.avatarPhotoId === photoId) {
|
if (!photoId || peer.avatarPhotoId === photoId) {
|
||||||
global = updateChat(global, peerId, {
|
global = updateChat(global, peerId, {
|
||||||
avatarPhotoId: undefined,
|
avatarPhotoId: undefined,
|
||||||
profilePhotos: undefined,
|
|
||||||
});
|
});
|
||||||
|
global = replacePeerPhotos(global, peerId, undefined);
|
||||||
} else {
|
} else {
|
||||||
global = deletePeerPhoto(global, peerId, photoId);
|
global = deletePeerPhoto(global, peerId, photoId);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -245,6 +245,9 @@ function unsafeMigrateCache(cached: GlobalState, initialState: GlobalState) {
|
|||||||
if (!cached.topBotApps) {
|
if (!cached.topBotApps) {
|
||||||
cached.topBotApps = initialState.topBotApps;
|
cached.topBotApps = initialState.topBotApps;
|
||||||
}
|
}
|
||||||
|
if (!cached.users.commonChatsById) {
|
||||||
|
cached.users.commonChatsById = initialState.users.commonChatsById;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateCache(force?: boolean) {
|
function updateCache(force?: boolean) {
|
||||||
@ -390,10 +393,10 @@ function reduceUsers<T extends GlobalState>(global: T): GlobalState['users'] {
|
|||||||
]).slice(0, GLOBAL_STATE_CACHE_USER_LIST_LIMIT);
|
]).slice(0, GLOBAL_STATE_CACHE_USER_LIST_LIMIT);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
...INITIAL_GLOBAL_STATE.users,
|
||||||
byId: pickTruthy(byId, idsToSave),
|
byId: pickTruthy(byId, idsToSave),
|
||||||
statusesById: pickTruthy(statusesById, idsToSave),
|
statusesById: pickTruthy(statusesById, idsToSave),
|
||||||
fullInfoById: pickTruthy(fullInfoById, idsToSave),
|
fullInfoById: pickTruthy(fullInfoById, idsToSave),
|
||||||
previewMediaByBotId: {},
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -98,6 +98,7 @@ export const INITIAL_GLOBAL_STATE: GlobalState = {
|
|||||||
statusesById: {},
|
statusesById: {},
|
||||||
fullInfoById: {},
|
fullInfoById: {},
|
||||||
previewMediaByBotId: {},
|
previewMediaByBotId: {},
|
||||||
|
commonChatsById: {},
|
||||||
},
|
},
|
||||||
|
|
||||||
chats: {
|
chats: {
|
||||||
@ -298,6 +299,7 @@ export const INITIAL_GLOBAL_STATE: GlobalState = {
|
|||||||
isHidden: false,
|
isHidden: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
profilePhotosById: {},
|
||||||
monetizationInfo: {},
|
monetizationInfo: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -12,5 +12,5 @@ export * from './payments';
|
|||||||
export * from './statistics';
|
export * from './statistics';
|
||||||
export * from './stories';
|
export * from './stories';
|
||||||
export * from './translations';
|
export * from './translations';
|
||||||
|
export * from './peers';
|
||||||
export * from './password';
|
export * from './password';
|
||||||
export * from './general';
|
|
||||||
|
|||||||
@ -1,11 +1,16 @@
|
|||||||
import type {
|
import type {
|
||||||
ApiChat, ApiChatFullInfo, ApiPhoto, ApiUser, ApiUserFullInfo,
|
ApiChat, ApiChatFullInfo, ApiPeerPhotos, ApiPhoto, ApiUser, ApiUserFullInfo,
|
||||||
} from '../../api/types';
|
} from '../../api/types';
|
||||||
import type { GlobalState } from '../types';
|
import type { GlobalState } from '../types';
|
||||||
|
|
||||||
import { uniqueByField } from '../../util/iteratees';
|
import { omit, uniqueByField } from '../../util/iteratees';
|
||||||
import { isChatChannel, isUserId } from '../helpers';
|
import { isChatChannel, isUserId } from '../helpers';
|
||||||
import { selectChatFullInfo, selectPeer, selectUserFullInfo } from '../selectors';
|
import {
|
||||||
|
selectChatFullInfo,
|
||||||
|
selectPeer,
|
||||||
|
selectPeerPhotos,
|
||||||
|
selectUserFullInfo,
|
||||||
|
} from '../selectors';
|
||||||
import { updateChat, updateChatFullInfo } from './chats';
|
import { updateChat, updateChatFullInfo } from './chats';
|
||||||
import { updateUser, updateUserFullInfo } from './users';
|
import { updateUser, updateUserFullInfo } from './users';
|
||||||
|
|
||||||
@ -38,19 +43,38 @@ export function updatePeerPhotosIsLoading<T extends GlobalState>(
|
|||||||
peerId: string,
|
peerId: string,
|
||||||
isLoading: boolean,
|
isLoading: boolean,
|
||||||
) {
|
) {
|
||||||
const peer = selectPeer(global, peerId);
|
const profilePhotos = selectPeerPhotos(global, peerId);
|
||||||
if (!peer || !peer.profilePhotos) {
|
if (!profilePhotos) {
|
||||||
return global;
|
return global;
|
||||||
}
|
}
|
||||||
|
|
||||||
return updatePeer(global, peerId, {
|
return replacePeerPhotos(global, peerId, {
|
||||||
profilePhotos: {
|
...profilePhotos,
|
||||||
...peer.profilePhotos,
|
isLoading,
|
||||||
isLoading,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function replacePeerPhotos<T extends GlobalState>(
|
||||||
|
global: T,
|
||||||
|
peerId: string,
|
||||||
|
value?: ApiPeerPhotos,
|
||||||
|
) {
|
||||||
|
if (!value) {
|
||||||
|
return {
|
||||||
|
...global,
|
||||||
|
profilePhotosById: omit(global.profilePhotosById, [peerId]),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...global,
|
||||||
|
profilePhotosById: {
|
||||||
|
...global.profilePhotosById,
|
||||||
|
[peerId]: value,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function updatePeerPhotos<T extends GlobalState>(
|
export function updatePeerPhotos<T extends GlobalState>(
|
||||||
global: T,
|
global: T,
|
||||||
peerId: string,
|
peerId: string,
|
||||||
@ -62,15 +86,12 @@ export function updatePeerPhotos<T extends GlobalState>(
|
|||||||
shouldInvalidateCache?: boolean;
|
shouldInvalidateCache?: boolean;
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
const peer = selectPeer(global, peerId);
|
const profilePhotos = selectPeerPhotos(global, peerId);
|
||||||
if (!peer) {
|
|
||||||
return global;
|
|
||||||
}
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
newPhotos, count, nextOffset, fullInfo, shouldInvalidateCache,
|
newPhotos, count, nextOffset, fullInfo, shouldInvalidateCache,
|
||||||
} = update;
|
} = update;
|
||||||
const currentPhotos = peer.profilePhotos;
|
const currentPhotos = profilePhotos;
|
||||||
const profilePhoto = fullInfo.profilePhoto;
|
const profilePhoto = fullInfo.profilePhoto;
|
||||||
const fallbackPhoto = 'fallbackPhoto' in fullInfo ? fullInfo.fallbackPhoto : undefined;
|
const fallbackPhoto = 'fallbackPhoto' in fullInfo ? fullInfo.fallbackPhoto : undefined;
|
||||||
const personalPhoto = 'personalPhoto' in fullInfo ? fullInfo.personalPhoto : undefined;
|
const personalPhoto = 'personalPhoto' in fullInfo ? fullInfo.personalPhoto : undefined;
|
||||||
@ -89,15 +110,13 @@ export function updatePeerPhotos<T extends GlobalState>(
|
|||||||
newPhotos.push(fallbackPhoto);
|
newPhotos.push(fallbackPhoto);
|
||||||
}
|
}
|
||||||
|
|
||||||
return updatePeer(global, peerId, {
|
return replacePeerPhotos(global, peerId, {
|
||||||
profilePhotos: {
|
fallbackPhoto,
|
||||||
fallbackPhoto,
|
personalPhoto,
|
||||||
personalPhoto,
|
photos: newPhotos,
|
||||||
photos: newPhotos,
|
count,
|
||||||
count,
|
nextOffset,
|
||||||
nextOffset,
|
isLoading: false,
|
||||||
isLoading: false,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,15 +124,13 @@ export function updatePeerPhotos<T extends GlobalState>(
|
|||||||
const currentPhotoArray = hasFallbackPhoto ? currentPhotos.photos.slice(0, -1) : currentPhotos.photos;
|
const currentPhotoArray = hasFallbackPhoto ? currentPhotos.photos.slice(0, -1) : currentPhotos.photos;
|
||||||
|
|
||||||
const photos = uniqueByField([...currentPhotoArray, ...newPhotos, fallbackPhoto].filter(Boolean), 'id');
|
const photos = uniqueByField([...currentPhotoArray, ...newPhotos, fallbackPhoto].filter(Boolean), 'id');
|
||||||
return updatePeer(global, peerId, {
|
return replacePeerPhotos(global, peerId, {
|
||||||
profilePhotos: {
|
fallbackPhoto,
|
||||||
fallbackPhoto,
|
personalPhoto,
|
||||||
personalPhoto,
|
photos,
|
||||||
photos,
|
count,
|
||||||
count,
|
nextOffset,
|
||||||
nextOffset,
|
isLoading: false,
|
||||||
isLoading: false,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,7 +141,8 @@ export function deletePeerPhoto<T extends GlobalState>(
|
|||||||
isFromActionMessage?: boolean,
|
isFromActionMessage?: boolean,
|
||||||
) {
|
) {
|
||||||
const peer = selectPeer(global, peerId);
|
const peer = selectPeer(global, peerId);
|
||||||
if (!peer || !peer.profilePhotos) {
|
const profilePhotos = selectPeerPhotos(global, peerId);
|
||||||
|
if (!peer || !profilePhotos) {
|
||||||
return global;
|
return global;
|
||||||
}
|
}
|
||||||
const isChannel = 'title' in peer && isChatChannel(peer);
|
const isChannel = 'title' in peer && isChatChannel(peer);
|
||||||
@ -133,7 +151,7 @@ export function deletePeerPhoto<T extends GlobalState>(
|
|||||||
const chatFullInfo = selectChatFullInfo(global, peerId);
|
const chatFullInfo = selectChatFullInfo(global, peerId);
|
||||||
|
|
||||||
const isAvatar = peer.avatarPhotoId === photoId && (!isChannel || isFromActionMessage);
|
const isAvatar = peer.avatarPhotoId === photoId && (!isChannel || isFromActionMessage);
|
||||||
const nextAvatarPhoto = isAvatar ? peer.profilePhotos.photos[1] : undefined;
|
const nextAvatarPhoto = isAvatar ? profilePhotos.photos[1] : undefined;
|
||||||
|
|
||||||
if (userFullInfo) {
|
if (userFullInfo) {
|
||||||
const newFallbackPhoto = userFullInfo.fallbackPhoto?.id === photoId ? undefined : userFullInfo.fallbackPhoto;
|
const newFallbackPhoto = userFullInfo.fallbackPhoto?.id === photoId ? undefined : userFullInfo.fallbackPhoto;
|
||||||
@ -156,13 +174,17 @@ export function deletePeerPhoto<T extends GlobalState>(
|
|||||||
const avatarPhotoId = isAvatar ? nextAvatarPhoto?.id : peer.avatarPhotoId;
|
const avatarPhotoId = isAvatar ? nextAvatarPhoto?.id : peer.avatarPhotoId;
|
||||||
const shouldKeepInPhotos = isAvatar && 'title' in peer && isChatChannel(peer);
|
const shouldKeepInPhotos = isAvatar && 'title' in peer && isChatChannel(peer);
|
||||||
const photos = shouldKeepInPhotos
|
const photos = shouldKeepInPhotos
|
||||||
? peer.profilePhotos.photos.filter((photo) => photo.id !== photoId) : peer.profilePhotos.photos.slice();
|
? profilePhotos.photos.filter((photo) => photo.id !== photoId) : profilePhotos.photos.slice();
|
||||||
return updatePeer(global, peerId, {
|
|
||||||
|
global = updatePeer(global, peerId, {
|
||||||
avatarPhotoId,
|
avatarPhotoId,
|
||||||
profilePhotos: avatarPhotoId ? {
|
|
||||||
...peer.profilePhotos,
|
|
||||||
photos,
|
|
||||||
count: peer.profilePhotos.count - 1,
|
|
||||||
} : undefined,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
global = replacePeerPhotos(global, peerId, avatarPhotoId ? {
|
||||||
|
...profilePhotos,
|
||||||
|
photos,
|
||||||
|
count: profilePhotos.count - 1,
|
||||||
|
} : undefined);
|
||||||
|
|
||||||
|
return global;
|
||||||
}
|
}
|
||||||
@ -19,7 +19,7 @@ import {
|
|||||||
selectIsChatWithSelf,
|
selectIsChatWithSelf,
|
||||||
selectPeer, selectPeerStories, selectPeerStory, selectTabState, selectUser,
|
selectPeer, selectPeerStories, selectPeerStory, selectTabState, selectUser,
|
||||||
} from '../selectors';
|
} from '../selectors';
|
||||||
import { updatePeer } from './general';
|
import { updatePeer } from './peers';
|
||||||
import { updateTabState } from './tabs';
|
import { updateTabState } from './tabs';
|
||||||
|
|
||||||
export function addStories<T extends GlobalState>(global: T, newStoriesByPeerId: Record<string, ApiPeerStories>): T {
|
export function addStories<T extends GlobalState>(global: T, newStoriesByPeerId: Record<string, ApiPeerStories>): T {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import type {
|
import type {
|
||||||
ApiMissingInvitedUser, ApiUser, ApiUserFullInfo, ApiUserStatus,
|
ApiMissingInvitedUser, ApiUser, ApiUserCommonChats, ApiUserFullInfo, ApiUserStatus,
|
||||||
} from '../../api/types';
|
} from '../../api/types';
|
||||||
import type { GlobalState, TabArgs, TabState } from '../types';
|
import type { GlobalState, TabArgs, TabState } from '../types';
|
||||||
|
|
||||||
@ -240,6 +240,21 @@ export function updateUserFullInfo<T extends GlobalState>(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function updateUserCommonChats<T extends GlobalState>(
|
||||||
|
global: T, userId: string, commonChats: ApiUserCommonChats,
|
||||||
|
): T {
|
||||||
|
return {
|
||||||
|
...global,
|
||||||
|
users: {
|
||||||
|
...global.users,
|
||||||
|
commonChatsById: {
|
||||||
|
...global.users.commonChatsById,
|
||||||
|
[userId]: commonChats,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// @optimization Allows to avoid redundant updates which cause a lot of renders
|
// @optimization Allows to avoid redundant updates which cause a lot of renders
|
||||||
export function addUserStatuses<T extends GlobalState>(global: T, newById: Record<string, ApiUserStatus>): T {
|
export function addUserStatuses<T extends GlobalState>(global: T, newById: Record<string, ApiUserStatus>): T {
|
||||||
const { statusesById } = global.users;
|
const { statusesById } = global.users;
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import type {
|
import type {
|
||||||
ApiChat, ApiChatFullInfo, ApiChatType, ApiPeer,
|
ApiChat, ApiChatFullInfo, ApiChatType,
|
||||||
} from '../../api/types';
|
} from '../../api/types';
|
||||||
import type { ChatListType, GlobalState, TabArgs } from '../types';
|
import type { ChatListType, GlobalState, TabArgs } from '../types';
|
||||||
import { MAIN_THREAD_ID } from '../../api/types';
|
import { MAIN_THREAD_ID } from '../../api/types';
|
||||||
@ -24,10 +24,6 @@ import {
|
|||||||
selectBot, selectIsCurrentUserPremium, selectUser, selectUserFullInfo,
|
selectBot, selectIsCurrentUserPremium, selectUser, selectUserFullInfo,
|
||||||
} from './users';
|
} from './users';
|
||||||
|
|
||||||
export function selectPeer<T extends GlobalState>(global: T, peerId: string): ApiPeer | undefined {
|
|
||||||
return selectUser(global, peerId) || selectChat(global, peerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function selectChat<T extends GlobalState>(global: T, chatId: string): ApiChat | undefined {
|
export function selectChat<T extends GlobalState>(global: T, chatId: string): ApiChat | undefined {
|
||||||
return global.chats.byId[chatId];
|
return global.chats.byId[chatId];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,3 +11,4 @@ export * from './settings';
|
|||||||
export * from './statistics';
|
export * from './statistics';
|
||||||
export * from './stories';
|
export * from './stories';
|
||||||
export * from './tabs';
|
export * from './tabs';
|
||||||
|
export * from './peers';
|
||||||
|
|||||||
@ -64,9 +64,9 @@ import {
|
|||||||
selectChatFullInfo,
|
selectChatFullInfo,
|
||||||
selectChatLastMessageId,
|
selectChatLastMessageId,
|
||||||
selectIsChatWithSelf,
|
selectIsChatWithSelf,
|
||||||
selectPeer,
|
|
||||||
selectRequestedChatTranslationLanguage,
|
selectRequestedChatTranslationLanguage,
|
||||||
} from './chats';
|
} from './chats';
|
||||||
|
import { selectPeer } from './peers';
|
||||||
import { selectPeerStory } from './stories';
|
import { selectPeerStory } from './stories';
|
||||||
import { selectIsStickerFavorite } from './symbols';
|
import { selectIsStickerFavorite } from './symbols';
|
||||||
import { selectTabState } from './tabs';
|
import { selectTabState } from './tabs';
|
||||||
|
|||||||
13
src/global/selectors/peers.ts
Normal file
13
src/global/selectors/peers.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import type { ApiPeer } from '../../api/types';
|
||||||
|
import type { GlobalState } from '../types';
|
||||||
|
|
||||||
|
import { selectChat } from './chats';
|
||||||
|
import { selectUser } from './users';
|
||||||
|
|
||||||
|
export function selectPeer<T extends GlobalState>(global: T, peerId: string): ApiPeer | undefined {
|
||||||
|
return selectUser(global, peerId) || selectChat(global, peerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function selectPeerPhotos<T extends GlobalState>(global: T, peerId: string) {
|
||||||
|
return global.profilePhotosById[peerId];
|
||||||
|
}
|
||||||
@ -2,7 +2,7 @@ import type { ApiPeerStories, ApiTypeStory } from '../../api/types';
|
|||||||
import type { GlobalState, TabArgs } from '../types';
|
import type { GlobalState, TabArgs } from '../types';
|
||||||
|
|
||||||
import { getCurrentTabId } from '../../util/establishMultitabRole';
|
import { getCurrentTabId } from '../../util/establishMultitabRole';
|
||||||
import { selectPeer } from './chats';
|
import { selectPeer } from './peers';
|
||||||
import { selectTabState } from './tabs';
|
import { selectTabState } from './tabs';
|
||||||
|
|
||||||
export function selectCurrentViewedStory<T extends GlobalState>(
|
export function selectCurrentViewedStory<T extends GlobalState>(
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import type {
|
import type {
|
||||||
ApiUser, ApiUserFullInfo, ApiUserStatus,
|
ApiUser, ApiUserCommonChats, ApiUserFullInfo, ApiUserStatus,
|
||||||
} from '../../api/types';
|
} from '../../api/types';
|
||||||
import type { GlobalState } from '../types';
|
import type { GlobalState } from '../types';
|
||||||
|
|
||||||
@ -17,6 +17,12 @@ export function selectUserFullInfo<T extends GlobalState>(global: T, userId: str
|
|||||||
return global.users.fullInfoById[userId];
|
return global.users.fullInfoById[userId];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function selectUserCommonChats<T extends GlobalState>(
|
||||||
|
global: T, userId: string,
|
||||||
|
): ApiUserCommonChats | undefined {
|
||||||
|
return global.users.commonChatsById[userId];
|
||||||
|
}
|
||||||
|
|
||||||
export function selectIsUserBlocked<T extends GlobalState>(global: T, userId: string) {
|
export function selectIsUserBlocked<T extends GlobalState>(global: T, userId: string) {
|
||||||
return selectUserFullInfo(global, userId)?.isBlocked;
|
return selectUserFullInfo(global, userId)?.isBlocked;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -47,6 +47,7 @@ import type {
|
|||||||
ApiPaymentFormNativeParams,
|
ApiPaymentFormNativeParams,
|
||||||
ApiPaymentSavedInfo,
|
ApiPaymentSavedInfo,
|
||||||
ApiPeerColors,
|
ApiPeerColors,
|
||||||
|
ApiPeerPhotos,
|
||||||
ApiPeerStories,
|
ApiPeerStories,
|
||||||
ApiPhoneCall,
|
ApiPhoneCall,
|
||||||
ApiPhoto,
|
ApiPhoto,
|
||||||
@ -80,6 +81,7 @@ import type {
|
|||||||
ApiUpdateAuthorizationStateType,
|
ApiUpdateAuthorizationStateType,
|
||||||
ApiUpdateConnectionStateType,
|
ApiUpdateConnectionStateType,
|
||||||
ApiUser,
|
ApiUser,
|
||||||
|
ApiUserCommonChats,
|
||||||
ApiUserFullInfo,
|
ApiUserFullInfo,
|
||||||
ApiUserStatus,
|
ApiUserStatus,
|
||||||
ApiVideo,
|
ApiVideo,
|
||||||
@ -933,7 +935,9 @@ export type GlobalState = {
|
|||||||
// Obtained from GetFullUser / UserFullInfo
|
// Obtained from GetFullUser / UserFullInfo
|
||||||
fullInfoById: Record<string, ApiUserFullInfo>;
|
fullInfoById: Record<string, ApiUserFullInfo>;
|
||||||
previewMediaByBotId: Record<string, ApiBotPreviewMedia[]>;
|
previewMediaByBotId: Record<string, ApiBotPreviewMedia[]>;
|
||||||
|
commonChatsById: Record<string, ApiUserCommonChats>;
|
||||||
};
|
};
|
||||||
|
profilePhotosById: Record<string, ApiPeerPhotos>;
|
||||||
|
|
||||||
chats: {
|
chats: {
|
||||||
// TODO Replace with `Partial<Record>` to properly handle missing keys
|
// TODO Replace with `Partial<Record>` to properly handle missing keys
|
||||||
@ -2672,7 +2676,9 @@ export interface ActionPayloads {
|
|||||||
deleteContact: { userId: string };
|
deleteContact: { userId: string };
|
||||||
loadUser: { userId: string };
|
loadUser: { userId: string };
|
||||||
setUserSearchQuery: { query?: string } & WithTabId;
|
setUserSearchQuery: { query?: string } & WithTabId;
|
||||||
loadCommonChats: WithTabId | undefined;
|
loadCommonChats: {
|
||||||
|
userId: string;
|
||||||
|
};
|
||||||
reportSpam: { chatId: string };
|
reportSpam: { chatId: string };
|
||||||
loadFullUser: { userId: string; withPhotos?: boolean };
|
loadFullUser: { userId: string; withPhotos?: boolean };
|
||||||
openAddContactDialog: { userId?: string } & WithTabId;
|
openAddContactDialog: { userId?: string } & WithTabId;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user