Left Search: Search message deep link (#4061)

This commit is contained in:
Alexander Zinchuk 2023-12-12 12:34:44 +01:00
parent 0f5bdc05be
commit 74fd74203e
4 changed files with 62 additions and 6 deletions

View File

@ -177,8 +177,7 @@ const ChatResults: FC<OwnProps & StateProps> = ({
return globalMessagesByChatId?.[chatId]?.byId[Number(messageId)];
})
.filter(Boolean)
.sort((a, b) => b.date - a.date);
.filter(Boolean);
}, [foundIds, globalMessagesByChatId, searchQuery, searchDate]);
const handleClickShowMoreLocal = useCallback(() => {

View File

@ -5,10 +5,12 @@ import type { ActionReturnType, GlobalState, TabArgs } from '../../types';
import { GLOBAL_SEARCH_SLICE, GLOBAL_TOPIC_SEARCH_SLICE } from '../../../config';
import { timestampPlusDay } from '../../../util/dateFormat';
import { DeepLinkType, isDeepLink, tryParseDeepLink } from '../../../util/deepLinkParser';
import { getCurrentTabId } from '../../../util/establishMultitabRole';
import { buildCollectionByKey } from '../../../util/iteratees';
import { throttle } from '../../../util/schedulers';
import { callApi } from '../../../api/gramjs';
import { isChatChannel, isChatGroup, toChannelId } from '../../helpers/chats';
import { addActionHandler, getGlobal, setGlobal } from '../../index';
import {
addChats,
@ -19,7 +21,9 @@ import {
updateGlobalSearchResults,
updateTopics,
} from '../../reducers';
import { selectChat, selectCurrentGlobalSearchQuery, selectTabState } from '../../selectors';
import {
selectChat, selectChatByUsername, selectChatMessage, selectCurrentGlobalSearchQuery, selectTabState,
} from '../../selectors';
const searchThrottled = throttle((cb) => cb(), 500, false);
@ -120,6 +124,8 @@ async function searchMessagesGlobal<T extends GlobalState>(
nextRate: number | undefined;
} | undefined;
let messageLink: ApiMessage | undefined;
if (chat) {
const localResultRequest = callApi('searchMessagesLocal', {
chat,
@ -164,6 +170,14 @@ async function searchMessagesGlobal<T extends GlobalState>(
maxDate,
minDate,
});
if (isDeepLink(query)) {
const link = tryParseDeepLink(query);
if (link?.type === DeepLinkType.PublicMessageLink) {
messageLink = await getMessageByPublicLink(global, link);
} else if (link?.type === DeepLinkType.PrivateMessageLink) {
messageLink = await getMessageByPrivateLink(global, link);
}
}
}
global = getGlobal();
@ -174,6 +188,10 @@ async function searchMessagesGlobal<T extends GlobalState>(
return;
}
if (messageLink) {
result.totalCount = result.messages.unshift(messageLink);
}
const {
messages, users, chats, totalCount, nextRate,
} = result;
@ -210,3 +228,38 @@ async function searchMessagesGlobal<T extends GlobalState>(
setGlobal(global);
}
async function getMessageByPublicLink(global: GlobalState, link: { username: string; messageId: number }) {
const { username, messageId } = link;
const localChat = selectChatByUsername(global, username);
if (localChat) {
return getChatGroupOrChannelMessage(global, localChat, messageId);
}
const { chat } = await callApi('getChatByUsername', username) ?? {};
if (!chat) {
return undefined;
}
return getChatGroupOrChannelMessage(global, chat, messageId);
}
function getMessageByPrivateLink(global: GlobalState, link: { channelId: string; messageId: number }) {
const { channelId, messageId } = link;
const internalChannelId = toChannelId(channelId);
const chat = selectChat(global, internalChannelId);
if (!chat) {
return undefined;
}
return getChatGroupOrChannelMessage(global, chat, messageId);
}
async function getChatGroupOrChannelMessage(global: GlobalState, chat: ApiChat, messageId: number) {
if (!isChatGroup(chat) && !isChatChannel(chat)) {
return undefined;
}
const localMessage = selectChatMessage(global, chat.id, messageId);
if (localMessage) {
return localMessage;
}
const result = await callApi('fetchMessage', { chat, messageId });
return result === 'MESSAGE_DELETED' ? undefined : result?.message;
}

View File

@ -26,13 +26,12 @@ import {
MAX_MEDIA_FILES_FOR_ALBUM,
MESSAGE_LIST_SLICE,
RE_TELEGRAM_LINK,
RE_TG_LINK,
RE_TME_LINK,
SERVICE_NOTIFICATIONS_USER_ID,
SUPPORTED_AUDIO_CONTENT_TYPES,
SUPPORTED_IMAGE_CONTENT_TYPES,
SUPPORTED_VIDEO_CONTENT_TYPES,
} from '../../../config';
import { isDeepLink } from '../../../util/deepLinkParser';
import { ensureProtocol } from '../../../util/ensureProtocol';
import { getCurrentTabId } from '../../../util/establishMultitabRole';
import {
@ -1542,7 +1541,7 @@ addActionHandler('openUrl', (global, actions, payload): ActionReturnType => {
const urlWithProtocol = ensureProtocol(url)!;
const isStoriesViewerOpen = Boolean(selectTabState(global, tabId).storyViewer.peerId);
if (urlWithProtocol.match(RE_TME_LINK) || urlWithProtocol.match(RE_TG_LINK)) {
if (isDeepLink(urlWithProtocol)) {
if (isStoriesViewerOpen) {
actions.closeStoryViewer({ tabId });
}

View File

@ -1,3 +1,4 @@
import { RE_TG_LINK, RE_TME_LINK } from '../config';
import { isUsernameValid } from './username';
export type DeepLinkMethod = 'resolve' | 'login' | 'passport' | 'settings' | 'join' | 'addstickers' | 'addemoji' |
@ -50,6 +51,10 @@ type BuilderReturnType<T extends DeepLink> = T | undefined;
const ELIGIBLE_HOSTNAMES = new Set(['t.me', 'telegram.me', 'telegram.dog']);
export function isDeepLink(link: string): boolean {
return Boolean(link.match(RE_TME_LINK) || link.match(RE_TG_LINK));
}
export function tryParseDeepLink(link: string): DeepLink | undefined {
try {
return parseDeepLink(link);