Link: Fix opening forum topics (#5558)
This commit is contained in:
parent
bb5ec799a1
commit
0ac730a043
@ -1577,6 +1577,43 @@ addActionHandler('openChatByUsername', async (global, actions, payload): Promise
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
addActionHandler('openPrivateChannel', (global, actions, payload): ActionReturnType => {
|
||||||
|
const {
|
||||||
|
id, commentId, messageId, threadId, tabId = getCurrentTabId(),
|
||||||
|
} = payload;
|
||||||
|
const chat = selectChat(global, id);
|
||||||
|
if (!chat) {
|
||||||
|
actions.showNotification({
|
||||||
|
message: {
|
||||||
|
key: 'PrivateChannelInaccessible',
|
||||||
|
},
|
||||||
|
tabId,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!commentId && !messageId && !threadId) {
|
||||||
|
actions.openChat({ id, tabId });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (commentId && messageId) {
|
||||||
|
actions.openThread({
|
||||||
|
isComments: true,
|
||||||
|
originChannelId: chat.id,
|
||||||
|
originMessageId: messageId,
|
||||||
|
tabId,
|
||||||
|
focusMessageId: commentId,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
openChatWithParams(global, actions, chat, {
|
||||||
|
messageId,
|
||||||
|
threadId,
|
||||||
|
}, tabId);
|
||||||
|
});
|
||||||
|
|
||||||
addActionHandler('togglePreHistoryHidden', async (global, actions, payload): Promise<void> => {
|
addActionHandler('togglePreHistoryHidden', async (global, actions, payload): Promise<void> => {
|
||||||
const {
|
const {
|
||||||
chatId, isEnabled,
|
chatId, isEnabled,
|
||||||
@ -3075,7 +3112,6 @@ async function openChatByUsername<T extends GlobalState>(
|
|||||||
const {
|
const {
|
||||||
username, threadId, channelPostId, startParam, ref, startAttach, attach, text,
|
username, threadId, channelPostId, startParam, ref, startAttach, attach, text,
|
||||||
} = params;
|
} = params;
|
||||||
global = getGlobal();
|
|
||||||
const currentChat = selectCurrentChat(global, tabId);
|
const currentChat = selectCurrentChat(global, tabId);
|
||||||
|
|
||||||
// Attach in the current chat
|
// Attach in the current chat
|
||||||
@ -3120,10 +3156,61 @@ async function openChatByUsername<T extends GlobalState>(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (channelPostId) {
|
openChatWithParams(global, actions, chat, {
|
||||||
actions.focusMessage({
|
isCurrentChat,
|
||||||
chatId: chat.id, threadId, messageId: channelPostId, tabId,
|
threadId,
|
||||||
});
|
messageId: channelPostId,
|
||||||
|
startParam,
|
||||||
|
referrer,
|
||||||
|
startAttach,
|
||||||
|
attach,
|
||||||
|
text,
|
||||||
|
}, tabId);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function openChatWithParams<T extends GlobalState>(
|
||||||
|
global: T,
|
||||||
|
actions: RequiredGlobalActions,
|
||||||
|
chat: ApiChat,
|
||||||
|
params: {
|
||||||
|
isCurrentChat?: boolean;
|
||||||
|
threadId?: ThreadId;
|
||||||
|
messageId?: number;
|
||||||
|
startParam?: string;
|
||||||
|
referrer?: string;
|
||||||
|
startAttach?: string;
|
||||||
|
attach?: string;
|
||||||
|
text?: string;
|
||||||
|
},
|
||||||
|
...[tabId = getCurrentTabId()]: TabArgs<T>
|
||||||
|
) {
|
||||||
|
const {
|
||||||
|
isCurrentChat, threadId, messageId, startParam, referrer, startAttach, attach, text,
|
||||||
|
} = params;
|
||||||
|
|
||||||
|
if (messageId) {
|
||||||
|
let isTopicProcessed = false;
|
||||||
|
// In forums, link to a topic start message should open the topic
|
||||||
|
if (chat.isForum && !threadId) {
|
||||||
|
let topic = selectTopics(global, chat.id)?.[messageId];
|
||||||
|
if (!topic) {
|
||||||
|
const topicResult = await callApi('fetchTopicById', { chat, topicId: messageId });
|
||||||
|
topic = topicResult?.topic;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (topic) {
|
||||||
|
actions.openThread({
|
||||||
|
chatId: chat.id, threadId: topic.id, tabId,
|
||||||
|
});
|
||||||
|
isTopicProcessed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isTopicProcessed) {
|
||||||
|
actions.focusMessage({
|
||||||
|
chatId: chat.id, threadId, messageId, tabId,
|
||||||
|
});
|
||||||
|
}
|
||||||
} else if (!isCurrentChat) {
|
} else if (!isCurrentChat) {
|
||||||
actions.openThread({ chatId: chat.id, threadId: threadId ?? MAIN_THREAD_ID, tabId });
|
actions.openThread({ chatId: chat.id, threadId: threadId ?? MAIN_THREAD_ID, tabId });
|
||||||
}
|
}
|
||||||
|
|||||||
@ -88,22 +88,6 @@ addActionHandler('processOpenChatOrThread', (global, actions, payload): ActionRe
|
|||||||
return updateCurrentMessageList(global, chatId, threadId, type, shouldReplaceHistory, shouldReplaceLast, tabId);
|
return updateCurrentMessageList(global, chatId, threadId, type, shouldReplaceHistory, shouldReplaceLast, tabId);
|
||||||
});
|
});
|
||||||
|
|
||||||
addActionHandler('openPrivateChannel', (global, actions, payload): ActionReturnType => {
|
|
||||||
const { id, tabId = getCurrentTabId() } = payload;
|
|
||||||
const chat = selectChat(global, id);
|
|
||||||
if (!chat) {
|
|
||||||
actions.showNotification({
|
|
||||||
message: {
|
|
||||||
key: 'PrivateChannelInaccessible',
|
|
||||||
},
|
|
||||||
tabId,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
actions.openChat({ id, tabId });
|
|
||||||
});
|
|
||||||
|
|
||||||
addActionHandler('openChatInNewTab', (global, actions, payload): ActionReturnType => {
|
addActionHandler('openChatInNewTab', (global, actions, payload): ActionReturnType => {
|
||||||
const { chatId, threadId = MAIN_THREAD_ID } = payload;
|
const { chatId, threadId = MAIN_THREAD_ID } = payload;
|
||||||
|
|
||||||
|
|||||||
@ -1089,6 +1089,9 @@ export interface ActionPayloads {
|
|||||||
} & WithTabId;
|
} & WithTabId;
|
||||||
openPrivateChannel: {
|
openPrivateChannel: {
|
||||||
id: string;
|
id: string;
|
||||||
|
threadId?: ThreadId;
|
||||||
|
messageId?: number;
|
||||||
|
commentId?: number;
|
||||||
} & WithTabId;
|
} & WithTabId;
|
||||||
loadFullChat: {
|
loadFullChat: {
|
||||||
chatId: string;
|
chatId: string;
|
||||||
|
|||||||
@ -18,7 +18,6 @@ interface PublicMessageLink {
|
|||||||
isSingle: boolean;
|
isSingle: boolean;
|
||||||
threadId?: ThreadId;
|
threadId?: ThreadId;
|
||||||
commentId?: number;
|
commentId?: number;
|
||||||
mediaTimestamp?: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PrivateMessageLink {
|
export interface PrivateMessageLink {
|
||||||
@ -28,7 +27,6 @@ export interface PrivateMessageLink {
|
|||||||
isSingle: boolean;
|
isSingle: boolean;
|
||||||
threadId?: ThreadId;
|
threadId?: ThreadId;
|
||||||
commentId?: number;
|
commentId?: number;
|
||||||
mediaTimestamp?: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ShareLink {
|
interface ShareLink {
|
||||||
@ -173,7 +171,7 @@ function parseTgLink(url: URL) {
|
|||||||
switch (deepLinkType) {
|
switch (deepLinkType) {
|
||||||
case 'publicMessageLink': {
|
case 'publicMessageLink': {
|
||||||
const {
|
const {
|
||||||
domain, post, single, thread, comment, t,
|
domain, post, single, thread, comment,
|
||||||
} = queryParams;
|
} = queryParams;
|
||||||
return buildPublicMessageLink({
|
return buildPublicMessageLink({
|
||||||
username: domain,
|
username: domain,
|
||||||
@ -181,12 +179,11 @@ function parseTgLink(url: URL) {
|
|||||||
single,
|
single,
|
||||||
threadId: thread,
|
threadId: thread,
|
||||||
commentId: comment,
|
commentId: comment,
|
||||||
mediaTimestamp: t,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
case 'privateMessageLink': {
|
case 'privateMessageLink': {
|
||||||
const {
|
const {
|
||||||
channel, post, single, thread, comment, t,
|
channel, post, single, thread, comment,
|
||||||
} = queryParams;
|
} = queryParams;
|
||||||
return buildPrivateMessageLink({
|
return buildPrivateMessageLink({
|
||||||
channelId: channel,
|
channelId: channel,
|
||||||
@ -194,7 +191,6 @@ function parseTgLink(url: URL) {
|
|||||||
single,
|
single,
|
||||||
threadId: thread,
|
threadId: thread,
|
||||||
commentId: comment,
|
commentId: comment,
|
||||||
mediaTimestamp: t,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
case 'shareLink':
|
case 'shareLink':
|
||||||
@ -255,7 +251,7 @@ function parseHttpLink(url: URL) {
|
|||||||
switch (deepLinkType) {
|
switch (deepLinkType) {
|
||||||
case 'publicMessageLink': {
|
case 'publicMessageLink': {
|
||||||
const {
|
const {
|
||||||
single, comment, t,
|
single, comment,
|
||||||
} = queryParams;
|
} = queryParams;
|
||||||
const {
|
const {
|
||||||
username,
|
username,
|
||||||
@ -276,12 +272,11 @@ function parseHttpLink(url: URL) {
|
|||||||
single,
|
single,
|
||||||
threadId: thread,
|
threadId: thread,
|
||||||
commentId: comment,
|
commentId: comment,
|
||||||
mediaTimestamp: t,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
case 'privateMessageLink': {
|
case 'privateMessageLink': {
|
||||||
const {
|
const {
|
||||||
single, comment, t,
|
single, comment,
|
||||||
} = queryParams;
|
} = queryParams;
|
||||||
const {
|
const {
|
||||||
channelId,
|
channelId,
|
||||||
@ -302,7 +297,6 @@ function parseHttpLink(url: URL) {
|
|||||||
single,
|
single,
|
||||||
threadId: thread,
|
threadId: thread,
|
||||||
commentId: comment,
|
commentId: comment,
|
||||||
mediaTimestamp: t,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
case 'shareLink': {
|
case 'shareLink': {
|
||||||
@ -463,7 +457,7 @@ function buildShareLink(params: BuilderParams<ShareLink>): BuilderReturnType<Sha
|
|||||||
|
|
||||||
function buildPublicMessageLink(params: PublicMessageLinkBuilderParams): BuilderReturnType<PublicMessageLink> {
|
function buildPublicMessageLink(params: PublicMessageLinkBuilderParams): BuilderReturnType<PublicMessageLink> {
|
||||||
const {
|
const {
|
||||||
messageId, threadId, commentId, username, single, mediaTimestamp,
|
messageId, threadId, commentId, username, single,
|
||||||
} = params;
|
} = params;
|
||||||
if (!username || !isUsernameValid(username)) {
|
if (!username || !isUsernameValid(username)) {
|
||||||
return undefined;
|
return undefined;
|
||||||
@ -484,13 +478,12 @@ function buildPublicMessageLink(params: PublicMessageLinkBuilderParams): Builder
|
|||||||
isSingle: single === '',
|
isSingle: single === '',
|
||||||
threadId: threadId ? Number(threadId) : undefined,
|
threadId: threadId ? Number(threadId) : undefined,
|
||||||
commentId: commentId ? Number(commentId) : undefined,
|
commentId: commentId ? Number(commentId) : undefined,
|
||||||
mediaTimestamp,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildPrivateMessageLink(params: PrivateMessageLinkBuilderParams): BuilderReturnType<PrivateMessageLink> {
|
function buildPrivateMessageLink(params: PrivateMessageLinkBuilderParams): BuilderReturnType<PrivateMessageLink> {
|
||||||
const {
|
const {
|
||||||
messageId, threadId, commentId, channelId, single, mediaTimestamp,
|
messageId, threadId, commentId, channelId, single,
|
||||||
} = params;
|
} = params;
|
||||||
if (!channelId || !isNumber(channelId)) {
|
if (!channelId || !isNumber(channelId)) {
|
||||||
return undefined;
|
return undefined;
|
||||||
@ -506,12 +499,11 @@ function buildPrivateMessageLink(params: PrivateMessageLinkBuilderParams): Build
|
|||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
type: 'privateMessageLink',
|
type: 'privateMessageLink',
|
||||||
channelId,
|
channelId: toChannelId(channelId),
|
||||||
messageId: Number(messageId),
|
messageId: Number(messageId),
|
||||||
isSingle: single === '',
|
isSingle: single === '',
|
||||||
threadId: threadId ? Number(threadId) : undefined,
|
threadId: threadId ? Number(threadId) : undefined,
|
||||||
commentId: commentId ? Number(commentId) : undefined,
|
commentId: commentId ? Number(commentId) : undefined,
|
||||||
mediaTimestamp,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,9 @@
|
|||||||
import { getActions } from '../global';
|
import { getActions } from '../global';
|
||||||
|
|
||||||
import type { ApiChatType, ApiFormattedText } from '../api/types';
|
import type { ApiChatType, ApiFormattedText } from '../api/types';
|
||||||
import type { DeepLinkMethod, PrivateMessageLink } from './deepLinkParser';
|
import type { DeepLinkMethod } from './deepLinkParser';
|
||||||
|
|
||||||
import { API_CHAT_TYPES, RE_TG_LINK } from '../config';
|
import { API_CHAT_TYPES, RE_TG_LINK } from '../config';
|
||||||
import { toChannelId } from '../global/helpers';
|
|
||||||
import { tryParseDeepLink } from './deepLinkParser';
|
import { tryParseDeepLink } from './deepLinkParser';
|
||||||
import { IS_BAD_URL_PARSER } from './windowEnvironment';
|
import { IS_BAD_URL_PARSER } from './windowEnvironment';
|
||||||
|
|
||||||
@ -15,7 +14,12 @@ export const processDeepLink = (url: string): boolean => {
|
|||||||
if (parsedLink) {
|
if (parsedLink) {
|
||||||
switch (parsedLink.type) {
|
switch (parsedLink.type) {
|
||||||
case 'privateMessageLink':
|
case 'privateMessageLink':
|
||||||
handlePrivateMessageLink(parsedLink, actions);
|
actions.openPrivateChannel({
|
||||||
|
id: parsedLink.channelId,
|
||||||
|
threadId: parsedLink.threadId,
|
||||||
|
messageId: parsedLink.messageId,
|
||||||
|
commentId: parsedLink.commentId,
|
||||||
|
});
|
||||||
return true;
|
return true;
|
||||||
case 'publicMessageLink': {
|
case 'publicMessageLink': {
|
||||||
actions.openChatByUsername({
|
actions.openChatByUsername({
|
||||||
@ -223,20 +227,6 @@ export function formatShareText(url?: string, text?: string, title?: string): Ap
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function handlePrivateMessageLink(link: PrivateMessageLink, actions: ReturnType<typeof getActions>) {
|
|
||||||
const {
|
|
||||||
focusMessage,
|
|
||||||
} = actions;
|
|
||||||
const {
|
|
||||||
channelId, messageId, threadId,
|
|
||||||
} = link;
|
|
||||||
focusMessage({
|
|
||||||
chatId: toChannelId(channelId),
|
|
||||||
threadId,
|
|
||||||
messageId,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseChooseParameter(choose?: string) {
|
function parseChooseParameter(choose?: string) {
|
||||||
if (!choose) return undefined;
|
if (!choose) return undefined;
|
||||||
const types = choose.toLowerCase().split(' ');
|
const types = choose.toLowerCase().split(' ');
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user