Profile: add similar channels tab (#4104)
This commit is contained in:
parent
20d8087d87
commit
d2b834d1a6
@ -15,9 +15,21 @@ import localDb from '../localDb';
|
|||||||
import { buildJson } from './misc';
|
import { buildJson } from './misc';
|
||||||
|
|
||||||
type LimitType = 'default' | 'premium';
|
type LimitType = 'default' | 'premium';
|
||||||
type Limit = 'upload_max_fileparts' | 'stickers_faved_limit' | 'saved_gifs_limit' | 'dialog_filters_chats_limit' |
|
type Limit =
|
||||||
'dialog_filters_limit' | 'dialogs_folder_pinned_limit' | 'dialogs_pinned_limit' | 'caption_length_limit' |
|
| 'upload_max_fileparts'
|
||||||
'channels_limit' | 'channels_public_limit' | 'about_length_limit' | 'chatlist_invites_limit' | 'chatlist_joined_limit';
|
| 'stickers_faved_limit'
|
||||||
|
| 'saved_gifs_limit'
|
||||||
|
| 'dialog_filters_chats_limit'
|
||||||
|
| 'dialog_filters_limit'
|
||||||
|
| 'dialogs_folder_pinned_limit'
|
||||||
|
| 'dialogs_pinned_limit'
|
||||||
|
| 'caption_length_limit'
|
||||||
|
| 'channels_limit'
|
||||||
|
| 'channels_public_limit'
|
||||||
|
| 'about_length_limit'
|
||||||
|
| 'chatlist_invites_limit'
|
||||||
|
| 'chatlist_joined_limit'
|
||||||
|
| 'recommended_channels_limit';
|
||||||
type LimitKey = `${Limit}_${LimitType}`;
|
type LimitKey = `${Limit}_${LimitType}`;
|
||||||
type LimitsConfig = Record<LimitKey, number>;
|
type LimitsConfig = Record<LimitKey, number>;
|
||||||
|
|
||||||
@ -111,6 +123,7 @@ export function buildAppConfig(json: GramJs.TypeJSONValue, hash: number): ApiApp
|
|||||||
aboutLength: getLimit(appConfig, 'about_length_limit', 'aboutLength'),
|
aboutLength: getLimit(appConfig, 'about_length_limit', 'aboutLength'),
|
||||||
chatlistInvites: getLimit(appConfig, 'chatlist_invites_limit', 'chatlistInvites'),
|
chatlistInvites: getLimit(appConfig, 'chatlist_invites_limit', 'chatlistInvites'),
|
||||||
chatlistJoined: getLimit(appConfig, 'chatlist_joined_limit', 'chatlistJoined'),
|
chatlistJoined: getLimit(appConfig, 'chatlist_joined_limit', 'chatlistJoined'),
|
||||||
|
recommendedChannels: getLimit(appConfig, 'recommended_channels_limit', 'recommendedChannels'),
|
||||||
},
|
},
|
||||||
hash,
|
hash,
|
||||||
areStoriesHidden: appConfig.stories_all_hidden,
|
areStoriesHidden: appConfig.stories_all_hidden,
|
||||||
|
|||||||
@ -1895,6 +1895,22 @@ export function setViewForumAsMessages({ chat, isEnabled }: { chat: ApiChat; isE
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function fetchChannelRecommendations({ chat }: { chat: ApiChat }) {
|
||||||
|
const { id, accessHash } = chat;
|
||||||
|
const channel = buildInputEntity(id, accessHash);
|
||||||
|
|
||||||
|
const result = await invokeRequest(new GramJs.channels.GetChannelRecommendations({
|
||||||
|
channel: channel as GramJs.InputChannel,
|
||||||
|
}));
|
||||||
|
if (!result) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateLocalDb(result);
|
||||||
|
|
||||||
|
return result?.chats.map((_chat) => buildApiChatFromPreview(_chat)).filter(Boolean);
|
||||||
|
}
|
||||||
|
|
||||||
function handleUserPrivacyRestrictedUpdates(updates: GramJs.TypeUpdates) {
|
function handleUserPrivacyRestrictedUpdates(updates: GramJs.TypeUpdates) {
|
||||||
if (!(updates instanceof GramJs.Updates) && !(updates instanceof GramJs.UpdatesCombined)) {
|
if (!(updates instanceof GramJs.Updates) && !(updates instanceof GramJs.UpdatesCombined)) {
|
||||||
return undefined;
|
return undefined;
|
||||||
|
|||||||
@ -24,6 +24,7 @@ export {
|
|||||||
editTopic, toggleForum, fetchTopicById, createTopic, toggleParticipantsHidden, checkChatlistInvite,
|
editTopic, toggleForum, fetchTopicById, createTopic, toggleParticipantsHidden, checkChatlistInvite,
|
||||||
joinChatlistInvite, createChalistInvite, editChatlistInvite, deleteChatlistInvite, fetchChatlistInvites,
|
joinChatlistInvite, createChalistInvite, editChatlistInvite, deleteChatlistInvite, fetchChatlistInvites,
|
||||||
fetchLeaveChatlistSuggestions, leaveChatlist, togglePeerTranslations, setViewForumAsMessages,
|
fetchLeaveChatlistSuggestions, leaveChatlist, togglePeerTranslations, setViewForumAsMessages,
|
||||||
|
fetchChannelRecommendations,
|
||||||
} from './chats';
|
} from './chats';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
|||||||
@ -98,6 +98,7 @@ const LIMITS_ORDER: ApiLimitTypeWithoutUpload[] = [
|
|||||||
'captionLength',
|
'captionLength',
|
||||||
'dialogFilters',
|
'dialogFilters',
|
||||||
'dialogFiltersChats',
|
'dialogFiltersChats',
|
||||||
|
'recommendedChannels',
|
||||||
];
|
];
|
||||||
|
|
||||||
const LIMITS_TITLES: Record<ApiLimitTypeWithoutUpload, string> = {
|
const LIMITS_TITLES: Record<ApiLimitTypeWithoutUpload, string> = {
|
||||||
@ -110,6 +111,7 @@ const LIMITS_TITLES: Record<ApiLimitTypeWithoutUpload, string> = {
|
|||||||
captionLength: 'CaptionsLimitTitle',
|
captionLength: 'CaptionsLimitTitle',
|
||||||
dialogFilters: 'FoldersLimitTitle',
|
dialogFilters: 'FoldersLimitTitle',
|
||||||
dialogFiltersChats: 'ChatPerFolderLimitTitle',
|
dialogFiltersChats: 'ChatPerFolderLimitTitle',
|
||||||
|
recommendedChannels: 'SimilarChannelsLimitTitle',
|
||||||
};
|
};
|
||||||
|
|
||||||
const LIMITS_DESCRIPTIONS: Record<ApiLimitTypeWithoutUpload, string> = {
|
const LIMITS_DESCRIPTIONS: Record<ApiLimitTypeWithoutUpload, string> = {
|
||||||
@ -122,6 +124,7 @@ const LIMITS_DESCRIPTIONS: Record<ApiLimitTypeWithoutUpload, string> = {
|
|||||||
captionLength: 'CaptionsLimitSubtitle',
|
captionLength: 'CaptionsLimitSubtitle',
|
||||||
dialogFilters: 'FoldersLimitSubtitle',
|
dialogFilters: 'FoldersLimitSubtitle',
|
||||||
dialogFiltersChats: 'ChatPerFolderLimitSubtitle',
|
dialogFiltersChats: 'ChatPerFolderLimitSubtitle',
|
||||||
|
recommendedChannels: 'SimilarChannelsLimitSubtitle',
|
||||||
};
|
};
|
||||||
|
|
||||||
const BORDER_THRESHOLD = 20;
|
const BORDER_THRESHOLD = 20;
|
||||||
|
|||||||
@ -121,6 +121,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.similarChannels-list,
|
||||||
&.commonChats-list,
|
&.commonChats-list,
|
||||||
&.members-list {
|
&.members-list {
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
@ -133,5 +134,30 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.similarChannels-list {
|
||||||
|
.ListItem.blured {
|
||||||
|
filter: opacity(0.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
.show-more-channels {
|
||||||
|
width: calc(100% - 1rem);
|
||||||
|
margin: 0 auto;
|
||||||
|
margin-top: -1.8125rem;
|
||||||
|
z-index: 1;
|
||||||
|
border-radius: var(--border-radius-default-small);
|
||||||
|
box-shadow: 0px 0px 1rem 1rem white;
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
margin-left: 0.625rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.more-similar {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 1rem;
|
||||||
|
font-size: 0.8125rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,15 +34,20 @@ import {
|
|||||||
selectChatFullInfo,
|
selectChatFullInfo,
|
||||||
selectChatMessages,
|
selectChatMessages,
|
||||||
selectCurrentMediaSearch,
|
selectCurrentMediaSearch,
|
||||||
|
selectIsCurrentUserPremium,
|
||||||
selectIsRightColumnShown,
|
selectIsRightColumnShown,
|
||||||
selectPeerFullInfo,
|
selectPeerFullInfo,
|
||||||
selectPeerStories,
|
selectPeerStories,
|
||||||
|
selectSimilarChannelIds,
|
||||||
selectTabState,
|
selectTabState,
|
||||||
selectTheme,
|
selectTheme,
|
||||||
selectUser,
|
selectUser,
|
||||||
} from '../../global/selectors';
|
} from '../../global/selectors';
|
||||||
|
import { selectPremiumLimit } from '../../global/selectors/limits';
|
||||||
|
import buildClassName from '../../util/buildClassName';
|
||||||
import { captureEvents, SwipeDirection } from '../../util/captureEvents';
|
import { captureEvents, SwipeDirection } from '../../util/captureEvents';
|
||||||
import { IS_TOUCH_ENV } from '../../util/windowEnvironment';
|
import { IS_TOUCH_ENV } from '../../util/windowEnvironment';
|
||||||
|
import renderText from '../common/helpers/renderText';
|
||||||
import { getSenderName } from '../left/search/helpers/getSenderName';
|
import { getSenderName } from '../left/search/helpers/getSenderName';
|
||||||
|
|
||||||
import usePeerStoriesPolling from '../../hooks/polling/usePeerStoriesPolling';
|
import usePeerStoriesPolling from '../../hooks/polling/usePeerStoriesPolling';
|
||||||
@ -66,6 +71,7 @@ import PrivateChatInfo from '../common/PrivateChatInfo';
|
|||||||
import ProfileInfo from '../common/ProfileInfo';
|
import ProfileInfo from '../common/ProfileInfo';
|
||||||
import WebLink from '../common/WebLink';
|
import WebLink from '../common/WebLink';
|
||||||
import MediaStory from '../story/MediaStory';
|
import MediaStory from '../story/MediaStory';
|
||||||
|
import Button from '../ui/Button';
|
||||||
import FloatingActionButton from '../ui/FloatingActionButton';
|
import FloatingActionButton from '../ui/FloatingActionButton';
|
||||||
import InfiniteScroll from '../ui/InfiniteScroll';
|
import InfiniteScroll from '../ui/InfiniteScroll';
|
||||||
import ListItem, { type MenuItemContextAction } from '../ui/ListItem';
|
import ListItem, { type MenuItemContextAction } from '../ui/ListItem';
|
||||||
@ -113,6 +119,9 @@ type StateProps = {
|
|||||||
isChatProtected?: boolean;
|
isChatProtected?: boolean;
|
||||||
nextProfileTab?: ProfileTabType;
|
nextProfileTab?: ProfileTabType;
|
||||||
shouldWarnAboutSvg?: boolean;
|
shouldWarnAboutSvg?: boolean;
|
||||||
|
similarChannels?: string[];
|
||||||
|
isCurrentUserPremium?: boolean;
|
||||||
|
limitSimilarChannels: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
const TABS = [
|
const TABS = [
|
||||||
@ -158,6 +167,9 @@ const Profile: FC<OwnProps & StateProps> = ({
|
|||||||
isChatProtected,
|
isChatProtected,
|
||||||
nextProfileTab,
|
nextProfileTab,
|
||||||
shouldWarnAboutSvg,
|
shouldWarnAboutSvg,
|
||||||
|
similarChannels,
|
||||||
|
isCurrentUserPremium,
|
||||||
|
limitSimilarChannels,
|
||||||
}) => {
|
}) => {
|
||||||
const {
|
const {
|
||||||
setLocalMediaSearchType,
|
setLocalMediaSearchType,
|
||||||
@ -172,6 +184,8 @@ const Profile: FC<OwnProps & StateProps> = ({
|
|||||||
setNewChatMembersDialogState,
|
setNewChatMembersDialogState,
|
||||||
loadPeerPinnedStories,
|
loadPeerPinnedStories,
|
||||||
loadStoriesArchive,
|
loadStoriesArchive,
|
||||||
|
openPremiumModal,
|
||||||
|
fetchChannelRecommendations,
|
||||||
} = getActions();
|
} = getActions();
|
||||||
|
|
||||||
// eslint-disable-next-line no-null/no-null
|
// eslint-disable-next-line no-null/no-null
|
||||||
@ -192,7 +206,19 @@ const Profile: FC<OwnProps & StateProps> = ({
|
|||||||
// in forum topics. Return it when it's fixed on the server side.
|
// in forum topics. Return it when it's fixed on the server side.
|
||||||
...(!topicId ? [{ type: 'voice', title: 'SharedVoiceTab2' }] : []),
|
...(!topicId ? [{ type: 'voice', title: 'SharedVoiceTab2' }] : []),
|
||||||
...(hasCommonChatsTab ? [{ type: 'commonChats', title: 'SharedGroupsTab2' }] : []),
|
...(hasCommonChatsTab ? [{ type: 'commonChats', title: 'SharedGroupsTab2' }] : []),
|
||||||
]), [chatId, currentUserId, hasCommonChatsTab, hasMembersTab, hasStoriesTab, isChannel, topicId]);
|
...(isChannel && similarChannels?.length
|
||||||
|
? [{ type: 'similarChannels', title: 'SimilarChannelsTab' }]
|
||||||
|
: []),
|
||||||
|
]), [
|
||||||
|
chatId,
|
||||||
|
currentUserId,
|
||||||
|
hasCommonChatsTab,
|
||||||
|
hasMembersTab,
|
||||||
|
hasStoriesTab,
|
||||||
|
isChannel,
|
||||||
|
topicId,
|
||||||
|
similarChannels,
|
||||||
|
]);
|
||||||
|
|
||||||
const initialTab = useMemo(() => {
|
const initialTab = useMemo(() => {
|
||||||
if (!nextProfileTab) {
|
if (!nextProfileTab) {
|
||||||
@ -213,6 +239,12 @@ const Profile: FC<OwnProps & StateProps> = ({
|
|||||||
setActiveTab(index);
|
setActiveTab(index);
|
||||||
}, [nextProfileTab, tabs]);
|
}, [nextProfileTab, tabs]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (isChannel) {
|
||||||
|
fetchChannelRecommendations({ chatId });
|
||||||
|
}
|
||||||
|
}, [chatId, isChannel]);
|
||||||
|
|
||||||
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 handleLoadPeerStories = useCallback(({ offsetId }: { offsetId: number }) => {
|
const handleLoadPeerStories = useCallback(({ offsetId }: { offsetId: number }) => {
|
||||||
@ -240,6 +272,7 @@ const Profile: FC<OwnProps & StateProps> = ({
|
|||||||
topicId,
|
topicId,
|
||||||
storyIds,
|
storyIds,
|
||||||
archiveStoryIds,
|
archiveStoryIds,
|
||||||
|
similarChannels,
|
||||||
);
|
);
|
||||||
const isFirstTab = (hasStoriesTab && resultType === 'stories')
|
const isFirstTab = (hasStoriesTab && resultType === 'stories')
|
||||||
|| resultType === 'members'
|
|| resultType === 'members'
|
||||||
@ -512,6 +545,35 @@ const Profile: FC<OwnProps & StateProps> = ({
|
|||||||
<GroupChatInfo chatId={id} />
|
<GroupChatInfo chatId={id} />
|
||||||
</ListItem>
|
</ListItem>
|
||||||
))
|
))
|
||||||
|
) : resultType === 'similarChannels' ? (
|
||||||
|
<div key={resultType}>
|
||||||
|
{(viewportIds as string[])!.map((channelId, i) => (
|
||||||
|
<ListItem
|
||||||
|
key={channelId}
|
||||||
|
teactOrderKey={i}
|
||||||
|
className={buildClassName(
|
||||||
|
'chat-item-clickable search-result',
|
||||||
|
!isCurrentUserPremium && i === similarChannels!.length - 1 && 'blured',
|
||||||
|
)}
|
||||||
|
// eslint-disable-next-line react/jsx-no-bind
|
||||||
|
onClick={() => openChat({ id: channelId })}
|
||||||
|
>
|
||||||
|
<GroupChatInfo avatarSize="large" chatId={channelId} withFullInfo />
|
||||||
|
</ListItem>
|
||||||
|
))}
|
||||||
|
{!isCurrentUserPremium && (
|
||||||
|
<>
|
||||||
|
{/* eslint-disable-next-line react/jsx-no-bind */}
|
||||||
|
<Button className="show-more-channels" size="smaller" onClick={() => openPremiumModal()}>
|
||||||
|
{lang('UnlockSimilar')}
|
||||||
|
<i className="icon icon-unlock-badge" />
|
||||||
|
</Button>
|
||||||
|
<div className="more-similar">
|
||||||
|
{renderText(lang('MoreSimilarText', limitSimilarChannels), ['simple_markdown'])}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
) : undefined}
|
) : undefined}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -604,6 +666,8 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
&& (getHasAdminRight(chat, 'inviteUsers') || !isUserRightBanned(chat, 'inviteUsers') || chat.isCreator);
|
&& (getHasAdminRight(chat, 'inviteUsers') || !isUserRightBanned(chat, 'inviteUsers') || chat.isCreator);
|
||||||
const canDeleteMembers = hasMembersTab && chat && (getHasAdminRight(chat, 'banUsers') || chat.isCreator);
|
const canDeleteMembers = hasMembersTab && chat && (getHasAdminRight(chat, 'banUsers') || chat.isCreator);
|
||||||
const activeDownloads = selectActiveDownloads(global, chatId);
|
const activeDownloads = selectActiveDownloads(global, chatId);
|
||||||
|
const similarChannels = selectSimilarChannelIds(global, chatId);
|
||||||
|
const isCurrentUserPremium = selectIsCurrentUserPremium(global);
|
||||||
|
|
||||||
let hasCommonChatsTab;
|
let hasCommonChatsTab;
|
||||||
let resolvedUserId;
|
let resolvedUserId;
|
||||||
@ -648,6 +712,9 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
isChatProtected: chat?.isProtected,
|
isChatProtected: chat?.isProtected,
|
||||||
nextProfileTab: selectTabState(global).nextProfileTab,
|
nextProfileTab: selectTabState(global).nextProfileTab,
|
||||||
shouldWarnAboutSvg: global.settings.byKey.shouldWarnAboutSvg,
|
shouldWarnAboutSvg: global.settings.byKey.shouldWarnAboutSvg,
|
||||||
|
similarChannels,
|
||||||
|
isCurrentUserPremium,
|
||||||
|
limitSimilarChannels: selectPremiumLimit(global, 'recommendedChannels'),
|
||||||
...(hasMembersTab && members && { members, adminMembersById }),
|
...(hasMembersTab && members && { members, adminMembersById }),
|
||||||
...(hasCommonChatsTab && user && { commonChatIds: user.commonChats?.ids }),
|
...(hasCommonChatsTab && user && { commonChatIds: user.commonChats?.ids }),
|
||||||
};
|
};
|
||||||
|
|||||||
@ -29,6 +29,7 @@ export default function useProfileViewportIds(
|
|||||||
topicId?: number,
|
topicId?: number,
|
||||||
storyIds?: number[],
|
storyIds?: number[],
|
||||||
archiveStoryIds?: number[],
|
archiveStoryIds?: number[],
|
||||||
|
similarChannels?: string[],
|
||||||
) {
|
) {
|
||||||
const resultType = tabType === 'members' || !mediaSearchType ? tabType : mediaSearchType;
|
const resultType = tabType === 'members' || !mediaSearchType ? tabType : mediaSearchType;
|
||||||
|
|
||||||
@ -142,6 +143,9 @@ export default function useProfileViewportIds(
|
|||||||
getMore = getMoreStoriesArchive;
|
getMore = getMoreStoriesArchive;
|
||||||
noProfileInfo = noProfileInfoForStoriesArchive;
|
noProfileInfo = noProfileInfoForStoriesArchive;
|
||||||
break;
|
break;
|
||||||
|
case 'similarChannels':
|
||||||
|
viewportIds = similarChannels;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return [resultType, viewportIds, getMore, noProfileInfo] as const;
|
return [resultType, viewportIds, getMore, noProfileInfo] as const;
|
||||||
|
|||||||
@ -337,4 +337,5 @@ export const DEFAULT_LIMITS: Record<ApiLimitType, readonly [number, number]> = {
|
|||||||
aboutLength: [70, 140],
|
aboutLength: [70, 140],
|
||||||
chatlistInvites: [3, 100],
|
chatlistInvites: [3, 100],
|
||||||
chatlistJoined: [2, 20],
|
chatlistJoined: [2, 20],
|
||||||
|
recommendedChannels: [10, 100],
|
||||||
};
|
};
|
||||||
|
|||||||
@ -51,6 +51,7 @@ import {
|
|||||||
addChatMembers,
|
addChatMembers,
|
||||||
addChats,
|
addChats,
|
||||||
addMessages,
|
addMessages,
|
||||||
|
addSimilarChannels,
|
||||||
addUsers,
|
addUsers,
|
||||||
addUserStatuses,
|
addUserStatuses,
|
||||||
addUsersToRestrictedInviteList,
|
addUsersToRestrictedInviteList,
|
||||||
@ -2517,6 +2518,29 @@ addActionHandler('setViewForumAsMessages', (global, actions, payload): ActionRet
|
|||||||
void callApi('setViewForumAsMessages', { chat, isEnabled });
|
void callApi('setViewForumAsMessages', { chat, isEnabled });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
addActionHandler('fetchChannelRecommendations', async (global, actions, payload): Promise<void> => {
|
||||||
|
const { chatId } = payload;
|
||||||
|
const chat = selectChat(global, chatId);
|
||||||
|
|
||||||
|
if (!chat) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const similarChannels = await callApi('fetchChannelRecommendations', {
|
||||||
|
chat,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!similarChannels) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
global = getGlobal();
|
||||||
|
global = addChats(global, buildCollectionByKey(similarChannels, 'id'));
|
||||||
|
global = addSimilarChannels(global, chatId, similarChannels.map((channel) => channel.id));
|
||||||
|
|
||||||
|
setGlobal(global);
|
||||||
|
});
|
||||||
|
|
||||||
async function loadChats(
|
async function loadChats(
|
||||||
listType: 'active' | 'archived',
|
listType: 'active' | 'archived',
|
||||||
offsetId?: string,
|
offsetId?: string,
|
||||||
|
|||||||
@ -205,6 +205,10 @@ function unsafeMigrateCache(cached: GlobalState, initialState: GlobalState) {
|
|||||||
cached.stories.orderedPeerIds = initialState.stories.orderedPeerIds;
|
cached.stories.orderedPeerIds = initialState.stories.orderedPeerIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!cached.chats.similarChannelsById) {
|
||||||
|
cached.chats.similarChannelsById = initialState.chats.similarChannelsById;
|
||||||
|
}
|
||||||
|
|
||||||
// Clear old color storage to optimize cache size
|
// Clear old color storage to optimize cache size
|
||||||
if (untypedCached?.appConfig?.peerColors) {
|
if (untypedCached?.appConfig?.peerColors) {
|
||||||
untypedCached.appConfig.peerColors = undefined;
|
untypedCached.appConfig.peerColors = undefined;
|
||||||
@ -373,6 +377,7 @@ function reduceChats<T extends GlobalState>(global: T): GlobalState['chats'] {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
...global.chats,
|
...global.chats,
|
||||||
|
similarChannelsById: {},
|
||||||
isFullyLoaded: {},
|
isFullyLoaded: {},
|
||||||
byId: pick(global.chats.byId, idsToSave),
|
byId: pick(global.chats.byId, idsToSave),
|
||||||
fullInfoById: pick(global.chats.fullInfoById, idsToSave),
|
fullInfoById: pick(global.chats.fullInfoById, idsToSave),
|
||||||
|
|||||||
@ -105,6 +105,7 @@ export const INITIAL_GLOBAL_STATE: GlobalState = {
|
|||||||
totalCount: {},
|
totalCount: {},
|
||||||
byId: {},
|
byId: {},
|
||||||
fullInfoById: {},
|
fullInfoById: {},
|
||||||
|
similarChannelsById: {},
|
||||||
},
|
},
|
||||||
|
|
||||||
messages: {
|
messages: {
|
||||||
|
|||||||
@ -401,3 +401,20 @@ export function deleteTopic<T extends GlobalState>(
|
|||||||
|
|
||||||
return global;
|
return global;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function addSimilarChannels<T extends GlobalState>(
|
||||||
|
global: T,
|
||||||
|
chatId: string,
|
||||||
|
similarChannels: string[],
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
...global,
|
||||||
|
chats: {
|
||||||
|
...global.chats,
|
||||||
|
similarChannelsById: {
|
||||||
|
...global.chats.similarChannelsById,
|
||||||
|
[chatId]: similarChannels,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
@ -316,3 +316,10 @@ export function selectRequestedChatTranslationLanguage<T extends GlobalState>(
|
|||||||
|
|
||||||
return requestedTranslations.byChatId[chatId]?.toLanguage;
|
return requestedTranslations.byChatId[chatId]?.toLanguage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function selectSimilarChannelIds<T extends GlobalState>(
|
||||||
|
global: T,
|
||||||
|
chatId: string,
|
||||||
|
): string[] | undefined {
|
||||||
|
return global.chats.similarChannelsById[chatId];
|
||||||
|
}
|
||||||
|
|||||||
@ -169,13 +169,23 @@ export interface ServiceNotification {
|
|||||||
isDeleted?: boolean;
|
isDeleted?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ApiLimitType = (
|
export type ApiLimitType =
|
||||||
'uploadMaxFileparts' | 'stickersFaved' | 'savedGifs' | 'dialogFiltersChats' | 'dialogFilters' | 'dialogFolderPinned' |
|
| 'uploadMaxFileparts'
|
||||||
'captionLength' | 'channels' | 'channelsPublic' | 'aboutLength' | 'chatlistInvites' | 'chatlistJoined'
|
| 'stickersFaved'
|
||||||
);
|
| 'savedGifs'
|
||||||
|
| 'dialogFiltersChats'
|
||||||
|
| 'dialogFilters'
|
||||||
|
| 'dialogFolderPinned'
|
||||||
|
| 'captionLength'
|
||||||
|
| 'channels'
|
||||||
|
| 'channelsPublic'
|
||||||
|
| 'aboutLength'
|
||||||
|
| 'chatlistInvites'
|
||||||
|
| 'chatlistJoined'
|
||||||
|
| 'recommendedChannels';
|
||||||
|
|
||||||
export type ApiLimitTypeWithModal = Exclude<ApiLimitType, (
|
export type ApiLimitTypeWithModal = Exclude<ApiLimitType, (
|
||||||
'captionLength' | 'aboutLength' | 'stickersFaved' | 'savedGifs'
|
'captionLength' | 'aboutLength' | 'stickersFaved' | 'savedGifs' | 'recommendedChannels'
|
||||||
)>;
|
)>;
|
||||||
|
|
||||||
export type TranslatedMessage = {
|
export type TranslatedMessage = {
|
||||||
@ -771,6 +781,7 @@ export type GlobalState = {
|
|||||||
forDiscussionIds?: string[];
|
forDiscussionIds?: string[];
|
||||||
// Obtained from GetFullChat / GetFullChannel
|
// Obtained from GetFullChat / GetFullChannel
|
||||||
fullInfoById: Record<string, ApiChatFullInfo>;
|
fullInfoById: Record<string, ApiChatFullInfo>;
|
||||||
|
similarChannelsById: Record<string, string[]>;
|
||||||
};
|
};
|
||||||
|
|
||||||
messages: {
|
messages: {
|
||||||
@ -1759,6 +1770,9 @@ export interface ActionPayloads {
|
|||||||
fetchChat: {
|
fetchChat: {
|
||||||
chatId: string;
|
chatId: string;
|
||||||
};
|
};
|
||||||
|
fetchChannelRecommendations: {
|
||||||
|
chatId: string;
|
||||||
|
};
|
||||||
updateChatMutedState: {
|
updateChatMutedState: {
|
||||||
chatId: string;
|
chatId: string;
|
||||||
isMuted?: boolean;
|
isMuted?: boolean;
|
||||||
|
|||||||
@ -1443,6 +1443,7 @@ channels.deleteTopicHistory#34435f2d channel:InputChannel top_msg_id:int = messa
|
|||||||
channels.toggleParticipantsHidden#6a6e7854 channel:InputChannel enabled:Bool = Updates;
|
channels.toggleParticipantsHidden#6a6e7854 channel:InputChannel enabled:Bool = Updates;
|
||||||
channels.clickSponsoredMessage#18afbc93 channel:InputChannel random_id:bytes = Bool;
|
channels.clickSponsoredMessage#18afbc93 channel:InputChannel random_id:bytes = Bool;
|
||||||
channels.toggleViewForumAsMessages#9738bb15 channel:InputChannel enabled:Bool = Updates;
|
channels.toggleViewForumAsMessages#9738bb15 channel:InputChannel enabled:Bool = Updates;
|
||||||
|
channels.getChannelRecommendations#83b70d97 channel:InputChannel = messages.Chats;
|
||||||
bots.canSendMessage#1359f4e6 bot:InputUser = Bool;
|
bots.canSendMessage#1359f4e6 bot:InputUser = Bool;
|
||||||
bots.allowSendMessage#f132e3ef bot:InputUser = Updates;
|
bots.allowSendMessage#f132e3ef bot:InputUser = Updates;
|
||||||
bots.invokeWebViewCustomMethod#87fc5e7 bot:InputUser custom_method:string params:DataJSON = DataJSON;
|
bots.invokeWebViewCustomMethod#87fc5e7 bot:InputUser custom_method:string params:DataJSON = DataJSON;
|
||||||
|
|||||||
@ -214,6 +214,7 @@
|
|||||||
"channels.toggleUsername",
|
"channels.toggleUsername",
|
||||||
"channels.viewSponsoredMessage",
|
"channels.viewSponsoredMessage",
|
||||||
"channels.getSponsoredMessages",
|
"channels.getSponsoredMessages",
|
||||||
|
"channels.getChannelRecommendations",
|
||||||
"bots.canSendMessage",
|
"bots.canSendMessage",
|
||||||
"bots.allowSendMessage",
|
"bots.allowSendMessage",
|
||||||
"bots.invokeWebViewCustomMethod",
|
"bots.invokeWebViewCustomMethod",
|
||||||
|
|||||||
@ -355,9 +355,17 @@ export enum NewChatMembersProgress {
|
|||||||
Loading,
|
Loading,
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ProfileTabType = (
|
export type ProfileTabType =
|
||||||
'members' | 'commonChats' | 'media' | 'documents' | 'links' | 'audio' | 'voice' | 'stories' | 'storiesArchive'
|
| 'members'
|
||||||
);
|
| 'commonChats'
|
||||||
|
| 'media'
|
||||||
|
| 'documents'
|
||||||
|
| 'links'
|
||||||
|
| 'audio'
|
||||||
|
| 'voice'
|
||||||
|
| 'stories'
|
||||||
|
| 'storiesArchive'
|
||||||
|
| 'similarChannels';
|
||||||
export type SharedMediaType = 'media' | 'documents' | 'links' | 'audio' | 'voice';
|
export type SharedMediaType = 'media' | 'documents' | 'links' | 'audio' | 'voice';
|
||||||
export type ApiPrivacyKey = 'phoneNumber' | 'addByPhone' | 'lastSeen' | 'profilePhoto' | 'voiceMessages' |
|
export type ApiPrivacyKey = 'phoneNumber' | 'addByPhone' | 'lastSeen' | 'profilePhoto' | 'voiceMessages' |
|
||||||
'forwards' | 'chatInvite' | 'phoneCall' | 'phoneP2P' | 'bio';
|
'forwards' | 'chatInvite' | 'phoneCall' | 'phoneP2P' | 'bio';
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user