Profile: Common Chats tab (#1547)
This commit is contained in:
parent
aefd2f1cce
commit
becfab6fe7
@ -416,7 +416,7 @@ export function buildInputReportReason(reason: ApiReportReason) {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildMtpPeerId(id: string, type: 'user' | 'chat' | 'channel') {
|
export function buildMtpPeerId(id: string, type: 'user' | 'chat' | 'channel') {
|
||||||
// Workaround for old-fashioned IDs stored locally
|
// Workaround for old-fashioned IDs stored locally
|
||||||
if (typeof id === 'number') {
|
if (typeof id === 'number') {
|
||||||
return BigInt(Math.abs(id));
|
return BigInt(Math.abs(id));
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { Api as GramJs } from '../../lib/gramjs';
|
import { Api as GramJs } from '../../lib/gramjs';
|
||||||
import localDb from './localDb';
|
import localDb from './localDb';
|
||||||
import { getApiChatIdFromMtpPeer } from './apiBuilders/peers';
|
import { buildApiPeerId, getApiChatIdFromMtpPeer } from './apiBuilders/peers';
|
||||||
|
|
||||||
export function resolveMessageApiChatId(mtpMessage: GramJs.TypeMessage) {
|
export function resolveMessageApiChatId(mtpMessage: GramJs.TypeMessage) {
|
||||||
if (!(mtpMessage instanceof GramJs.Message || mtpMessage instanceof GramJs.MessageService)) {
|
if (!(mtpMessage instanceof GramJs.Message || mtpMessage instanceof GramJs.MessageService)) {
|
||||||
@ -41,3 +41,9 @@ export function addPhotoToLocalDb(photo: GramJs.TypePhoto) {
|
|||||||
localDb.photos[String(photo.id)] = photo;
|
localDb.photos[String(photo.id)] = photo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function addChatToLocalDb(chat: GramJs.TypeChat) {
|
||||||
|
if (chat instanceof GramJs.Chat || chat instanceof GramJs.Channel) {
|
||||||
|
localDb.chats[buildApiPeerId(chat.id, chat instanceof GramJs.Chat ? 'chat' : 'channel')] = chat;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -39,7 +39,7 @@ import {
|
|||||||
buildChatBannedRights,
|
buildChatBannedRights,
|
||||||
buildChatAdminRights,
|
buildChatAdminRights,
|
||||||
} from '../gramjsBuilders';
|
} from '../gramjsBuilders';
|
||||||
import { addMessageToLocalDb } from '../helpers';
|
import { addChatToLocalDb, addMessageToLocalDb } from '../helpers';
|
||||||
import { buildApiPeerId, getApiChatIdFromMtpPeer } from '../apiBuilders/peers';
|
import { buildApiPeerId, getApiChatIdFromMtpPeer } from '../apiBuilders/peers';
|
||||||
|
|
||||||
const MAX_INT_32 = 2 ** 31 - 1;
|
const MAX_INT_32 = 2 ** 31 - 1;
|
||||||
@ -1075,11 +1075,7 @@ function updateLocalDb(result: (
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ('chats' in result) {
|
if ('chats' in result) {
|
||||||
result.chats.forEach((chat) => {
|
result.chats.forEach(addChatToLocalDb);
|
||||||
if (chat instanceof GramJs.Chat || chat instanceof GramJs.Channel) {
|
|
||||||
localDb.chats[buildApiPeerId(chat.id, chat instanceof GramJs.Chat ? 'chat' : 'channel')] = chat;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('messages' in result) {
|
if ('messages' in result) {
|
||||||
|
|||||||
@ -27,7 +27,7 @@ export {
|
|||||||
|
|
||||||
export {
|
export {
|
||||||
fetchFullUser, fetchNearestCountry, fetchTopUsers, fetchContactList, fetchUsers,
|
fetchFullUser, fetchNearestCountry, fetchTopUsers, fetchContactList, fetchUsers,
|
||||||
addContact, updateContact, deleteUser, fetchProfilePhotos,
|
addContact, updateContact, deleteUser, fetchProfilePhotos, fetchCommonChats,
|
||||||
} from './users';
|
} from './users';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
|||||||
@ -4,19 +4,21 @@ import {
|
|||||||
OnApiUpdate, ApiUser, ApiChat, ApiPhoto,
|
OnApiUpdate, ApiUser, ApiChat, ApiPhoto,
|
||||||
} from '../../types';
|
} from '../../types';
|
||||||
|
|
||||||
import { PROFILE_PHOTOS_LIMIT } from '../../../config';
|
import { COMMON_CHATS_LIMIT, PROFILE_PHOTOS_LIMIT } from '../../../config';
|
||||||
import { invokeRequest } from './client';
|
import { invokeRequest } from './client';
|
||||||
import { searchMessagesLocal } from './messages';
|
import { searchMessagesLocal } from './messages';
|
||||||
import {
|
import {
|
||||||
buildInputEntity,
|
buildInputEntity,
|
||||||
buildInputPeer,
|
buildInputPeer,
|
||||||
buildInputContact,
|
buildInputContact,
|
||||||
|
buildMtpPeerId,
|
||||||
|
getEntityTypeById,
|
||||||
} from '../gramjsBuilders';
|
} from '../gramjsBuilders';
|
||||||
import { buildApiUser, buildApiUserFromFull } from '../apiBuilders/users';
|
import { buildApiUser, buildApiUserFromFull } from '../apiBuilders/users';
|
||||||
import { buildApiChatFromPreview } from '../apiBuilders/chats';
|
import { buildApiChatFromPreview } from '../apiBuilders/chats';
|
||||||
import { buildApiPhoto } from '../apiBuilders/common';
|
import { buildApiPhoto } from '../apiBuilders/common';
|
||||||
import localDb from '../localDb';
|
import localDb from '../localDb';
|
||||||
import { addPhotoToLocalDb } from '../helpers';
|
import { addChatToLocalDb, addPhotoToLocalDb } from '../helpers';
|
||||||
import { buildApiPeerId } from '../apiBuilders/peers';
|
import { buildApiPeerId } from '../apiBuilders/peers';
|
||||||
|
|
||||||
let onUpdate: OnApiUpdate;
|
let onUpdate: OnApiUpdate;
|
||||||
@ -54,6 +56,34 @@ export async function fetchFullUser({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function fetchCommonChats(id: string, accessHash?: string, maxId?: string) {
|
||||||
|
const commonChats = await invokeRequest(new GramJs.messages.GetCommonChats({
|
||||||
|
userId: buildInputEntity(id, accessHash) as GramJs.InputUser,
|
||||||
|
maxId: maxId ? buildMtpPeerId(maxId, getEntityTypeById(maxId)) : undefined,
|
||||||
|
limit: COMMON_CHATS_LIMIT,
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (!commonChats) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateLocalDb(commonChats);
|
||||||
|
|
||||||
|
const chatIds: string[] = [];
|
||||||
|
const chats: ApiChat[] = [];
|
||||||
|
|
||||||
|
commonChats.chats.forEach((mtpChat) => {
|
||||||
|
const chat = buildApiChatFromPreview(mtpChat);
|
||||||
|
|
||||||
|
if (chat) {
|
||||||
|
chats.push(chat);
|
||||||
|
chatIds.push(chat.id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return { chats, chatIds, isFullyLoaded: chatIds.length < COMMON_CHATS_LIMIT };
|
||||||
|
}
|
||||||
|
|
||||||
export async function fetchNearestCountry() {
|
export async function fetchNearestCountry() {
|
||||||
const dcInfo = await invokeRequest(new GramJs.help.GetNearestDc());
|
const dcInfo = await invokeRequest(new GramJs.help.GetNearestDc());
|
||||||
|
|
||||||
@ -217,6 +247,12 @@ export async function fetchProfilePhotos(user?: ApiUser, chat?: ApiChat) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateLocalDb(result: (GramJs.photos.Photos | GramJs.photos.PhotosSlice)) {
|
function updateLocalDb(result: (GramJs.photos.Photos | GramJs.photos.PhotosSlice | GramJs.messages.Chats)) {
|
||||||
result.photos.forEach(addPhotoToLocalDb);
|
if ('chats' in result) {
|
||||||
|
result.chats.forEach(addChatToLocalDb);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('photos' in result) {
|
||||||
|
result.photos.forEach(addPhotoToLocalDb);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,6 +18,11 @@ export interface ApiUser {
|
|||||||
photos?: ApiPhoto[];
|
photos?: ApiPhoto[];
|
||||||
botPlaceholder?: string;
|
botPlaceholder?: string;
|
||||||
canBeInvitedToGroup?: boolean;
|
canBeInvitedToGroup?: boolean;
|
||||||
|
commonChats?: {
|
||||||
|
ids: string[];
|
||||||
|
maxId: string;
|
||||||
|
isFullyLoaded: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
// Obtained from GetFullUser / UserFullInfo
|
// Obtained from GetFullUser / UserFullInfo
|
||||||
fullInfo?: ApiUserFullInfo;
|
fullInfo?: ApiUserFullInfo;
|
||||||
|
|||||||
@ -129,6 +129,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.commonChats-list,
|
||||||
&.members-list {
|
&.members-list {
|
||||||
padding: 0.5rem 1rem;
|
padding: 0.5rem 1rem;
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,8 @@ import {
|
|||||||
ApiMessage,
|
ApiMessage,
|
||||||
ApiChatMember,
|
ApiChatMember,
|
||||||
ApiUser,
|
ApiUser,
|
||||||
MAIN_THREAD_ID, ApiChat,
|
ApiChat,
|
||||||
|
MAIN_THREAD_ID,
|
||||||
} from '../../api/types';
|
} from '../../api/types';
|
||||||
import { GlobalActions } from '../../global/types';
|
import { GlobalActions } from '../../global/types';
|
||||||
import {
|
import {
|
||||||
@ -31,6 +32,7 @@ import {
|
|||||||
selectIsRightColumnShown,
|
selectIsRightColumnShown,
|
||||||
selectTheme,
|
selectTheme,
|
||||||
selectActiveDownloadIds,
|
selectActiveDownloadIds,
|
||||||
|
selectUser,
|
||||||
} from '../../modules/selectors';
|
} from '../../modules/selectors';
|
||||||
import { pick } from '../../util/iteratees';
|
import { pick } from '../../util/iteratees';
|
||||||
import { captureEvents, SwipeDirection } from '../../util/captureEvents';
|
import { captureEvents, SwipeDirection } from '../../util/captureEvents';
|
||||||
@ -57,6 +59,7 @@ import WebLink from '../common/WebLink';
|
|||||||
import NothingFound from '../common/NothingFound';
|
import NothingFound from '../common/NothingFound';
|
||||||
import FloatingActionButton from '../ui/FloatingActionButton';
|
import FloatingActionButton from '../ui/FloatingActionButton';
|
||||||
import DeleteMemberModal from './DeleteMemberModal';
|
import DeleteMemberModal from './DeleteMemberModal';
|
||||||
|
import GroupChatInfo from '../common/GroupChatInfo';
|
||||||
|
|
||||||
import './Profile.scss';
|
import './Profile.scss';
|
||||||
|
|
||||||
@ -75,11 +78,13 @@ type StateProps = {
|
|||||||
chatMessages?: Record<number, ApiMessage>;
|
chatMessages?: Record<number, ApiMessage>;
|
||||||
foundIds?: number[];
|
foundIds?: number[];
|
||||||
mediaSearchType?: SharedMediaType;
|
mediaSearchType?: SharedMediaType;
|
||||||
|
hasCommonChatsTab?: boolean;
|
||||||
hasMembersTab?: boolean;
|
hasMembersTab?: boolean;
|
||||||
areMembersHidden?: boolean;
|
areMembersHidden?: boolean;
|
||||||
canAddMembers?: boolean;
|
canAddMembers?: boolean;
|
||||||
canDeleteMembers?: boolean;
|
canDeleteMembers?: boolean;
|
||||||
members?: ApiChatMember[];
|
members?: ApiChatMember[];
|
||||||
|
commonChatIds?: string[];
|
||||||
chatsById: Record<string, ApiChat>;
|
chatsById: Record<string, ApiChat>;
|
||||||
usersById: Record<string, ApiUser>;
|
usersById: Record<string, ApiUser>;
|
||||||
isRightColumnShown: boolean;
|
isRightColumnShown: boolean;
|
||||||
@ -90,8 +95,9 @@ type StateProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
type DispatchProps = Pick<GlobalActions, (
|
type DispatchProps = Pick<GlobalActions, (
|
||||||
'setLocalMediaSearchType' | 'loadMoreMembers' | 'searchMediaMessagesLocal' | 'openMediaViewer' |
|
'setLocalMediaSearchType' | 'loadMoreMembers' | 'searchMediaMessagesLocal' | 'openMediaViewer' | 'loadCommonChats' |
|
||||||
'openAudioPlayer' | 'openUserInfo' | 'focusMessage' | 'loadProfilePhotos' | 'setNewChatMembersDialogState'
|
'openAudioPlayer' | 'openUserInfo' | 'focusMessage' | 'loadProfilePhotos' | 'setNewChatMembersDialogState' |
|
||||||
|
'openChat'
|
||||||
)>;
|
)>;
|
||||||
|
|
||||||
const TABS = [
|
const TABS = [
|
||||||
@ -115,10 +121,12 @@ const Profile: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
chatMessages,
|
chatMessages,
|
||||||
foundIds,
|
foundIds,
|
||||||
mediaSearchType,
|
mediaSearchType,
|
||||||
|
hasCommonChatsTab,
|
||||||
hasMembersTab,
|
hasMembersTab,
|
||||||
areMembersHidden,
|
areMembersHidden,
|
||||||
canAddMembers,
|
canAddMembers,
|
||||||
canDeleteMembers,
|
canDeleteMembers,
|
||||||
|
commonChatIds,
|
||||||
members,
|
members,
|
||||||
usersById,
|
usersById,
|
||||||
chatsById,
|
chatsById,
|
||||||
@ -129,6 +137,8 @@ const Profile: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
serverTimeOffset,
|
serverTimeOffset,
|
||||||
setLocalMediaSearchType,
|
setLocalMediaSearchType,
|
||||||
loadMoreMembers,
|
loadMoreMembers,
|
||||||
|
loadCommonChats,
|
||||||
|
openChat,
|
||||||
searchMediaMessagesLocal,
|
searchMediaMessagesLocal,
|
||||||
openMediaViewer,
|
openMediaViewer,
|
||||||
openAudioPlayer,
|
openAudioPlayer,
|
||||||
@ -150,12 +160,15 @@ const Profile: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
type: 'members', title: isChannel ? 'ChannelSubscribers' : 'GroupMembers',
|
type: 'members', title: isChannel ? 'ChannelSubscribers' : 'GroupMembers',
|
||||||
}] : []),
|
}] : []),
|
||||||
...TABS,
|
...TABS,
|
||||||
]), [hasMembersTab, isChannel]);
|
...(hasCommonChatsTab ? [{
|
||||||
|
type: 'commonChats', title: 'SharedGroupsTab2',
|
||||||
|
}] : []),
|
||||||
|
]), [hasCommonChatsTab, hasMembersTab, isChannel]);
|
||||||
const tabType = tabs[activeTab].type as ProfileTabType;
|
const tabType = tabs[activeTab].type as ProfileTabType;
|
||||||
|
|
||||||
const [resultType, viewportIds, getMore, noProfileInfo] = useProfileViewportIds(
|
const [resultType, viewportIds, getMore, noProfileInfo] = useProfileViewportIds(
|
||||||
isRightColumnShown, loadMoreMembers, searchMediaMessagesLocal, tabType, mediaSearchType, members,
|
isRightColumnShown, loadMoreMembers, loadCommonChats, searchMediaMessagesLocal, tabType, mediaSearchType, members,
|
||||||
usersById, chatMessages, foundIds, chatId, lastSyncTime, serverTimeOffset,
|
commonChatIds, usersById, chatsById, chatMessages, foundIds, chatId, lastSyncTime, serverTimeOffset,
|
||||||
);
|
);
|
||||||
const activeKey = tabs.findIndex(({ type }) => type === resultType);
|
const activeKey = tabs.findIndex(({ type }) => type === resultType);
|
||||||
|
|
||||||
@ -273,6 +286,9 @@ const Profile: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
case 'members':
|
case 'members':
|
||||||
text = areMembersHidden ? 'You have no access to group members list.' : 'No members found';
|
text = areMembersHidden ? 'You have no access to group members list.' : 'No members found';
|
||||||
break;
|
break;
|
||||||
|
case 'commonChats':
|
||||||
|
text = lang('NoGroupsInCommon');
|
||||||
|
break;
|
||||||
case 'documents':
|
case 'documents':
|
||||||
text = lang('lng_media_file_empty');
|
text = lang('lng_media_file_empty');
|
||||||
break;
|
break;
|
||||||
@ -373,6 +389,17 @@ const Profile: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
<PrivateChatInfo userId={id} forceShowSelf />
|
<PrivateChatInfo userId={id} forceShowSelf />
|
||||||
</ListItem>
|
</ListItem>
|
||||||
))
|
))
|
||||||
|
) : resultType === 'commonChats' ? (
|
||||||
|
(viewportIds as string[])!.map((id, i) => (
|
||||||
|
<ListItem
|
||||||
|
key={id}
|
||||||
|
teactOrderKey={i}
|
||||||
|
className="chat-item-clickable scroll-item small-icon"
|
||||||
|
onClick={() => openChat({ id })}
|
||||||
|
>
|
||||||
|
<GroupChatInfo chatId={id} />
|
||||||
|
</ListItem>
|
||||||
|
))
|
||||||
) : undefined}
|
) : undefined}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -474,11 +501,16 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
const activeDownloadIds = selectActiveDownloadIds(global, chatId);
|
const activeDownloadIds = selectActiveDownloadIds(global, chatId);
|
||||||
|
|
||||||
let resolvedUserId;
|
let resolvedUserId;
|
||||||
|
let user;
|
||||||
if (userId) {
|
if (userId) {
|
||||||
resolvedUserId = userId;
|
resolvedUserId = userId;
|
||||||
} else if (isUserId(chatId)) {
|
} else if (isUserId(chatId)) {
|
||||||
resolvedUserId = chatId;
|
resolvedUserId = chatId;
|
||||||
}
|
}
|
||||||
|
const hasCommonChatsTab = Boolean(resolvedUserId);
|
||||||
|
if (resolvedUserId) {
|
||||||
|
user = selectUser(global, resolvedUserId);
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
theme: selectTheme(global),
|
theme: selectTheme(global),
|
||||||
@ -487,6 +519,7 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
chatMessages,
|
chatMessages,
|
||||||
foundIds,
|
foundIds,
|
||||||
mediaSearchType,
|
mediaSearchType,
|
||||||
|
hasCommonChatsTab,
|
||||||
hasMembersTab,
|
hasMembersTab,
|
||||||
areMembersHidden,
|
areMembersHidden,
|
||||||
canAddMembers,
|
canAddMembers,
|
||||||
@ -500,6 +533,7 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
usersById,
|
usersById,
|
||||||
chatsById,
|
chatsById,
|
||||||
...(hasMembersTab && members && { members }),
|
...(hasMembersTab && members && { members }),
|
||||||
|
...(hasCommonChatsTab && user && { commonChatIds: user.commonChats?.ids }),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
(setGlobal, actions): DispatchProps => pick(actions, [
|
(setGlobal, actions): DispatchProps => pick(actions, [
|
||||||
@ -512,5 +546,7 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
'focusMessage',
|
'focusMessage',
|
||||||
'loadProfilePhotos',
|
'loadProfilePhotos',
|
||||||
'setNewChatMembersDialogState',
|
'setNewChatMembersDialogState',
|
||||||
|
'loadCommonChats',
|
||||||
|
'openChat',
|
||||||
]),
|
]),
|
||||||
)(Profile));
|
)(Profile));
|
||||||
|
|||||||
@ -1,21 +1,26 @@
|
|||||||
import { useMemo, useRef } from '../../../lib/teact/teact';
|
import { useMemo, useRef } from '../../../lib/teact/teact';
|
||||||
|
|
||||||
import { ApiChatMember, ApiMessage, ApiUser } from '../../../api/types';
|
import {
|
||||||
|
ApiChat, ApiChatMember, ApiMessage, ApiUser,
|
||||||
|
} from '../../../api/types';
|
||||||
import { ProfileTabType, SharedMediaType } from '../../../types';
|
import { ProfileTabType, SharedMediaType } from '../../../types';
|
||||||
|
|
||||||
import { MEMBERS_SLICE, MESSAGE_SEARCH_SLICE, SHARED_MEDIA_SLICE } from '../../../config';
|
import { MEMBERS_SLICE, MESSAGE_SEARCH_SLICE, SHARED_MEDIA_SLICE } from '../../../config';
|
||||||
import { getMessageContentIds, sortUserIds } from '../../../modules/helpers';
|
import { getMessageContentIds, sortChatIds, sortUserIds } from '../../../modules/helpers';
|
||||||
import useOnChange from '../../../hooks/useOnChange';
|
import useOnChange from '../../../hooks/useOnChange';
|
||||||
import useInfiniteScroll from '../../../hooks/useInfiniteScroll';
|
import useInfiniteScroll from '../../../hooks/useInfiniteScroll';
|
||||||
|
|
||||||
export default function useProfileViewportIds(
|
export default function useProfileViewportIds(
|
||||||
isRightColumnShown: boolean,
|
isRightColumnShown: boolean,
|
||||||
loadMoreMembers: AnyToVoidFunction,
|
loadMoreMembers: AnyToVoidFunction,
|
||||||
|
loadCommonChats: AnyToVoidFunction,
|
||||||
searchMessages: AnyToVoidFunction,
|
searchMessages: AnyToVoidFunction,
|
||||||
tabType: ProfileTabType,
|
tabType: ProfileTabType,
|
||||||
mediaSearchType?: SharedMediaType,
|
mediaSearchType?: SharedMediaType,
|
||||||
groupChatMembers?: ApiChatMember[],
|
groupChatMembers?: ApiChatMember[],
|
||||||
|
commonChatIds?: string[],
|
||||||
usersById?: Record<string, ApiUser>,
|
usersById?: Record<string, ApiUser>,
|
||||||
|
chatsById?: Record<string, ApiChat>,
|
||||||
chatMessages?: Record<number, ApiMessage>,
|
chatMessages?: Record<number, ApiMessage>,
|
||||||
foundIds?: number[],
|
foundIds?: number[],
|
||||||
chatId?: string,
|
chatId?: string,
|
||||||
@ -32,10 +37,22 @@ export default function useProfileViewportIds(
|
|||||||
return sortUserIds(groupChatMembers.map(({ userId }) => userId), usersById, undefined, serverTimeOffset);
|
return sortUserIds(groupChatMembers.map(({ userId }) => userId), usersById, undefined, serverTimeOffset);
|
||||||
}, [groupChatMembers, serverTimeOffset, usersById]);
|
}, [groupChatMembers, serverTimeOffset, usersById]);
|
||||||
|
|
||||||
const [memberViewportIds, getMoreMembers, noProfileInfoForMembers] = useInfiniteScrollForMembers(
|
const chatIds = useMemo(() => {
|
||||||
|
if (!commonChatIds || !chatsById) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sortChatIds(commonChatIds, chatsById, true);
|
||||||
|
}, [chatsById, commonChatIds]);
|
||||||
|
|
||||||
|
const [memberViewportIds, getMoreMembers, noProfileInfoForMembers] = useInfiniteScrollForLoadableItems(
|
||||||
resultType, loadMoreMembers, lastSyncTime, memberIds,
|
resultType, loadMoreMembers, lastSyncTime, memberIds,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const [commonChatViewportIds, getMoreCommonChats, noProfileInfoForCommonChats] = useInfiniteScrollForLoadableItems(
|
||||||
|
resultType, loadCommonChats, lastSyncTime, chatIds,
|
||||||
|
);
|
||||||
|
|
||||||
const [mediaViewportIds, getMoreMedia, noProfileInfoForMedia] = useInfiniteScrollForSharedMedia(
|
const [mediaViewportIds, getMoreMedia, noProfileInfoForMedia] = useInfiniteScrollForSharedMedia(
|
||||||
'media', resultType, searchMessages, lastSyncTime, chatMessages, foundIds,
|
'media', resultType, searchMessages, lastSyncTime, chatMessages, foundIds,
|
||||||
);
|
);
|
||||||
@ -66,6 +83,11 @@ export default function useProfileViewportIds(
|
|||||||
getMore = getMoreMembers;
|
getMore = getMoreMembers;
|
||||||
noProfileInfo = noProfileInfoForMembers;
|
noProfileInfo = noProfileInfoForMembers;
|
||||||
break;
|
break;
|
||||||
|
case 'commonChats':
|
||||||
|
viewportIds = commonChatViewportIds;
|
||||||
|
getMore = getMoreCommonChats;
|
||||||
|
noProfileInfo = noProfileInfoForCommonChats;
|
||||||
|
break;
|
||||||
case 'media':
|
case 'media':
|
||||||
viewportIds = mediaViewportIds;
|
viewportIds = mediaViewportIds;
|
||||||
getMore = getMoreMedia;
|
getMore = getMoreMedia;
|
||||||
@ -96,20 +118,20 @@ export default function useProfileViewportIds(
|
|||||||
return [resultType, viewportIds, getMore, noProfileInfo] as const;
|
return [resultType, viewportIds, getMore, noProfileInfo] as const;
|
||||||
}
|
}
|
||||||
|
|
||||||
function useInfiniteScrollForMembers(
|
function useInfiniteScrollForLoadableItems(
|
||||||
currentResultType?: ProfileTabType,
|
currentResultType?: ProfileTabType,
|
||||||
handleLoadMore?: AnyToVoidFunction,
|
handleLoadMore?: AnyToVoidFunction,
|
||||||
lastSyncTime?: number,
|
lastSyncTime?: number,
|
||||||
memberIds?: string[],
|
itemIds?: string[],
|
||||||
) {
|
) {
|
||||||
const [viewportIds, getMore] = useInfiniteScroll(
|
const [viewportIds, getMore] = useInfiniteScroll(
|
||||||
lastSyncTime ? handleLoadMore : undefined,
|
lastSyncTime ? handleLoadMore : undefined,
|
||||||
memberIds,
|
itemIds,
|
||||||
undefined,
|
undefined,
|
||||||
MEMBERS_SLICE,
|
MEMBERS_SLICE,
|
||||||
);
|
);
|
||||||
|
|
||||||
const isOnTop = !viewportIds || !memberIds || viewportIds[0] === memberIds[0];
|
const isOnTop = !viewportIds || !itemIds || viewportIds[0] === itemIds[0];
|
||||||
|
|
||||||
return [viewportIds, getMore, !isOnTop] as const;
|
return [viewportIds, getMore, !isOnTop] as const;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -57,6 +57,7 @@ export const PINNED_MESSAGES_LIMIT = 50;
|
|||||||
export const BLOCKED_LIST_LIMIT = 100;
|
export const BLOCKED_LIST_LIMIT = 100;
|
||||||
export const PROFILE_PHOTOS_LIMIT = 40;
|
export const PROFILE_PHOTOS_LIMIT = 40;
|
||||||
export const PROFILE_SENSITIVE_AREA = 500;
|
export const PROFILE_SENSITIVE_AREA = 500;
|
||||||
|
export const COMMON_CHATS_LIMIT = 100;
|
||||||
|
|
||||||
export const TOP_CHAT_MESSAGES_PRELOAD_LIMIT = 20;
|
export const TOP_CHAT_MESSAGES_PRELOAD_LIMIT = 20;
|
||||||
export const ALL_CHATS_PRELOAD_DISABLED = false;
|
export const ALL_CHATS_PRELOAD_DISABLED = false;
|
||||||
|
|||||||
@ -505,7 +505,7 @@ export type ActionTypes = (
|
|||||||
// users
|
// users
|
||||||
'loadFullUser' | 'openUserInfo' | 'loadNearestCountry' | 'loadTopUsers' | 'loadContactList' |
|
'loadFullUser' | 'openUserInfo' | 'loadNearestCountry' | 'loadTopUsers' | 'loadContactList' |
|
||||||
'loadCurrentUser' | 'updateProfile' | 'checkUsername' | 'addContact' | 'updateContact' |
|
'loadCurrentUser' | 'updateProfile' | 'checkUsername' | 'addContact' | 'updateContact' |
|
||||||
'deleteUser' | 'loadUser' | 'setUserSearchQuery' |
|
'deleteUser' | 'loadUser' | 'setUserSearchQuery' | 'loadCommonChats' |
|
||||||
// chat creation
|
// chat creation
|
||||||
'createChannel' | 'createGroupChat' | 'resetChatCreation' |
|
'createChannel' | 'createGroupChat' | 'resetChatCreation' |
|
||||||
// settings
|
// settings
|
||||||
|
|||||||
@ -1026,6 +1026,7 @@ messages.saveDraft#bc39e14b flags:# no_webpage:flags.1?true reply_to_msg_id:flag
|
|||||||
messages.getAllDrafts#6a3f8d65 = Updates;
|
messages.getAllDrafts#6a3f8d65 = Updates;
|
||||||
messages.readFeaturedStickers#5b118126 id:Vector<long> = Bool;
|
messages.readFeaturedStickers#5b118126 id:Vector<long> = Bool;
|
||||||
messages.getRecentStickers#9da9403b flags:# attached:flags.0?true hash:long = messages.RecentStickers;
|
messages.getRecentStickers#9da9403b flags:# attached:flags.0?true hash:long = messages.RecentStickers;
|
||||||
|
messages.getCommonChats#e40ca104 user_id:InputUser max_id:long limit:int = messages.Chats;
|
||||||
messages.getWebPage#32ca8f91 url:string hash:int = WebPage;
|
messages.getWebPage#32ca8f91 url:string hash:int = WebPage;
|
||||||
messages.toggleDialogPin#a731e257 flags:# pinned:flags.0?true peer:InputDialogPeer = Bool;
|
messages.toggleDialogPin#a731e257 flags:# pinned:flags.0?true peer:InputDialogPeer = Bool;
|
||||||
messages.getPinnedDialogs#d6b94df2 folder_id:int = messages.PeerDialogs;
|
messages.getPinnedDialogs#d6b94df2 folder_id:int = messages.PeerDialogs;
|
||||||
|
|||||||
@ -1027,6 +1027,7 @@ messages.saveDraft#bc39e14b flags:# no_webpage:flags.1?true reply_to_msg_id:flag
|
|||||||
messages.getAllDrafts#6a3f8d65 = Updates;
|
messages.getAllDrafts#6a3f8d65 = Updates;
|
||||||
messages.readFeaturedStickers#5b118126 id:Vector<long> = Bool;
|
messages.readFeaturedStickers#5b118126 id:Vector<long> = Bool;
|
||||||
messages.getRecentStickers#9da9403b flags:# attached:flags.0?true hash:long = messages.RecentStickers;
|
messages.getRecentStickers#9da9403b flags:# attached:flags.0?true hash:long = messages.RecentStickers;
|
||||||
|
messages.getCommonChats#e40ca104 user_id:InputUser max_id:long limit:int = messages.Chats;
|
||||||
messages.getWebPage#32ca8f91 url:string hash:int = WebPage;
|
messages.getWebPage#32ca8f91 url:string hash:int = WebPage;
|
||||||
messages.toggleDialogPin#a731e257 flags:# pinned:flags.0?true peer:InputDialogPeer = Bool;
|
messages.toggleDialogPin#a731e257 flags:# pinned:flags.0?true peer:InputDialogPeer = Bool;
|
||||||
messages.getPinnedDialogs#d6b94df2 folder_id:int = messages.PeerDialogs;
|
messages.getPinnedDialogs#d6b94df2 folder_id:int = messages.PeerDialogs;
|
||||||
|
|||||||
@ -6,10 +6,10 @@ import { ApiUser } from '../../../api/types';
|
|||||||
import { ManagementProgress } from '../../../types';
|
import { ManagementProgress } from '../../../types';
|
||||||
|
|
||||||
import { debounce, throttle } from '../../../util/schedulers';
|
import { debounce, throttle } from '../../../util/schedulers';
|
||||||
import { buildCollectionByKey, pick } from '../../../util/iteratees';
|
import { buildCollectionByKey, pick, unique } from '../../../util/iteratees';
|
||||||
import { isUserId } from '../../helpers';
|
import { isUserBot, isUserId } from '../../helpers';
|
||||||
import { callApi } from '../../../api/gramjs';
|
import { callApi } from '../../../api/gramjs';
|
||||||
import { selectChat, selectUser } from '../../selectors';
|
import { selectChat, selectCurrentMessageList, selectUser } from '../../selectors';
|
||||||
import {
|
import {
|
||||||
addChats, addUsers, updateChat, updateManagementProgress, updateUser, updateUsers,
|
addChats, addUsers, updateChat, updateManagementProgress, updateUser, updateUsers,
|
||||||
updateUserSearch, updateUserSearchFetchingStatus,
|
updateUserSearch, updateUserSearchFetchingStatus,
|
||||||
@ -67,6 +67,37 @@ addReducer('loadCurrentUser', () => {
|
|||||||
void callApi('fetchCurrentUser');
|
void callApi('fetchCurrentUser');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
addReducer('loadCommonChats', (global) => {
|
||||||
|
const { chatId } = selectCurrentMessageList(global) || {};
|
||||||
|
const user = chatId ? selectUser(global, chatId) : undefined;
|
||||||
|
if (!user || isUserBot(user) || user.commonChats?.isFullyLoaded) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
const maxId = user.commonChats?.maxId;
|
||||||
|
const result = await callApi('fetchCommonChats', user.id, user.accessHash!, maxId);
|
||||||
|
if (!result) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { chats, chatIds, isFullyLoaded } = result;
|
||||||
|
|
||||||
|
global = getGlobal();
|
||||||
|
if (chats.length) {
|
||||||
|
global = addChats(global, buildCollectionByKey(chats, 'id'));
|
||||||
|
}
|
||||||
|
global = updateUser(global, user.id, {
|
||||||
|
commonChats: {
|
||||||
|
maxId: chatIds.length ? chatIds[chatIds.length - 1] : '0',
|
||||||
|
ids: unique((user.commonChats?.ids || []).concat(chatIds)),
|
||||||
|
isFullyLoaded,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
setGlobal(global);
|
||||||
|
})();
|
||||||
|
});
|
||||||
|
|
||||||
addReducer('updateContact', (global, actions, payload) => {
|
addReducer('updateContact', (global, actions, payload) => {
|
||||||
const {
|
const {
|
||||||
userId, isMuted, firstName, lastName,
|
userId, isMuted, firstName, lastName,
|
||||||
|
|||||||
@ -284,7 +284,7 @@ export enum NewChatMembersProgress {
|
|||||||
Loading,
|
Loading,
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ProfileTabType = 'members' | 'media' | 'documents' | 'links' | 'audio' | 'voice';
|
export type ProfileTabType = 'members' | 'commonChats' | 'media' | 'documents' | 'links' | 'audio' | 'voice';
|
||||||
export type SharedMediaType = 'media' | 'documents' | 'links' | 'audio' | 'voice';
|
export type SharedMediaType = 'media' | 'documents' | 'links' | 'audio' | 'voice';
|
||||||
export type ApiPrivacyKey = 'phoneNumber' | 'lastSeen' | 'profilePhoto' | 'forwards' | 'chatInvite';
|
export type ApiPrivacyKey = 'phoneNumber' | 'lastSeen' | 'profilePhoto' | 'forwards' | 'chatInvite';
|
||||||
export type PrivacyVisibility = 'everybody' | 'contacts' | 'nonContacts' | 'nobody';
|
export type PrivacyVisibility = 'everybody' | 'contacts' | 'nonContacts' | 'nobody';
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user