From dbe78ad9e74c7f4fe93d63c044e827c97dfc5d75 Mon Sep 17 00:00:00 2001 From: zubiden <19638254+zubiden@users.noreply.github.com> Date: Tue, 9 Sep 2025 20:26:10 +0200 Subject: [PATCH] Channel: Support direct messages deeplink (#6175) --- src/global/actions/api/chats.ts | 17 ++++++++++++++--- src/util/deepLinkParser.ts | 11 ++++++++++- src/util/deeplink.ts | 1 + 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/global/actions/api/chats.ts b/src/global/actions/api/chats.ts index 28299968d..fe390012d 100644 --- a/src/global/actions/api/chats.ts +++ b/src/global/actions/api/chats.ts @@ -1654,7 +1654,7 @@ addActionHandler('acceptChatInvite', async (global, actions, payload): Promise => { const { username, messageId, commentId, startParam, startAttach, attach, threadId, originalParts, - startApp, shouldStartMainApp, mode, + startApp, shouldStartMainApp, mode, isDirect, text, onChatChanged, choose, ref, timestamp, linkContext, tabId = getCurrentTabId(), } = payload; @@ -3433,7 +3433,13 @@ async function openChatByUsername( return; } - const isCurrentChat = currentChat?.usernames?.some((c) => c.username === username); + const localChat = selectChatByUsername(global, username); + const localDirectChat = isDirect && localChat?.linkedMonoforumId && !localChat.isMonoforum + ? selectChat(global, localChat.linkedMonoforumId) : undefined; + + const isCurrentChat = !isDirect + ? currentChat?.usernames?.some((c) => c.username === username) + : localDirectChat?.id === currentChat?.id; if (!isCurrentChat) { // Open temporary empty chat to make the click response feel faster @@ -3459,7 +3465,12 @@ async function openChatByUsername( return; } - openChatWithParams(global, actions, chat, { + const monoforumChat = isDirect && !chat.isMonoforum && chat.linkedMonoforumId + ? selectChat(global, chat.linkedMonoforumId) : undefined; + + const targetChat = (isDirect && monoforumChat) || chat; + + openChatWithParams(global, actions, targetChat, { isCurrentChat, threadId, messageId: channelPostId, diff --git a/src/util/deepLinkParser.ts b/src/util/deepLinkParser.ts index 0948056b9..bc9bc736c 100644 --- a/src/util/deepLinkParser.ts +++ b/src/util/deepLinkParser.ts @@ -70,6 +70,7 @@ interface PublicUsernameOrBotLink { attach?: string; text?: string; choose?: string; + isDirect?: boolean; } interface PrivateChannelLink { @@ -146,6 +147,10 @@ type PublicMessageLinkBuilderParams = Omit, 'is single?: string; }; +type PublicUsernameOrBotLinkBuilderParams = Omit, 'isDirect'> & { + direct?: string; +}; + const ELIGIBLE_HOSTNAMES = new Set(['t.me', 'telegram.me', 'telegram.dog']); export function isDeepLink(link: string): boolean { @@ -249,6 +254,7 @@ function parseTgLink(url: URL) { attach: queryParams.attach, choose: queryParams.choose, ref: queryParams.ref, + direct: queryParams.direct, }); case 'privateChannelLink': { return buildPrivateChannelLink({ channelId: queryParams.channel }); @@ -355,6 +361,7 @@ function parseHttpLink(url: URL) { attach: queryParams.attach, choose: queryParams.choose, ref: queryParams.ref, + direct: queryParams.direct, }); case 'privateChannelLink': { return buildPrivateChannelLink({ channelId: pathParams[1] }); @@ -605,7 +612,7 @@ function buildTelegramPassportLink( } function buildPublicUsernameOrBotLink( - params: BuilderParams, + params: PublicUsernameOrBotLinkBuilderParams, ): BuilderReturnType { const { username, @@ -618,6 +625,7 @@ function buildPublicUsernameOrBotLink( appName, choose, ref, + direct, } = params; if (!username) { return undefined; @@ -637,6 +645,7 @@ function buildPublicUsernameOrBotLink( text, choose, ref, + isDirect: direct === '', }; } diff --git a/src/util/deeplink.ts b/src/util/deeplink.ts index 9f15c4ec9..f53304340 100644 --- a/src/util/deeplink.ts +++ b/src/util/deeplink.ts @@ -49,6 +49,7 @@ export const processDeepLink = (url: string, linkContext?: LinkContext): boolean attach: parsedLink.attach, choose, originalParts: [parsedLink.username, parsedLink.appName], + isDirect: parsedLink.isDirect, }); return true; }