Support Channel direct messages (#5990)
This commit is contained in:
parent
8f9310c7d5
commit
a85fec6c65
@ -98,6 +98,7 @@ export interface GramJsAppConfig extends LimitsConfig {
|
||||
stars_stargift_resale_amount_max?: number;
|
||||
stars_stargift_resale_amount_min?: number;
|
||||
stars_stargift_resale_commission_permille?: number;
|
||||
poll_answers_max?: number;
|
||||
}
|
||||
|
||||
function buildEmojiSounds(appConfig: GramJsAppConfig) {
|
||||
@ -198,5 +199,6 @@ export function buildAppConfig(json: GramJs.TypeJSONValue, hash: number): ApiApp
|
||||
starsStargiftResaleAmountMin: appConfig.stars_stargift_resale_amount_min,
|
||||
starsStargiftResaleAmountMax: appConfig.stars_stargift_resale_amount_max,
|
||||
starsStargiftResaleCommissionPermille: appConfig.stars_stargift_resale_commission_permille,
|
||||
pollMaxAnswers: appConfig.poll_answers_max,
|
||||
};
|
||||
}
|
||||
|
||||
@ -110,6 +110,9 @@ function buildApiChatFieldsFromPeerEntity(
|
||||
isJoinToSend: channel?.joinToSend,
|
||||
isJoinRequest: channel?.joinRequest,
|
||||
isForum: channel?.forum,
|
||||
isMonoforum: channel?.monoforum,
|
||||
linkedMonoforumId: channel?.linkedMonoforumId && buildApiPeerId(channel.linkedMonoforumId, 'channel'),
|
||||
areChannelMessagesAllowed: channel?.broadcastMessagesAllowed,
|
||||
areStoriesHidden,
|
||||
maxStoryId,
|
||||
hasStories: Boolean(maxStoryId) && !storiesUnavailable,
|
||||
|
||||
@ -426,11 +426,12 @@ export function buildApiMessageAction(action: GramJs.TypeMessageAction): ApiMess
|
||||
}
|
||||
if (action instanceof GramJs.MessageActionPaidMessagesPrice) {
|
||||
const {
|
||||
stars,
|
||||
stars, broadcastMessagesAllowed,
|
||||
} = action;
|
||||
return {
|
||||
mediaType: 'action',
|
||||
type: 'paidMessagesPrice',
|
||||
isAllowedInChannel: broadcastMessagesAllowed,
|
||||
stars: stars.toJSNumber(),
|
||||
};
|
||||
}
|
||||
|
||||
@ -287,6 +287,7 @@ export function buildMessageDraft(draft: GramJs.TypeDraftMessage): ApiDraft | un
|
||||
replyToMsgId: replyTo.replyToMsgId,
|
||||
replyToTopId: replyTo.topMsgId,
|
||||
replyToPeerId: replyTo.replyToPeerId && getApiChatIdFromMtpPeer(replyTo.replyToPeerId),
|
||||
monoforumPeerId: replyTo.monoforumPeerId && getApiChatIdFromMtpPeer(replyTo.monoforumPeerId),
|
||||
quoteText: replyTo.quoteText ? buildMessageTextContent(replyTo.quoteText, replyTo.quoteEntities) : undefined,
|
||||
quoteOffset: replyTo.quoteOffset,
|
||||
} satisfies ApiInputMessageReplyInfo : undefined;
|
||||
|
||||
@ -3,7 +3,7 @@ import { Api as GramJs } from '../../../lib/gramjs';
|
||||
|
||||
import type { ApiEmojiStatusType, ApiPeerColor } from '../../types';
|
||||
|
||||
import { CHANNEL_ID_LENGTH } from '../../../config';
|
||||
import { CHANNEL_ID_BASE } from '../../../config';
|
||||
import { numberToHexColor } from '../../../util/colors';
|
||||
|
||||
type TypePeerOrInput = GramJs.TypePeer | GramJs.TypeInputPeer | GramJs.TypeInputUser | GramJs.TypeInputChannel;
|
||||
@ -26,13 +26,10 @@ export function buildApiPeerId(id: BigInt.BigInteger, type: 'user' | 'chat' | 'c
|
||||
}
|
||||
|
||||
if (type === 'channel') {
|
||||
// Simulates TDLib https://github.com/tdlib/td/blob/d7203eb719304866a7eb7033ef03d421459335b8/td/telegram/DialogId.cpp#L54
|
||||
// But using only string operations. Should be fine until channel ids reach 10^12
|
||||
// Example: 12345678 -> -1000012345678
|
||||
return `-1${id.toString().padStart(CHANNEL_ID_LENGTH - 2, '0')}`;
|
||||
return id.add(CHANNEL_ID_BASE).negate().toString();
|
||||
}
|
||||
|
||||
return `-${id.toString()}`;
|
||||
return id.negate().toString();
|
||||
}
|
||||
|
||||
export function getApiChatIdFromMtpPeer(peer: TypePeerOrInput) {
|
||||
|
||||
@ -37,23 +37,22 @@ import {
|
||||
ApiMessageEntityTypes,
|
||||
} from '../../types';
|
||||
|
||||
import { CHANNEL_ID_LENGTH, DEFAULT_STATUS_ICON_ID } from '../../../config';
|
||||
import { CHANNEL_ID_BASE, DEFAULT_STATUS_ICON_ID } from '../../../config';
|
||||
import { pick } from '../../../util/iteratees';
|
||||
import { deserializeBytes } from '../helpers/misc';
|
||||
import localDb from '../localDb';
|
||||
|
||||
function checkIfChannelId(id: string) {
|
||||
return id.length === CHANNEL_ID_LENGTH && id.startsWith('-1');
|
||||
}
|
||||
|
||||
export function getEntityTypeById(chatOrUserId: string) {
|
||||
if (!chatOrUserId.startsWith('-')) {
|
||||
export function getEntityTypeById(peerId: string) {
|
||||
const n = Number(peerId);
|
||||
if (n > 0) {
|
||||
return 'user';
|
||||
} else if (checkIfChannelId(chatOrUserId)) {
|
||||
return 'channel';
|
||||
} else {
|
||||
return 'chat';
|
||||
}
|
||||
|
||||
if (n < -CHANNEL_ID_BASE) {
|
||||
return 'channel';
|
||||
}
|
||||
|
||||
return 'chat';
|
||||
}
|
||||
|
||||
export function buildPeer(chatOrUserId: string): GramJs.TypePeer {
|
||||
@ -569,11 +568,13 @@ export function buildMtpPeerId(id: string, type: 'user' | 'chat' | 'channel') {
|
||||
return BigInt(id);
|
||||
}
|
||||
|
||||
const n = Number(id);
|
||||
|
||||
if (type === 'channel') {
|
||||
return BigInt(id.slice(2)); // Slice "-1", zeroes are trimmed when converting to BigInt
|
||||
return BigInt(-n - CHANNEL_ID_BASE);
|
||||
}
|
||||
|
||||
return BigInt(id.slice(1));
|
||||
return BigInt(n * -1);
|
||||
}
|
||||
|
||||
export function buildInputGroupCall(groupCall: Partial<ApiGroupCall>) {
|
||||
@ -843,12 +844,13 @@ export function buildInputReplyTo(replyInfo: ApiInputReplyInfo) {
|
||||
|
||||
if (replyInfo.type === 'message') {
|
||||
const {
|
||||
replyToMsgId, replyToTopId, replyToPeerId, quoteText, quoteOffset,
|
||||
replyToMsgId, replyToTopId, replyToPeerId, quoteText, quoteOffset, monoforumPeerId,
|
||||
} = replyInfo;
|
||||
return new GramJs.InputReplyToMessage({
|
||||
replyToMsgId,
|
||||
topMsgId: replyToTopId,
|
||||
replyToPeerId: replyToPeerId ? buildInputPeerFromLocalDb(replyToPeerId)! : undefined,
|
||||
monoforumPeerId: monoforumPeerId ? buildInputPeerFromLocalDb(monoforumPeerId)! : undefined,
|
||||
quoteText: quoteText?.text,
|
||||
quoteEntities: quoteText?.entities?.map(buildMtpMessageEntity),
|
||||
quoteOffset,
|
||||
|
||||
@ -299,6 +299,10 @@ export async function fetchSavedChats({
|
||||
const chats: ApiChat[] = [];
|
||||
|
||||
dialogs.forEach((dialog) => {
|
||||
if (dialog instanceof GramJs.MonoForumDialog) {
|
||||
return;
|
||||
}
|
||||
|
||||
const peerEntity = peersByKey[getPeerKey(dialog.peer)];
|
||||
const chat = buildApiChatFromSavedDialog(dialog, peerEntity);
|
||||
const chatId = getApiChatIdFromMtpPeer(dialog.peer);
|
||||
@ -596,7 +600,7 @@ async function getFullChatInfo(chatId: string): Promise<FullChatData | undefined
|
||||
async function getFullChannelInfo(
|
||||
chat: ApiChat,
|
||||
): Promise<FullChatData | undefined> {
|
||||
const { id, adminRights } = chat;
|
||||
const { id, adminRights, isMonoforum } = chat;
|
||||
const accessHash = chat.accessHash!;
|
||||
const result = await invokeRequest(new GramJs.channels.GetFullChannel({
|
||||
channel: buildInputChannel(id, accessHash),
|
||||
@ -653,12 +657,14 @@ async function getFullChannelInfo(
|
||||
? exportedInvite.link
|
||||
: undefined;
|
||||
|
||||
const { members, userStatusesById } = (canViewParticipants && await fetchMembers({ chat })) || {};
|
||||
const canLoadParticipants = canViewParticipants && !isMonoforum;
|
||||
|
||||
const { members, userStatusesById } = (canLoadParticipants && await fetchMembers({ chat })) || {};
|
||||
const { members: kickedMembers, userStatusesById: bannedStatusesById } = (
|
||||
canViewParticipants && adminRights && await fetchMembers({ chat, memberFilter: 'kicked' })
|
||||
canLoadParticipants && adminRights && await fetchMembers({ chat, memberFilter: 'kicked' })
|
||||
) || {};
|
||||
const { members: adminMembers, userStatusesById: adminStatusesById } = (
|
||||
canViewParticipants && await fetchMembers({ chat, memberFilter: 'admin' })
|
||||
canLoadParticipants && await fetchMembers({ chat, memberFilter: 'admin' })
|
||||
) || {};
|
||||
const botCommands = botInfo ? buildApiChatBotCommands(botInfo) : undefined;
|
||||
const memberInfoRequest = !chat.isNotJoined && chat.type === 'chatTypeChannel'
|
||||
@ -710,7 +716,7 @@ async function getFullChannelInfo(
|
||||
chatId: buildApiPeerId(migratedFromChatId, 'chat'),
|
||||
maxMessageId: migratedFromMaxId,
|
||||
} : undefined,
|
||||
canViewMembers: canViewParticipants,
|
||||
canViewMembers: canLoadParticipants,
|
||||
canViewStatistics: canViewStats,
|
||||
canViewMonetization,
|
||||
isPreHistoryHidden: hiddenPrehistory,
|
||||
|
||||
@ -980,8 +980,8 @@ export async function sendMessageAction({
|
||||
}: {
|
||||
peer: ApiPeer; threadId?: ThreadId; action: ApiSendMessageAction;
|
||||
}) {
|
||||
const gramAction = buildSendMessageAction(action);
|
||||
if (!gramAction) {
|
||||
const mtpAction = buildSendMessageAction(action);
|
||||
if (!mtpAction) {
|
||||
if (DEBUG) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn('Unsupported message action', action);
|
||||
@ -993,7 +993,7 @@ export async function sendMessageAction({
|
||||
const result = await invokeRequest(new GramJs.messages.SetTyping({
|
||||
peer: buildInputPeer(peer.id, peer.accessHash),
|
||||
topMsgId: Number(threadId),
|
||||
action: gramAction,
|
||||
action: mtpAction,
|
||||
}), {
|
||||
shouldThrow: true,
|
||||
abortControllerChatId: peer.id,
|
||||
|
||||
@ -47,6 +47,9 @@ export interface ApiChat {
|
||||
emojiStatus?: ApiEmojiStatusType;
|
||||
isForum?: boolean;
|
||||
isForumAsMessages?: true;
|
||||
isMonoforum?: boolean;
|
||||
linkedMonoforumId?: string;
|
||||
areChannelMessagesAllowed?: boolean;
|
||||
boostLevel?: number;
|
||||
botVerificationIconId?: string;
|
||||
hasAutoTranslation?: true;
|
||||
|
||||
@ -278,6 +278,7 @@ export interface ApiMessageActionPaidMessagesRefunded extends ActionMediaType {
|
||||
export interface ApiMessageActionPaidMessagesPrice extends ActionMediaType {
|
||||
type: 'paidMessagesPrice';
|
||||
stars: number;
|
||||
isAllowedInChannel?: boolean;
|
||||
}
|
||||
|
||||
export interface ApiMessageActionUnsupported extends ActionMediaType {
|
||||
|
||||
@ -379,6 +379,7 @@ export interface ApiInputMessageReplyInfo {
|
||||
replyToMsgId: number;
|
||||
replyToTopId?: number;
|
||||
replyToPeerId?: string;
|
||||
monoforumPeerId?: string;
|
||||
quoteText?: ApiFormattedText;
|
||||
quoteOffset?: number;
|
||||
}
|
||||
|
||||
@ -250,6 +250,7 @@ export interface ApiAppConfig {
|
||||
starsStargiftResaleAmountMin?: number;
|
||||
starsStargiftResaleAmountMax?: number;
|
||||
starsStargiftResaleCommissionPermille?: number;
|
||||
pollMaxAnswers?: number;
|
||||
}
|
||||
|
||||
export interface ApiConfig {
|
||||
|
||||
@ -1918,7 +1918,8 @@
|
||||
"SectionDescriptionStarsForForMessages" = "You will receive {percent} of the selected fee (~{amount}) for each incoming message.";
|
||||
"SubtitlePrivacyAddUsers" = "Add Users";
|
||||
"PrivacyPaidMessagesValue" = "Paid";
|
||||
"FirstMessageInPaidMessagesChat" = "**{user}** charges {amount} for each message.";
|
||||
"MessagesPlaceholderPaidUser" = "**{peer}** charges {amount} for each message.";
|
||||
"MessagesPlaceholderPaidChannel" = "**{peer}** charges {amount} per message to its admin.";
|
||||
"ButtonBuyStars" = "Buy Stars";
|
||||
"ComposerPlaceholderPaidMessage" = "Message for {amount}";
|
||||
"ComposerPlaceholderPaidReply" = "Reply for {amount}";
|
||||
@ -1965,8 +1966,12 @@
|
||||
"FrozenAccountAppealSubtitle" = "Appeal via {botLink} before {date} or your account will be deleted.";
|
||||
"ButtonAppeal" = "Submit an Appeal";
|
||||
"ButtonUnderstood" = "Understood";
|
||||
"ActionPaidMessageGroupPrice" = "Messages now cost **{stars}** in this group";
|
||||
"ActionPaidMessageGroupPriceFree" = "Messages are now free in this group";
|
||||
"ActionPaidMessagePrice" = "{peer} changed price to **{amount}** per message";
|
||||
"ActionPaidMessagePriceYou" = "You changed price to **{amount}** per message";
|
||||
"ActionPaidMessagePriceFree" = "{peer} made messages free";
|
||||
"ActionPaidMessagePriceFreeYou" = "You made messages free";
|
||||
"ActionMessageChannelFree" = "{peer} now accepts private messages";
|
||||
"ActionMessageChannelDisabled" = "{peer} no longer accepts private messages";
|
||||
"ApiMessageActionPaidMessagesRefundedOutgoing" = "You refunded **{stars}** to {user}";
|
||||
"ApiMessageActionPaidMessagesRefundedIncoming" = "{user} refunded **{stars}** to you";
|
||||
"NotificationTitleNotSupportedInFrozenAccount" = "Your account is frozen";
|
||||
@ -2012,4 +2017,8 @@
|
||||
"ValueGiftSortByNumber" = "Number";
|
||||
"ResellGiftsNoFound" = "No gifts found";
|
||||
"ResellGiftsClearFilters" = "Clear Filters";
|
||||
"MonoforumBadge" = "DIRECT";
|
||||
"MonoforumStatus" = "Channel messages";
|
||||
"MonoforumComposerPlaceholder" = "Choose a message to reply";
|
||||
"ChannelSendMessage" = "Direct Messages";
|
||||
"AutomaticTranslation" = "Automatic Translation";
|
||||
|
||||
@ -150,4 +150,13 @@
|
||||
&.premium-gradient-bg > .inner {
|
||||
background-image: var(--premium-gradient);
|
||||
}
|
||||
|
||||
&.message-bubble {
|
||||
--radius: 0;
|
||||
|
||||
mask-image: url("../../assets/icons/forumTopic/blue.svg");
|
||||
mask-position: center;
|
||||
mask-repeat: no-repeat;
|
||||
mask-size: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@ -85,6 +85,7 @@ type OwnProps = {
|
||||
storyViewerMode?: 'full' | 'single-peer' | 'disabled';
|
||||
loopIndefinitely?: boolean;
|
||||
noPersonalPhoto?: boolean;
|
||||
asMessageBubble?: boolean;
|
||||
observeIntersection?: ObserveFn;
|
||||
onClick?: (e: ReactMouseEvent<HTMLDivElement, MouseEvent>, hasMedia: boolean) => void;
|
||||
onContextMenu?: (e: React.MouseEvent) => void;
|
||||
@ -111,6 +112,7 @@ const Avatar: FC<OwnProps> = ({
|
||||
storyViewerMode = 'single-peer',
|
||||
loopIndefinitely,
|
||||
noPersonalPhoto,
|
||||
asMessageBubble,
|
||||
onClick,
|
||||
onContextMenu,
|
||||
}) => {
|
||||
@ -261,6 +263,7 @@ const Avatar: FC<OwnProps> = ({
|
||||
isReplies && 'replies-bot-account',
|
||||
isPremiumGradient && 'premium-gradient-bg',
|
||||
isRoundedRect && 'forum',
|
||||
asMessageBubble && 'message-bubble',
|
||||
(photo || webPhoto) && 'force-fit',
|
||||
((withStory && realPeer?.hasStories) || forPremiumPromo) && 'with-story-circle',
|
||||
withStorySolid && realPeer?.hasStories && 'with-story-solid',
|
||||
|
||||
@ -300,6 +300,7 @@ type StateProps =
|
||||
isAccountFrozen?: boolean;
|
||||
isAppConfigLoaded?: boolean;
|
||||
insertingPeerIdMention?: string;
|
||||
pollMaxAnswers?: number;
|
||||
};
|
||||
|
||||
enum MainButtonState {
|
||||
@ -413,10 +414,6 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
shouldPlayEffect,
|
||||
maxMessageLength,
|
||||
isSilentPosting,
|
||||
onDropHide,
|
||||
onFocus,
|
||||
onBlur,
|
||||
onForward,
|
||||
isPaymentMessageConfirmDialogOpen,
|
||||
starsBalance,
|
||||
isStarsBalanceModalOpen,
|
||||
@ -424,6 +421,11 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
isAccountFrozen,
|
||||
isAppConfigLoaded,
|
||||
insertingPeerIdMention,
|
||||
pollMaxAnswers,
|
||||
onDropHide,
|
||||
onFocus,
|
||||
onBlur,
|
||||
onForward,
|
||||
}) => {
|
||||
const {
|
||||
sendMessage,
|
||||
@ -481,9 +483,12 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
|
||||
const canMediaBeReplaced = editingMessage && canEditMedia(editingMessage);
|
||||
|
||||
const isMonoforum = chat?.isMonoforum;
|
||||
const { emojiSet, members: groupChatMembers, botCommands: chatBotCommands } = chatFullInfo || {};
|
||||
const chatEmojiSetId = emojiSet?.id;
|
||||
|
||||
const canSchedule = !paidMessagesStars && !isMonoforum;
|
||||
|
||||
const isSentStoryReactionHeart = sentStoryReaction && isSameReaction(sentStoryReaction, HEART_REACTION);
|
||||
|
||||
useEffect(processMessageInputForCustomEmoji, [getHtml]);
|
||||
@ -510,10 +515,10 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
}, [chatId]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isAppConfigLoaded && chatId && isReady && !isInStoryViewer) {
|
||||
if (isAppConfigLoaded && chatId && isReady && !isInStoryViewer && !isMonoforum) {
|
||||
loadScheduledHistory({ chatId });
|
||||
}
|
||||
}, [isReady, chatId, threadId, isInStoryViewer, isAppConfigLoaded]);
|
||||
}, [isReady, chatId, threadId, isInStoryViewer, isAppConfigLoaded, isMonoforum]);
|
||||
|
||||
useEffect(() => {
|
||||
const isChannelWithProfiles = isChannel && chat?.areProfilesShown;
|
||||
@ -541,10 +546,11 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
() => getAllowedAttachmentOptions(chat,
|
||||
chatFullInfo,
|
||||
isChatWithBot,
|
||||
isChatWithSelf,
|
||||
isInStoryViewer,
|
||||
paidMessagesStars,
|
||||
isInScheduledList),
|
||||
[chat, chatFullInfo, isChatWithBot, isInStoryViewer, paidMessagesStars, isInScheduledList],
|
||||
[chat, chatFullInfo, isChatWithBot, isChatWithSelf, isInStoryViewer, paidMessagesStars, isInScheduledList],
|
||||
);
|
||||
|
||||
const isNeedPremium = isContactRequirePremium && isInStoryViewer;
|
||||
@ -804,7 +810,7 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
getHtml,
|
||||
setHtml,
|
||||
editedMessage: editingMessage,
|
||||
isDisabled: isInStoryViewer || Boolean(requestedDraft),
|
||||
isDisabled: isInStoryViewer || Boolean(requestedDraft) || isMonoforum,
|
||||
});
|
||||
|
||||
const resetComposer = useLastCallback((shouldPreserveInput = false) => {
|
||||
@ -1847,8 +1853,8 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
shouldForceAsFile={shouldForceAsFile}
|
||||
isForCurrentMessageList={isForCurrentMessageList}
|
||||
isForMessage={isInMessageList}
|
||||
shouldSchedule={!paidMessagesStars && isInScheduledList}
|
||||
canSchedule={!paidMessagesStars}
|
||||
shouldSchedule={canSchedule && isInScheduledList}
|
||||
canSchedule={canSchedule}
|
||||
forceDarkTheme={isInStoryViewer}
|
||||
onCaptionUpdate={onCaptionUpdate}
|
||||
onSendSilent={handleSendSilentAttachments}
|
||||
@ -1869,6 +1875,7 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
isOpen={pollModal.isOpen}
|
||||
isQuiz={pollModal.isQuiz}
|
||||
shouldBeAnonymous={isChannel}
|
||||
maxOptionsCount={pollMaxAnswers}
|
||||
onClear={closePollModal}
|
||||
onSend={handlePollSend}
|
||||
/>
|
||||
@ -2304,7 +2311,7 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
{canShowCustomSendMenu && (
|
||||
<CustomSendMenu
|
||||
isOpen={isCustomSendMenuOpen}
|
||||
canSchedule={!paidMessagesStars && isInMessageList && !isViewOnceEnabled}
|
||||
canSchedule={canSchedule && isInMessageList && !isViewOnceEnabled}
|
||||
canScheduleUntilOnline={canScheduleUntilOnline && !isViewOnceEnabled}
|
||||
onSendSilent={!isChatWithSelf ? handleSendSilent : undefined}
|
||||
onSendSchedule={!isInScheduledList ? handleSendScheduled : undefined}
|
||||
@ -2344,6 +2351,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
(global, {
|
||||
chatId, threadId, storyId, messageListType, isMobile, type,
|
||||
}): StateProps => {
|
||||
const appConfig = global.appConfig;
|
||||
const chat = selectChat(global, chatId);
|
||||
const chatBot = !isSystemBot(chatId) ? selectBot(global, chatId) : undefined;
|
||||
const isChatWithBot = Boolean(chatBot);
|
||||
@ -2514,6 +2522,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
isAccountFrozen,
|
||||
isAppConfigLoaded,
|
||||
insertingPeerIdMention,
|
||||
pollMaxAnswers: appConfig?.pollMaxAnswers,
|
||||
};
|
||||
},
|
||||
)(Composer));
|
||||
|
||||
@ -90,11 +90,11 @@ const DeleteMessageModal: FC<OwnProps & StateProps> = ({
|
||||
contactName,
|
||||
willDeleteForCurrentUserOnly,
|
||||
willDeleteForAll,
|
||||
onConfirm,
|
||||
chatBot,
|
||||
adminMembersById,
|
||||
canBanUsers,
|
||||
linkedChatId,
|
||||
onConfirm,
|
||||
}) => {
|
||||
const {
|
||||
closeDeleteMessageModal,
|
||||
@ -130,7 +130,11 @@ const DeleteMessageModal: FC<OwnProps & StateProps> = ({
|
||||
const global = getGlobal();
|
||||
const senderArray = getSendersFromSelectedMessages(global, chat.id, messageIds);
|
||||
return senderArray ? unique(senderArray)
|
||||
.filter((peer) => peer?.id !== chat?.id && peer?.id !== linkedChatId) : MEMO_EMPTY_ARRAY;
|
||||
.filter((peer) => (
|
||||
peer?.id !== chat?.id
|
||||
&& peer?.id !== linkedChatId
|
||||
&& peer?.id !== chat?.linkedMonoforumId
|
||||
)) : MEMO_EMPTY_ARRAY;
|
||||
}, [chat, isChannel, linkedChatId, messageIds]);
|
||||
|
||||
const buildNestedOptionListWithAvatars = useLastCallback(() => {
|
||||
@ -144,16 +148,24 @@ const DeleteMessageModal: FC<OwnProps & StateProps> = ({
|
||||
});
|
||||
|
||||
const peerListToDeleteAll = useMemo(() => {
|
||||
return peerList.filter((peer) => peer.id !== linkedChatId && peer.id !== currentUserId);
|
||||
}, [peerList, currentUserId, linkedChatId]);
|
||||
return peerList.filter((peer) => (
|
||||
peer.id !== linkedChatId
|
||||
&& peer.id !== chat?.linkedMonoforumId
|
||||
&& peer.id !== currentUserId
|
||||
));
|
||||
}, [peerList, currentUserId, linkedChatId, chat?.linkedMonoforumId]);
|
||||
|
||||
const peerListToReportSpam = useMemo(() => {
|
||||
return peerList.filter((peer) => peer.id !== currentUserId && peer.id !== linkedChatId);
|
||||
}, [peerList, currentUserId, linkedChatId]);
|
||||
return peerList.filter((peer) => (
|
||||
peer.id !== currentUserId
|
||||
&& peer.id !== linkedChatId
|
||||
&& peer.id !== chat?.linkedMonoforumId
|
||||
));
|
||||
}, [peerList, currentUserId, linkedChatId, chat?.linkedMonoforumId]);
|
||||
|
||||
const peerListToBan = useMemo(() => {
|
||||
const isCurrentUserInList = peerList.some((peer) => peer.id === currentUserId);
|
||||
const shouldReturnEmpty = !canBanUsers || isCurrentUserInList;
|
||||
const shouldReturnEmpty = !canBanUsers || isCurrentUserInList || chat?.isMonoforum;
|
||||
|
||||
if (shouldReturnEmpty) {
|
||||
return MEMO_EMPTY_ARRAY;
|
||||
@ -163,7 +175,7 @@ const DeleteMessageModal: FC<OwnProps & StateProps> = ({
|
||||
const isAdmin = adminMembersById?.[peer.id];
|
||||
return isCreator || !isAdmin;
|
||||
});
|
||||
}, [peerList, isCreator, currentUserId, canBanUsers, adminMembersById]);
|
||||
}, [peerList, isCreator, currentUserId, canBanUsers, adminMembersById, chat?.isMonoforum]);
|
||||
|
||||
const shouldShowAdditionalOptions = useMemo(() => {
|
||||
return Boolean(peerListToDeleteAll.length || peerListToReportSpam.length || peerListToBan.length);
|
||||
@ -184,11 +196,12 @@ const DeleteMessageModal: FC<OwnProps & StateProps> = ({
|
||||
label: oldLang('ReportSpamTitle'),
|
||||
nestedOptions: messageIds && peerList.length >= 2 ? [
|
||||
...buildNestedOptionListWithAvatars().filter((opt) => opt.value !== linkedChatId
|
||||
&& opt.value !== chat?.linkedMonoforumId
|
||||
&& opt.value !== currentUserId),
|
||||
] : undefined,
|
||||
},
|
||||
];
|
||||
}, [messageIds, peerList, oldLang, linkedChatId, currentUserId]);
|
||||
}, [messageIds, peerList, oldLang, linkedChatId, chat?.linkedMonoforumId, currentUserId]);
|
||||
|
||||
const ACTION_DELETE_OPTION: IRadioOption[] = useMemo(() => {
|
||||
return [
|
||||
@ -199,11 +212,12 @@ const DeleteMessageModal: FC<OwnProps & StateProps> = ({
|
||||
: oldLang('DeleteAllFrom', Object.values(peerNames)[0]),
|
||||
nestedOptions: messageIds && peerList.length >= 2 ? [
|
||||
...buildNestedOptionListWithAvatars().filter((opt) => opt.value !== linkedChatId
|
||||
&& opt.value !== chat?.linkedMonoforumId
|
||||
&& opt.value !== currentUserId),
|
||||
] : undefined,
|
||||
},
|
||||
];
|
||||
}, [messageIds, peerList, oldLang, peerNames, linkedChatId, currentUserId]);
|
||||
}, [messageIds, peerList, oldLang, peerNames, linkedChatId, chat?.linkedMonoforumId, currentUserId]);
|
||||
|
||||
const ACTION_BAN_OPTION: IRadioOption[] = useMemo(() => {
|
||||
return [
|
||||
@ -279,7 +293,7 @@ const DeleteMessageModal: FC<OwnProps & StateProps> = ({
|
||||
if (isSchedule) {
|
||||
deleteScheduledMessages({ messageIds });
|
||||
} else if (shouldShowOption) {
|
||||
if (peerIdsToReportSpam) {
|
||||
if (peerIdsToReportSpam?.length) {
|
||||
const global = getGlobal();
|
||||
const peerIdList = peerIdsToReportSpam.filter((option) => !Number.isNaN(Number(option)));
|
||||
const messageList = messageIds.reduce<Record<string, number[]>>((acc, msgId) => {
|
||||
@ -296,24 +310,24 @@ const DeleteMessageModal: FC<OwnProps & StateProps> = ({
|
||||
handleReportSpam(messageList);
|
||||
}
|
||||
|
||||
if (peerIdsToDeleteAll) {
|
||||
if (peerIdsToDeleteAll?.length) {
|
||||
const peerIdList = peerIdsToDeleteAll.filter((option) => !Number.isNaN(Number(option)));
|
||||
handleDeleteAllPeerMessages(peerIdList);
|
||||
}
|
||||
|
||||
if (peerIdsToBan && !havePermissionChanged) {
|
||||
if (peerIdsToBan?.length && !havePermissionChanged) {
|
||||
const peerIdList = peerIdsToBan.filter((option) => !Number.isNaN(Number(option)));
|
||||
handleDeleteMember(peerIdList);
|
||||
const filteredMessageIdList = filterMessageIdByPeerId(peerIdList, messageIds);
|
||||
handleDeleteMessages(filteredMessageIdList);
|
||||
}
|
||||
|
||||
if (peerIdsToBan && havePermissionChanged) {
|
||||
if (peerIdsToBan?.length && havePermissionChanged) {
|
||||
const peerIdList = peerIdsToBan.filter((option) => !Number.isNaN(Number(option)));
|
||||
handleUpdateChatMemberBannedRights(peerIdList);
|
||||
}
|
||||
|
||||
if (!peerIdsToReportSpam || !peerIdsToDeleteAll || !peerIdsToBan) {
|
||||
if (!peerIdsToReportSpam?.length || !peerIdsToDeleteAll?.length || !peerIdsToBan?.length) {
|
||||
deleteMessages({ messageIds, shouldDeleteForAll });
|
||||
}
|
||||
} else {
|
||||
@ -426,21 +440,19 @@ const DeleteMessageModal: FC<OwnProps & StateProps> = ({
|
||||
<p className={styles.actionTitle}>{oldLang('DeleteAdditionalActions')}</p>
|
||||
{renderAdditionalActionOptions()}
|
||||
{renderPartiallyRestrictedUser()}
|
||||
{
|
||||
peerIdsToBan && canBanUsers ? (
|
||||
<ListItem
|
||||
narrow
|
||||
buttonClassName={styles.button}
|
||||
onClick={toggleAdditionalOptions}
|
||||
>
|
||||
{oldLang(isAdditionalOptionsVisible ? 'DeleteToggleBanUsers' : 'DeleteToggleRestrictUsers')}
|
||||
<Icon
|
||||
name={isAdditionalOptionsVisible ? 'up' : 'down'}
|
||||
className={buildClassName(styles.button, 'ml-2')}
|
||||
/>
|
||||
</ListItem>
|
||||
) : setIsAdditionalOptionsVisible(false)
|
||||
}
|
||||
{peerIdsToBan?.length && canBanUsers ? (
|
||||
<ListItem
|
||||
narrow
|
||||
buttonClassName={styles.button}
|
||||
onClick={toggleAdditionalOptions}
|
||||
>
|
||||
{oldLang(isAdditionalOptionsVisible ? 'DeleteToggleBanUsers' : 'DeleteToggleRestrictUsers')}
|
||||
<Icon
|
||||
name={isAdditionalOptionsVisible ? 'up' : 'down'}
|
||||
className={buildClassName(styles.button, 'ml-2')}
|
||||
/>
|
||||
</ListItem>
|
||||
) : setIsAdditionalOptionsVisible(false)}
|
||||
</>
|
||||
)}
|
||||
{(canDeleteForAll || chatBot || !shouldShowOption) && (
|
||||
|
||||
@ -38,3 +38,15 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.monoforumBadge {
|
||||
padding: 0.125rem 0.25rem;
|
||||
border-radius: 0.25rem;
|
||||
|
||||
font-size: 0.625rem;
|
||||
font-weight: 500;
|
||||
line-height: 1;
|
||||
color: var(--color-white);
|
||||
|
||||
background-color: var(--color-gray);
|
||||
}
|
||||
|
||||
@ -24,6 +24,7 @@ import { copyTextToClipboard } from '../../util/clipboard';
|
||||
import stopEvent from '../../util/stopEvent';
|
||||
import renderText from './helpers/renderText';
|
||||
|
||||
import useLang from '../../hooks/useLang';
|
||||
import useLastCallback from '../../hooks/useLastCallback';
|
||||
import useOldLang from '../../hooks/useOldLang';
|
||||
|
||||
@ -44,12 +45,14 @@ type OwnProps = {
|
||||
emojiStatusSize?: number;
|
||||
isSavedMessages?: boolean;
|
||||
isSavedDialog?: boolean;
|
||||
isMonoforum?: boolean;
|
||||
monoforumBadgeClassName?: string;
|
||||
noLoopLimit?: boolean;
|
||||
canCopyTitle?: boolean;
|
||||
iconElement?: React.ReactNode;
|
||||
statusSparklesColor?: string;
|
||||
onEmojiStatusClick?: NoneToVoidFunction;
|
||||
observeIntersection?: ObserveFn;
|
||||
statusSparklesColor?: string;
|
||||
};
|
||||
|
||||
const FullNameTitle: FC<OwnProps> = ({
|
||||
@ -65,15 +68,20 @@ const FullNameTitle: FC<OwnProps> = ({
|
||||
canCopyTitle,
|
||||
iconElement,
|
||||
statusSparklesColor,
|
||||
isMonoforum,
|
||||
monoforumBadgeClassName,
|
||||
onEmojiStatusClick,
|
||||
observeIntersection,
|
||||
}) => {
|
||||
const lang = useOldLang();
|
||||
const { showNotification } = getActions();
|
||||
|
||||
const oldLang = useOldLang();
|
||||
const lang = useLang();
|
||||
|
||||
const realPeer = 'id' in peer ? peer : undefined;
|
||||
const customPeer = 'isCustomPeer' in peer ? peer : undefined;
|
||||
const isUser = realPeer && isApiPeerUser(realPeer);
|
||||
const title = realPeer && (isUser ? getUserFullName(realPeer) : getChatTitle(lang, realPeer));
|
||||
const title = realPeer && (isUser ? getUserFullName(realPeer) : getChatTitle(oldLang, realPeer));
|
||||
const isPremium = (isUser && realPeer.isPremium) || customPeer?.isPremium;
|
||||
const canShowEmojiStatus = withEmojiStatus && !isSavedMessages;
|
||||
const emojiStatus = realPeer?.emojiStatus
|
||||
@ -91,27 +99,27 @@ const FullNameTitle: FC<OwnProps> = ({
|
||||
|
||||
const specialTitle = useMemo(() => {
|
||||
if (customPeer) {
|
||||
return renderText(customPeer.title || lang(customPeer.titleKey!));
|
||||
return renderText(customPeer.title || oldLang(customPeer.titleKey!));
|
||||
}
|
||||
|
||||
if (isSavedMessages) {
|
||||
return lang(isSavedDialog ? 'MyNotes' : 'SavedMessages');
|
||||
return oldLang(isSavedDialog ? 'MyNotes' : 'SavedMessages');
|
||||
}
|
||||
|
||||
if (isAnonymousForwardsChat(realPeer!.id)) {
|
||||
return lang('AnonymousForward');
|
||||
return oldLang('AnonymousForward');
|
||||
}
|
||||
|
||||
if (isChatWithRepliesBot(realPeer!.id)) {
|
||||
return lang('RepliesTitle');
|
||||
return oldLang('RepliesTitle');
|
||||
}
|
||||
|
||||
if (isChatWithVerificationCodesBot(realPeer!.id)) {
|
||||
return lang('VerifyCodesNotifications');
|
||||
return oldLang('VerifyCodesNotifications');
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}, [customPeer, isSavedDialog, isSavedMessages, lang, realPeer]);
|
||||
}, [customPeer, isSavedDialog, isSavedMessages, oldLang, realPeer]);
|
||||
const botVerificationIconId = realPeer?.botVerificationIconId;
|
||||
|
||||
return (
|
||||
@ -164,6 +172,11 @@ const FullNameTitle: FC<OwnProps> = ({
|
||||
</Transition>
|
||||
)}
|
||||
{canShowEmojiStatus && !emojiStatus && isPremium && <StarIcon />}
|
||||
{isMonoforum && (
|
||||
<div className={buildClassName(styles.monoforumBadge, monoforumBadgeClassName)}>
|
||||
{lang('MonoforumBadge')}
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{iconElement}
|
||||
|
||||
@ -19,6 +19,7 @@ import {
|
||||
selectChat,
|
||||
selectChatMessages,
|
||||
selectChatOnlineCount,
|
||||
selectMonoforumChannel,
|
||||
selectThreadInfo,
|
||||
selectThreadMessagesCount,
|
||||
selectTopic,
|
||||
@ -28,6 +29,7 @@ import buildClassName from '../../util/buildClassName';
|
||||
import { REM } from './helpers/mediaDimensions';
|
||||
import renderText from './helpers/renderText';
|
||||
|
||||
import useLang from '../../hooks/useLang';
|
||||
import useLastCallback from '../../hooks/useLastCallback';
|
||||
import useOldLang from '../../hooks/useOldLang';
|
||||
|
||||
@ -63,20 +65,21 @@ type OwnProps = {
|
||||
withStory?: boolean;
|
||||
storyViewerOrigin?: StoryViewerOrigin;
|
||||
isSavedDialog?: boolean;
|
||||
withMonoforumStatus?: boolean;
|
||||
onClick?: VoidFunction;
|
||||
onEmojiStatusClick?: NoneToVoidFunction;
|
||||
};
|
||||
|
||||
type StateProps =
|
||||
{
|
||||
chat?: ApiChat;
|
||||
threadInfo?: ApiThreadInfo;
|
||||
topic?: ApiTopic;
|
||||
onlineCount?: number;
|
||||
areMessagesLoaded: boolean;
|
||||
messagesCount?: number;
|
||||
self?: ApiUser;
|
||||
};
|
||||
type StateProps = {
|
||||
chat?: ApiChat;
|
||||
threadInfo?: ApiThreadInfo;
|
||||
topic?: ApiTopic;
|
||||
onlineCount?: number;
|
||||
areMessagesLoaded: boolean;
|
||||
messagesCount?: number;
|
||||
self?: ApiUser;
|
||||
monoforumChannel?: ApiChat;
|
||||
};
|
||||
|
||||
const GroupChatInfo: FC<OwnProps & StateProps> = ({
|
||||
typingStatus,
|
||||
@ -93,7 +96,7 @@ const GroupChatInfo: FC<OwnProps & StateProps> = ({
|
||||
withChatType,
|
||||
threadInfo,
|
||||
noRtl,
|
||||
chat,
|
||||
chat: realChat,
|
||||
onlineCount,
|
||||
areMessagesLoaded,
|
||||
topic,
|
||||
@ -105,6 +108,8 @@ const GroupChatInfo: FC<OwnProps & StateProps> = ({
|
||||
emojiStatusSize,
|
||||
isSavedDialog,
|
||||
self,
|
||||
withMonoforumStatus,
|
||||
monoforumChannel,
|
||||
onClick,
|
||||
onEmojiStatusClick,
|
||||
}) => {
|
||||
@ -114,7 +119,10 @@ const GroupChatInfo: FC<OwnProps & StateProps> = ({
|
||||
loadMoreProfilePhotos,
|
||||
} = getActions();
|
||||
|
||||
const lang = useOldLang();
|
||||
const chat = !withMonoforumStatus && monoforumChannel ? monoforumChannel : realChat;
|
||||
|
||||
const oldLang = useOldLang();
|
||||
const lang = useLang();
|
||||
|
||||
const isSuperGroup = chat && isChatSuperGroup(chat);
|
||||
const isTopic = Boolean(chat?.isForum && threadInfo && topic);
|
||||
@ -148,6 +156,24 @@ const GroupChatInfo: FC<OwnProps & StateProps> = ({
|
||||
}
|
||||
|
||||
function renderStatusOrTyping() {
|
||||
if (withUpdatingStatus && !areMessagesLoaded && !isRestricted) {
|
||||
return (
|
||||
<DotAnimation className="status" content={oldLang('Updating')} />
|
||||
);
|
||||
}
|
||||
|
||||
if (withMonoforumStatus) {
|
||||
return (
|
||||
<span className="status" dir="auto">
|
||||
{lang('MonoforumStatus')}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
if (realChat?.isMonoforum) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (status) {
|
||||
return withDots ? (
|
||||
<DotAnimation className="status" content={status} />
|
||||
@ -159,12 +185,6 @@ const GroupChatInfo: FC<OwnProps & StateProps> = ({
|
||||
);
|
||||
}
|
||||
|
||||
if (withUpdatingStatus && !areMessagesLoaded && !isRestricted) {
|
||||
return (
|
||||
<DotAnimation className="status" content={lang('Updating')} />
|
||||
);
|
||||
}
|
||||
|
||||
if (!chat) {
|
||||
return undefined;
|
||||
}
|
||||
@ -182,7 +202,7 @@ const GroupChatInfo: FC<OwnProps & StateProps> = ({
|
||||
activeKey={messagesCount !== undefined ? 1 : 2}
|
||||
className="message-count-transition"
|
||||
>
|
||||
{messagesCount !== undefined && lang('messages', messagesCount, 'i')}
|
||||
{messagesCount !== undefined && oldLang('messages', messagesCount, 'i')}
|
||||
</Transition>
|
||||
</span>
|
||||
);
|
||||
@ -190,12 +210,12 @@ const GroupChatInfo: FC<OwnProps & StateProps> = ({
|
||||
|
||||
if (withChatType) {
|
||||
return (
|
||||
<span className="status" dir="auto">{lang(getChatTypeString(chat))}</span>
|
||||
<span className="status" dir="auto">{oldLang(getChatTypeString(chat))}</span>
|
||||
);
|
||||
}
|
||||
|
||||
const groupStatus = getGroupStatus(lang, chat);
|
||||
const onlineStatus = onlineCount ? `, ${lang('OnlineCount', onlineCount, 'i')}` : undefined;
|
||||
const groupStatus = getGroupStatus(oldLang, chat);
|
||||
const onlineStatus = onlineCount ? `, ${oldLang('OnlineCount', onlineCount, 'i')}` : undefined;
|
||||
|
||||
return (
|
||||
<span className="status">
|
||||
@ -211,7 +231,7 @@ const GroupChatInfo: FC<OwnProps & StateProps> = ({
|
||||
className={
|
||||
buildClassName('ChatInfo', className)
|
||||
}
|
||||
dir={!noRtl && lang.isRtl ? 'rtl' : undefined}
|
||||
dir={!noRtl && oldLang.isRtl ? 'rtl' : undefined}
|
||||
onClick={onClick}
|
||||
>
|
||||
{!noAvatar && !isTopic && (
|
||||
@ -231,6 +251,7 @@ const GroupChatInfo: FC<OwnProps & StateProps> = ({
|
||||
size={avatarSize}
|
||||
peer={chat}
|
||||
withStory={withStory}
|
||||
asMessageBubble={Boolean(monoforumChannel)}
|
||||
storyViewerOrigin={storyViewerOrigin}
|
||||
storyViewerMode="single-peer"
|
||||
isSavedDialog={isSavedDialog}
|
||||
@ -251,6 +272,7 @@ const GroupChatInfo: FC<OwnProps & StateProps> = ({
|
||||
: (
|
||||
<FullNameTitle
|
||||
peer={chat}
|
||||
isMonoforum={!withMonoforumStatus && Boolean(monoforumChannel)}
|
||||
emojiStatusSize={emojiStatusSize}
|
||||
withEmojiStatus={!noEmojiStatus}
|
||||
isSavedDialog={isSavedDialog}
|
||||
@ -272,6 +294,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
const topic = threadId ? selectTopic(global, chatId, threadId) : undefined;
|
||||
const messagesCount = topic && selectThreadMessagesCount(global, chatId, threadId!);
|
||||
const self = selectUser(global, global.currentUserId!);
|
||||
const monoforumChannel = selectMonoforumChannel(global, chatId);
|
||||
|
||||
return {
|
||||
chat,
|
||||
@ -281,6 +304,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
areMessagesLoaded,
|
||||
messagesCount,
|
||||
self,
|
||||
monoforumChannel,
|
||||
};
|
||||
},
|
||||
)(GroupChatInfo));
|
||||
|
||||
@ -27,6 +27,7 @@ import { MEMO_EMPTY_ARRAY } from '../../util/memo';
|
||||
import renderText from './helpers/renderText';
|
||||
|
||||
import useIntervalForceUpdate from '../../hooks/schedulers/useIntervalForceUpdate';
|
||||
import useLang from '../../hooks/useLang';
|
||||
import useLastCallback from '../../hooks/useLastCallback';
|
||||
import useOldLang from '../../hooks/useOldLang';
|
||||
import usePreviousDeprecated from '../../hooks/usePreviousDeprecated';
|
||||
@ -45,6 +46,7 @@ type OwnProps = {
|
||||
peerId: string;
|
||||
forceShowSelf?: boolean;
|
||||
canPlayVideo: boolean;
|
||||
isForMonoforum?: boolean;
|
||||
};
|
||||
|
||||
type StateProps =
|
||||
@ -81,6 +83,7 @@ const ProfileInfo: FC<OwnProps & StateProps> = ({
|
||||
emojiStatusSlug,
|
||||
profilePhotos,
|
||||
peerId,
|
||||
isForMonoforum,
|
||||
}) => {
|
||||
const {
|
||||
openMediaViewer,
|
||||
@ -91,7 +94,8 @@ const ProfileInfo: FC<OwnProps & StateProps> = ({
|
||||
openUniqueGiftBySlug,
|
||||
} = getActions();
|
||||
|
||||
const lang = useOldLang();
|
||||
const oldLang = useOldLang();
|
||||
const lang = useLang();
|
||||
|
||||
useIntervalForceUpdate(user ? STATUS_UPDATE_INTERVAL : undefined);
|
||||
|
||||
@ -100,7 +104,7 @@ const ProfileInfo: FC<OwnProps & StateProps> = ({
|
||||
const prevAvatarOwnerId = usePreviousDeprecated(avatarOwnerId);
|
||||
const [hasSlideAnimation, setHasSlideAnimation] = useState(true);
|
||||
// slideOptimized doesn't work well when animation is dynamically disabled
|
||||
const slideAnimation = hasSlideAnimation ? (lang.isRtl ? 'slideRtl' : 'slide') : 'none';
|
||||
const slideAnimation = hasSlideAnimation ? (oldLang.isRtl ? 'slideRtl' : 'slide') : 'none';
|
||||
|
||||
const [currentPhotoIndex, setCurrentPhotoIndex] = useState(0);
|
||||
const isFirst = photos.length <= 1 || currentPhotoIndex === 0;
|
||||
@ -217,9 +221,9 @@ const ProfileInfo: FC<OwnProps & StateProps> = ({
|
||||
letterClassName={styles.topicIconTitle}
|
||||
noLoopLimit
|
||||
/>
|
||||
<h3 className={styles.topicTitle} dir={lang.isRtl ? 'rtl' : undefined}>{renderText(topic!.title)}</h3>
|
||||
<h3 className={styles.topicTitle} dir={oldLang.isRtl ? 'rtl' : undefined}>{renderText(topic!.title)}</h3>
|
||||
<p className={styles.topicMessagesCounter}>
|
||||
{messagesCount ? lang('Chat.Title.Topic', messagesCount, 'i') : lang('lng_forum_no_messages')}
|
||||
{messagesCount ? oldLang('Chat.Title.Topic', messagesCount, 'i') : oldLang('lng_forum_no_messages')}
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
@ -265,6 +269,14 @@ const ProfileInfo: FC<OwnProps & StateProps> = ({
|
||||
const isSystemBotChat = isSystemBot(peerId);
|
||||
if (isAnonymousForwards || isSystemBotChat) return undefined;
|
||||
|
||||
if (isForMonoforum) {
|
||||
return (
|
||||
<span className={buildClassName(styles.status, 'status')} dir="auto">
|
||||
{lang('MonoforumStatus')}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
if (user) {
|
||||
return (
|
||||
<div
|
||||
@ -275,11 +287,11 @@ const ProfileInfo: FC<OwnProps & StateProps> = ({
|
||||
)}
|
||||
>
|
||||
<span className={styles.userStatus} dir="auto">
|
||||
{getUserStatus(lang, user, userStatus)}
|
||||
{getUserStatus(oldLang, user, userStatus)}
|
||||
</span>
|
||||
{userStatus?.isReadDateRestrictedByMe && (
|
||||
<span className={styles.getStatus} onClick={handleOpenGetReadDateModal}>
|
||||
<span>{lang('StatusHiddenShow')}</span>
|
||||
<span>{oldLang('StatusHiddenShow')}</span>
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
@ -290,8 +302,8 @@ const ProfileInfo: FC<OwnProps & StateProps> = ({
|
||||
<span className={buildClassName(styles.status, 'status')} dir="auto">
|
||||
{
|
||||
isChatChannel(chat!)
|
||||
? lang('Subscribers', chat!.membersCount ?? 0, 'i')
|
||||
: lang('Members', chat!.membersCount ?? 0, 'i')
|
||||
? oldLang('Subscribers', chat!.membersCount ?? 0, 'i')
|
||||
: oldLang('Members', chat!.membersCount ?? 0, 'i')
|
||||
}
|
||||
</span>
|
||||
);
|
||||
@ -304,7 +316,7 @@ const ProfileInfo: FC<OwnProps & StateProps> = ({
|
||||
return (
|
||||
<div
|
||||
className={buildClassName('ProfileInfo')}
|
||||
dir={lang.isRtl ? 'rtl' : undefined}
|
||||
dir={oldLang.isRtl ? 'rtl' : undefined}
|
||||
>
|
||||
<div className={styles.photoWrapper}>
|
||||
{renderPhotoTabs()}
|
||||
@ -315,7 +327,7 @@ const ProfileInfo: FC<OwnProps & StateProps> = ({
|
||||
)}
|
||||
>
|
||||
<div className={styles.fallbackPhotoContents}>
|
||||
{lang(profilePhotos.personalPhoto.isVideo ? 'UserInfo.CustomVideo' : 'UserInfo.CustomPhoto')}
|
||||
{oldLang(profilePhotos.personalPhoto.isVideo ? 'UserInfo.CustomVideo' : 'UserInfo.CustomPhoto')}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@ -333,7 +345,7 @@ const ProfileInfo: FC<OwnProps & StateProps> = ({
|
||||
size="mini"
|
||||
/>
|
||||
)}
|
||||
{lang(profilePhotos.fallbackPhoto.isVideo ? 'UserInfo.PublicVideo' : 'UserInfo.PublicPhoto')}
|
||||
{oldLang(profilePhotos.fallbackPhoto.isVideo ? 'UserInfo.PublicVideo' : 'UserInfo.PublicPhoto')}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@ -344,24 +356,24 @@ const ProfileInfo: FC<OwnProps & StateProps> = ({
|
||||
{!isFirst && (
|
||||
<button
|
||||
type="button"
|
||||
dir={lang.isRtl ? 'rtl' : undefined}
|
||||
dir={oldLang.isRtl ? 'rtl' : undefined}
|
||||
className={buildClassName(styles.navigation, styles.navigation_prev)}
|
||||
aria-label={lang('AccDescrPrevious')}
|
||||
aria-label={oldLang('AccDescrPrevious')}
|
||||
onClick={selectPreviousMedia}
|
||||
/>
|
||||
)}
|
||||
{!isLast && (
|
||||
<button
|
||||
type="button"
|
||||
dir={lang.isRtl ? 'rtl' : undefined}
|
||||
dir={oldLang.isRtl ? 'rtl' : undefined}
|
||||
className={buildClassName(styles.navigation, styles.navigation_next)}
|
||||
aria-label={lang('Next')}
|
||||
aria-label={oldLang('Next')}
|
||||
onClick={selectNextMedia}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className={styles.info} dir={lang.isRtl ? 'rtl' : 'auto'}>
|
||||
<div className={styles.info} dir={oldLang.isRtl ? 'rtl' : 'auto'}>
|
||||
{(user || chat) && (
|
||||
<FullNameTitle
|
||||
peer={(user || chat)!}
|
||||
|
||||
@ -12,7 +12,7 @@ import {
|
||||
} from '../../global/helpers';
|
||||
import { filterPeersByQuery } from '../../global/helpers/peers';
|
||||
import {
|
||||
filterChatIdsByType, selectChat, selectChatFullInfo, selectUser,
|
||||
filterChatIdsByType, selectChat, selectChatFullInfo, selectIsMonoforumAdmin, selectUser,
|
||||
} from '../../global/selectors';
|
||||
import { unique } from '../../util/iteratees';
|
||||
import sortChatIds from './helpers/sortChatIds';
|
||||
@ -77,9 +77,15 @@ const RecipientPicker: FC<OwnProps & StateProps> = ({
|
||||
const user = selectUser(global, id);
|
||||
if (user && !isDeletedUser(user)) return true;
|
||||
|
||||
const chatFullInfo = selectChatFullInfo(global, id);
|
||||
if (!chat) return false;
|
||||
|
||||
return chat && (!chatFullInfo || getCanPostInChat(chat, undefined, undefined, chatFullInfo));
|
||||
if (chat.isMonoforum && selectIsMonoforumAdmin(global, id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const chatFullInfo = selectChatFullInfo(global, id);
|
||||
// TODO: Handle bulk check with API call
|
||||
return !chatFullInfo || getCanPostInChat(chat, undefined, undefined, chatFullInfo);
|
||||
});
|
||||
|
||||
const sorted = sortChatIds(
|
||||
|
||||
@ -10,6 +10,7 @@ import type { MessageList } from '../../types';
|
||||
import { EMOJI_SIZE_MODAL, STICKER_SIZE_MODAL, TME_LINK_PREFIX } from '../../config';
|
||||
import { getAllowedAttachmentOptions, getCanPostInChat } from '../../global/helpers';
|
||||
import {
|
||||
selectBot,
|
||||
selectCanScheduleUntilOnline,
|
||||
selectChat,
|
||||
selectChatFullInfo,
|
||||
@ -261,7 +262,12 @@ export default memo(withGlobal<OwnProps>(
|
||||
const { chatId, threadId } = currentMessageList || {};
|
||||
const chat = chatId && selectChat(global, chatId);
|
||||
const chatFullInfo = chatId ? selectChatFullInfo(global, chatId) : undefined;
|
||||
const sendOptions = chat ? getAllowedAttachmentOptions(chat, chatFullInfo) : undefined;
|
||||
const chatBot = chatId && selectBot(global, chatId);
|
||||
const isSavedMessages = chatId ? selectIsChatWithSelf(global, chatId) : undefined;
|
||||
|
||||
const sendOptions = chat
|
||||
? getAllowedAttachmentOptions(chat, chatFullInfo, Boolean(chatBot), isSavedMessages)
|
||||
: undefined;
|
||||
const threadInfo = chatId && threadId ? selectThreadInfo(global, chatId, threadId) : undefined;
|
||||
const isMessageThread = Boolean(!threadInfo?.isCommentsInfo && threadInfo?.fromChannelId);
|
||||
const topic = chatId && threadId ? selectTopic(global, chatId, threadId) : undefined;
|
||||
@ -269,7 +275,6 @@ export default memo(withGlobal<OwnProps>(
|
||||
chat && threadId && getCanPostInChat(chat, topic, isMessageThread, chatFullInfo)
|
||||
&& sendOptions?.canSendStickers,
|
||||
);
|
||||
const isSavedMessages = Boolean(chatId) && selectIsChatWithSelf(global, chatId);
|
||||
|
||||
const stickerSetInfo = fromSticker ? fromSticker.stickerSetInfo
|
||||
: stickerSetShortName ? { shortName: stickerSetShortName } : undefined;
|
||||
|
||||
@ -14,7 +14,7 @@ import {
|
||||
getCanPostInChat, getGroupStatus, getUserStatus, isUserOnline,
|
||||
} from '../../../global/helpers';
|
||||
import { isApiPeerChat } from '../../../global/helpers/peers';
|
||||
import { selectPeer, selectTopics, selectUserStatus } from '../../../global/selectors';
|
||||
import { selectMonoforumChannel, selectPeer, selectTopics, selectUserStatus } from '../../../global/selectors';
|
||||
import buildClassName from '../../../util/buildClassName';
|
||||
import { REM } from '../helpers/mediaDimensions';
|
||||
import renderText from '../helpers/renderText';
|
||||
@ -47,12 +47,12 @@ export type OwnProps = {
|
||||
searchPlaceholder: string;
|
||||
search: string;
|
||||
className?: string;
|
||||
isLowStackPriority?: boolean;
|
||||
loadMore?: NoneToVoidFunction;
|
||||
onSearchChange: (search: string) => void;
|
||||
onSelectChatOrUser: (chatOrUserId: string, threadId?: ThreadId) => void;
|
||||
onClose: NoneToVoidFunction;
|
||||
onCloseAnimationEnd?: NoneToVoidFunction;
|
||||
isLowStackPriority?: boolean;
|
||||
};
|
||||
|
||||
const CHAT_LIST_SLIDE = 0;
|
||||
@ -77,7 +77,7 @@ const ChatOrUserPicker: FC<OwnProps> = ({
|
||||
}) => {
|
||||
const { loadTopics } = getActions();
|
||||
|
||||
const lang = useOldLang();
|
||||
const oldLang = useOldLang();
|
||||
const containerRef = useRef<HTMLDivElement>();
|
||||
const topicContainerRef = useRef<HTMLDivElement>();
|
||||
const searchRef = useRef<HTMLInputElement>();
|
||||
@ -181,23 +181,28 @@ const ChatOrUserPicker: FC<OwnProps> = ({
|
||||
|
||||
const renderChatItem = useCallback((id: string, index: number) => {
|
||||
const global = getGlobal();
|
||||
const peer = selectPeer(global, id);
|
||||
let peer = selectPeer(global, id);
|
||||
if (!peer) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const monoforumChannel = selectMonoforumChannel(global, id);
|
||||
if (monoforumChannel) {
|
||||
peer = monoforumChannel;
|
||||
}
|
||||
|
||||
const isSelf = peer && !isApiPeerChat(peer) ? peer.isSelf : undefined;
|
||||
|
||||
function getSubtitle() {
|
||||
if (!peer) return undefined;
|
||||
if (peer.id === currentUserId) return [lang('SavedMessagesInfo')];
|
||||
if (peer.id === currentUserId) return [oldLang('SavedMessagesInfo')];
|
||||
if (isApiPeerChat(peer)) {
|
||||
return [getGroupStatus(lang, peer)];
|
||||
return [getGroupStatus(oldLang, peer)];
|
||||
}
|
||||
|
||||
const userStatus = selectUserStatus(global, peer.id);
|
||||
return [
|
||||
getUserStatus(lang, peer, userStatus),
|
||||
getUserStatus(oldLang, peer, userStatus),
|
||||
buildClassName(isUserOnline(peer, userStatus, true) && 'online'),
|
||||
];
|
||||
}
|
||||
@ -208,10 +213,20 @@ const ChatOrUserPicker: FC<OwnProps> = ({
|
||||
<PickerItem
|
||||
key={id}
|
||||
className={ITEM_CLASS_NAME}
|
||||
title={<FullNameTitle peer={peer} isSavedMessages={isSelf} />}
|
||||
title={(
|
||||
<div className="title-wrapper">
|
||||
<FullNameTitle
|
||||
className="item-title"
|
||||
peer={peer}
|
||||
isMonoforum={Boolean(monoforumChannel)}
|
||||
isSavedMessages={isSelf}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
avatarElement={(
|
||||
<Avatar
|
||||
peer={peer}
|
||||
asMessageBubble={Boolean(monoforumChannel)}
|
||||
isSavedMessages={isSelf}
|
||||
size="medium"
|
||||
/>
|
||||
@ -224,13 +239,13 @@ const ChatOrUserPicker: FC<OwnProps> = ({
|
||||
onClick={() => handleClick(id)}
|
||||
/>
|
||||
);
|
||||
}, [currentUserId, lang, viewportOffset]);
|
||||
}, [currentUserId, oldLang, viewportOffset]);
|
||||
|
||||
function renderTopicList() {
|
||||
return (
|
||||
<>
|
||||
<div className="modal-header" dir={lang.isRtl ? 'rtl' : undefined}>
|
||||
<Button round color="translucent" size="smaller" ariaLabel={lang('Back')} onClick={handleHeaderBackClick}>
|
||||
<div className="modal-header" dir={oldLang.isRtl ? 'rtl' : undefined}>
|
||||
<Button round color="translucent" size="smaller" ariaLabel={oldLang('Back')} onClick={handleHeaderBackClick}>
|
||||
<Icon name="arrow-left" />
|
||||
</Button>
|
||||
<InputText
|
||||
@ -276,12 +291,12 @@ const ChatOrUserPicker: FC<OwnProps> = ({
|
||||
function renderChatList() {
|
||||
return (
|
||||
<>
|
||||
<div className="modal-header" dir={lang.isRtl ? 'rtl' : undefined}>
|
||||
<div className="modal-header" dir={oldLang.isRtl ? 'rtl' : undefined}>
|
||||
<Button
|
||||
round
|
||||
color="translucent"
|
||||
size="smaller"
|
||||
ariaLabel={lang('Close')}
|
||||
ariaLabel={oldLang('Close')}
|
||||
onClick={onClose}
|
||||
>
|
||||
<Icon name="close" />
|
||||
@ -308,7 +323,7 @@ const ChatOrUserPicker: FC<OwnProps> = ({
|
||||
{viewportIds.map(renderChatItem)}
|
||||
</InfiniteScroll>
|
||||
) : viewportIds && !viewportIds.length ? (
|
||||
<p className="no-results">{lang('lng_blocked_list_not_found')}</p>
|
||||
<p className="no-results">{oldLang('lng_blocked_list_not_found')}</p>
|
||||
) : (
|
||||
<Loading />
|
||||
)}
|
||||
|
||||
@ -438,6 +438,11 @@
|
||||
.avatar-badge-wrapper .ChatBadge:not(.pinned).muted {
|
||||
background: var(--color-gray);
|
||||
}
|
||||
|
||||
.monoforum-badge {
|
||||
color: var(--color-chat-active);
|
||||
background-color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -35,6 +35,7 @@ import {
|
||||
selectIsCurrentUserFrozen,
|
||||
selectIsForumPanelClosed,
|
||||
selectIsForumPanelOpen,
|
||||
selectMonoforumChannel,
|
||||
selectNotifyDefaults,
|
||||
selectNotifyException,
|
||||
selectOutgoingStatus,
|
||||
@ -94,6 +95,7 @@ type OwnProps = {
|
||||
|
||||
type StateProps = {
|
||||
chat?: ApiChat;
|
||||
monoforumChannel?: ApiChat;
|
||||
lastMessageStory?: ApiTypeStory;
|
||||
listedTopicIds?: number[];
|
||||
topics?: Record<number, ApiTopic>;
|
||||
@ -128,6 +130,7 @@ const Chat: FC<OwnProps & StateProps> = ({
|
||||
topics,
|
||||
observeIntersection,
|
||||
chat,
|
||||
monoforumChannel,
|
||||
lastMessageStory,
|
||||
isMuted,
|
||||
user,
|
||||
@ -177,7 +180,7 @@ const Chat: FC<OwnProps & StateProps> = ({
|
||||
const [shouldRenderMuteModal, markRenderMuteModal, unmarkRenderMuteModal] = useFlag();
|
||||
const [shouldRenderChatFolderModal, markRenderChatFolderModal, unmarkRenderChatFolderModal] = useFlag();
|
||||
|
||||
const { isForum, isForumAsMessages } = chat || {};
|
||||
const { isForum, isForumAsMessages, isMonoforum } = chat || {};
|
||||
|
||||
useEnsureMessage(isSavedDialog ? currentUserId : chatId, lastMessageId, lastMessage);
|
||||
|
||||
@ -355,11 +358,12 @@ const Chat: FC<OwnProps & StateProps> = ({
|
||||
>
|
||||
<div className={buildClassName('status', 'status-clickable')}>
|
||||
<Avatar
|
||||
peer={peer}
|
||||
peer={isMonoforum ? monoforumChannel : peer}
|
||||
isSavedMessages={user?.isSelf}
|
||||
isSavedDialog={isSavedDialog}
|
||||
size={isPreview ? 'medium' : 'large'}
|
||||
withStory={!user?.isSelf}
|
||||
asMessageBubble={isMonoforum}
|
||||
withStory={!user?.isSelf && !isMonoforum}
|
||||
withStoryGap={isAvatarOnlineShown || Boolean(chat.subscriptionUntil)}
|
||||
storyViewerOrigin={StoryViewerOrigin.ChatList}
|
||||
storyViewerMode="single-peer"
|
||||
@ -387,7 +391,9 @@ const Chat: FC<OwnProps & StateProps> = ({
|
||||
<div className="info">
|
||||
<div className="info-row">
|
||||
<FullNameTitle
|
||||
peer={peer}
|
||||
peer={isMonoforum ? monoforumChannel! : peer}
|
||||
isMonoforum={isMonoforum}
|
||||
monoforumBadgeClassName="monoforum-badge"
|
||||
withEmojiStatus
|
||||
isSavedMessages={chatId === user?.id && user?.isSelf}
|
||||
isSavedDialog={isSavedDialog}
|
||||
@ -489,6 +495,8 @@ export default memo(withGlobal<OwnProps>(
|
||||
const lastMessageStory = storyData && selectPeerStory(global, storyData.peerId, storyData.id);
|
||||
const isAccountFrozen = selectIsCurrentUserFrozen(global);
|
||||
|
||||
const monoforumChannel = selectMonoforumChannel(global, chatId);
|
||||
|
||||
return {
|
||||
chat,
|
||||
isMuted: getIsChatMuted(chat, selectNotifyDefaults(global), selectNotifyException(global, chat.id)),
|
||||
@ -515,6 +523,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
isSynced: global.isSynced,
|
||||
lastMessageStory,
|
||||
isAccountFrozen,
|
||||
monoforumChannel,
|
||||
};
|
||||
},
|
||||
)(Chat));
|
||||
|
||||
@ -74,6 +74,7 @@ interface StateProps {
|
||||
canLeave?: boolean;
|
||||
canEnterVoiceChat?: boolean;
|
||||
canCreateVoiceChat?: boolean;
|
||||
channelMonoforumId?: string;
|
||||
pendingJoinRequests?: number;
|
||||
shouldJoinToSend?: boolean;
|
||||
shouldSendJoinRequest?: boolean;
|
||||
@ -110,6 +111,7 @@ const HeaderActions: FC<OwnProps & StateProps> = ({
|
||||
canLeave,
|
||||
canEnterVoiceChat,
|
||||
canCreateVoiceChat,
|
||||
channelMonoforumId,
|
||||
pendingJoinRequests,
|
||||
isRightColumnShown,
|
||||
isForForum,
|
||||
@ -451,6 +453,7 @@ const HeaderActions: FC<OwnProps & StateProps> = ({
|
||||
pendingJoinRequests={pendingJoinRequests}
|
||||
onJoinRequestsClick={handleJoinRequestsClick}
|
||||
withForumActions={isForForum}
|
||||
channelMonoforumId={channelMonoforumId}
|
||||
onSubscribeChannel={handleSubscribeClick}
|
||||
onSearchClick={handleSearchClick}
|
||||
onAsMessagesClick={handleAsMessagesClick}
|
||||
@ -499,7 +502,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
const canStartBot = !canRestartBot && Boolean(selectIsChatBotNotStarted(global, chatId));
|
||||
const canUnblock = isUserBlocked && !bot;
|
||||
const canSubscribe = Boolean(
|
||||
(isMainThread || chat.isForum) && (isChannel || isSuperGroup) && chat.isNotJoined,
|
||||
(isMainThread || chat.isForum) && (isChannel || isSuperGroup) && chat.isNotJoined && !chat.isMonoforum,
|
||||
);
|
||||
const canSearch = isMainThread || isDiscussionThread;
|
||||
const canCall = ARE_CALLS_SUPPORTED && isUserId(chat.id) && !isChatWithSelf && !bot && !chat.isSupport
|
||||
@ -508,12 +511,12 @@ export default memo(withGlobal<OwnProps>(
|
||||
const canLeave = isSavedDialog || (isMainThread && !canSubscribe);
|
||||
const canEnterVoiceChat = ARE_CALLS_SUPPORTED && isMainThread && chat.isCallActive;
|
||||
const canCreateVoiceChat = ARE_CALLS_SUPPORTED && isMainThread && !chat.isCallActive
|
||||
&& (chat.adminRights?.manageCall || (chat.isCreator && isChatBasicGroup(chat)));
|
||||
&& (chat.adminRights?.manageCall || (chat.isCreator && isChatBasicGroup(chat))) && !chat.isMonoforum;
|
||||
const canViewStatistics = isMainThread && chatFullInfo?.canViewStatistics;
|
||||
const canViewMonetization = isMainThread && chatFullInfo?.canViewMonetization;
|
||||
const canViewBoosts = isMainThread
|
||||
const canViewBoosts = isMainThread && !chat.isMonoforum
|
||||
&& (isSuperGroup || isChannel) && (canViewStatistics || getHasAdminRight(chat, 'postStories'));
|
||||
const canShowBoostModal = !canViewBoosts && (isSuperGroup || isChannel);
|
||||
const canShowBoostModal = !canViewBoosts && (isSuperGroup || isChannel) && !chat.isMonoforum;
|
||||
const pendingJoinRequests = isMainThread ? chatFullInfo?.requestsPending : undefined;
|
||||
const shouldJoinToSend = Boolean(chat?.isNotJoined && chat.isJoinToSend);
|
||||
const shouldSendJoinRequest = Boolean(chat?.isNotJoined && chat.isJoinRequest);
|
||||
@ -523,6 +526,8 @@ export default memo(withGlobal<OwnProps>(
|
||||
const canTranslate = selectCanTranslateChat(global, chatId) && !fullInfo?.isTranslationDisabled;
|
||||
const isAccountFrozen = selectIsCurrentUserFrozen(global);
|
||||
|
||||
const channelMonoforumId = isChatChannel(chat) ? chat.linkedMonoforumId : undefined;
|
||||
|
||||
return {
|
||||
noMenu: false,
|
||||
isChannel,
|
||||
@ -552,6 +557,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
detectedChatLanguage: chat.detectedLanguage,
|
||||
canUnblock,
|
||||
isAccountFrozen,
|
||||
channelMonoforumId,
|
||||
};
|
||||
},
|
||||
)(HeaderActions));
|
||||
|
||||
@ -17,6 +17,7 @@ import {
|
||||
getCanManageTopic,
|
||||
getHasAdminRight,
|
||||
getIsSavedDialog,
|
||||
isChatAdmin,
|
||||
isChatChannel,
|
||||
isChatGroup,
|
||||
isSystemBot,
|
||||
@ -94,6 +95,7 @@ export type OwnProps = {
|
||||
canCreateVoiceChat?: boolean;
|
||||
pendingJoinRequests?: number;
|
||||
canTranslate?: boolean;
|
||||
channelMonoforumId?: string;
|
||||
onSubscribeChannel: () => void;
|
||||
onSearchClick: () => void;
|
||||
onAsMessagesClick: () => void;
|
||||
@ -176,14 +178,15 @@ const HeaderMenuContainer: FC<OwnProps & StateProps> = ({
|
||||
isChatWithSelf,
|
||||
savedDialog,
|
||||
canShowBoostModal,
|
||||
disallowedGifts,
|
||||
isAccountFrozen,
|
||||
channelMonoforumId,
|
||||
onJoinRequestsClick,
|
||||
onSubscribeChannel,
|
||||
onSearchClick,
|
||||
onAsMessagesClick,
|
||||
onClose,
|
||||
onCloseAnimationEnd,
|
||||
disallowedGifts,
|
||||
isAccountFrozen,
|
||||
}) => {
|
||||
const {
|
||||
updateChatMutedState,
|
||||
@ -488,6 +491,11 @@ const HeaderMenuContainer: FC<OwnProps & StateProps> = ({
|
||||
closeMenu();
|
||||
});
|
||||
|
||||
const handleSendChannelMessage = useLastCallback(() => {
|
||||
openChat({ id: channelMonoforumId });
|
||||
closeMenu();
|
||||
});
|
||||
|
||||
useEffect(disableScrolling, []);
|
||||
|
||||
const botButtons = useMemo(() => {
|
||||
@ -585,6 +593,14 @@ const HeaderMenuContainer: FC<OwnProps & StateProps> = ({
|
||||
<MenuSeparator />
|
||||
</>
|
||||
)}
|
||||
{channelMonoforumId && (
|
||||
<MenuItem
|
||||
icon="message"
|
||||
onClick={handleSendChannelMessage}
|
||||
>
|
||||
{lang('ChannelSendMessage')}
|
||||
</MenuItem>
|
||||
)}
|
||||
{isViewGroupInfoShown && (
|
||||
<MenuItem
|
||||
icon="info"
|
||||
@ -835,7 +851,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
const isMainThread = threadId === MAIN_THREAD_ID;
|
||||
const isChatWithSelf = selectIsChatWithSelf(global, chatId);
|
||||
const { chatId: currentChatId, threadId: currentThreadId } = selectCurrentMessageList(global) || {};
|
||||
const canReportChat = isMainThread && !user && (isChatChannel(chat) || isChatGroup(chat));
|
||||
const canReportChat = isMainThread && !user && (isChatChannel(chat) || isChatGroup(chat)) && !isChatAdmin(chat);
|
||||
|
||||
const chatBot = !isSystemBot(chatId) ? selectBot(global, chatId) : undefined;
|
||||
const userFullInfo = isPrivate ? selectUserFullInfo(global, chatId) : undefined;
|
||||
|
||||
@ -28,6 +28,7 @@ import {
|
||||
isAnonymousForwardsChat,
|
||||
isChatChannel,
|
||||
isChatGroup,
|
||||
isChatMonoforum,
|
||||
isSystemBot,
|
||||
} from '../../global/helpers';
|
||||
import {
|
||||
@ -48,6 +49,7 @@ import {
|
||||
selectIsInSelectMode,
|
||||
selectIsViewportNewest,
|
||||
selectLastScrollOffset,
|
||||
selectMonoforumChannel,
|
||||
selectPerformanceSettingsValue,
|
||||
selectScrollOffset,
|
||||
selectTabState,
|
||||
@ -107,6 +109,7 @@ type StateProps = {
|
||||
isChatLoaded?: boolean;
|
||||
isChannelChat?: boolean;
|
||||
isGroupChat?: boolean;
|
||||
isChatMonoforum?: boolean;
|
||||
isChatWithSelf?: boolean;
|
||||
isSystemBotChat?: boolean;
|
||||
isAnonymousForwards?: boolean;
|
||||
@ -139,6 +142,7 @@ type StateProps = {
|
||||
isChatProtected?: boolean;
|
||||
hasCustomGreeting?: boolean;
|
||||
isAppConfigLoaded?: boolean;
|
||||
monoforumChannelId?: string;
|
||||
canTranslate?: boolean;
|
||||
translationLanguage?: string;
|
||||
shouldAutoTranslate?: boolean;
|
||||
@ -169,6 +173,7 @@ const MessageList: FC<OwnProps & StateProps> = ({
|
||||
isChannelWithAvatars,
|
||||
canPost,
|
||||
isSynced,
|
||||
isChatMonoforum,
|
||||
isReady,
|
||||
isChatWithSelf,
|
||||
isSystemBotChat,
|
||||
@ -203,6 +208,7 @@ const MessageList: FC<OwnProps & StateProps> = ({
|
||||
isChatProtected,
|
||||
isAccountFrozen,
|
||||
hasCustomGreeting,
|
||||
monoforumChannelId,
|
||||
isAppConfigLoaded,
|
||||
canTranslate,
|
||||
translationLanguage,
|
||||
@ -695,7 +701,7 @@ const MessageList: FC<OwnProps & StateProps> = ({
|
||||
isChatProtected && 'hide-on-print',
|
||||
);
|
||||
|
||||
const hasMessages = (messageIds && messageGroups) || lastMessage;
|
||||
const hasMessages = Boolean((messageIds && messageGroups) || lastMessage);
|
||||
|
||||
useEffect(() => {
|
||||
if (hasMessages) return;
|
||||
@ -716,12 +722,12 @@ const MessageList: FC<OwnProps & StateProps> = ({
|
||||
{restrictionReason ? restrictionReason.text : `This is a private ${isChannelChat ? 'channel' : 'chat'}`}
|
||||
</span>
|
||||
</div>
|
||||
) : paidMessagesStars && isPrivate && !hasMessages && !hasCustomGreeting ? (
|
||||
<RequirementToContactMessage paidMessagesStars={paidMessagesStars} userId={chatId} />
|
||||
) : paidMessagesStars && !hasMessages && !hasCustomGreeting ? (
|
||||
<RequirementToContactMessage paidMessagesStars={paidMessagesStars} peerId={monoforumChannelId || chatId} />
|
||||
) : isContactRequirePremium && !hasMessages ? (
|
||||
<RequirementToContactMessage userId={chatId} />
|
||||
<RequirementToContactMessage peerId={chatId} />
|
||||
) : (isBot || isNonContact) && !hasMessages ? (
|
||||
<MessageListAccountInfo chatId={chatId} />
|
||||
<MessageListAccountInfo chatId={chatId} hasMessages={hasMessages} />
|
||||
) : shouldRenderGreeting ? (
|
||||
<ContactGreeting key={chatId} userId={chatId} />
|
||||
) : messageIds && (!messageGroups || isGroupChatJustCreated || isEmptyTopic) ? (
|
||||
@ -738,6 +744,7 @@ const MessageList: FC<OwnProps & StateProps> = ({
|
||||
chatId={chatId}
|
||||
isComments={isComments}
|
||||
isChannelChat={isChannelChat}
|
||||
isChatMonoforum={isChatMonoforum}
|
||||
isSavedDialog={isSavedDialog}
|
||||
messageIds={messageIds || [lastMessage!.id]}
|
||||
messageGroups={messageGroups || groupMessages([lastMessage!])}
|
||||
@ -820,6 +827,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
const hasCustomGreeting = Boolean(userFullInfo?.businessIntro);
|
||||
const isAppConfigLoaded = global.isAppConfigLoaded;
|
||||
|
||||
const monoforumChannelId = selectMonoforumChannel(global, chatId)?.id;
|
||||
const canTranslate = selectCanTranslateChat(global, chatId) && !chatFullInfo?.isTranslationDisabled;
|
||||
const shouldAutoTranslate = chat?.hasAutoTranslation;
|
||||
const translationLanguage = selectTranslationLanguage(global);
|
||||
@ -830,6 +838,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
isRestricted,
|
||||
restrictionReason,
|
||||
isChannelChat: isChatChannel(chat),
|
||||
isChatMonoforum: isChatMonoforum(chat),
|
||||
isGroupChat: isChatGroup(chat),
|
||||
isChannelWithAvatars: chat.areProfilesShown,
|
||||
isCreator: chat.isCreator,
|
||||
@ -860,6 +869,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
isAccountFrozen,
|
||||
hasCustomGreeting,
|
||||
isAppConfigLoaded,
|
||||
monoforumChannelId,
|
||||
canTranslate,
|
||||
translationLanguage,
|
||||
shouldAutoTranslate,
|
||||
|
||||
@ -46,7 +46,7 @@ import styles from './MessageListAccountInfo.module.scss';
|
||||
|
||||
type OwnProps = {
|
||||
chatId: string;
|
||||
isInMessageList?: boolean;
|
||||
hasMessages?: boolean;
|
||||
};
|
||||
|
||||
type StateProps = {
|
||||
@ -66,6 +66,7 @@ const MessageListAccountInfo: FC<OwnProps & StateProps> = ({
|
||||
phoneCodeList,
|
||||
commonChats,
|
||||
userFullInfo,
|
||||
hasMessages,
|
||||
}) => {
|
||||
const { loadCommonChats, openChatWithInfo } = getActions();
|
||||
const oldLang = useOldLang();
|
||||
@ -170,7 +171,9 @@ const MessageListAccountInfo: FC<OwnProps & StateProps> = ({
|
||||
return (
|
||||
<div className={buildClassName(styles.root, 'empty')}>
|
||||
{isLoadingFullUser && isChatInfoEmpty && <span>{oldLang('Loading')}</span>}
|
||||
{(isBotInfoEmpty && isChatInfoEmpty) && !isLoadingFullUser && <span>{oldLang('NoMessages')}</span>}
|
||||
{(isBotInfoEmpty && isChatInfoEmpty) && !isLoadingFullUser && !hasMessages && (
|
||||
<span>{oldLang('NoMessages')}</span>
|
||||
)}
|
||||
{botInfo && (
|
||||
<div
|
||||
className={buildClassName(styles.chatInfo, styles.botBackground)}
|
||||
|
||||
@ -50,6 +50,7 @@ interface OwnProps {
|
||||
isUnread: boolean;
|
||||
withUsers: boolean;
|
||||
isChannelChat: boolean | undefined;
|
||||
isChatMonoforum?: boolean;
|
||||
isEmptyThread?: boolean;
|
||||
isComments?: boolean;
|
||||
noAvatars: boolean;
|
||||
@ -87,6 +88,7 @@ const MessageListContent: FC<OwnProps> = ({
|
||||
isEmptyThread,
|
||||
withUsers,
|
||||
isChannelChat,
|
||||
isChatMonoforum,
|
||||
noAvatars,
|
||||
containerRef,
|
||||
anchorIdRef,
|
||||
@ -261,7 +263,7 @@ const MessageListContent: FC<OwnProps> = ({
|
||||
// Service notifications saved in cache in previous versions may share the same `previousLocalId`
|
||||
const key = isServiceNotificationMessage(message) ? `${message.date}_${originalId}` : originalId;
|
||||
|
||||
const noComments = hasLinkedChat === false || !isChannelChat;
|
||||
const noComments = hasLinkedChat === false || !isChannelChat || Boolean(isChatMonoforum);
|
||||
|
||||
return compact([
|
||||
message.id === memoUnreadDividerBeforeIdRef.current && unreadDivider,
|
||||
@ -377,7 +379,7 @@ const MessageListContent: FC<OwnProps> = ({
|
||||
<div className="messages-container" teactFastList>
|
||||
{withHistoryTriggers && <div ref={backwardsTriggerRef} key="backwards-trigger" className="backwards-trigger" />}
|
||||
{shouldRenderAccountInfo
|
||||
&& <MessageListAccountInfo key={`account_info_${chatId}`} chatId={chatId} />}
|
||||
&& <MessageListAccountInfo key={`account_info_${chatId}`} chatId={chatId} hasMessages />}
|
||||
{dateGroups.flat()}
|
||||
{withHistoryTriggers && (
|
||||
<div
|
||||
|
||||
@ -51,6 +51,7 @@ import {
|
||||
selectIsChatBotNotStarted,
|
||||
selectIsCurrentUserFrozen,
|
||||
selectIsInSelectMode,
|
||||
selectIsMonoforumAdmin,
|
||||
selectIsRightColumnShown,
|
||||
selectIsUserBlocked,
|
||||
selectPeerPaidMessagesStars,
|
||||
@ -76,6 +77,7 @@ import useAppLayout from '../../hooks/useAppLayout';
|
||||
import useCustomBackground from '../../hooks/useCustomBackground';
|
||||
import useForceUpdate from '../../hooks/useForceUpdate';
|
||||
import useHistoryBack from '../../hooks/useHistoryBack';
|
||||
import useLang from '../../hooks/useLang';
|
||||
import useLastCallback from '../../hooks/useLastCallback';
|
||||
import useOldLang from '../../hooks/useOldLang';
|
||||
import usePrevDuringAnimation from '../../hooks/usePrevDuringAnimation';
|
||||
@ -163,6 +165,7 @@ type StateProps = {
|
||||
paidMessagesStars?: number;
|
||||
isAccountFrozen?: boolean;
|
||||
freezeAppealChat?: ApiChat;
|
||||
shouldBlockSendInMonoforum?: boolean;
|
||||
};
|
||||
|
||||
function isImage(item: DataTransferItem) {
|
||||
@ -226,6 +229,7 @@ function MiddleColumn({
|
||||
paidMessagesStars,
|
||||
isAccountFrozen,
|
||||
freezeAppealChat,
|
||||
shouldBlockSendInMonoforum,
|
||||
}: OwnProps & StateProps) {
|
||||
const {
|
||||
openChat,
|
||||
@ -247,7 +251,8 @@ function MiddleColumn({
|
||||
const { width: windowWidth } = useWindowSize();
|
||||
const { isTablet, isDesktop } = useAppLayout();
|
||||
|
||||
const lang = useOldLang();
|
||||
const oldLang = useOldLang();
|
||||
const lang = useLang();
|
||||
const [dropAreaState, setDropAreaState] = useState(DropAreaState.None);
|
||||
const [isScrollDownNeeded, setIsScrollDownShown] = useState(false);
|
||||
const isScrollDownShown = isScrollDownNeeded && (!isMobile || !hasActiveMiddleSearch);
|
||||
@ -412,7 +417,8 @@ function MiddleColumn({
|
||||
joinChannel({ chatId: chatId! });
|
||||
if (renderingShouldSendJoinRequest) {
|
||||
showNotification({
|
||||
message: isChannel ? lang('RequestToJoinChannelSentDescription') : lang('RequestToJoinGroupSentDescription'),
|
||||
message: isChannel
|
||||
? oldLang('RequestToJoinChannelSentDescription') : oldLang('RequestToJoinGroupSentDescription'),
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -451,14 +457,17 @@ function MiddleColumn({
|
||||
);
|
||||
|
||||
const messageSendingRestrictionReason = getMessageSendingRestrictionReason(
|
||||
lang, currentUserBannedRights, defaultBannedRights,
|
||||
oldLang, currentUserBannedRights, defaultBannedRights,
|
||||
);
|
||||
const forumComposerPlaceholder = getForumComposerPlaceholder(
|
||||
oldLang, chat, threadId, topics, Boolean(draftReplyInfo),
|
||||
);
|
||||
const forumComposerPlaceholder = getForumComposerPlaceholder(lang, chat, threadId, topics, Boolean(draftReplyInfo));
|
||||
|
||||
const composerRestrictionMessage = messageSendingRestrictionReason
|
||||
?? forumComposerPlaceholder
|
||||
?? (isContactRequirePremium ? <PremiumRequiredPlaceholder userId={chatId!} /> : undefined)
|
||||
?? (isAccountFrozen && freezeAppealChat?.id !== chatId ? <FrozenAccountPlaceholder /> : undefined);
|
||||
|| forumComposerPlaceholder
|
||||
|| (shouldBlockSendInMonoforum ? lang('MonoforumComposerPlaceholder') : undefined)
|
||||
|| (isContactRequirePremium ? <PremiumRequiredPlaceholder userId={chatId!} /> : undefined)
|
||||
|| (isAccountFrozen && freezeAppealChat?.id !== chatId ? <FrozenAccountPlaceholder /> : undefined);
|
||||
|
||||
// CSS Variables calculation doesn't work properly with transforms, so we calculate transform values in JS
|
||||
const {
|
||||
@ -587,7 +596,7 @@ function MiddleColumn({
|
||||
/>
|
||||
)}
|
||||
{isPinnedMessageList && canUnpin && (
|
||||
<div className="middle-column-footer-button-container" dir={lang.isRtl ? 'rtl' : undefined}>
|
||||
<div className="middle-column-footer-button-container" dir={oldLang.isRtl ? 'rtl' : undefined}>
|
||||
<Button
|
||||
size="tiny"
|
||||
fluid
|
||||
@ -596,12 +605,12 @@ function MiddleColumn({
|
||||
onClick={handleOpenUnpinModal}
|
||||
>
|
||||
<Icon name="unpin" />
|
||||
<span>{lang('Chat.Pinned.UnpinAll', pinnedMessagesCount, 'i')}</span>
|
||||
<span>{oldLang('Chat.Pinned.UnpinAll', pinnedMessagesCount, 'i')}</span>
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
{canShowOpenChatButton && (
|
||||
<div className="middle-column-footer-button-container" dir={lang.isRtl ? 'rtl' : undefined}>
|
||||
<div className="middle-column-footer-button-container" dir={oldLang.isRtl ? 'rtl' : undefined}>
|
||||
<Button
|
||||
size="tiny"
|
||||
fluid
|
||||
@ -609,7 +618,7 @@ function MiddleColumn({
|
||||
className="composer-button open-chat-button"
|
||||
onClick={handleOpenChatFromSaved}
|
||||
>
|
||||
<span>{lang('SavedOpenChat')}</span>
|
||||
<span>{oldLang('SavedOpenChat')}</span>
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
@ -625,7 +634,7 @@ function MiddleColumn({
|
||||
{(
|
||||
isMobile && (renderingCanSubscribe || (renderingShouldJoinToSend && !renderingShouldSendJoinRequest))
|
||||
) && (
|
||||
<div className="middle-column-footer-button-container" dir={lang.isRtl ? 'rtl' : undefined}>
|
||||
<div className="middle-column-footer-button-container" dir={oldLang.isRtl ? 'rtl' : undefined}>
|
||||
<Button
|
||||
size="tiny"
|
||||
fluid
|
||||
@ -633,12 +642,12 @@ function MiddleColumn({
|
||||
className="composer-button join-subscribe-button"
|
||||
onClick={handleSubscribeClick}
|
||||
>
|
||||
{lang(renderingIsChannel ? 'ProfileJoinChannel' : 'ProfileJoinGroup')}
|
||||
{oldLang(renderingIsChannel ? 'ProfileJoinChannel' : 'ProfileJoinGroup')}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
{isMobile && renderingShouldSendJoinRequest && (
|
||||
<div className="middle-column-footer-button-container" dir={lang.isRtl ? 'rtl' : undefined}>
|
||||
<div className="middle-column-footer-button-container" dir={oldLang.isRtl ? 'rtl' : undefined}>
|
||||
<Button
|
||||
size="tiny"
|
||||
fluid
|
||||
@ -646,12 +655,12 @@ function MiddleColumn({
|
||||
className="composer-button join-subscribe-button"
|
||||
onClick={handleSubscribeClick}
|
||||
>
|
||||
{lang('ChannelJoinRequest')}
|
||||
{oldLang('ChannelJoinRequest')}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
{isMobile && renderingCanStartBot && (
|
||||
<div className="middle-column-footer-button-container" dir={lang.isRtl ? 'rtl' : undefined}>
|
||||
<div className="middle-column-footer-button-container" dir={oldLang.isRtl ? 'rtl' : undefined}>
|
||||
<Button
|
||||
size="tiny"
|
||||
fluid
|
||||
@ -659,12 +668,12 @@ function MiddleColumn({
|
||||
className="composer-button join-subscribe-button"
|
||||
onClick={handleStartBot}
|
||||
>
|
||||
{lang('BotStart')}
|
||||
{oldLang('BotStart')}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
{isMobile && renderingCanRestartBot && (
|
||||
<div className="middle-column-footer-button-container" dir={lang.isRtl ? 'rtl' : undefined}>
|
||||
<div className="middle-column-footer-button-container" dir={oldLang.isRtl ? 'rtl' : undefined}>
|
||||
<Button
|
||||
size="tiny"
|
||||
fluid
|
||||
@ -672,12 +681,12 @@ function MiddleColumn({
|
||||
className="composer-button join-subscribe-button"
|
||||
onClick={handleRestartBot}
|
||||
>
|
||||
{lang('BotRestart')}
|
||||
{oldLang('BotRestart')}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
{isMobile && renderingCanUnblock && (
|
||||
<div className="middle-column-footer-button-container" dir={lang.isRtl ? 'rtl' : undefined}>
|
||||
<div className="middle-column-footer-button-container" dir={oldLang.isRtl ? 'rtl' : undefined}>
|
||||
<Button
|
||||
size="tiny"
|
||||
fluid
|
||||
@ -685,7 +694,7 @@ function MiddleColumn({
|
||||
className="composer-button join-subscribe-button"
|
||||
onClick={handleUnblock}
|
||||
>
|
||||
{lang('Unblock')}
|
||||
{oldLang('Unblock')}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
@ -788,7 +797,8 @@ export default memo(withGlobal<OwnProps>(
|
||||
const isMainThread = messageListType === 'thread' && threadId === MAIN_THREAD_ID;
|
||||
const isChannel = Boolean(chat && isChatChannel(chat));
|
||||
const canSubscribe = Boolean(
|
||||
chat && isMainThread && (isChannel || isChatSuperGroup(chat)) && chat.isNotJoined && !chat.joinRequests,
|
||||
chat && isMainThread && (isChannel || isChatSuperGroup(chat)) && chat.isNotJoined && !chat.joinRequests
|
||||
&& !chat.isMonoforum,
|
||||
);
|
||||
const shouldJoinToSend = Boolean(chat?.isNotJoined && chat.isJoinToSend);
|
||||
const shouldSendJoinRequest = Boolean(chat?.isNotJoined && chat.isJoinRequest);
|
||||
@ -803,6 +813,8 @@ export default memo(withGlobal<OwnProps>(
|
||||
const shouldBlockSendInForum = chat?.isForum
|
||||
? threadId === MAIN_THREAD_ID && !draftReplyInfo && (selectTopic(global, chatId, GENERAL_TOPIC_ID)?.isClosed)
|
||||
: false;
|
||||
const isMonoforumAdmin = selectIsMonoforumAdmin(global, chatId);
|
||||
const shouldBlockSendInMonoforum = Boolean(chat?.isMonoforum && !draftReplyInfo && isMonoforumAdmin);
|
||||
const topics = selectTopics(global, chatId);
|
||||
|
||||
const isSavedDialog = getIsSavedDialog(chatId, threadId, global.currentUserId);
|
||||
@ -840,6 +852,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
&& !isBotNotStarted
|
||||
&& !(shouldJoinToSend && chat?.isNotJoined)
|
||||
&& !shouldBlockSendInForum
|
||||
&& !shouldBlockSendInMonoforum
|
||||
&& !isSavedDialog
|
||||
&& (!isAccountFrozen || freezeAppealChat?.id === chatId),
|
||||
isPinnedMessageList,
|
||||
@ -864,6 +877,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
paidMessagesStars,
|
||||
isAccountFrozen,
|
||||
freezeAppealChat,
|
||||
shouldBlockSendInMonoforum,
|
||||
};
|
||||
},
|
||||
)(MiddleColumn));
|
||||
|
||||
@ -261,6 +261,8 @@ const MiddleHeader: FC<OwnProps & StateProps> = ({
|
||||
const savedMessagesStatus = isSavedDialog ? lang('SavedMessages') : undefined;
|
||||
|
||||
const realChatId = isSavedDialog ? String(threadId) : chatId;
|
||||
|
||||
const displayChatId = chat?.isMonoforum ? chat.linkedMonoforumId! : realChatId;
|
||||
return (
|
||||
<>
|
||||
{(isLeftColumnHideable || currentTransitionKey > 0) && renderBackButton(shouldShowCloseButton, !isSavedDialog)}
|
||||
@ -272,10 +274,10 @@ const MiddleHeader: FC<OwnProps & StateProps> = ({
|
||||
onTouchStart={handleLongPressTouchStart}
|
||||
onTouchEnd={handleLongPressTouchEnd}
|
||||
>
|
||||
{isUserId(realChatId) ? (
|
||||
{isUserId(displayChatId) ? (
|
||||
<PrivateChatInfo
|
||||
key={realChatId}
|
||||
userId={realChatId}
|
||||
key={displayChatId}
|
||||
userId={displayChatId}
|
||||
typingStatus={typingStatus}
|
||||
status={connectionStatusText || savedMessagesStatus}
|
||||
withDots={Boolean(connectionStatusText)}
|
||||
@ -291,10 +293,11 @@ const MiddleHeader: FC<OwnProps & StateProps> = ({
|
||||
/>
|
||||
) : (
|
||||
<GroupChatInfo
|
||||
key={realChatId}
|
||||
chatId={realChatId}
|
||||
key={displayChatId}
|
||||
chatId={displayChatId}
|
||||
threadId={!isSavedDialog ? threadId : undefined}
|
||||
typingStatus={typingStatus}
|
||||
withMonoforumStatus={chat?.isMonoforum}
|
||||
status={connectionStatusText || savedMessagesStatus}
|
||||
withDots={Boolean(connectionStatusText)}
|
||||
withMediaViewer={threadId === MAIN_THREAD_ID}
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
import { memo } from '../../lib/teact/teact';
|
||||
import { getActions, withGlobal } from '../../global';
|
||||
|
||||
import { getUserFirstOrLastName } from '../../global/helpers';
|
||||
import { selectTheme, selectThemeValues, selectUser } from '../../global/selectors';
|
||||
import type { ApiPeer } from '../../api/types';
|
||||
|
||||
import { getPeerTitle, isApiPeerUser } from '../../global/helpers/peers';
|
||||
import { selectPeer, selectTheme, selectThemeValues } from '../../global/selectors';
|
||||
import { formatStarsAsIcon } from '../../util/localization/format';
|
||||
import { LOCAL_TGS_URLS } from '../common/helpers/animatedAssets';
|
||||
import renderText from '../common/helpers/renderText';
|
||||
@ -19,17 +21,18 @@ import Button from '../ui/Button';
|
||||
import styles from './RequirementToContactMessage.module.scss';
|
||||
|
||||
type OwnProps = {
|
||||
|
||||
userId: string;
|
||||
peerId: string;
|
||||
paidMessagesStars?: number;
|
||||
};
|
||||
|
||||
type StateProps = {
|
||||
patternColor?: string;
|
||||
userName?: string;
|
||||
peer?: ApiPeer;
|
||||
};
|
||||
|
||||
function RequirementToContactMessage({ patternColor, userName, paidMessagesStars }: OwnProps & StateProps) {
|
||||
function RequirementToContactMessage({
|
||||
patternColor, peer, paidMessagesStars,
|
||||
}: OwnProps & StateProps) {
|
||||
const oldLang = useOldLang();
|
||||
const lang = useLang();
|
||||
const { openPremiumModal, openStarsBalanceModal } = getActions();
|
||||
@ -40,6 +43,8 @@ function RequirementToContactMessage({ patternColor, userName, paidMessagesStars
|
||||
openStarsBalanceModal({});
|
||||
});
|
||||
|
||||
if (!peer) return undefined;
|
||||
|
||||
return (
|
||||
<div className={styles.root}>
|
||||
<div className={styles.inner}>
|
||||
@ -55,8 +60,8 @@ function RequirementToContactMessage({ patternColor, userName, paidMessagesStars
|
||||
<span className={styles.description}>
|
||||
{
|
||||
paidMessagesStars
|
||||
? lang('FirstMessageInPaidMessagesChat', {
|
||||
user: userName,
|
||||
? lang(isApiPeerUser(peer) ? 'MessagesPlaceholderPaidUser' : 'MessagesPlaceholderPaidChannel', {
|
||||
peer: getPeerTitle(lang, peer),
|
||||
amount: formatStarsAsIcon(lang,
|
||||
paidMessagesStars,
|
||||
{
|
||||
@ -68,7 +73,7 @@ function RequirementToContactMessage({ patternColor, userName, paidMessagesStars
|
||||
withNodes: true,
|
||||
withMarkdown: true,
|
||||
})
|
||||
: renderText(oldLang('MessageLockedPremium', userName), ['simple_markdown'])
|
||||
: renderText(oldLang('MessageLockedPremium', getPeerTitle(lang, peer)), ['simple_markdown'])
|
||||
}
|
||||
</span>
|
||||
<Button
|
||||
@ -95,14 +100,14 @@ function RequirementToContactMessage({ patternColor, userName, paidMessagesStars
|
||||
}
|
||||
|
||||
export default memo(
|
||||
withGlobal<OwnProps>((global, { userId }): StateProps => {
|
||||
withGlobal<OwnProps>((global, { peerId: userId }): StateProps => {
|
||||
const theme = selectTheme(global);
|
||||
const { patternColor } = selectThemeValues(global, theme) || {};
|
||||
const user = selectUser(global, userId);
|
||||
const peer = selectPeer(global, userId);
|
||||
|
||||
return {
|
||||
patternColor,
|
||||
userName: getUserFirstOrLastName(user),
|
||||
peer,
|
||||
};
|
||||
})(RequirementToContactMessage),
|
||||
);
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import type { ChangeEvent } from 'react';
|
||||
import type { ElementRef, FC } from '../../../lib/teact/teact';
|
||||
import type React from '../../../lib/teact/teact';
|
||||
import type { ElementRef } from '../../../lib/teact/teact';
|
||||
import {
|
||||
memo, useEffect, useRef, useState,
|
||||
} from '../../../lib/teact/teact';
|
||||
@ -28,19 +27,25 @@ export type OwnProps = {
|
||||
isOpen: boolean;
|
||||
shouldBeAnonymous?: boolean;
|
||||
isQuiz?: boolean;
|
||||
maxOptionsCount?: number;
|
||||
onSend: (pollSummary: ApiNewPoll) => void;
|
||||
onClear: () => void;
|
||||
};
|
||||
|
||||
const MAX_LIST_HEIGHT = 320;
|
||||
const MAX_OPTIONS_COUNT = 10;
|
||||
const FALLBACK_MAX_OPTIONS_COUNT = 12;
|
||||
const MAX_OPTION_LENGTH = 100;
|
||||
const MAX_QUESTION_LENGTH = 255;
|
||||
const MAX_SOLUTION_LENGTH = 200;
|
||||
|
||||
const PollModal: FC<OwnProps> = ({
|
||||
isOpen, isQuiz, shouldBeAnonymous, onSend, onClear,
|
||||
}) => {
|
||||
const PollModal = ({
|
||||
isOpen,
|
||||
isQuiz,
|
||||
shouldBeAnonymous,
|
||||
maxOptionsCount = FALLBACK_MAX_OPTIONS_COUNT,
|
||||
onSend,
|
||||
onClear,
|
||||
}: OwnProps) => {
|
||||
const questionInputRef = useRef<HTMLInputElement>();
|
||||
const optionsListRef = useRef<HTMLDivElement>();
|
||||
|
||||
@ -170,7 +175,7 @@ const PollModal: FC<OwnProps> = ({
|
||||
const updateOption = useLastCallback((index: number, text: string) => {
|
||||
const newOptions = [...options];
|
||||
newOptions[index] = text;
|
||||
if (newOptions[newOptions.length - 1].trim().length && newOptions.length < MAX_OPTIONS_COUNT) {
|
||||
if (newOptions[newOptions.length - 1].trim().length && newOptions.length < maxOptionsCount) {
|
||||
addNewOption(newOptions);
|
||||
} else {
|
||||
setOptions(newOptions);
|
||||
@ -265,7 +270,7 @@ const PollModal: FC<OwnProps> = ({
|
||||
<div className="option-wrapper">
|
||||
<InputText
|
||||
maxLength={MAX_OPTION_LENGTH}
|
||||
label={index !== options.length - 1 || options.length === MAX_OPTIONS_COUNT
|
||||
label={index !== options.length - 1 || options.length === maxOptionsCount
|
||||
? lang('OptionHint')
|
||||
: lang('CreatePoll.AddOption')}
|
||||
error={getOptionsError(index)}
|
||||
|
||||
@ -717,13 +717,21 @@ const ActionMessageText = ({
|
||||
return action.message;
|
||||
|
||||
case 'paidMessagesPrice': {
|
||||
const { stars } = action;
|
||||
const { stars, isAllowedInChannel } = action;
|
||||
if (stars === 0) {
|
||||
return lang('ActionPaidMessageGroupPriceFree');
|
||||
if (isChannel) {
|
||||
return lang(
|
||||
isAllowedInChannel ? 'ActionMessageChannelFree' : 'ActionMessageChannelDisabled',
|
||||
{ peer: chatLink },
|
||||
{ withNodes: true },
|
||||
);
|
||||
}
|
||||
return translateWithYou(lang, 'ActionPaidMessagePriceFree', isOutgoing, { peer: senderLink });
|
||||
}
|
||||
return lang('ActionPaidMessageGroupPrice', {
|
||||
stars: formatStarsAsText(lang, stars),
|
||||
}, { withNodes: true, withMarkdown: true });
|
||||
return translateWithYou(lang, 'ActionPaidMessagePrice', isOutgoing, {
|
||||
peer: senderLink,
|
||||
amount: formatStarsAsText(lang, stars),
|
||||
}, { withMarkdown: true });
|
||||
}
|
||||
|
||||
case 'paidMessagesRefunded': {
|
||||
|
||||
@ -65,6 +65,7 @@ import {
|
||||
selectPollFromMessage,
|
||||
selectRequestedChatTranslationLanguage,
|
||||
selectRequestedMessageTranslationLanguage,
|
||||
selectSavedDialogIdFromMessage,
|
||||
selectStickerSet,
|
||||
selectThreadInfo,
|
||||
selectTopic,
|
||||
@ -156,6 +157,7 @@ type StateProps = {
|
||||
isWithPaidReaction?: boolean;
|
||||
userFullName?: string;
|
||||
canGift?: boolean;
|
||||
savedDialogId?: string;
|
||||
};
|
||||
|
||||
const selection = window.getSelection();
|
||||
@ -223,6 +225,7 @@ const ContextMenuContainer: FC<OwnProps & StateProps> = ({
|
||||
userFullName,
|
||||
canGift,
|
||||
className,
|
||||
savedDialogId,
|
||||
onClose,
|
||||
onCloseAnimationEnd,
|
||||
}) => {
|
||||
@ -416,6 +419,7 @@ const ContextMenuContainer: FC<OwnProps & StateProps> = ({
|
||||
replyToMsgId: message.id,
|
||||
quoteText,
|
||||
quoteOffset: selectionQuoteOffset,
|
||||
monoforumPeerId: savedDialogId,
|
||||
replyToPeerId: undefined,
|
||||
});
|
||||
}
|
||||
@ -813,6 +817,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
const hasTtl = hasMessageTtl(message);
|
||||
const canShowSeenBy = Boolean(!isLocal
|
||||
&& chat
|
||||
&& !chat.isMonoforum
|
||||
&& !isMessageUnread
|
||||
&& seenByMaxChatMembers
|
||||
&& seenByExpiresAt
|
||||
@ -849,6 +854,8 @@ export default memo(withGlobal<OwnProps>(
|
||||
|
||||
const canGift = selectCanGift(global, message.chatId);
|
||||
|
||||
const savedDialogId = selectSavedDialogIdFromMessage(global, message);
|
||||
|
||||
return {
|
||||
threadId,
|
||||
chat,
|
||||
@ -904,6 +911,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
story,
|
||||
userFullName,
|
||||
canGift,
|
||||
savedDialogId,
|
||||
};
|
||||
},
|
||||
)(ContextMenuContainer));
|
||||
|
||||
@ -38,11 +38,11 @@ export function translateWithYou<K extends LangKey>(
|
||||
options?: {
|
||||
pluralValue?: number;
|
||||
asText?: boolean;
|
||||
isMarkdown?: boolean;
|
||||
withMarkdown?: boolean;
|
||||
renderTextFilters?: string[];
|
||||
},
|
||||
): TeactNode {
|
||||
const { pluralValue, asText, isMarkdown, renderTextFilters } = options || {};
|
||||
const { pluralValue, asText, withMarkdown, renderTextFilters } = options || {};
|
||||
const translationKey = isYou ? (`${key}You` as LangKey) : key;
|
||||
|
||||
return lang(
|
||||
@ -50,7 +50,7 @@ export function translateWithYou<K extends LangKey>(
|
||||
translationKey,
|
||||
variables,
|
||||
{
|
||||
withNodes: !asText, isMarkdown, pluralValue, renderTextFilters,
|
||||
withNodes: !asText, withMarkdown, pluralValue, renderTextFilters,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@ -26,6 +26,7 @@ import {
|
||||
selectForwardedSender,
|
||||
selectIsChatWithSelf,
|
||||
selectIsCurrentUserPremium,
|
||||
selectMonoforumChannel,
|
||||
selectSender,
|
||||
selectTabState,
|
||||
} from '../../../global/selectors';
|
||||
@ -67,6 +68,7 @@ export type OwnProps = {
|
||||
type StateProps = {
|
||||
isActive?: boolean;
|
||||
chat?: ApiChat;
|
||||
monoforumChat?: ApiChat;
|
||||
threadId?: ThreadId;
|
||||
requestedQuery?: string;
|
||||
savedTags?: Record<ApiReactionKey, ApiSavedReactionTag>;
|
||||
@ -97,6 +99,7 @@ const runDebouncedForSearch = debounce((cb) => cb(), 200, false);
|
||||
const MiddleSearch: FC<StateProps> = ({
|
||||
isActive,
|
||||
chat,
|
||||
monoforumChat,
|
||||
threadId,
|
||||
requestedQuery,
|
||||
savedTags,
|
||||
@ -645,7 +648,7 @@ const MiddleSearch: FC<StateProps> = ({
|
||||
{!isMobile && (
|
||||
<Avatar
|
||||
className={styles.avatar}
|
||||
peer={chat}
|
||||
peer={monoforumChat || chat}
|
||||
size="medium"
|
||||
isSavedMessages={isSavedMessages}
|
||||
/>
|
||||
@ -793,8 +796,11 @@ export default memo(withGlobal<OwnProps>(
|
||||
|
||||
const savedTags = isSavedMessages && !isSavedDialog ? global.savedReactionTags?.byKey : undefined;
|
||||
|
||||
const monoforumChat = selectMonoforumChannel(global, chatId);
|
||||
|
||||
return {
|
||||
chat,
|
||||
monoforumChat,
|
||||
requestedQuery,
|
||||
totalCount,
|
||||
threadId,
|
||||
|
||||
@ -77,7 +77,8 @@ const GifSearch: FC<OwnProps & StateProps> = ({
|
||||
observe: observeIntersection,
|
||||
} = useIntersectionObserver({ rootRef: containerRef, debounceMs: INTERSECTION_DEBOUNCE });
|
||||
|
||||
const canSendGifs = canPostInChat && getAllowedAttachmentOptions(chat, chatFullInfo, isChatWithBot).canSendGifs;
|
||||
const canSendGifs = canPostInChat
|
||||
&& getAllowedAttachmentOptions(chat, chatFullInfo, isChatWithBot, isSavedMessages).canSendGifs;
|
||||
|
||||
const handleGifClick = useCallback((gif: ApiVideo, isSilent?: boolean, shouldSchedule?: boolean) => {
|
||||
if (canSendGifs) {
|
||||
|
||||
@ -49,6 +49,7 @@ import {
|
||||
selectCurrentSharedMediaSearch,
|
||||
selectIsCurrentUserPremium,
|
||||
selectIsRightColumnShown,
|
||||
selectMonoforumChannel,
|
||||
selectPeerStories,
|
||||
selectSimilarBotsIds,
|
||||
selectSimilarChannelIds,
|
||||
@ -114,11 +115,12 @@ type OwnProps = {
|
||||
threadId?: ThreadId;
|
||||
profileState: ProfileState;
|
||||
isMobile?: boolean;
|
||||
onProfileStateChange: (state: ProfileState) => void;
|
||||
isActive: boolean;
|
||||
onProfileStateChange: (state: ProfileState) => void;
|
||||
};
|
||||
|
||||
type StateProps = {
|
||||
monoforumChannel?: ApiChat;
|
||||
theme: ThemeKey;
|
||||
isChannel?: boolean;
|
||||
isBot?: boolean;
|
||||
@ -183,6 +185,7 @@ const Profile: FC<OwnProps & StateProps> = ({
|
||||
threadId,
|
||||
profileState,
|
||||
theme,
|
||||
monoforumChannel,
|
||||
isChannel,
|
||||
isBot,
|
||||
currentUserId,
|
||||
@ -376,6 +379,9 @@ const Profile: FC<OwnProps & StateProps> = ({
|
||||
const handleLoadGifts = useCallback(() => {
|
||||
loadPeerSavedGifts({ peerId: chatId });
|
||||
}, [chatId]);
|
||||
const handleLoadMoreMembers = useCallback(() => {
|
||||
loadMoreMembers({ chatId });
|
||||
}, [chatId, loadMoreMembers]);
|
||||
|
||||
useEffectWithPrevDeps(([prevGifts]) => {
|
||||
if (!gifts || !prevGifts) {
|
||||
@ -397,7 +403,7 @@ const Profile: FC<OwnProps & StateProps> = ({
|
||||
}, [gifts, startViewTransition]);
|
||||
|
||||
const [resultType, viewportIds, getMore, noProfileInfo] = useProfileViewportIds({
|
||||
loadMoreMembers,
|
||||
loadMoreMembers: handleLoadMoreMembers,
|
||||
searchMessages: searchSharedMediaMessages,
|
||||
loadStories: handleLoadPeerStories,
|
||||
loadStoriesArchive: handleLoadStoriesArchive,
|
||||
@ -872,7 +878,12 @@ const Profile: FC<OwnProps & StateProps> = ({
|
||||
onScroll={handleScroll}
|
||||
>
|
||||
{!noProfileInfo && !isSavedMessages && (
|
||||
renderProfileInfo(profileId, isRightColumnShown && canRenderContent, isSavedDialog)
|
||||
renderProfileInfo(
|
||||
monoforumChannel?.id || profileId,
|
||||
isRightColumnShown && canRenderContent,
|
||||
isSavedDialog,
|
||||
Boolean(monoforumChannel),
|
||||
)
|
||||
)}
|
||||
{!isRestricted && (
|
||||
<div
|
||||
@ -915,10 +926,10 @@ const Profile: FC<OwnProps & StateProps> = ({
|
||||
);
|
||||
};
|
||||
|
||||
function renderProfileInfo(profileId: string, isReady: boolean, isSavedDialog?: boolean) {
|
||||
function renderProfileInfo(profileId: string, isReady: boolean, isSavedDialog?: boolean, isForMonoforum?: boolean) {
|
||||
return (
|
||||
<div className="profile-info">
|
||||
<ProfileInfo peerId={profileId} canPlayVideo={isReady} />
|
||||
<ProfileInfo peerId={profileId} canPlayVideo={isReady} isForMonoforum={isForMonoforum} />
|
||||
<ChatExtra chatOrUserId={profileId} isSavedDialog={isSavedDialog} />
|
||||
</div>
|
||||
);
|
||||
@ -949,7 +960,8 @@ export default memo(withGlobal<OwnProps>(
|
||||
const isGroup = chat && isChatGroup(chat);
|
||||
const isChannel = chat && isChatChannel(chat);
|
||||
const isBot = user && isUserBot(user);
|
||||
const hasMembersTab = !isTopicInfo && !isSavedDialog && (isGroup || (isChannel && isChatAdmin(chat)));
|
||||
const hasMembersTab = !isTopicInfo && !isSavedDialog
|
||||
&& (isGroup || (isChannel && isChatAdmin(chat))) && !chat?.isMonoforum;
|
||||
const members = chatFullInfo?.members;
|
||||
const adminMembersById = chatFullInfo?.adminMembersById;
|
||||
const areMembersHidden = hasMembersTab && chat
|
||||
@ -984,6 +996,8 @@ export default memo(withGlobal<OwnProps>(
|
||||
const hasGiftsTab = Boolean(peerFullInfo?.starGiftCount) && !isSavedDialog;
|
||||
const peerGifts = selectTabState(global).savedGifts.giftsByPeerId[chatId];
|
||||
|
||||
const monoforumChannel = selectMonoforumChannel(global, chatId);
|
||||
|
||||
return {
|
||||
theme: selectTheme(global),
|
||||
isChannel,
|
||||
@ -1025,6 +1039,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
limitSimilarPeers: selectPremiumLimit(global, 'recommendedChannels'),
|
||||
...(hasMembersTab && members && { members, adminMembersById }),
|
||||
...(hasCommonChatsTab && user && { commonChatIds: commonChats?.ids }),
|
||||
monoforumChannel,
|
||||
};
|
||||
},
|
||||
)(Profile));
|
||||
|
||||
@ -423,6 +423,7 @@ const RightColumn: FC<OwnProps & StateProps> = ({
|
||||
export default memo(withGlobal<OwnProps>(
|
||||
(global, { isMobile }): StateProps => {
|
||||
const { chatId, threadId } = selectCurrentMessageList(global) || {};
|
||||
|
||||
const areActiveChatsLoaded = selectAreActiveChatsLoaded(global);
|
||||
const {
|
||||
management, shouldSkipHistoryAnimations, nextProfileTab, shouldCloseRightColumn,
|
||||
|
||||
@ -173,12 +173,12 @@ const RightHeader: FC<OwnProps & StateProps> = ({
|
||||
isInsideTopic,
|
||||
canEditTopic,
|
||||
isSavedMessages,
|
||||
onClose,
|
||||
onScreenSelect,
|
||||
canEditBot,
|
||||
giftProfileFilter,
|
||||
canUseGiftFilter,
|
||||
canUseGiftAdminFilter,
|
||||
onClose,
|
||||
onScreenSelect,
|
||||
}) => {
|
||||
const {
|
||||
setStickerSearchQuery,
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import type { FC } from '../../../lib/teact/teact';
|
||||
import {
|
||||
memo, useCallback,
|
||||
useMemo, useState,
|
||||
memo, useMemo, useState,
|
||||
} from '../../../lib/teact/teact';
|
||||
import { getActions, withGlobal } from '../../../global';
|
||||
|
||||
@ -10,6 +9,7 @@ import type { ApiChat, ApiChatMember } from '../../../api/types';
|
||||
import { filterPeersByQuery } from '../../../global/helpers/peers';
|
||||
import { selectChatFullInfo } from '../../../global/selectors';
|
||||
|
||||
import useLastCallback from '../../../hooks/useLastCallback';
|
||||
import useOldLang from '../../../hooks/useOldLang';
|
||||
|
||||
import ChatOrUserPicker from '../../common/pickers/ChatOrUserPicker';
|
||||
@ -52,10 +52,14 @@ const RemoveGroupUserModal: FC<OwnProps & StateProps> = ({
|
||||
return filterPeersByQuery({ ids: availableMemberIds, query: search, type: 'user' });
|
||||
}, [chatMembers, currentUserId, search]);
|
||||
|
||||
const handleRemoveUser = useCallback((userId: string) => {
|
||||
const handleLoadMore = useLastCallback(() => {
|
||||
loadMoreMembers({ chatId: chat.id });
|
||||
});
|
||||
|
||||
const handleRemoveUser = useLastCallback((userId: string) => {
|
||||
deleteChatMember({ chatId: chat.id, userId });
|
||||
onClose();
|
||||
}, [chat.id, deleteChatMember, onClose]);
|
||||
});
|
||||
|
||||
return (
|
||||
<ChatOrUserPicker
|
||||
@ -64,7 +68,7 @@ const RemoveGroupUserModal: FC<OwnProps & StateProps> = ({
|
||||
searchPlaceholder={lang('ChannelBlockUser')}
|
||||
search={search}
|
||||
onSearchChange={setSearch}
|
||||
loadMore={loadMoreMembers}
|
||||
loadMore={handleLoadMore}
|
||||
onSelectChatOrUser={handleRemoveUser}
|
||||
onClose={onClose}
|
||||
/>
|
||||
|
||||
@ -343,7 +343,7 @@ export const REPLIES_USER_ID = '1271266957'; // TODO For Test connection ID must
|
||||
export const VERIFICATION_CODES_USER_ID = '489000';
|
||||
export const ANONYMOUS_USER_ID = '2666000';
|
||||
export const RESTRICTED_EMOJI_SET_ID = '7173162320003080';
|
||||
export const CHANNEL_ID_LENGTH = 14; // 14 symbols, based on TDLib's `ZERO_CHANNEL_ID = -1000000000000`
|
||||
export const CHANNEL_ID_BASE = 10 ** 12;
|
||||
export const DEFAULT_GIF_SEARCH_BOT_USERNAME = 'gif';
|
||||
export const ALL_FOLDER_ID = 0;
|
||||
export const ARCHIVED_FOLDER_ID = 1;
|
||||
|
||||
@ -52,6 +52,7 @@ import {
|
||||
isChatArchived,
|
||||
isChatBasicGroup,
|
||||
isChatChannel,
|
||||
isChatMonoforum,
|
||||
isChatSuperGroup,
|
||||
isUserBot,
|
||||
} from '../../helpers';
|
||||
@ -2130,11 +2131,11 @@ addActionHandler('resetOpenChatWithDraft', (global, actions, payload): ActionRet
|
||||
});
|
||||
|
||||
addActionHandler('loadMoreMembers', async (global, actions, payload): Promise<void> => {
|
||||
const { chatId } = payload || {};
|
||||
|
||||
if (selectIsCurrentUserFrozen(global)) return;
|
||||
const { tabId = getCurrentTabId() } = payload || {};
|
||||
const { chatId } = selectCurrentMessageList(global, tabId) || {};
|
||||
const chat = chatId ? selectChat(global, chatId) : undefined;
|
||||
if (!chat || isChatBasicGroup(chat)) {
|
||||
const chat = selectChat(global, chatId);
|
||||
if (!chat || isChatBasicGroup(chat) || isChatMonoforum(chat)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -581,12 +581,17 @@ addActionHandler('saveDraft', (global, actions, payload): ActionReturnType => {
|
||||
const {
|
||||
chatId, threadId, text,
|
||||
} = payload;
|
||||
if (!text) {
|
||||
const chat = selectChat(global, chatId);
|
||||
if (!text || !chat) {
|
||||
return;
|
||||
}
|
||||
|
||||
const currentDraft = selectDraft(global, chatId, threadId);
|
||||
|
||||
if (chat.isMonoforum && !currentDraft?.replyInfo) {
|
||||
return; // Monoforum doesn't support drafts outside threads
|
||||
}
|
||||
|
||||
const newDraft: ApiDraft = {
|
||||
text,
|
||||
replyInfo: currentDraft?.replyInfo,
|
||||
@ -654,8 +659,12 @@ addActionHandler('resetDraftReplyInfo', (global, actions, payload): ActionReturn
|
||||
return;
|
||||
}
|
||||
const { chatId, threadId } = currentMessageList;
|
||||
const chat = selectChat(global, chatId);
|
||||
|
||||
const currentDraft = selectDraft(global, chatId, threadId);
|
||||
if (chat?.isMonoforum && !currentDraft?.replyInfo) {
|
||||
return; // Monoforum doesn't support drafts outside threads
|
||||
}
|
||||
const newDraft: ApiDraft | undefined = !currentDraft?.text ? undefined : {
|
||||
...currentDraft,
|
||||
replyInfo: undefined,
|
||||
@ -671,7 +680,11 @@ addActionHandler('saveEffectInDraft', (global, actions, payload): ActionReturnTy
|
||||
chatId, threadId, effectId,
|
||||
} = payload;
|
||||
|
||||
const chat = selectChat(global, chatId);
|
||||
const currentDraft = selectDraft(global, chatId, threadId);
|
||||
if (chat?.isMonoforum && !currentDraft?.replyInfo) {
|
||||
return; // Monoforum doesn't support drafts outside threads
|
||||
}
|
||||
|
||||
const newDraft = {
|
||||
...currentDraft,
|
||||
@ -986,7 +999,7 @@ addActionHandler('sendMessageAction', async (global, actions, payload): Promise<
|
||||
if (selectIsChatWithSelf(global, chatId)) return;
|
||||
|
||||
const chat = selectChat(global, chatId)!;
|
||||
if (!chat) return;
|
||||
if (!chat || chat.isMonoforum) return;
|
||||
const user = selectUser(global, chatId);
|
||||
if (user && (isUserBot(user) || isDeletedUser(user))) return;
|
||||
|
||||
@ -2140,6 +2153,7 @@ addActionHandler('openChatOrTopicWithReplyInDraft', (global, actions, payload):
|
||||
replyToMsgId: replyingInfo.messageId,
|
||||
replyToTopId: replyingInfo.toThreadId,
|
||||
replyToPeerId: currentChatId,
|
||||
monoforumPeerId: replyingInfo.toThreadId,
|
||||
quoteText: replyingInfo.quoteText,
|
||||
quoteOffset: replyingInfo.quoteOffset,
|
||||
} as ApiInputMessageReplyInfo;
|
||||
|
||||
@ -30,6 +30,8 @@ import {
|
||||
selectChatMessage,
|
||||
selectCurrentChat,
|
||||
selectCurrentMessageList,
|
||||
selectIsChatWithBot,
|
||||
selectIsChatWithSelf,
|
||||
selectIsCurrentUserPremium,
|
||||
selectIsTrustedBot,
|
||||
selectPeerPaidMessagesStars,
|
||||
@ -344,11 +346,13 @@ addActionHandler('showAllowedMessageTypesNotification', (global, actions, payloa
|
||||
const chat = selectChat(global, chatId);
|
||||
if (!chat) return;
|
||||
const chatFullInfo = selectChatFullInfo(global, chatId);
|
||||
const isSavedMessages = chatId ? selectIsChatWithSelf(global, chatId) : undefined;
|
||||
const isChatWithBot = chatId ? selectIsChatWithBot(global, chat) : undefined;
|
||||
|
||||
const {
|
||||
canSendPlainText, canSendPhotos, canSendVideos, canSendDocuments, canSendAudios,
|
||||
canSendStickers, canSendRoundVideos, canSendVoices,
|
||||
} = getAllowedAttachmentOptions(chat, chatFullInfo);
|
||||
} = getAllowedAttachmentOptions(chat, chatFullInfo, isChatWithBot, isSavedMessages);
|
||||
const allowedContent = compact([
|
||||
canSendPlainText ? 'Chat.SendAllowedContentTypeText' : undefined,
|
||||
canSendPhotos ? 'Chat.SendAllowedContentTypePhoto' : undefined,
|
||||
|
||||
@ -47,6 +47,10 @@ export function isChatChannel(chat: ApiChat) {
|
||||
return chat.type === 'chatTypeChannel';
|
||||
}
|
||||
|
||||
export function isChatMonoforum(chat: ApiChat) {
|
||||
return chat.isMonoforum;
|
||||
}
|
||||
|
||||
export function isCommonBoxChat(chat: ApiChat) {
|
||||
return chat.type === 'chatTypePrivate' || chat.type === 'chatTypeBasicGroup';
|
||||
}
|
||||
@ -152,7 +156,8 @@ export function getCanPostInChat(
|
||||
}
|
||||
|
||||
if (chat.isRestricted || chat.isForbidden || chat.migratedTo
|
||||
|| (!isMessageThread && chat.isNotJoined) || isSystemBot(chat.id) || isAnonymousForwardsChat(chat.id)) {
|
||||
|| (chat.isNotJoined && !isChatMonoforum(chat) && !isMessageThread)
|
||||
|| isSystemBot(chat.id) || isAnonymousForwardsChat(chat.id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -190,6 +195,7 @@ export function getAllowedAttachmentOptions(
|
||||
chat?: ApiChat,
|
||||
chatFullInfo?: ApiChatFullInfo,
|
||||
isChatWithBot = false,
|
||||
isSavedMessages = false,
|
||||
isStoryReply = false,
|
||||
paidMessagesStars?: number,
|
||||
isInScheduledList = false,
|
||||
@ -215,9 +221,9 @@ export function getAllowedAttachmentOptions(
|
||||
|
||||
return {
|
||||
canAttachMedia: isAdmin || isStoryReply || !isUserRightBanned(chat, 'sendMedia', chatFullInfo),
|
||||
canAttachPolls: !isStoryReply
|
||||
canAttachPolls: !isStoryReply && !chat.isMonoforum
|
||||
&& (isAdmin || !isUserRightBanned(chat, 'sendPolls', chatFullInfo))
|
||||
&& (!isUserId(chat.id) || isChatWithBot),
|
||||
&& (!isUserId(chat.id) || isChatWithBot || isSavedMessages),
|
||||
canSendStickers: isAdmin || isStoryReply || !isUserRightBanned(chat, 'sendStickers', chatFullInfo),
|
||||
canSendGifs: isAdmin || isStoryReply || !isUserRightBanned(chat, 'sendGifs', chatFullInfo),
|
||||
canAttachEmbedLinks: !isStoryReply && (isAdmin || !isUserRightBanned(chat, 'embedLinks', chatFullInfo)),
|
||||
|
||||
@ -349,3 +349,28 @@ export function selectChatLastMessage<T extends GlobalState>(
|
||||
const realChatId = listType === 'saved' ? global.currentUserId! : chatId;
|
||||
return global.messages.byChatId[realChatId]?.byId[id];
|
||||
}
|
||||
|
||||
export function selectIsMonoforumAdmin<T extends GlobalState>(
|
||||
global: T, chatId: string,
|
||||
) {
|
||||
const chat = selectChat(global, chatId);
|
||||
if (!chat?.isMonoforum) return;
|
||||
|
||||
const channel = selectMonoforumChannel(global, chatId);
|
||||
if (!channel) return;
|
||||
|
||||
return Boolean(chat.isCreator || chat.adminRights || channel.isCreator || channel.adminRights);
|
||||
}
|
||||
|
||||
/**
|
||||
* Only selects monoforum channel for monoforum chats.
|
||||
* Returns `undefined` for other chats, including channels that have linked monoforum.
|
||||
*/
|
||||
export function selectMonoforumChannel<T extends GlobalState>(
|
||||
global: T, chatId: string,
|
||||
) {
|
||||
const chat = selectChat(global, chatId);
|
||||
if (!chat) return;
|
||||
|
||||
return chat.isMonoforum ? selectChat(global, chat.linkedMonoforumId!) : undefined;
|
||||
}
|
||||
|
||||
@ -72,7 +72,7 @@ export function selectCanManage<T extends GlobalState>(
|
||||
chatId: string,
|
||||
) {
|
||||
const chat = selectChat(global, chatId);
|
||||
if (!chat || chat.isRestricted) return false;
|
||||
if (!chat || chat.isRestricted || chat.isMonoforum) return false;
|
||||
|
||||
const isPrivate = isUserId(chat.id);
|
||||
const user = isPrivate ? selectUser(global, chatId) : undefined;
|
||||
|
||||
@ -72,6 +72,7 @@ import {
|
||||
selectChat,
|
||||
selectChatFullInfo,
|
||||
selectChatLastMessageId,
|
||||
selectIsChatWithBot,
|
||||
selectIsChatWithSelf,
|
||||
selectRequestedChatTranslationLanguage,
|
||||
} from './chats';
|
||||
@ -651,6 +652,7 @@ export function selectAllowedMessageActionsSlow<T extends GlobalState>(
|
||||
const { content } = message;
|
||||
const isDocumentSticker = isMessageDocumentSticker(message);
|
||||
const isBoostMessage = message.content.action?.type === 'boostApply';
|
||||
const isMonoforum = chat.isMonoforum;
|
||||
|
||||
const hasChatPinPermission = (chat.isCreator
|
||||
|| (!isChannel && !isUserRightBanned(chat, 'pinMessages'))
|
||||
@ -726,7 +728,7 @@ export function selectAllowedMessageActionsSlow<T extends GlobalState>(
|
||||
const canFaveSticker = !isAction && hasSticker && !hasFavoriteSticker;
|
||||
const canUnfaveSticker = !isAction && hasFavoriteSticker;
|
||||
const canCopy = !isAction;
|
||||
const canCopyLink = !isLocal && !isAction && (isChannel || isSuperGroup);
|
||||
const canCopyLink = !isLocal && !isAction && (isChannel || isSuperGroup) && !isMonoforum;
|
||||
const canSelect = !isLocal && !isAction;
|
||||
|
||||
const canDownload = Boolean(content.webPage?.document || content.webPage?.video || content.webPage?.photo
|
||||
@ -1462,7 +1464,10 @@ export function selectForwardsCanBeSentToChat<T extends GlobalState>(
|
||||
|
||||
const chatFullInfo = selectChatFullInfo(global, toChatId);
|
||||
const chatMessages = selectChatMessages(global, fromChatId!);
|
||||
const options = getAllowedAttachmentOptions(chat, chatFullInfo);
|
||||
|
||||
const isSavedMessages = toChatId ? selectIsChatWithSelf(global, toChatId) : undefined;
|
||||
const isChatWithBot = toChatId ? selectIsChatWithBot(global, chat) : undefined;
|
||||
const options = getAllowedAttachmentOptions(chat, chatFullInfo, isChatWithBot, isSavedMessages);
|
||||
return !messageIds!.some((messageId) => сheckMessageSendingDenied(chatMessages[messageId], options));
|
||||
}
|
||||
function сheckMessageSendingDenied(message: ApiMessage, options: IAllowedAttachmentOptions) {
|
||||
|
||||
@ -354,7 +354,9 @@ export interface ActionPayloads {
|
||||
} & WithTabId;
|
||||
openThreadWithInfo: ActionPayloads['openThread'] & WithTabId;
|
||||
openLinkedChat: { id: string } & WithTabId;
|
||||
loadMoreMembers: WithTabId | undefined;
|
||||
loadMoreMembers: {
|
||||
chatId: string;
|
||||
};
|
||||
setActiveChatFolder: {
|
||||
activeChatFolder: number;
|
||||
} & WithTabId;
|
||||
|
||||
@ -12,5 +12,5 @@ for (const tl of Object.values(Api)) {
|
||||
}
|
||||
}
|
||||
|
||||
export const LAYER = 203;
|
||||
export const LAYER = 204;
|
||||
export { tlobjects };
|
||||
|
||||
167
src/lib/gramjs/tl/api.d.ts
vendored
167
src/lib/gramjs/tl/api.d.ts
vendored
File diff suppressed because one or more lines are too long
@ -80,7 +80,7 @@ userStatusLastMonth#65899777 flags:# by_me:flags.0?true = UserStatus;
|
||||
chatEmpty#29562865 id:long = Chat;
|
||||
chat#41cbf256 flags:# creator:flags.0?true left:flags.2?true deactivated:flags.5?true call_active:flags.23?true call_not_empty:flags.24?true noforwards:flags.25?true id:long title:string photo:ChatPhoto participants_count:int date:int version:int migrated_to:flags.6?InputChannel admin_rights:flags.14?ChatAdminRights default_banned_rights:flags.18?ChatBannedRights = Chat;
|
||||
chatForbidden#6592a1a7 id:long title:string = Chat;
|
||||
channel#7482147e flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true signatures:flags.11?true min:flags.12?true scam:flags.19?true has_link:flags.20?true has_geo:flags.21?true slowmode_enabled:flags.22?true call_active:flags.23?true call_not_empty:flags.24?true fake:flags.25?true gigagroup:flags.26?true noforwards:flags.27?true join_to_send:flags.28?true join_request:flags.29?true forum:flags.30?true flags2:# stories_hidden:flags2.1?true stories_hidden_min:flags2.2?true stories_unavailable:flags2.3?true signature_profiles:flags2.12?true autotranslation:flags2.15?true id:long access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int restriction_reason:flags.9?Vector<RestrictionReason> admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int usernames:flags2.0?Vector<Username> stories_max_id:flags2.4?int color:flags2.7?PeerColor profile_color:flags2.8?PeerColor emoji_status:flags2.9?EmojiStatus level:flags2.10?int subscription_until_date:flags2.11?int bot_verification_icon:flags2.13?long send_paid_messages_stars:flags2.14?long = Chat;
|
||||
channel#fe685355 flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true signatures:flags.11?true min:flags.12?true scam:flags.19?true has_link:flags.20?true has_geo:flags.21?true slowmode_enabled:flags.22?true call_active:flags.23?true call_not_empty:flags.24?true fake:flags.25?true gigagroup:flags.26?true noforwards:flags.27?true join_to_send:flags.28?true join_request:flags.29?true forum:flags.30?true flags2:# stories_hidden:flags2.1?true stories_hidden_min:flags2.2?true stories_unavailable:flags2.3?true signature_profiles:flags2.12?true autotranslation:flags2.15?true broadcast_messages_allowed:flags2.16?true monoforum:flags2.17?true forum_tabs:flags2.19?true id:long access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int restriction_reason:flags.9?Vector<RestrictionReason> admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int usernames:flags2.0?Vector<Username> stories_max_id:flags2.4?int color:flags2.7?PeerColor profile_color:flags2.8?PeerColor emoji_status:flags2.9?EmojiStatus level:flags2.10?int subscription_until_date:flags2.11?int bot_verification_icon:flags2.13?long send_paid_messages_stars:flags2.14?long linked_monoforum_id:flags2.18?long = Chat;
|
||||
channelForbidden#17d493d5 flags:# broadcast:flags.5?true megagroup:flags.8?true id:long access_hash:long title:string until_date:flags.16?int = Chat;
|
||||
chatFull#2633421b flags:# can_set_username:flags.7?true has_scheduled:flags.8?true translations_disabled:flags.19?true id:long about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:flags.13?ExportedChatInvite bot_info:flags.3?Vector<BotInfo> pinned_msg_id:flags.6?int folder_id:flags.11?int call:flags.12?InputGroupCall ttl_period:flags.14?int groupcall_default_join_as:flags.15?Peer theme_emoticon:flags.16?string requests_pending:flags.17?int recent_requesters:flags.17?Vector<long> available_reactions:flags.18?ChatReactions reactions_limit:flags.20?int = ChatFull;
|
||||
channelFull#52d6806b flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_set_location:flags.16?true has_scheduled:flags.19?true can_view_stats:flags.20?true blocked:flags.22?true flags2:# can_delete_channel:flags2.0?true antispam:flags2.1?true participants_hidden:flags2.2?true translations_disabled:flags2.3?true stories_pinned_available:flags2.5?true view_forum_as_messages:flags2.6?true restricted_sponsored:flags2.11?true can_view_revenue:flags2.12?true paid_media_allowed:flags2.14?true can_view_stars_revenue:flags2.15?true paid_reactions_available:flags2.16?true stargifts_available:flags2.19?true paid_messages_available:flags2.20?true id:long about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:flags.23?ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?long migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?long location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int call:flags.21?InputGroupCall ttl_period:flags.24?int pending_suggestions:flags.25?Vector<string> groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string requests_pending:flags.28?int recent_requesters:flags.28?Vector<long> default_send_as:flags.29?Peer available_reactions:flags.30?ChatReactions reactions_limit:flags2.13?int stories:flags2.4?PeerStories wallpaper:flags2.7?WallPaper boosts_applied:flags2.8?int boosts_unrestrict:flags2.9?int emojiset:flags2.10?StickerSet bot_verification:flags2.17?BotVerification stargifts_count:flags2.18?int = ChatFull;
|
||||
@ -160,7 +160,7 @@ messageActionPrizeStars#b00c47a2 flags:# unclaimed:flags.0?true stars:long trans
|
||||
messageActionStarGift#4717e8a4 flags:# name_hidden:flags.0?true saved:flags.2?true converted:flags.3?true upgraded:flags.5?true refunded:flags.9?true can_upgrade:flags.10?true gift:StarGift message:flags.1?TextWithEntities convert_stars:flags.4?long upgrade_msg_id:flags.5?int upgrade_stars:flags.8?long from_id:flags.11?Peer peer:flags.12?Peer saved_id:flags.12?long = MessageAction;
|
||||
messageActionStarGiftUnique#2e3ae60e flags:# upgrade:flags.0?true transferred:flags.1?true saved:flags.2?true refunded:flags.5?true gift:StarGift can_export_at:flags.3?int transfer_stars:flags.4?long from_id:flags.6?Peer peer:flags.7?Peer saved_id:flags.7?long resale_stars:flags.8?long can_transfer_at:flags.9?int can_resell_at:flags.10?int = MessageAction;
|
||||
messageActionPaidMessagesRefunded#ac1f1fcd count:int stars:long = MessageAction;
|
||||
messageActionPaidMessagesPrice#bcd71419 stars:long = MessageAction;
|
||||
messageActionPaidMessagesPrice#84b88578 flags:# broadcast_messages_allowed:flags.0?true stars:long = MessageAction;
|
||||
messageActionConferenceCall#2ffe2f7a flags:# missed:flags.0?true active:flags.1?true video:flags.4?true call_id:long duration:flags.2?int other_participants:flags.3?Vector<Peer> = MessageAction;
|
||||
dialog#d58a08c6 flags:# pinned:flags.2?true unread_mark:flags.3?true view_forum_as_messages:flags.6?true peer:Peer top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_mentions_count:int unread_reactions_count:int notify_settings:PeerNotifySettings pts:flags.0?int draft:flags.1?DraftMessage folder_id:flags.4?int ttl_period:flags.5?int = Dialog;
|
||||
dialogFolder#71bd134c flags:# pinned:flags.2?true folder:Folder peer:Peer top_message:int unread_muted_peers_count:int unread_unmuted_peers_count:int unread_muted_messages_count:int unread_unmuted_messages_count:int = Dialog;
|
||||
@ -279,7 +279,7 @@ updateBotCallbackQuery#b9cfc48d flags:# query_id:long user_id:long peer:Peer msg
|
||||
updateEditMessage#e40370a3 message:Message pts:int pts_count:int = Update;
|
||||
updateInlineBotCallbackQuery#691e9052 flags:# query_id:long user_id:long msg_id:InputBotInlineMessageID chat_instance:long data:flags.0?bytes game_short_name:flags.1?string = Update;
|
||||
updateReadChannelOutbox#b75f99a9 channel_id:long max_id:int = Update;
|
||||
updateDraftMessage#1b49ec6d flags:# peer:Peer top_msg_id:flags.0?int draft:DraftMessage = Update;
|
||||
updateDraftMessage#edfc111e flags:# peer:Peer top_msg_id:flags.0?int saved_peer_id:flags.1?Peer draft:DraftMessage = Update;
|
||||
updateReadFeaturedStickers#571d2742 = Update;
|
||||
updateRecentStickers#9a422c20 = Update;
|
||||
updateConfig#a229dd06 = Update;
|
||||
@ -295,10 +295,10 @@ updatePhoneCall#ab0f6b1e phone_call:PhoneCall = Update;
|
||||
updateLangPackTooLong#46560264 lang_code:string = Update;
|
||||
updateLangPack#56022f4d difference:LangPackDifference = Update;
|
||||
updateFavedStickers#e511996d = Update;
|
||||
updateChannelReadMessagesContents#ea29055d flags:# channel_id:long top_msg_id:flags.0?int messages:Vector<int> = Update;
|
||||
updateChannelReadMessagesContents#25f324f7 flags:# channel_id:long top_msg_id:flags.0?int saved_peer_id:flags.1?Peer messages:Vector<int> = Update;
|
||||
updateContactsReset#7084a7be = Update;
|
||||
updateChannelAvailableMessages#b23fc698 channel_id:long available_min_id:int = Update;
|
||||
updateDialogUnreadMark#e16459c3 flags:# unread:flags.0?true peer:DialogPeer = Update;
|
||||
updateDialogUnreadMark#b658f23e flags:# unread:flags.0?true peer:DialogPeer saved_peer_id:flags.1?Peer = Update;
|
||||
updateMessagePoll#aca1657b flags:# poll_id:long poll:flags.0?Poll results:PollResults = Update;
|
||||
updateChatDefaultBannedRights#54c01850 peer:Peer default_banned_rights:ChatBannedRights version:int = Update;
|
||||
updateFolderPeers#19360dc0 folder_peers:Vector<FolderPeer> pts:int pts_count:int = Update;
|
||||
@ -332,7 +332,7 @@ updateGroupCallConnection#b783982 flags:# presentation:flags.0?true params:DataJ
|
||||
updateBotCommands#4d712f2e peer:Peer bot_id:long commands:Vector<BotCommand> = Update;
|
||||
updatePendingJoinRequests#7063c3db peer:Peer requests_pending:int recent_requesters:Vector<long> = Update;
|
||||
updateBotChatInviteRequester#11dfa986 peer:Peer date:int user_id:long about:string invite:ExportedChatInvite qts:int = Update;
|
||||
updateMessageReactions#5e1b3cb8 flags:# peer:Peer msg_id:int top_msg_id:flags.0?int reactions:MessageReactions = Update;
|
||||
updateMessageReactions#1e297bfa flags:# peer:Peer msg_id:int top_msg_id:flags.0?int saved_peer_id:flags.1?Peer reactions:MessageReactions = Update;
|
||||
updateAttachMenuBots#17b7a20b = Update;
|
||||
updateWebViewResultSent#1592b79d query_id:long = Update;
|
||||
updateBotMenuButton#14b85813 bot_id:long button:BotMenuButton = Update;
|
||||
@ -380,6 +380,8 @@ updateBotPurchasedPaidMedia#283bd312 user_id:long payload:string qts:int = Updat
|
||||
updatePaidReactionPrivacy#8b725fce private:PaidReactionPrivacy = Update;
|
||||
updateSentPhoneCode#504aa18f sent_code:auth.SentCode = Update;
|
||||
updateGroupCallChainBlocks#a477288f call:InputGroupCall sub_chain_id:int blocks:Vector<bytes> next_offset:int = Update;
|
||||
updateReadMonoForumInbox#77b0e372 channel_id:long saved_peer_id:Peer read_max_id:int = Update;
|
||||
updateReadMonoForumOutbox#a4a79376 channel_id:long saved_peer_id:Peer read_max_id:int = Update;
|
||||
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
|
||||
updates.differenceEmpty#5d75a138 date:int seq:int = updates.Difference;
|
||||
updates.difference#f49ca0 new_messages:Vector<Message> new_encrypted_messages:Vector<EncryptedMessage> other_updates:Vector<Update> chats:Vector<Chat> users:Vector<User> state:updates.State = updates.Difference;
|
||||
@ -1234,8 +1236,9 @@ storyViewPublicForward#9083670b flags:# blocked:flags.0?true blocked_my_stories_
|
||||
storyViewPublicRepost#bd74cf49 flags:# blocked:flags.0?true blocked_my_stories_from:flags.1?true peer_id:Peer story:StoryItem = StoryView;
|
||||
stories.storyViewsList#59d78fc5 flags:# count:int views_count:int forwards_count:int reactions_count:int views:Vector<StoryView> chats:Vector<Chat> users:Vector<User> next_offset:flags.0?string = stories.StoryViewsList;
|
||||
stories.storyViews#de9eed1d views:Vector<StoryViews> users:Vector<User> = stories.StoryViews;
|
||||
inputReplyToMessage#22c0f6d5 flags:# reply_to_msg_id:int top_msg_id:flags.0?int reply_to_peer_id:flags.1?InputPeer quote_text:flags.2?string quote_entities:flags.3?Vector<MessageEntity> quote_offset:flags.4?int = InputReplyTo;
|
||||
inputReplyToMessage#b07038b0 flags:# reply_to_msg_id:int top_msg_id:flags.0?int reply_to_peer_id:flags.1?InputPeer quote_text:flags.2?string quote_entities:flags.3?Vector<MessageEntity> quote_offset:flags.4?int monoforum_peer_id:flags.5?InputPeer = InputReplyTo;
|
||||
inputReplyToStory#5881323a peer:InputPeer story_id:int = InputReplyTo;
|
||||
inputReplyToMonoForum#69d66c45 monoforum_peer_id:InputPeer = InputReplyTo;
|
||||
exportedStoryLink#3fc9053b link:string = ExportedStoryLink;
|
||||
storiesStealthMode#712e27fd flags:# active_until_date:flags.0?int cooldown_until_date:flags.1?int = StoriesStealthMode;
|
||||
mediaAreaCoordinates#cfc9e002 flags:# x:double y:double w:double h:double rotation:double radius:flags.0?double = MediaAreaCoordinates;
|
||||
@ -1280,6 +1283,7 @@ storyReactionPublicForward#bbab2643 message:Message = StoryReaction;
|
||||
storyReactionPublicRepost#cfcd0f13 peer_id:Peer story:StoryItem = StoryReaction;
|
||||
stories.storyReactionsList#aa5f789c flags:# count:int reactions:Vector<StoryReaction> chats:Vector<Chat> users:Vector<User> next_offset:flags.0?string = stories.StoryReactionsList;
|
||||
savedDialog#bd87cb6c flags:# pinned:flags.2?true peer:Peer top_message:int = SavedDialog;
|
||||
monoForumDialog#64407ea7 flags:# unread_mark:flags.3?true peer:Peer top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_reactions_count:int draft:flags.1?DraftMessage = SavedDialog;
|
||||
messages.savedDialogs#f83ae221 dialogs:Vector<SavedDialog> messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.SavedDialogs;
|
||||
messages.savedDialogsSlice#44ba9dd9 count:int dialogs:Vector<SavedDialog> messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.SavedDialogs;
|
||||
messages.savedDialogsNotModified#c01f6fe8 count:int = messages.SavedDialogs;
|
||||
@ -1527,7 +1531,7 @@ messages.receivedMessages#5a954c0 max_id:int = Vector<ReceivedNotifyMessage>;
|
||||
messages.setTyping#58943ee2 flags:# peer:InputPeer top_msg_id:flags.0?int action:SendMessageAction = Bool;
|
||||
messages.sendMessage#fbf2340a flags:# no_webpage:flags.1?true silent:flags.5?true background:flags.6?true clear_draft:flags.7?true noforwards:flags.14?true update_stickersets_order:flags.15?true invert_media:flags.16?true allow_paid_floodskip:flags.19?true peer:InputPeer reply_to:flags.0?InputReplyTo message:string random_id:long reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> schedule_date:flags.10?int send_as:flags.13?InputPeer quick_reply_shortcut:flags.17?InputQuickReplyShortcut effect:flags.18?long allow_paid_stars:flags.21?long = Updates;
|
||||
messages.sendMedia#a550cd78 flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true noforwards:flags.14?true update_stickersets_order:flags.15?true invert_media:flags.16?true allow_paid_floodskip:flags.19?true peer:InputPeer reply_to:flags.0?InputReplyTo media:InputMedia message:string random_id:long reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> schedule_date:flags.10?int send_as:flags.13?InputPeer quick_reply_shortcut:flags.17?InputQuickReplyShortcut effect:flags.18?long allow_paid_stars:flags.21?long = Updates;
|
||||
messages.forwardMessages#bb9fa475 flags:# silent:flags.5?true background:flags.6?true with_my_score:flags.8?true drop_author:flags.11?true drop_media_captions:flags.12?true noforwards:flags.14?true allow_paid_floodskip:flags.19?true from_peer:InputPeer id:Vector<int> random_id:Vector<long> to_peer:InputPeer top_msg_id:flags.9?int schedule_date:flags.10?int send_as:flags.13?InputPeer quick_reply_shortcut:flags.17?InputQuickReplyShortcut video_timestamp:flags.20?int allow_paid_stars:flags.21?long = Updates;
|
||||
messages.forwardMessages#38f0188c flags:# silent:flags.5?true background:flags.6?true with_my_score:flags.8?true drop_author:flags.11?true drop_media_captions:flags.12?true noforwards:flags.14?true allow_paid_floodskip:flags.19?true from_peer:InputPeer id:Vector<int> random_id:Vector<long> to_peer:InputPeer top_msg_id:flags.9?int reply_to:flags.22?InputReplyTo schedule_date:flags.10?int send_as:flags.13?InputPeer quick_reply_shortcut:flags.17?InputQuickReplyShortcut video_timestamp:flags.20?int allow_paid_stars:flags.21?long = Updates;
|
||||
messages.reportSpam#cf1592db peer:InputPeer = Bool;
|
||||
messages.getPeerSettings#efd9a6a2 peer:InputPeer = messages.PeerSettings;
|
||||
messages.report#fc78af9b peer:InputPeer id:Vector<int> option:bytes message:string = ReportResult;
|
||||
@ -1578,7 +1582,7 @@ messages.getUnreadMentions#f107e790 flags:# peer:InputPeer top_msg_id:flags.0?in
|
||||
messages.readMentions#36e5bf4d flags:# peer:InputPeer top_msg_id:flags.0?int = messages.AffectedHistory;
|
||||
messages.sendMultiMedia#1bf89d74 flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true noforwards:flags.14?true update_stickersets_order:flags.15?true invert_media:flags.16?true allow_paid_floodskip:flags.19?true peer:InputPeer reply_to:flags.0?InputReplyTo multi_media:Vector<InputSingleMedia> schedule_date:flags.10?int send_as:flags.13?InputPeer quick_reply_shortcut:flags.17?InputQuickReplyShortcut effect:flags.18?long allow_paid_stars:flags.21?long = Updates;
|
||||
messages.searchStickerSets#35705b8a flags:# exclude_featured:flags.0?true q:string hash:long = messages.FoundStickerSets;
|
||||
messages.markDialogUnread#c286d98f flags:# unread:flags.0?true peer:InputDialogPeer = Bool;
|
||||
messages.markDialogUnread#8c5006f8 flags:# unread:flags.0?true parent_peer:flags.1?InputPeer peer:InputDialogPeer = Bool;
|
||||
messages.updatePinnedMessage#d2aaf7ec flags:# silent:flags.0?true unpin:flags.1?true pm_oneside:flags.2?true peer:InputPeer id:int = Updates;
|
||||
messages.sendVote#10ea6184 peer:InputPeer msg_id:int options:Vector<bytes> = Updates;
|
||||
messages.getOnlines#6e2be050 peer:InputPeer = ChatOnlines;
|
||||
@ -1599,7 +1603,7 @@ messages.updateDialogFiltersOrder#c563c1e4 order:Vector<int> = Bool;
|
||||
messages.getReplies#22ddd30c peer:InputPeer msg_id:int offset_id:int offset_date:int add_offset:int limit:int max_id:int min_id:int hash:long = messages.Messages;
|
||||
messages.getDiscussionMessage#446972fd peer:InputPeer msg_id:int = messages.DiscussionMessage;
|
||||
messages.readDiscussion#f731a9f4 peer:InputPeer msg_id:int read_max_id:int = Bool;
|
||||
messages.unpinAllMessages#ee22b9a8 flags:# peer:InputPeer top_msg_id:flags.0?int = messages.AffectedHistory;
|
||||
messages.unpinAllMessages#62dd747 flags:# peer:InputPeer top_msg_id:flags.0?int saved_peer_id:flags.1?InputPeer = messages.AffectedHistory;
|
||||
messages.deleteChat#5bd0ee50 chat_id:long = Bool;
|
||||
messages.getExportedChatInvites#a2b5a3f6 flags:# revoked:flags.3?true peer:InputPeer admin_id:InputUser offset_date:flags.2?int offset_link:flags.2?string limit:int = messages.ExportedChatInvites;
|
||||
messages.editExportedChatInvite#bdca2f75 flags:# revoked:flags.2?true peer:InputPeer link:string expire_date:flags.0?int usage_limit:flags.1?int request_needed:flags.3?Bool title:flags.4?string = messages.ExportedChatInvite;
|
||||
@ -1618,8 +1622,8 @@ messages.setChatAvailableReactions#864b2581 flags:# peer:InputPeer available_rea
|
||||
messages.getAvailableReactions#18dea0ac hash:int = messages.AvailableReactions;
|
||||
messages.setDefaultReaction#4f47a016 reaction:Reaction = Bool;
|
||||
messages.translateText#63183030 flags:# peer:flags.0?InputPeer id:flags.0?Vector<int> text:flags.1?Vector<TextWithEntities> to_lang:string = messages.TranslatedText;
|
||||
messages.getUnreadReactions#3223495b flags:# peer:InputPeer top_msg_id:flags.0?int offset_id:int add_offset:int limit:int max_id:int min_id:int = messages.Messages;
|
||||
messages.readReactions#54aa7f8e flags:# peer:InputPeer top_msg_id:flags.0?int = messages.AffectedHistory;
|
||||
messages.getUnreadReactions#bd7f90ac flags:# peer:InputPeer top_msg_id:flags.0?int saved_peer_id:flags.1?InputPeer offset_id:int add_offset:int limit:int max_id:int min_id:int = messages.Messages;
|
||||
messages.readReactions#9ec44f93 flags:# peer:InputPeer top_msg_id:flags.0?int saved_peer_id:flags.1?InputPeer = messages.AffectedHistory;
|
||||
messages.getAttachMenuBots#16fcc2cb hash:long = AttachMenuBots;
|
||||
messages.getAttachMenuBot#77216192 bot:InputUser = AttachMenuBotsBot;
|
||||
messages.toggleBotInAttachMenu#69f59d69 flags:# write_allowed:flags.0?true bot:InputUser enabled:Bool = Bool;
|
||||
@ -1639,9 +1643,9 @@ messages.getExtendedMedia#84f80814 peer:InputPeer id:Vector<int> = Updates;
|
||||
messages.togglePeerTranslations#e47cb579 flags:# disabled:flags.0?true peer:InputPeer = Bool;
|
||||
messages.getBotApp#34fdc5c3 app:InputBotApp hash:long = messages.BotApp;
|
||||
messages.requestAppWebView#53618bce flags:# write_allowed:flags.0?true compact:flags.7?true fullscreen:flags.8?true peer:InputPeer app:InputBotApp start_param:flags.1?string theme_params:flags.2?DataJSON platform:string = WebViewResult;
|
||||
messages.getSavedDialogs#5381d21a flags:# exclude_pinned:flags.0?true offset_date:int offset_id:int offset_peer:InputPeer limit:int hash:long = messages.SavedDialogs;
|
||||
messages.getSavedHistory#3d9a414d peer:InputPeer offset_id:int offset_date:int add_offset:int limit:int max_id:int min_id:int hash:long = messages.Messages;
|
||||
messages.deleteSavedHistory#6e98102b flags:# peer:InputPeer max_id:int min_date:flags.2?int max_date:flags.3?int = messages.AffectedHistory;
|
||||
messages.getSavedDialogs#1e91fc99 flags:# exclude_pinned:flags.0?true parent_peer:flags.1?InputPeer offset_date:int offset_id:int offset_peer:InputPeer limit:int hash:long = messages.SavedDialogs;
|
||||
messages.getSavedHistory#998ab009 flags:# parent_peer:flags.0?InputPeer peer:InputPeer offset_id:int offset_date:int add_offset:int limit:int max_id:int min_id:int hash:long = messages.Messages;
|
||||
messages.deleteSavedHistory#4dc5085f flags:# parent_peer:flags.0?InputPeer peer:InputPeer max_id:int min_date:flags.2?int max_date:flags.3?int = messages.AffectedHistory;
|
||||
messages.getPinnedSavedDialogs#d63d94e0 = messages.SavedDialogs;
|
||||
messages.toggleSavedDialogPin#ac81bbde flags:# pinned:flags.0?true peer:InputDialogPeer = Bool;
|
||||
messages.getSavedReactionTags#3637e05b flags:# peer:flags.0?InputPeer hash:long = messages.SavedReactionTags;
|
||||
@ -1715,7 +1719,7 @@ channels.toggleJoinRequest#4c2985b6 channel:InputChannel enabled:Bool = Updates;
|
||||
channels.reorderUsernames#b45ced1d channel:InputChannel order:Vector<string> = Bool;
|
||||
channels.toggleUsername#50f24105 channel:InputChannel username:string active:Bool = Bool;
|
||||
channels.deactivateAllUsernames#a245dd3 channel:InputChannel = Bool;
|
||||
channels.toggleForum#a4298b29 channel:InputChannel enabled:Bool = Updates;
|
||||
channels.toggleForum#3ff75734 channel:InputChannel enabled:Bool tabs:Bool = Updates;
|
||||
channels.createForumTopic#f40c0224 flags:# channel:InputChannel title:string icon_color:flags.0?int icon_emoji_id:flags.3?long random_id:long send_as:flags.2?InputPeer = Updates;
|
||||
channels.getForumTopics#de560d1 flags:# channel:InputChannel q:flags.0?string offset_date:int offset_id:int offset_topic:int limit:int = messages.ForumTopics;
|
||||
channels.getForumTopicsByID#b0831eb9 channel:InputChannel topics:Vector<int> = messages.ForumTopics;
|
||||
@ -1726,7 +1730,7 @@ channels.toggleParticipantsHidden#6a6e7854 channel:InputChannel enabled:Bool = U
|
||||
channels.toggleViewForumAsMessages#9738bb15 channel:InputChannel enabled:Bool = Updates;
|
||||
channels.getChannelRecommendations#25a71742 flags:# channel:flags.0?InputChannel = messages.Chats;
|
||||
channels.searchPosts#d19f987b hashtag:string offset_rate:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages;
|
||||
channels.updatePaidMessagesPrice#fc84653f channel:InputChannel send_paid_messages_stars:long = Updates;
|
||||
channels.updatePaidMessagesPrice#4b12327b flags:# broadcast_messages_allowed:flags.0?true channel:InputChannel send_paid_messages_stars:long = Updates;
|
||||
channels.toggleAutotranslation#167fc0a1 channel:InputChannel enabled:Bool = Updates;
|
||||
bots.setBotInfo#10cf3123 flags:# bot:flags.2?InputUser lang_code:string name:flags.3?string about:flags.0?string description:flags.1?string = Bool;
|
||||
bots.canSendMessage#1359f4e6 bot:InputUser = Bool;
|
||||
@ -1835,4 +1839,4 @@ premium.getBoostsList#60f67660 flags:# gifts:flags.0?true peer:InputPeer offset:
|
||||
premium.getMyBoosts#be77b4a = premium.MyBoosts;
|
||||
premium.applyBoost#6b7da746 flags:# slots:flags.0?Vector<int> peer:InputPeer = premium.MyBoosts;
|
||||
premium.getBoostsStatus#42f1f61 peer:InputPeer = premium.BoostsStatus;
|
||||
fragment.getCollectibleInfo#be1e85ba collectible:InputCollectible = fragment.CollectibleInfo;`;
|
||||
fragment.getCollectibleInfo#be1e85ba collectible:InputCollectible = fragment.CollectibleInfo;`;
|
||||
@ -99,7 +99,7 @@ userStatusLastMonth#65899777 flags:# by_me:flags.0?true = UserStatus;
|
||||
chatEmpty#29562865 id:long = Chat;
|
||||
chat#41cbf256 flags:# creator:flags.0?true left:flags.2?true deactivated:flags.5?true call_active:flags.23?true call_not_empty:flags.24?true noforwards:flags.25?true id:long title:string photo:ChatPhoto participants_count:int date:int version:int migrated_to:flags.6?InputChannel admin_rights:flags.14?ChatAdminRights default_banned_rights:flags.18?ChatBannedRights = Chat;
|
||||
chatForbidden#6592a1a7 id:long title:string = Chat;
|
||||
channel#7482147e flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true signatures:flags.11?true min:flags.12?true scam:flags.19?true has_link:flags.20?true has_geo:flags.21?true slowmode_enabled:flags.22?true call_active:flags.23?true call_not_empty:flags.24?true fake:flags.25?true gigagroup:flags.26?true noforwards:flags.27?true join_to_send:flags.28?true join_request:flags.29?true forum:flags.30?true flags2:# stories_hidden:flags2.1?true stories_hidden_min:flags2.2?true stories_unavailable:flags2.3?true signature_profiles:flags2.12?true autotranslation:flags2.15?true id:long access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int restriction_reason:flags.9?Vector<RestrictionReason> admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int usernames:flags2.0?Vector<Username> stories_max_id:flags2.4?int color:flags2.7?PeerColor profile_color:flags2.8?PeerColor emoji_status:flags2.9?EmojiStatus level:flags2.10?int subscription_until_date:flags2.11?int bot_verification_icon:flags2.13?long send_paid_messages_stars:flags2.14?long = Chat;
|
||||
channel#fe685355 flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true signatures:flags.11?true min:flags.12?true scam:flags.19?true has_link:flags.20?true has_geo:flags.21?true slowmode_enabled:flags.22?true call_active:flags.23?true call_not_empty:flags.24?true fake:flags.25?true gigagroup:flags.26?true noforwards:flags.27?true join_to_send:flags.28?true join_request:flags.29?true forum:flags.30?true flags2:# stories_hidden:flags2.1?true stories_hidden_min:flags2.2?true stories_unavailable:flags2.3?true signature_profiles:flags2.12?true autotranslation:flags2.15?true broadcast_messages_allowed:flags2.16?true monoforum:flags2.17?true forum_tabs:flags2.19?true id:long access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int restriction_reason:flags.9?Vector<RestrictionReason> admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int usernames:flags2.0?Vector<Username> stories_max_id:flags2.4?int color:flags2.7?PeerColor profile_color:flags2.8?PeerColor emoji_status:flags2.9?EmojiStatus level:flags2.10?int subscription_until_date:flags2.11?int bot_verification_icon:flags2.13?long send_paid_messages_stars:flags2.14?long linked_monoforum_id:flags2.18?long = Chat;
|
||||
channelForbidden#17d493d5 flags:# broadcast:flags.5?true megagroup:flags.8?true id:long access_hash:long title:string until_date:flags.16?int = Chat;
|
||||
|
||||
chatFull#2633421b flags:# can_set_username:flags.7?true has_scheduled:flags.8?true translations_disabled:flags.19?true id:long about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:flags.13?ExportedChatInvite bot_info:flags.3?Vector<BotInfo> pinned_msg_id:flags.6?int folder_id:flags.11?int call:flags.12?InputGroupCall ttl_period:flags.14?int groupcall_default_join_as:flags.15?Peer theme_emoticon:flags.16?string requests_pending:flags.17?int recent_requesters:flags.17?Vector<long> available_reactions:flags.18?ChatReactions reactions_limit:flags.20?int = ChatFull;
|
||||
@ -186,7 +186,7 @@ messageActionPrizeStars#b00c47a2 flags:# unclaimed:flags.0?true stars:long trans
|
||||
messageActionStarGift#4717e8a4 flags:# name_hidden:flags.0?true saved:flags.2?true converted:flags.3?true upgraded:flags.5?true refunded:flags.9?true can_upgrade:flags.10?true gift:StarGift message:flags.1?TextWithEntities convert_stars:flags.4?long upgrade_msg_id:flags.5?int upgrade_stars:flags.8?long from_id:flags.11?Peer peer:flags.12?Peer saved_id:flags.12?long = MessageAction;
|
||||
messageActionStarGiftUnique#2e3ae60e flags:# upgrade:flags.0?true transferred:flags.1?true saved:flags.2?true refunded:flags.5?true gift:StarGift can_export_at:flags.3?int transfer_stars:flags.4?long from_id:flags.6?Peer peer:flags.7?Peer saved_id:flags.7?long resale_stars:flags.8?long can_transfer_at:flags.9?int can_resell_at:flags.10?int = MessageAction;
|
||||
messageActionPaidMessagesRefunded#ac1f1fcd count:int stars:long = MessageAction;
|
||||
messageActionPaidMessagesPrice#bcd71419 stars:long = MessageAction;
|
||||
messageActionPaidMessagesPrice#84b88578 flags:# broadcast_messages_allowed:flags.0?true stars:long = MessageAction;
|
||||
messageActionConferenceCall#2ffe2f7a flags:# missed:flags.0?true active:flags.1?true video:flags.4?true call_id:long duration:flags.2?int other_participants:flags.3?Vector<Peer> = MessageAction;
|
||||
|
||||
dialog#d58a08c6 flags:# pinned:flags.2?true unread_mark:flags.3?true view_forum_as_messages:flags.6?true peer:Peer top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_mentions_count:int unread_reactions_count:int notify_settings:PeerNotifySettings pts:flags.0?int draft:flags.1?DraftMessage folder_id:flags.4?int ttl_period:flags.5?int = Dialog;
|
||||
@ -332,7 +332,7 @@ updateBotCallbackQuery#b9cfc48d flags:# query_id:long user_id:long peer:Peer msg
|
||||
updateEditMessage#e40370a3 message:Message pts:int pts_count:int = Update;
|
||||
updateInlineBotCallbackQuery#691e9052 flags:# query_id:long user_id:long msg_id:InputBotInlineMessageID chat_instance:long data:flags.0?bytes game_short_name:flags.1?string = Update;
|
||||
updateReadChannelOutbox#b75f99a9 channel_id:long max_id:int = Update;
|
||||
updateDraftMessage#1b49ec6d flags:# peer:Peer top_msg_id:flags.0?int draft:DraftMessage = Update;
|
||||
updateDraftMessage#edfc111e flags:# peer:Peer top_msg_id:flags.0?int saved_peer_id:flags.1?Peer draft:DraftMessage = Update;
|
||||
updateReadFeaturedStickers#571d2742 = Update;
|
||||
updateRecentStickers#9a422c20 = Update;
|
||||
updateConfig#a229dd06 = Update;
|
||||
@ -348,10 +348,10 @@ updatePhoneCall#ab0f6b1e phone_call:PhoneCall = Update;
|
||||
updateLangPackTooLong#46560264 lang_code:string = Update;
|
||||
updateLangPack#56022f4d difference:LangPackDifference = Update;
|
||||
updateFavedStickers#e511996d = Update;
|
||||
updateChannelReadMessagesContents#ea29055d flags:# channel_id:long top_msg_id:flags.0?int messages:Vector<int> = Update;
|
||||
updateChannelReadMessagesContents#25f324f7 flags:# channel_id:long top_msg_id:flags.0?int saved_peer_id:flags.1?Peer messages:Vector<int> = Update;
|
||||
updateContactsReset#7084a7be = Update;
|
||||
updateChannelAvailableMessages#b23fc698 channel_id:long available_min_id:int = Update;
|
||||
updateDialogUnreadMark#e16459c3 flags:# unread:flags.0?true peer:DialogPeer = Update;
|
||||
updateDialogUnreadMark#b658f23e flags:# unread:flags.0?true peer:DialogPeer saved_peer_id:flags.1?Peer = Update;
|
||||
updateMessagePoll#aca1657b flags:# poll_id:long poll:flags.0?Poll results:PollResults = Update;
|
||||
updateChatDefaultBannedRights#54c01850 peer:Peer default_banned_rights:ChatBannedRights version:int = Update;
|
||||
updateFolderPeers#19360dc0 folder_peers:Vector<FolderPeer> pts:int pts_count:int = Update;
|
||||
@ -385,7 +385,7 @@ updateGroupCallConnection#b783982 flags:# presentation:flags.0?true params:DataJ
|
||||
updateBotCommands#4d712f2e peer:Peer bot_id:long commands:Vector<BotCommand> = Update;
|
||||
updatePendingJoinRequests#7063c3db peer:Peer requests_pending:int recent_requesters:Vector<long> = Update;
|
||||
updateBotChatInviteRequester#11dfa986 peer:Peer date:int user_id:long about:string invite:ExportedChatInvite qts:int = Update;
|
||||
updateMessageReactions#5e1b3cb8 flags:# peer:Peer msg_id:int top_msg_id:flags.0?int reactions:MessageReactions = Update;
|
||||
updateMessageReactions#1e297bfa flags:# peer:Peer msg_id:int top_msg_id:flags.0?int saved_peer_id:flags.1?Peer reactions:MessageReactions = Update;
|
||||
updateAttachMenuBots#17b7a20b = Update;
|
||||
updateWebViewResultSent#1592b79d query_id:long = Update;
|
||||
updateBotMenuButton#14b85813 bot_id:long button:BotMenuButton = Update;
|
||||
@ -433,6 +433,8 @@ updateBotPurchasedPaidMedia#283bd312 user_id:long payload:string qts:int = Updat
|
||||
updatePaidReactionPrivacy#8b725fce private:PaidReactionPrivacy = Update;
|
||||
updateSentPhoneCode#504aa18f sent_code:auth.SentCode = Update;
|
||||
updateGroupCallChainBlocks#a477288f call:InputGroupCall sub_chain_id:int blocks:Vector<bytes> next_offset:int = Update;
|
||||
updateReadMonoForumInbox#77b0e372 channel_id:long saved_peer_id:Peer read_max_id:int = Update;
|
||||
updateReadMonoForumOutbox#a4a79376 channel_id:long saved_peer_id:Peer read_max_id:int = Update;
|
||||
|
||||
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
|
||||
|
||||
@ -1638,8 +1640,9 @@ stories.storyViewsList#59d78fc5 flags:# count:int views_count:int forwards_count
|
||||
|
||||
stories.storyViews#de9eed1d views:Vector<StoryViews> users:Vector<User> = stories.StoryViews;
|
||||
|
||||
inputReplyToMessage#22c0f6d5 flags:# reply_to_msg_id:int top_msg_id:flags.0?int reply_to_peer_id:flags.1?InputPeer quote_text:flags.2?string quote_entities:flags.3?Vector<MessageEntity> quote_offset:flags.4?int = InputReplyTo;
|
||||
inputReplyToMessage#b07038b0 flags:# reply_to_msg_id:int top_msg_id:flags.0?int reply_to_peer_id:flags.1?InputPeer quote_text:flags.2?string quote_entities:flags.3?Vector<MessageEntity> quote_offset:flags.4?int monoforum_peer_id:flags.5?InputPeer = InputReplyTo;
|
||||
inputReplyToStory#5881323a peer:InputPeer story_id:int = InputReplyTo;
|
||||
inputReplyToMonoForum#69d66c45 monoforum_peer_id:InputPeer = InputReplyTo;
|
||||
|
||||
exportedStoryLink#3fc9053b link:string = ExportedStoryLink;
|
||||
|
||||
@ -1712,6 +1715,7 @@ storyReactionPublicRepost#cfcd0f13 peer_id:Peer story:StoryItem = StoryReaction;
|
||||
stories.storyReactionsList#aa5f789c flags:# count:int reactions:Vector<StoryReaction> chats:Vector<Chat> users:Vector<User> next_offset:flags.0?string = stories.StoryReactionsList;
|
||||
|
||||
savedDialog#bd87cb6c flags:# pinned:flags.2?true peer:Peer top_message:int = SavedDialog;
|
||||
monoForumDialog#64407ea7 flags:# unread_mark:flags.3?true peer:Peer top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_reactions_count:int draft:flags.1?DraftMessage = SavedDialog;
|
||||
|
||||
messages.savedDialogs#f83ae221 dialogs:Vector<SavedDialog> messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.SavedDialogs;
|
||||
messages.savedDialogsSlice#44ba9dd9 count:int dialogs:Vector<SavedDialog> messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.SavedDialogs;
|
||||
@ -2177,7 +2181,7 @@ messages.receivedMessages#5a954c0 max_id:int = Vector<ReceivedNotifyMessage>;
|
||||
messages.setTyping#58943ee2 flags:# peer:InputPeer top_msg_id:flags.0?int action:SendMessageAction = Bool;
|
||||
messages.sendMessage#fbf2340a flags:# no_webpage:flags.1?true silent:flags.5?true background:flags.6?true clear_draft:flags.7?true noforwards:flags.14?true update_stickersets_order:flags.15?true invert_media:flags.16?true allow_paid_floodskip:flags.19?true peer:InputPeer reply_to:flags.0?InputReplyTo message:string random_id:long reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> schedule_date:flags.10?int send_as:flags.13?InputPeer quick_reply_shortcut:flags.17?InputQuickReplyShortcut effect:flags.18?long allow_paid_stars:flags.21?long = Updates;
|
||||
messages.sendMedia#a550cd78 flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true noforwards:flags.14?true update_stickersets_order:flags.15?true invert_media:flags.16?true allow_paid_floodskip:flags.19?true peer:InputPeer reply_to:flags.0?InputReplyTo media:InputMedia message:string random_id:long reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> schedule_date:flags.10?int send_as:flags.13?InputPeer quick_reply_shortcut:flags.17?InputQuickReplyShortcut effect:flags.18?long allow_paid_stars:flags.21?long = Updates;
|
||||
messages.forwardMessages#bb9fa475 flags:# silent:flags.5?true background:flags.6?true with_my_score:flags.8?true drop_author:flags.11?true drop_media_captions:flags.12?true noforwards:flags.14?true allow_paid_floodskip:flags.19?true from_peer:InputPeer id:Vector<int> random_id:Vector<long> to_peer:InputPeer top_msg_id:flags.9?int schedule_date:flags.10?int send_as:flags.13?InputPeer quick_reply_shortcut:flags.17?InputQuickReplyShortcut video_timestamp:flags.20?int allow_paid_stars:flags.21?long = Updates;
|
||||
messages.forwardMessages#38f0188c flags:# silent:flags.5?true background:flags.6?true with_my_score:flags.8?true drop_author:flags.11?true drop_media_captions:flags.12?true noforwards:flags.14?true allow_paid_floodskip:flags.19?true from_peer:InputPeer id:Vector<int> random_id:Vector<long> to_peer:InputPeer top_msg_id:flags.9?int reply_to:flags.22?InputReplyTo schedule_date:flags.10?int send_as:flags.13?InputPeer quick_reply_shortcut:flags.17?InputQuickReplyShortcut video_timestamp:flags.20?int allow_paid_stars:flags.21?long = Updates;
|
||||
messages.reportSpam#cf1592db peer:InputPeer = Bool;
|
||||
messages.getPeerSettings#efd9a6a2 peer:InputPeer = messages.PeerSettings;
|
||||
messages.report#fc78af9b peer:InputPeer id:Vector<int> option:bytes message:string = ReportResult;
|
||||
@ -2259,8 +2263,8 @@ messages.sendMultiMedia#1bf89d74 flags:# silent:flags.5?true background:flags.6?
|
||||
messages.uploadEncryptedFile#5057c497 peer:InputEncryptedChat file:InputEncryptedFile = EncryptedFile;
|
||||
messages.searchStickerSets#35705b8a flags:# exclude_featured:flags.0?true q:string hash:long = messages.FoundStickerSets;
|
||||
messages.getSplitRanges#1cff7e08 = Vector<MessageRange>;
|
||||
messages.markDialogUnread#c286d98f flags:# unread:flags.0?true peer:InputDialogPeer = Bool;
|
||||
messages.getDialogUnreadMarks#22e24e22 = Vector<DialogPeer>;
|
||||
messages.markDialogUnread#8c5006f8 flags:# unread:flags.0?true parent_peer:flags.1?InputPeer peer:InputDialogPeer = Bool;
|
||||
messages.getDialogUnreadMarks#21202222 flags:# parent_peer:flags.0?InputPeer = Vector<DialogPeer>;
|
||||
messages.clearAllDrafts#7e58ee9c = Bool;
|
||||
messages.updatePinnedMessage#d2aaf7ec flags:# silent:flags.0?true unpin:flags.1?true pm_oneside:flags.2?true peer:InputPeer id:int = Updates;
|
||||
messages.sendVote#10ea6184 peer:InputPeer msg_id:int options:Vector<bytes> = Updates;
|
||||
@ -2290,7 +2294,7 @@ messages.getOldFeaturedStickers#7ed094a1 offset:int limit:int hash:long = messag
|
||||
messages.getReplies#22ddd30c peer:InputPeer msg_id:int offset_id:int offset_date:int add_offset:int limit:int max_id:int min_id:int hash:long = messages.Messages;
|
||||
messages.getDiscussionMessage#446972fd peer:InputPeer msg_id:int = messages.DiscussionMessage;
|
||||
messages.readDiscussion#f731a9f4 peer:InputPeer msg_id:int read_max_id:int = Bool;
|
||||
messages.unpinAllMessages#ee22b9a8 flags:# peer:InputPeer top_msg_id:flags.0?int = messages.AffectedHistory;
|
||||
messages.unpinAllMessages#62dd747 flags:# peer:InputPeer top_msg_id:flags.0?int saved_peer_id:flags.1?InputPeer = messages.AffectedHistory;
|
||||
messages.deleteChat#5bd0ee50 chat_id:long = Bool;
|
||||
messages.deletePhoneCallHistory#f9cbe409 flags:# revoke:flags.0?true = messages.AffectedFoundMessages;
|
||||
messages.checkHistoryImport#43fe19f3 import_head:string = messages.HistoryImportParsed;
|
||||
@ -2321,8 +2325,8 @@ messages.setChatAvailableReactions#864b2581 flags:# peer:InputPeer available_rea
|
||||
messages.getAvailableReactions#18dea0ac hash:int = messages.AvailableReactions;
|
||||
messages.setDefaultReaction#4f47a016 reaction:Reaction = Bool;
|
||||
messages.translateText#63183030 flags:# peer:flags.0?InputPeer id:flags.0?Vector<int> text:flags.1?Vector<TextWithEntities> to_lang:string = messages.TranslatedText;
|
||||
messages.getUnreadReactions#3223495b flags:# peer:InputPeer top_msg_id:flags.0?int offset_id:int add_offset:int limit:int max_id:int min_id:int = messages.Messages;
|
||||
messages.readReactions#54aa7f8e flags:# peer:InputPeer top_msg_id:flags.0?int = messages.AffectedHistory;
|
||||
messages.getUnreadReactions#bd7f90ac flags:# peer:InputPeer top_msg_id:flags.0?int saved_peer_id:flags.1?InputPeer offset_id:int add_offset:int limit:int max_id:int min_id:int = messages.Messages;
|
||||
messages.readReactions#9ec44f93 flags:# peer:InputPeer top_msg_id:flags.0?int saved_peer_id:flags.1?InputPeer = messages.AffectedHistory;
|
||||
messages.searchSentMedia#107e31a0 q:string filter:MessagesFilter limit:int = messages.Messages;
|
||||
messages.getAttachMenuBots#16fcc2cb hash:long = AttachMenuBots;
|
||||
messages.getAttachMenuBot#77216192 bot:InputUser = AttachMenuBotsBot;
|
||||
@ -2354,9 +2358,9 @@ messages.getBotApp#34fdc5c3 app:InputBotApp hash:long = messages.BotApp;
|
||||
messages.requestAppWebView#53618bce flags:# write_allowed:flags.0?true compact:flags.7?true fullscreen:flags.8?true peer:InputPeer app:InputBotApp start_param:flags.1?string theme_params:flags.2?DataJSON platform:string = WebViewResult;
|
||||
messages.setChatWallPaper#8ffacae1 flags:# for_both:flags.3?true revert:flags.4?true peer:InputPeer wallpaper:flags.0?InputWallPaper settings:flags.2?WallPaperSettings id:flags.1?int = Updates;
|
||||
messages.searchEmojiStickerSets#92b4494c flags:# exclude_featured:flags.0?true q:string hash:long = messages.FoundStickerSets;
|
||||
messages.getSavedDialogs#5381d21a flags:# exclude_pinned:flags.0?true offset_date:int offset_id:int offset_peer:InputPeer limit:int hash:long = messages.SavedDialogs;
|
||||
messages.getSavedHistory#3d9a414d peer:InputPeer offset_id:int offset_date:int add_offset:int limit:int max_id:int min_id:int hash:long = messages.Messages;
|
||||
messages.deleteSavedHistory#6e98102b flags:# peer:InputPeer max_id:int min_date:flags.2?int max_date:flags.3?int = messages.AffectedHistory;
|
||||
messages.getSavedDialogs#1e91fc99 flags:# exclude_pinned:flags.0?true parent_peer:flags.1?InputPeer offset_date:int offset_id:int offset_peer:InputPeer limit:int hash:long = messages.SavedDialogs;
|
||||
messages.getSavedHistory#998ab009 flags:# parent_peer:flags.0?InputPeer peer:InputPeer offset_id:int offset_date:int add_offset:int limit:int max_id:int min_id:int hash:long = messages.Messages;
|
||||
messages.deleteSavedHistory#4dc5085f flags:# parent_peer:flags.0?InputPeer peer:InputPeer max_id:int min_date:flags.2?int max_date:flags.3?int = messages.AffectedHistory;
|
||||
messages.getPinnedSavedDialogs#d63d94e0 = messages.SavedDialogs;
|
||||
messages.toggleSavedDialogPin#ac81bbde flags:# pinned:flags.0?true peer:InputDialogPeer = Bool;
|
||||
messages.reorderPinnedSavedDialogs#8b716587 flags:# force:flags.0?true order:Vector<InputDialogPeer> = Bool;
|
||||
@ -2391,6 +2395,8 @@ messages.savePreparedInlineMessage#f21f7f2f flags:# result:InputBotInlineResult
|
||||
messages.getPreparedInlineMessage#857ebdb8 bot:InputUser id:string = messages.PreparedInlineMessage;
|
||||
messages.searchStickers#29b1c66a flags:# emojis:flags.0?true q:string emoticon:string lang_code:Vector<string> offset:int limit:int hash:long = messages.FoundStickers;
|
||||
messages.reportMessagesDelivery#5a6d7395 flags:# push:flags.0?true peer:InputPeer id:Vector<int> = Bool;
|
||||
messages.getSavedDialogsByID#6f6f9c96 flags:# parent_peer:flags.1?InputPeer ids:Vector<InputPeer> = messages.SavedDialogs;
|
||||
messages.readSavedHistory#ba4a3b5b parent_peer:InputPeer peer:InputPeer max_id:int = Bool;
|
||||
|
||||
updates.getState#edd4882a = updates.State;
|
||||
updates.getDifference#19c2f763 flags:# pts:int pts_limit:flags.1?int pts_total_limit:flags.0?int date:int qts:int qts_limit:flags.2?int = updates.Difference;
|
||||
@ -2479,7 +2485,7 @@ channels.toggleJoinRequest#4c2985b6 channel:InputChannel enabled:Bool = Updates;
|
||||
channels.reorderUsernames#b45ced1d channel:InputChannel order:Vector<string> = Bool;
|
||||
channels.toggleUsername#50f24105 channel:InputChannel username:string active:Bool = Bool;
|
||||
channels.deactivateAllUsernames#a245dd3 channel:InputChannel = Bool;
|
||||
channels.toggleForum#a4298b29 channel:InputChannel enabled:Bool = Updates;
|
||||
channels.toggleForum#3ff75734 channel:InputChannel enabled:Bool tabs:Bool = Updates;
|
||||
channels.createForumTopic#f40c0224 flags:# channel:InputChannel title:string icon_color:flags.0?int icon_emoji_id:flags.3?long random_id:long send_as:flags.2?InputPeer = Updates;
|
||||
channels.getForumTopics#de560d1 flags:# channel:InputChannel q:flags.0?string offset_date:int offset_id:int offset_topic:int limit:int = messages.ForumTopics;
|
||||
channels.getForumTopicsByID#b0831eb9 channel:InputChannel topics:Vector<int> = messages.ForumTopics;
|
||||
@ -2498,8 +2504,9 @@ channels.setBoostsToUnblockRestrictions#ad399cee channel:InputChannel boosts:int
|
||||
channels.setEmojiStickers#3cd930b7 channel:InputChannel stickerset:InputStickerSet = Bool;
|
||||
channels.restrictSponsoredMessages#9ae91519 channel:InputChannel restricted:Bool = Updates;
|
||||
channels.searchPosts#d19f987b hashtag:string offset_rate:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages;
|
||||
channels.updatePaidMessagesPrice#fc84653f channel:InputChannel send_paid_messages_stars:long = Updates;
|
||||
channels.updatePaidMessagesPrice#4b12327b flags:# broadcast_messages_allowed:flags.0?true channel:InputChannel send_paid_messages_stars:long = Updates;
|
||||
channels.toggleAutotranslation#167fc0a1 channel:InputChannel enabled:Bool = Updates;
|
||||
channels.getMessageAuthor#ece2a0e6 channel:InputChannel id:int = User;
|
||||
|
||||
bots.sendCustomRequest#aa2769ed custom_method:string params:DataJSON = DataJSON;
|
||||
bots.answerWebhookJSONQuery#e6213f4d query_id:long data:DataJSON = Bool;
|
||||
|
||||
31
src/types/language.d.ts
vendored
31
src/types/language.d.ts
vendored
@ -1509,7 +1509,7 @@ export interface LangPair {
|
||||
'FrozenAccountAppealTitle': undefined;
|
||||
'ButtonAppeal': undefined;
|
||||
'ButtonUnderstood': undefined;
|
||||
'ActionPaidMessageGroupPriceFree': undefined;
|
||||
'ActionPaidMessagePriceFreeYou': undefined;
|
||||
'NotificationTitleNotSupportedInFrozenAccount': undefined;
|
||||
'NotificationMessageNotSupportedInFrozenAccount': undefined;
|
||||
'GiftRibbonSale': undefined;
|
||||
@ -1530,6 +1530,10 @@ export interface LangPair {
|
||||
'ValueGiftSortByNumber': undefined;
|
||||
'ResellGiftsNoFound': undefined;
|
||||
'ResellGiftsClearFilters': undefined;
|
||||
'MonoforumBadge': undefined;
|
||||
'MonoforumStatus': undefined;
|
||||
'MonoforumComposerPlaceholder': undefined;
|
||||
'ChannelSendMessage': undefined;
|
||||
'AutomaticTranslation': undefined;
|
||||
}
|
||||
|
||||
@ -2393,8 +2397,12 @@ export interface LangPairWithVariables<V = LangVariable> {
|
||||
'percent': V;
|
||||
'amount': V;
|
||||
};
|
||||
'FirstMessageInPaidMessagesChat': {
|
||||
'user': V;
|
||||
'MessagesPlaceholderPaidUser': {
|
||||
'peer': V;
|
||||
'amount': V;
|
||||
};
|
||||
'MessagesPlaceholderPaidChannel': {
|
||||
'peer': V;
|
||||
'amount': V;
|
||||
};
|
||||
'ComposerPlaceholderPaidMessage': {
|
||||
@ -2434,8 +2442,21 @@ export interface LangPairWithVariables<V = LangVariable> {
|
||||
'botLink': V;
|
||||
'date': V;
|
||||
};
|
||||
'ActionPaidMessageGroupPrice': {
|
||||
'stars': V;
|
||||
'ActionPaidMessagePrice': {
|
||||
'peer': V;
|
||||
'amount': V;
|
||||
};
|
||||
'ActionPaidMessagePriceYou': {
|
||||
'amount': V;
|
||||
};
|
||||
'ActionPaidMessagePriceFree': {
|
||||
'peer': V;
|
||||
};
|
||||
'ActionMessageChannelFree': {
|
||||
'peer': V;
|
||||
};
|
||||
'ActionMessageChannelDisabled': {
|
||||
'peer': V;
|
||||
};
|
||||
'ApiMessageActionPaidMessagesRefundedOutgoing': {
|
||||
'stars': V;
|
||||
|
||||
@ -1,15 +1,17 @@
|
||||
import { CHANNEL_ID_LENGTH } from '../../config';
|
||||
import { CHANNEL_ID_BASE } from '../../config';
|
||||
|
||||
export function isUserId(entityId: string) {
|
||||
return !entityId.startsWith('-');
|
||||
}
|
||||
|
||||
export function isChannelId(entityId: string) {
|
||||
return entityId.length === CHANNEL_ID_LENGTH && entityId.startsWith('-1');
|
||||
const n = Number(entityId);
|
||||
return n < -CHANNEL_ID_BASE;
|
||||
}
|
||||
|
||||
export function toChannelId(mtpId: string) {
|
||||
return `-1${mtpId.padStart(CHANNEL_ID_LENGTH - 2, '0')}`;
|
||||
const n = Number(mtpId);
|
||||
return String(-CHANNEL_ID_BASE - n);
|
||||
}
|
||||
|
||||
export function getCleanPeerId(peerId: string) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user