Implement TDLib-like channel prefix (#3858)
This commit is contained in:
parent
3cd9192c1d
commit
f8c021b043
@ -220,9 +220,14 @@ export function buildApiChatFromPreview(
|
|||||||
if (preview instanceof GramJs.ChatEmpty || preview instanceof GramJs.UserEmpty) {
|
if (preview instanceof GramJs.ChatEmpty || preview instanceof GramJs.UserEmpty) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
const id = buildApiPeerId(
|
||||||
|
preview.id,
|
||||||
|
preview instanceof GramJs.User ? 'user'
|
||||||
|
: (preview instanceof GramJs.Chat || preview instanceof GramJs.ChatForbidden) ? 'chat' : 'channel',
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: buildApiPeerId(preview.id, preview instanceof GramJs.User ? 'user' : 'chat'),
|
id,
|
||||||
type: getApiChatTypeFromPeerEntity(preview),
|
type: getApiChatTypeFromPeerEntity(preview),
|
||||||
title: preview instanceof GramJs.User ? getUserName(preview) : preview.title,
|
title: preview instanceof GramJs.User ? getUserName(preview) : preview.title,
|
||||||
...buildApiChatFieldsFromPeerEntity(preview, isSupport),
|
...buildApiChatFieldsFromPeerEntity(preview, isSupport),
|
||||||
|
|||||||
@ -15,7 +15,15 @@ export function isPeerChannel(peer: GramJs.TypePeer | GramJs.TypeInputPeer): pee
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function buildApiPeerId(id: BigInt.BigInteger, type: 'user' | 'chat' | 'channel') {
|
export function buildApiPeerId(id: BigInt.BigInteger, type: 'user' | 'chat' | 'channel') {
|
||||||
return type === 'user' ? String(id) : `-${id}`;
|
if (type === 'user') {
|
||||||
|
return id.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === 'channel') {
|
||||||
|
return `-100${id}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return `-${id}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getApiChatIdFromMtpPeer(peer: GramJs.TypePeer | GramJs.TypeInputPeer) {
|
export function getApiChatIdFromMtpPeer(peer: GramJs.TypePeer | GramJs.TypeInputPeer) {
|
||||||
|
|||||||
@ -37,19 +37,17 @@ import { pick } from '../../../util/iteratees';
|
|||||||
import { deserializeBytes } from '../helpers';
|
import { deserializeBytes } from '../helpers';
|
||||||
import localDb from '../localDb';
|
import localDb from '../localDb';
|
||||||
|
|
||||||
const CHANNEL_ID_MIN_LENGTH = 11; // Example: -1000000000
|
const CHANNEL_ID_MIN_LENGTH = 11; // Example: -1234567890
|
||||||
|
const CHANNEL_ID_NEW_FORMAT_MIN_LENGTH = 14; // Example: -1001234567890
|
||||||
|
|
||||||
function checkIfChannelId(id: string) {
|
function checkIfChannelId(id: string) {
|
||||||
// HOTFIX New group id range starts with -4
|
if (id.length >= CHANNEL_ID_NEW_FORMAT_MIN_LENGTH) return id.startsWith('-100');
|
||||||
|
// LEGACY Unprefixed channel id
|
||||||
if (id.length === CHANNEL_ID_MIN_LENGTH && id.startsWith('-4')) return false;
|
if (id.length === CHANNEL_ID_MIN_LENGTH && id.startsWith('-4')) return false;
|
||||||
return id.length >= CHANNEL_ID_MIN_LENGTH;
|
return id.length >= CHANNEL_ID_MIN_LENGTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getEntityTypeById(chatOrUserId: string) {
|
export function getEntityTypeById(chatOrUserId: string) {
|
||||||
if (typeof chatOrUserId === 'number') {
|
|
||||||
return getEntityTypeByDeprecatedId(chatOrUserId);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!chatOrUserId.startsWith('-')) {
|
if (!chatOrUserId.startsWith('-')) {
|
||||||
return 'user';
|
return 'user';
|
||||||
} else if (checkIfChannelId(chatOrUserId)) {
|
} else if (checkIfChannelId(chatOrUserId)) {
|
||||||
@ -59,17 +57,6 @@ export function getEntityTypeById(chatOrUserId: string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Workaround for old-fashioned IDs stored locally
|
|
||||||
export function getEntityTypeByDeprecatedId(chatOrUserId: number) {
|
|
||||||
if (chatOrUserId > 0) {
|
|
||||||
return 'user';
|
|
||||||
} else if (chatOrUserId <= -1000000000) {
|
|
||||||
return 'channel';
|
|
||||||
} else {
|
|
||||||
return 'chat';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function buildPeer(chatOrUserId: string): GramJs.TypePeer {
|
export function buildPeer(chatOrUserId: string): GramJs.TypePeer {
|
||||||
const type = getEntityTypeById(chatOrUserId);
|
const type = getEntityTypeById(chatOrUserId);
|
||||||
|
|
||||||
@ -546,12 +533,20 @@ export function buildInputThemeParams(params: ApiThemeParameters) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function buildMtpPeerId(id: string, type: 'user' | 'chat' | 'channel') {
|
export function buildMtpPeerId(id: string, type: 'user' | 'chat' | 'channel') {
|
||||||
// Workaround for old-fashioned IDs stored locally
|
if (type === 'user') {
|
||||||
if (typeof id === 'number') {
|
return BigInt(id);
|
||||||
return BigInt(Math.abs(id));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return type === 'user' ? BigInt(id) : BigInt(id.slice(1));
|
if (type === 'channel') {
|
||||||
|
if (id.length === CHANNEL_ID_NEW_FORMAT_MIN_LENGTH) {
|
||||||
|
return BigInt(id.slice(4));
|
||||||
|
}
|
||||||
|
|
||||||
|
// LEGACY Unprefixed channel id
|
||||||
|
return BigInt(id.slice(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
return BigInt(id.slice(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function buildInputGroupCall(groupCall: Partial<ApiGroupCall>) {
|
export function buildInputGroupCall(groupCall: Partial<ApiGroupCall>) {
|
||||||
|
|||||||
@ -480,7 +480,7 @@ export async function repairFileReference({
|
|||||||
if (!result || result instanceof GramJs.messages.MessagesNotModified) return false;
|
if (!result || result instanceof GramJs.messages.MessagesNotModified) return false;
|
||||||
|
|
||||||
if (peer && 'pts' in result) {
|
if (peer && 'pts' in result) {
|
||||||
updateChannelState(peer.channelId.toString(), result.pts);
|
updateChannelState(buildApiPeerId(peer.channelId, 'channel'), result.pts);
|
||||||
}
|
}
|
||||||
|
|
||||||
const message = result.messages[0];
|
const message = result.messages[0];
|
||||||
|
|||||||
@ -13,7 +13,6 @@ import { TME_LINK_PREFIX } from '../../config';
|
|||||||
import {
|
import {
|
||||||
getChatLink,
|
getChatLink,
|
||||||
getHasAdminRight,
|
getHasAdminRight,
|
||||||
getTopicLink,
|
|
||||||
isChatChannel,
|
isChatChannel,
|
||||||
isUserId,
|
isUserId,
|
||||||
isUserRightBanned,
|
isUserRightBanned,
|
||||||
@ -25,6 +24,7 @@ import {
|
|||||||
selectCurrentMessageList,
|
selectCurrentMessageList,
|
||||||
selectNotifyExceptions,
|
selectNotifyExceptions,
|
||||||
selectNotifySettings,
|
selectNotifySettings,
|
||||||
|
selectTopicLink,
|
||||||
selectUser,
|
selectUser,
|
||||||
selectUserFullInfo,
|
selectUserFullInfo,
|
||||||
} from '../../global/selectors';
|
} from '../../global/selectors';
|
||||||
@ -55,6 +55,7 @@ type StateProps =
|
|||||||
topicId?: number;
|
topicId?: number;
|
||||||
description?: string;
|
description?: string;
|
||||||
chatInviteLink?: string;
|
chatInviteLink?: string;
|
||||||
|
topicLink?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const runDebounced = debounce((cb) => cb(), 500, false);
|
const runDebounced = debounce((cb) => cb(), 500, false);
|
||||||
@ -69,6 +70,7 @@ const ChatExtra: FC<OwnProps & StateProps> = ({
|
|||||||
topicId,
|
topicId,
|
||||||
description,
|
description,
|
||||||
chatInviteLink,
|
chatInviteLink,
|
||||||
|
topicLink,
|
||||||
}) => {
|
}) => {
|
||||||
const {
|
const {
|
||||||
loadFullUser,
|
loadFullUser,
|
||||||
@ -118,10 +120,8 @@ const ChatExtra: FC<OwnProps & StateProps> = ({
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
return isTopicInfo
|
return isTopicInfo ? topicLink! : getChatLink(chat) || chatInviteLink;
|
||||||
? getTopicLink(chat.id, activeChatUsernames?.[0].username, topicId)
|
}, [chat, isTopicInfo, topicLink, chatInviteLink]);
|
||||||
: getChatLink(chat) || chatInviteLink;
|
|
||||||
}, [chat, isTopicInfo, activeChatUsernames, topicId, chatInviteLink]);
|
|
||||||
|
|
||||||
const handleNotificationChange = useLastCallback(() => {
|
const handleNotificationChange = useLastCallback(() => {
|
||||||
setAreNotificationsEnabled((current) => {
|
setAreNotificationsEnabled((current) => {
|
||||||
@ -281,6 +281,8 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
|| getHasAdminRight(chat, 'inviteUsers')
|
|| getHasAdminRight(chat, 'inviteUsers')
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const topicLink = topicId ? selectTopicLink(global, chatOrUserId, topicId) : undefined;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
phoneCodeList,
|
phoneCodeList,
|
||||||
chat,
|
chat,
|
||||||
@ -290,6 +292,7 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
topicId,
|
topicId,
|
||||||
chatInviteLink,
|
chatInviteLink,
|
||||||
description,
|
description,
|
||||||
|
topicLink,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
)(ChatExtra));
|
)(ChatExtra));
|
||||||
|
|||||||
@ -13,7 +13,6 @@ import type { IAlbum, IAnchorPosition } from '../../../types';
|
|||||||
import { PREVIEW_AVATAR_COUNT, SERVICE_NOTIFICATIONS_USER_ID } from '../../../config';
|
import { PREVIEW_AVATAR_COUNT, SERVICE_NOTIFICATIONS_USER_ID } from '../../../config';
|
||||||
import {
|
import {
|
||||||
areReactionsEmpty,
|
areReactionsEmpty,
|
||||||
getChatMessageLink,
|
|
||||||
getMessageVideo,
|
getMessageVideo,
|
||||||
isActionMessage,
|
isActionMessage,
|
||||||
isChatChannel,
|
isChatChannel,
|
||||||
@ -36,6 +35,7 @@ import {
|
|||||||
selectIsPremiumPurchaseBlocked,
|
selectIsPremiumPurchaseBlocked,
|
||||||
selectIsReactionPickerOpen,
|
selectIsReactionPickerOpen,
|
||||||
selectMessageCustomEmojiSets,
|
selectMessageCustomEmojiSets,
|
||||||
|
selectMessageLink,
|
||||||
selectMessageTranslations,
|
selectMessageTranslations,
|
||||||
selectRequestedChatTranslationLanguage,
|
selectRequestedChatTranslationLanguage,
|
||||||
selectRequestedMessageTranslationLanguage,
|
selectRequestedMessageTranslationLanguage,
|
||||||
@ -58,7 +58,6 @@ import MessageContextMenu from './MessageContextMenu';
|
|||||||
|
|
||||||
export type OwnProps = {
|
export type OwnProps = {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
chatUsername?: string;
|
|
||||||
message: ApiMessage;
|
message: ApiMessage;
|
||||||
album?: IAlbum;
|
album?: IAlbum;
|
||||||
anchor: IAnchorPosition;
|
anchor: IAnchorPosition;
|
||||||
@ -109,9 +108,9 @@ type StateProps = {
|
|||||||
enabledReactions?: ApiChatReactions;
|
enabledReactions?: ApiChatReactions;
|
||||||
canScheduleUntilOnline?: boolean;
|
canScheduleUntilOnline?: boolean;
|
||||||
maxUniqueReactions?: number;
|
maxUniqueReactions?: number;
|
||||||
threadId?: number;
|
|
||||||
canPlayAnimatedEmojis?: boolean;
|
canPlayAnimatedEmojis?: boolean;
|
||||||
isReactionPickerOpen?: boolean;
|
isReactionPickerOpen?: boolean;
|
||||||
|
messageLink?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const ContextMenuContainer: FC<OwnProps & StateProps> = ({
|
const ContextMenuContainer: FC<OwnProps & StateProps> = ({
|
||||||
@ -119,7 +118,6 @@ const ContextMenuContainer: FC<OwnProps & StateProps> = ({
|
|||||||
topReactions,
|
topReactions,
|
||||||
isOpen,
|
isOpen,
|
||||||
messageListType,
|
messageListType,
|
||||||
chatUsername,
|
|
||||||
message,
|
message,
|
||||||
customEmojiSetsInfo,
|
customEmojiSetsInfo,
|
||||||
customEmojiSets,
|
customEmojiSets,
|
||||||
@ -162,10 +160,10 @@ const ContextMenuContainer: FC<OwnProps & StateProps> = ({
|
|||||||
canTranslate,
|
canTranslate,
|
||||||
canShowOriginal,
|
canShowOriginal,
|
||||||
canSelectLanguage,
|
canSelectLanguage,
|
||||||
threadId,
|
isReactionPickerOpen,
|
||||||
|
messageLink,
|
||||||
onClose,
|
onClose,
|
||||||
onCloseAnimationEnd,
|
onCloseAnimationEnd,
|
||||||
isReactionPickerOpen,
|
|
||||||
}) => {
|
}) => {
|
||||||
const {
|
const {
|
||||||
openChat,
|
openChat,
|
||||||
@ -403,7 +401,7 @@ const ContextMenuContainer: FC<OwnProps & StateProps> = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const handleCopyLink = useLastCallback(() => {
|
const handleCopyLink = useLastCallback(() => {
|
||||||
copyTextToClipboard(getChatMessageLink(message.chatId, chatUsername, threadId, message.id));
|
copyTextToClipboard(messageLink!);
|
||||||
closeMenu();
|
closeMenu();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -641,6 +639,7 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
: undefined;
|
: undefined;
|
||||||
const canTranslate = !hasTranslation && selectCanTranslateMessage(global, message, detectedLanguage);
|
const canTranslate = !hasTranslation && selectCanTranslateMessage(global, message, detectedLanguage);
|
||||||
const isChatTranslated = selectRequestedChatTranslationLanguage(global, message.chatId);
|
const isChatTranslated = selectRequestedChatTranslationLanguage(global, message.chatId);
|
||||||
|
const messageLink = selectMessageLink(global, message.chatId, threadId, message.id);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
availableReactions: global.availableReactions,
|
availableReactions: global.availableReactions,
|
||||||
@ -677,12 +676,12 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
customEmojiSetsInfo,
|
customEmojiSetsInfo,
|
||||||
customEmojiSets,
|
customEmojiSets,
|
||||||
canScheduleUntilOnline: selectCanScheduleUntilOnline(global, message.chatId),
|
canScheduleUntilOnline: selectCanScheduleUntilOnline(global, message.chatId),
|
||||||
threadId,
|
|
||||||
canTranslate,
|
canTranslate,
|
||||||
canShowOriginal: hasTranslation && !isChatTranslated,
|
canShowOriginal: hasTranslation && !isChatTranslated,
|
||||||
canSelectLanguage: hasTranslation && !isChatTranslated,
|
canSelectLanguage: hasTranslation && !isChatTranslated,
|
||||||
canPlayAnimatedEmojis: selectCanPlayAnimatedEmojis(global),
|
canPlayAnimatedEmojis: selectCanPlayAnimatedEmojis(global),
|
||||||
isReactionPickerOpen: selectIsReactionPickerOpen(global),
|
isReactionPickerOpen: selectIsReactionPickerOpen(global),
|
||||||
|
messageLink,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
)(ContextMenuContainer));
|
)(ContextMenuContainer));
|
||||||
|
|||||||
@ -15,7 +15,6 @@ import type {
|
|||||||
ApiTopic,
|
ApiTopic,
|
||||||
ApiTypeStory,
|
ApiTypeStory,
|
||||||
ApiUser,
|
ApiUser,
|
||||||
ApiUsername,
|
|
||||||
} from '../../../api/types';
|
} from '../../../api/types';
|
||||||
import type {
|
import type {
|
||||||
ActiveEmojiInteraction,
|
ActiveEmojiInteraction,
|
||||||
@ -200,7 +199,6 @@ type OwnProps =
|
|||||||
type StateProps = {
|
type StateProps = {
|
||||||
theme: ISettings['theme'];
|
theme: ISettings['theme'];
|
||||||
forceSenderName?: boolean;
|
forceSenderName?: boolean;
|
||||||
chatUsernames?: ApiUsername[];
|
|
||||||
sender?: ApiUser | ApiChat;
|
sender?: ApiUser | ApiChat;
|
||||||
canShowSender: boolean;
|
canShowSender: boolean;
|
||||||
originSender?: ApiUser | ApiChat;
|
originSender?: ApiUser | ApiChat;
|
||||||
@ -288,7 +286,6 @@ const RESIZE_ANIMATION_DURATION = 400;
|
|||||||
|
|
||||||
const Message: FC<OwnProps & StateProps> = ({
|
const Message: FC<OwnProps & StateProps> = ({
|
||||||
message,
|
message,
|
||||||
chatUsernames,
|
|
||||||
observeIntersectionForBottom,
|
observeIntersectionForBottom,
|
||||||
observeIntersectionForLoading,
|
observeIntersectionForLoading,
|
||||||
observeIntersectionForPlaying,
|
observeIntersectionForPlaying,
|
||||||
@ -1278,7 +1275,6 @@ const Message: FC<OwnProps & StateProps> = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const forwardAuthor = isGroup && asForwarded ? message.postAuthorTitle : undefined;
|
const forwardAuthor = isGroup && asForwarded ? message.postAuthorTitle : undefined;
|
||||||
const chatUsername = useMemo(() => chatUsernames?.find((c) => c.isActive), [chatUsernames]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@ -1384,7 +1380,6 @@ const Message: FC<OwnProps & StateProps> = ({
|
|||||||
targetHref={contextMenuTarget?.matches('a[href]') ? (contextMenuTarget as HTMLAnchorElement).href : undefined}
|
targetHref={contextMenuTarget?.matches('a[href]') ? (contextMenuTarget as HTMLAnchorElement).href : undefined}
|
||||||
message={message}
|
message={message}
|
||||||
album={album}
|
album={album}
|
||||||
chatUsername={chatUsername?.username}
|
|
||||||
messageListType={messageListType}
|
messageListType={messageListType}
|
||||||
onClose={handleContextMenuClose}
|
onClose={handleContextMenuClose}
|
||||||
onCloseAnimationEnd={handleContextMenuHide}
|
onCloseAnimationEnd={handleContextMenuHide}
|
||||||
@ -1439,7 +1434,6 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
const isRepliesChat = isChatWithRepliesBot(chatId);
|
const isRepliesChat = isChatWithRepliesBot(chatId);
|
||||||
const isChannel = chat && isChatChannel(chat);
|
const isChannel = chat && isChatChannel(chat);
|
||||||
const isGroup = chat && isChatGroup(chat);
|
const isGroup = chat && isChatGroup(chat);
|
||||||
const chatUsernames = chat?.usernames;
|
|
||||||
const chatFullInfo = !isUserId(chatId) ? selectChatFullInfo(global, chatId) : undefined;
|
const chatFullInfo = !isUserId(chatId) ? selectChatFullInfo(global, chatId) : undefined;
|
||||||
const webPageStoryData = message.content.webPage?.story;
|
const webPageStoryData = message.content.webPage?.story;
|
||||||
const webPageStory = webPageStoryData
|
const webPageStory = webPageStoryData
|
||||||
@ -1529,7 +1523,6 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
theme: selectTheme(global),
|
theme: selectTheme(global),
|
||||||
chatUsernames,
|
|
||||||
forceSenderName,
|
forceSenderName,
|
||||||
canShowSender,
|
canShowSender,
|
||||||
originSender,
|
originSender,
|
||||||
|
|||||||
@ -285,7 +285,7 @@ export const RESTRICTED_EMOJI_SET_ID = '7173162320003080';
|
|||||||
export const DEFAULT_GIF_SEARCH_BOT_USERNAME = 'gif';
|
export const DEFAULT_GIF_SEARCH_BOT_USERNAME = 'gif';
|
||||||
export const ALL_FOLDER_ID = 0;
|
export const ALL_FOLDER_ID = 0;
|
||||||
export const ARCHIVED_FOLDER_ID = 1;
|
export const ARCHIVED_FOLDER_ID = 1;
|
||||||
export const DELETED_COMMENTS_CHANNEL_ID = '-777';
|
export const DELETED_COMMENTS_CHANNEL_ID = '-100777';
|
||||||
export const MAX_MEDIA_FILES_FOR_ALBUM = 10;
|
export const MAX_MEDIA_FILES_FOR_ALBUM = 10;
|
||||||
export const MAX_ACTIVE_PINNED_CHATS = 5;
|
export const MAX_ACTIVE_PINNED_CHATS = 5;
|
||||||
export const SCHEDULED_WHEN_ONLINE = 0x7FFFFFFE;
|
export const SCHEDULED_WHEN_ONLINE = 0x7FFFFFFE;
|
||||||
|
|||||||
@ -1065,7 +1065,7 @@ addActionHandler('openTelegramLink', (global, actions, payload): ActionReturnTyp
|
|||||||
tabId,
|
tabId,
|
||||||
});
|
});
|
||||||
} else if (part1 === 'c' && chatOrChannelPostId && messageId) {
|
} else if (part1 === 'c' && chatOrChannelPostId && messageId) {
|
||||||
const chatId = `-${chatOrChannelPostId}`;
|
const chatId = `-100${chatOrChannelPostId}`;
|
||||||
const chat = selectChat(global, chatId);
|
const chat = selectChat(global, chatId);
|
||||||
if (!chat) {
|
if (!chat) {
|
||||||
showNotification({ message: 'Chat does not exist', tabId });
|
showNotification({ message: 'Chat does not exist', tabId });
|
||||||
@ -1073,7 +1073,7 @@ addActionHandler('openTelegramLink', (global, actions, payload): ActionReturnTyp
|
|||||||
}
|
}
|
||||||
|
|
||||||
focusMessage({
|
focusMessage({
|
||||||
chatId,
|
chatId: chat.id,
|
||||||
messageId,
|
messageId,
|
||||||
tabId,
|
tabId,
|
||||||
});
|
});
|
||||||
|
|||||||
@ -18,7 +18,7 @@ import {
|
|||||||
import { formatDateToString, formatTime } from '../../util/dateFormat';
|
import { formatDateToString, formatTime } from '../../util/dateFormat';
|
||||||
import { orderBy } from '../../util/iteratees';
|
import { orderBy } from '../../util/iteratees';
|
||||||
import { prepareSearchWordsForNeedle } from '../../util/searchWords';
|
import { prepareSearchWordsForNeedle } from '../../util/searchWords';
|
||||||
import { getUserFirstOrLastName } from './users';
|
import { getMainUsername, getUserFirstOrLastName } from './users';
|
||||||
|
|
||||||
const FOREVER_BANNED_DATE = Date.now() / 1000 + 31622400; // 366 days
|
const FOREVER_BANNED_DATE = Date.now() / 1000 + 31622400; // 366 days
|
||||||
|
|
||||||
@ -26,11 +26,6 @@ const VERIFIED_PRIORITY_BASE = 3e9;
|
|||||||
const PINNED_PRIORITY_BASE = 3e8;
|
const PINNED_PRIORITY_BASE = 3e8;
|
||||||
|
|
||||||
export function isUserId(entityId: string) {
|
export function isUserId(entityId: string) {
|
||||||
// Workaround for old-fashioned IDs stored locally
|
|
||||||
if (typeof entityId === 'number') {
|
|
||||||
return entityId > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return !entityId.startsWith('-');
|
return !entityId.startsWith('-');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,20 +82,9 @@ export function getChatTitle(lang: LangFn, chat: ApiChat, isSelf = false) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getChatLink(chat: ApiChat) {
|
export function getChatLink(chat: ApiChat) {
|
||||||
const activeUsername = chat.usernames?.find((u) => u.isActive);
|
const activeUsername = getMainUsername(chat);
|
||||||
|
|
||||||
return activeUsername ? `${TME_LINK_PREFIX}${activeUsername.username}` : undefined;
|
return activeUsername ? `${TME_LINK_PREFIX}${activeUsername}` : undefined;
|
||||||
}
|
|
||||||
|
|
||||||
export function getChatMessageLink(chatId: string, chatUsername?: string, threadId?: number, messageId?: number) {
|
|
||||||
const chatPart = chatUsername || `c/${chatId.replace('-', '')}`;
|
|
||||||
const threadPart = threadId && threadId !== MAIN_THREAD_ID ? `/${threadId}` : '';
|
|
||||||
const messagePart = messageId ? `/${messageId}` : '';
|
|
||||||
return `${TME_LINK_PREFIX}${chatPart}${threadPart}${messagePart}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getTopicLink(chatId: string, chatUsername?: string, topicId?: number) {
|
|
||||||
return getChatMessageLink(chatId, chatUsername, topicId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getChatAvatarHash(
|
export function getChatAvatarHash(
|
||||||
|
|||||||
@ -13,7 +13,7 @@ import type {
|
|||||||
import { ApiMessageEntityTypes, MAIN_THREAD_ID } from '../../api/types';
|
import { ApiMessageEntityTypes, MAIN_THREAD_ID } from '../../api/types';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
GENERAL_TOPIC_ID, REPLIES_USER_ID, SERVICE_NOTIFICATIONS_USER_ID,
|
GENERAL_TOPIC_ID, REPLIES_USER_ID, SERVICE_NOTIFICATIONS_USER_ID, TME_LINK_PREFIX,
|
||||||
} from '../../config';
|
} from '../../config';
|
||||||
import { getCurrentTabId } from '../../util/establishMultitabRole';
|
import { getCurrentTabId } from '../../util/establishMultitabRole';
|
||||||
import { findLast } from '../../util/iteratees';
|
import { findLast } from '../../util/iteratees';
|
||||||
@ -25,6 +25,7 @@ import {
|
|||||||
getAllowedAttachmentOptions,
|
getAllowedAttachmentOptions,
|
||||||
getCanPostInChat,
|
getCanPostInChat,
|
||||||
getHasAdminRight,
|
getHasAdminRight,
|
||||||
|
getMainUsername,
|
||||||
getMessageAudio,
|
getMessageAudio,
|
||||||
getMessageDocument,
|
getMessageDocument,
|
||||||
getMessageOriginalId,
|
getMessageOriginalId,
|
||||||
@ -1353,3 +1354,28 @@ export function selectCanTranslateMessage<T extends GlobalState>(
|
|||||||
return IS_TRANSLATION_SUPPORTED && isTranslationEnabled && canTranslateLanguage && isTranslatable
|
return IS_TRANSLATION_SUPPORTED && isTranslationEnabled && canTranslateLanguage && isTranslatable
|
||||||
&& !chatRequestedLanguage;
|
&& !chatRequestedLanguage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function selectMessageLink<T extends GlobalState>(
|
||||||
|
global: T, chatId: string, threadId?: number, messageId?: number,
|
||||||
|
) {
|
||||||
|
const chat = selectChat(global, chatId);
|
||||||
|
if (!chat) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const chatUsername = getMainUsername(chat);
|
||||||
|
|
||||||
|
const isChannelId = isChatChannel(chat) || isChatSuperGroup(chat);
|
||||||
|
const normalizedId = isChannelId ? chatId.replace('-100', '') : chatId.replace('-', '');
|
||||||
|
|
||||||
|
const chatPart = chatUsername || `c/${normalizedId}`;
|
||||||
|
const threadPart = threadId && threadId !== MAIN_THREAD_ID ? `/${threadId}` : '';
|
||||||
|
const messagePart = messageId ? `/${messageId}` : '';
|
||||||
|
return `${TME_LINK_PREFIX}${chatPart}${threadPart}${messagePart}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function selectTopicLink<T extends GlobalState>(
|
||||||
|
global: T, chatId: string, topicId?: number,
|
||||||
|
) {
|
||||||
|
return selectMessageLink(global, chatId, topicId);
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user