diff --git a/src/components/common/DeleteChatModal.tsx b/src/components/common/DeleteChatModal.tsx index 531e98ce0..6fdb41a3a 100644 --- a/src/components/common/DeleteChatModal.tsx +++ b/src/components/common/DeleteChatModal.tsx @@ -6,7 +6,6 @@ import type { ApiChat } from '../../api/types'; import { getChatTitle, - getPrivateChatUserId, getUserFirstOrLastName, isChatBasicGroup, isChatChannel, @@ -244,12 +243,10 @@ export default memo(withGlobal( (global, { chat, isSavedDialog }): Complete => { const isPrivateChat = isUserId(chat.id); const isChatWithSelf = selectIsChatWithSelf(global, chat.id); - const user = isPrivateChat && selectUser(global, getPrivateChatUserId(chat)!); + const user = selectUser(global, chat.id); const isBot = user && isUserBot(user) && !chat.isSupport; const canDeleteForAll = (isPrivateChat && !isChatWithSelf && !isBot && !isSavedDialog); - const contactName = isPrivateChat - ? getUserFirstOrLastName(selectUser(global, getPrivateChatUserId(chat)!)) - : undefined; + const contactName = isPrivateChat ? getUserFirstOrLastName(user) : undefined; return { isPrivateChat, diff --git a/src/components/common/DeleteMessageModal.tsx b/src/components/common/DeleteMessageModal.tsx index 30c45dc6b..5d05a9cca 100644 --- a/src/components/common/DeleteMessageModal.tsx +++ b/src/components/common/DeleteMessageModal.tsx @@ -12,7 +12,6 @@ import type { IRadioOption } from '../ui/CheckboxGroup'; import { getHasAdminRight, - getPrivateChatUserId, getUserFirstOrLastName, isChatBasicGroup, isChatChannel, isChatSuperGroup, @@ -506,14 +505,14 @@ export default memo(withGlobal( const isSuperGroup = Boolean(chat) && isChatSuperGroup(chat); const isSchedule = deleteMessageModal?.isSchedule; const onConfirm = deleteMessageModal?.onConfirm; - const contactName = chat && isUserId(chat.id) - ? getUserFirstOrLastName(selectUser(global, getPrivateChatUserId(chat)!)) + const contactName = chatId && isUserId(chatId) + ? getUserFirstOrLastName(selectUser(global, chatId)) : undefined; const chatBot = Boolean(chat && !isSystemBot(chat.id) && selectBot(global, chat.id)); const adminMembersById = chatFullInfo?.adminMembersById; const canBanUsers = chat && getHasAdminRight(chat, 'banUsers') && !chat.isMonoforum; // TODO: Ban in channel in case of monoforum const isCreator = chat?.isCreator; - const isChatWithBot = chat ? selectIsChatWithBot(global, chat) : undefined; + const isChatWithBot = chatId ? selectIsChatWithBot(global, chatId) : undefined; const willDeleteForCurrentUserOnly = (chat && isChatBasicGroup(chat) && !canDeleteForAll) || isChatWithBot; const willDeleteForAll = chat && (isChatSuperGroup(chat) || isChannel); diff --git a/src/components/common/PinMessageModal.tsx b/src/components/common/PinMessageModal.tsx index 467c7666a..a3cdb1188 100644 --- a/src/components/common/PinMessageModal.tsx +++ b/src/components/common/PinMessageModal.tsx @@ -2,7 +2,6 @@ import { memo, useState } from '../../lib/teact/teact'; import { getActions, withGlobal } from '../../global'; import { - getPrivateChatUserId, getUserFirstOrLastName, isChatBasicGroup, isChatChannel, @@ -112,8 +111,8 @@ export default memo(withGlobal( const isGroup = Boolean(chat) && isChatBasicGroup(chat); const isSuperGroup = Boolean(chat) && isChatSuperGroup(chat); const canPinForAll = (isPrivateChat && !isChatWithSelf) || isSuperGroup || isGroup; - const contactName = chat && isUserId(chat.id) - ? getUserFirstOrLastName(selectUser(global, getPrivateChatUserId(chat)!)) + const contactName = chatId && isUserId(chatId) + ? getUserFirstOrLastName(selectUser(global, chatId)) : undefined; return { diff --git a/src/components/left/search/ChatMessage.tsx b/src/components/left/search/ChatMessage.tsx index 3ac980174..e72ffef30 100644 --- a/src/components/left/search/ChatMessage.tsx +++ b/src/components/left/search/ChatMessage.tsx @@ -1,10 +1,9 @@ -import type { FC } from '../../../lib/teact/teact'; import { memo } from '../../../lib/teact/teact'; import { getActions, withGlobal } from '../../../global'; import type { - ApiChat, ApiMessage, - ApiUser, + ApiMessage, + ApiPeer, } from '../../../api/types'; import { @@ -12,9 +11,9 @@ import { getMessageRoundVideo, getMessageSticker, getMessageVideo, - getPrivateChatUserId, } from '../../../global/helpers'; -import { selectChat, selectUser } from '../../../global/selectors'; +import { isApiPeerUser } from '../../../global/helpers/peers'; +import { selectPeer } from '../../../global/selectors'; import buildClassName from '../../../util/buildClassName'; import { formatPastTimeShort } from '../../../util/dates/dateFormat'; import { type LangFn } from '../../../util/localization'; @@ -44,17 +43,15 @@ type OwnProps = { }; type StateProps = { - chat?: ApiChat; - privateChatUser?: ApiUser; + peer?: ApiPeer; }; -const ChatMessage: FC = ({ +const ChatMessage = ({ message, searchQuery, chatId, - chat, - privateChatUser, -}) => { + peer, +}: OwnProps & StateProps) => { const { focusMessage } = getActions(); const { isMobile } = useAppLayout(); @@ -73,11 +70,11 @@ const ChatMessage: FC = ({ const buttonRef = useSelectWithEnter(handleClick); - if (!chat) { + if (!peer) { return undefined; } - const peer = privateChatUser || chat; + const user = isApiPeerUser(peer) ? peer : undefined; return ( = ({ >
@@ -141,17 +138,10 @@ function renderSummary( export default memo(withGlobal( (global, { chatId }): Complete => { - const chat = selectChat(global, chatId); - if (!chat) { - return {} as Complete; - } - - const privateChatUserId = getPrivateChatUserId(chat); - const privateChatUser = privateChatUserId ? selectUser(global, privateChatUserId) : undefined; + const peer = selectPeer(global, chatId); return { - chat, - privateChatUser, + peer, }; }, )(ChatMessage)); diff --git a/src/components/middle/message/Message.tsx b/src/components/middle/message/Message.tsx index a59be28cd..30c3dd31c 100644 --- a/src/components/middle/message/Message.tsx +++ b/src/components/middle/message/Message.tsx @@ -48,6 +48,7 @@ import { AudioOrigin } from '../../../types'; import { EMOJI_STATUS_LOOP_LIMIT, MESSAGE_APPEARANCE_DELAY } from '../../../config'; import { areReactionsEmpty, + getAllowedAttachmentOptions, getIsDownloading, getMainUsername, getMessageContent, @@ -88,6 +89,7 @@ import { selectFullWebPageFromMessage, selectIsChatProtected, selectIsChatRestricted, + selectIsChatWithBot, selectIsChatWithSelf, selectIsCurrentUserFrozen, selectIsCurrentUserPremium, @@ -331,6 +333,7 @@ type StateProps = { isMediaNsfw?: boolean; isReplyMediaNsfw?: boolean; summary?: TextSummary; + canSendStickers?: boolean; }; type MetaPosition = @@ -458,6 +461,7 @@ const Message = ({ minFutureTime, webPage, summary, + canSendStickers, observeIntersectionForBottom, observeIntersectionForLoading, observeIntersectionForPlaying, @@ -1369,6 +1373,7 @@ const Message = ({ )} {dice && ( ( const chat = selectChat(global, chatId); const isChatWithSelf = selectIsChatWithSelf(global, chatId); + const isChatWithBot = selectIsChatWithBot(global, chatId); const isSystemBotChat = isSystemBot(chatId); const isAnonymousForwards = isAnonymousForwardsChat(chatId); const isChannel = chat && isChatChannel(chat); @@ -2144,6 +2150,8 @@ export default memo(withGlobal( const summary = selectMessageSummary(global, chatId, message.id, requestedTranslationLanguage); + const allowedAttachmentOptions = getAllowedAttachmentOptions(chat, chatFullInfo, isChatWithBot); + return { theme: selectTheme(global), forceSenderName, @@ -2244,6 +2252,7 @@ export default memo(withGlobal( isReplyMediaNsfw, webPage, summary, + canSendStickers: allowedAttachmentOptions.canSendStickers, }; }, )(Message)); diff --git a/src/components/middle/message/dice/Dice.module.scss b/src/components/middle/message/dice/Dice.module.scss index 0d1bebe74..869aa5c09 100644 --- a/src/components/middle/message/dice/Dice.module.scss +++ b/src/components/middle/message/dice/Dice.module.scss @@ -1,14 +1,14 @@ .root { - cursor: var(--custom-cursor, pointer); - position: relative; - display: block !important; - width: var(--_size); height: var(--_size); } +.interactive { + cursor: pointer; +} + .sticker { position: absolute; inset: 0; diff --git a/src/components/middle/message/dice/Dice.tsx b/src/components/middle/message/dice/Dice.tsx index 721027b60..e60181458 100644 --- a/src/components/middle/message/dice/Dice.tsx +++ b/src/components/middle/message/dice/Dice.tsx @@ -29,6 +29,7 @@ const FALLBACK_SIZE = 13 * REM; const Dice = ({ dice, + canSendDice, idleSticker, valueSticker, winEffect, @@ -62,6 +63,7 @@ const Dice = ({ }); const handleClick = useLastCallback(() => { + if (!canSendDice) return; showNotification({ message: { key: 'DiceToast', @@ -85,7 +87,11 @@ const Dice = ({ }); return ( -
+
{idleSticker && (
{ + if (!canSendDice) return; showNotification({ message: { key: 'DiceToast', @@ -171,7 +173,12 @@ const SlotMachine = ({ } return ( -
+
{renderSticker(backgroundData, backgroundState !== 'base', false, true)} {renderSticker(frameWinData, backgroundState !== 'win', false, false, undefined, onWinBackgroundFrame)} diff --git a/src/components/right/GifSearch.tsx b/src/components/right/GifSearch.tsx index c0b69eb84..3bc5fd2ac 100644 --- a/src/components/right/GifSearch.tsx +++ b/src/components/right/GifSearch.tsx @@ -173,7 +173,7 @@ export default memo(withGlobal( const { chatId, threadId } = selectCurrentMessageList(global) || {}; const chat = chatId ? selectChat(global, chatId) : undefined; const chatFullInfo = chatId ? selectChatFullInfo(global, chatId) : undefined; - const isChatWithBot = chat ? selectIsChatWithBot(global, chat) : undefined; + const isChatWithBot = chatId ? selectIsChatWithBot(global, chatId) : undefined; const isSavedMessages = Boolean(chatId) && selectIsChatWithSelf(global, chatId); const threadInfo = chatId && threadId ? selectThreadInfo(global, chatId, threadId) : undefined; const isMessageThread = Boolean(!threadInfo?.isCommentsInfo && threadInfo?.fromChannelId); diff --git a/src/global/actions/api/messages.ts b/src/global/actions/api/messages.ts index 95f1c6826..5a0e2dd6e 100644 --- a/src/global/actions/api/messages.ts +++ b/src/global/actions/api/messages.ts @@ -70,6 +70,7 @@ import { isMessageLocal, isServiceNotificationMessage, isUserBot, + isUserRightBanned, splitMessagesForForwarding, } from '../../helpers'; import { isApiPeerChat, isApiPeerUser } from '../../helpers/peers'; @@ -452,9 +453,11 @@ addActionHandler('sendMessage', async (global, actions, payload): Promise }); } + const areStickersDisabled = isUserRightBanned(chat, 'sendStickers'); + const diceEmojies = global.appConfig.diceEmojies; let dice = payload.dice; - if (payload.text && !payload.entities?.length && diceEmojies.includes(payload.text)) { + if (!areStickersDisabled && payload.text && !payload.entities?.length && diceEmojies.includes(payload.text)) { dice = payload.text; } diff --git a/src/global/actions/ui/misc.ts b/src/global/actions/ui/misc.ts index 459426d43..34977c173 100644 --- a/src/global/actions/ui/misc.ts +++ b/src/global/actions/ui/misc.ts @@ -350,7 +350,7 @@ addActionHandler('showAllowedMessageTypesNotification', (global, actions, payloa if (!chat) return; const chatFullInfo = selectChatFullInfo(global, chatId); const isSavedMessages = chatId ? selectIsChatWithSelf(global, chatId) : undefined; - const isChatWithBot = chatId ? selectIsChatWithBot(global, chat) : undefined; + const isChatWithBot = chatId ? selectIsChatWithBot(global, chatId) : undefined; const { canSendPlainText, canSendPhotos, canSendVideos, canSendDocuments, canSendAudios, diff --git a/src/global/helpers/chats.ts b/src/global/helpers/chats.ts index 4533abc13..ffd4ce471 100644 --- a/src/global/helpers/chats.ts +++ b/src/global/helpers/chats.ts @@ -85,13 +85,6 @@ export function getChatTypeLangKey(chat: ApiChat): RegularLangKey { } } -export function getPrivateChatUserId(chat: ApiChat) { - if (chat.type !== 'chatTypePrivate' && chat.type !== 'chatTypeSecret') { - return undefined; - } - return chat.id; -} - export function getChatTitle(lang: OldLangFn | LangFn, chat: ApiChat, isSelf = false) { if (isSelf) { return lang('SavedMessages'); diff --git a/src/global/selectors/chats.ts b/src/global/selectors/chats.ts index 21b4d101e..d23f36f55 100644 --- a/src/global/selectors/chats.ts +++ b/src/global/selectors/chats.ts @@ -12,7 +12,6 @@ import { isUserId } from '../../util/entities/ids'; import { getCurrentTabId } from '../../util/establishMultitabRole'; import { getHasAdminRight, - getPrivateChatUserId, isChatChannel, isChatPublic, isChatSuperGroup, @@ -45,21 +44,12 @@ export function selectChatListLoadingParameters( return global.chats.loadingParameters[listType]; } -export function selectChatUser(global: T, chat: ApiChat) { - const userId = getPrivateChatUserId(chat); - if (!userId) { - return false; - } - - return selectUser(global, userId); -} - export function selectIsChatWithSelf(global: T, chatId: string) { return chatId === global.currentUserId; } -export function selectIsChatWithBot(global: T, chat: ApiChat) { - const user = selectChatUser(global, chat); +export function selectIsChatWithBot(global: T, chatId: string) { + const user = selectUser(global, chatId); return user && isUserBot(user); } diff --git a/src/global/selectors/messages.ts b/src/global/selectors/messages.ts index 1308a9184..3fb48bef1 100644 --- a/src/global/selectors/messages.ts +++ b/src/global/selectors/messages.ts @@ -1374,7 +1374,7 @@ export function selectForwardsCanBeSentToChat( const chatMessages = selectChatMessages(global, fromChatId!); const isSavedMessages = toChatId ? selectIsChatWithSelf(global, toChatId) : undefined; - const isChatWithBot = toChatId ? selectIsChatWithBot(global, chat) : undefined; + const isChatWithBot = toChatId ? selectIsChatWithBot(global, toChatId) : undefined; const options = getAllowedAttachmentOptions(chat, chatFullInfo, isChatWithBot, isSavedMessages); return !messageIds!.some((messageId) => сheckMessageSendingDenied(chatMessages[messageId], options)); } diff --git a/src/util/notifications.tsx b/src/util/notifications.tsx index a3f0efa59..8e3ba64ba 100644 --- a/src/util/notifications.tsx +++ b/src/util/notifications.tsx @@ -11,7 +11,6 @@ import { getChatAvatarHash, getChatTitle, getMessageRecentReaction, - getPrivateChatUserId, getUserFullName, } from '../global/helpers'; import { getIsChatMuted, getIsChatSilent, getShouldShowMessagePreview } from '../global/helpers/notifications'; @@ -320,8 +319,7 @@ function getNotificationContent(chat: ApiChat, message: ApiMessage, reaction?: A } const { isScreenLocked } = global.passcode; - const privateChatUserId = getPrivateChatUserId(chat); - const isSelf = privateChatUserId === global.currentUserId; + const isSelf = chat.id === global.currentUserId; let body: string; if (