From fc9b679a66e6038ce8aeab62c24098e2601370e7 Mon Sep 17 00:00:00 2001 From: Alexander Zinchuk Date: Sat, 19 Mar 2022 21:19:29 +0100 Subject: [PATCH] Middle Header: Add "Report Spam and Leave" button, fix animations (#1759) --- src/api/gramjs/apiBuilders/chats.ts | 15 ++ src/api/gramjs/apiBuilders/users.ts | 19 +- src/api/gramjs/methods/chats.ts | 15 ++ src/api/gramjs/methods/index.ts | 3 +- src/api/gramjs/methods/management.ts | 8 + src/api/gramjs/methods/users.ts | 5 +- src/api/gramjs/updater.ts | 5 +- src/api/types/chats.ts | 9 + src/api/types/users.ts | 8 - src/components/mediaViewer/VideoPlayer.tsx | 2 +- ...rReportPanel.scss => ChatReportPanel.scss} | 2 +- src/components/middle/ChatReportPanel.tsx | 186 ++++++++++++++++++ src/components/middle/MiddleColumn.tsx | 16 +- src/components/middle/MiddleHeader.tsx | 28 ++- src/components/middle/UserReportPanel.tsx | 125 ------------ src/global/actions/api/chats.ts | 11 ++ src/global/actions/api/management.ts | 13 ++ src/global/actions/api/users.ts | 8 +- src/global/reducers/users.ts | 7 +- src/global/types.ts | 4 +- src/lib/gramjs/tl/apiTl.js | 2 + src/lib/gramjs/tl/static/api.json | 2 + 22 files changed, 309 insertions(+), 184 deletions(-) rename src/components/middle/{UserReportPanel.scss => ChatReportPanel.scss} (97%) create mode 100644 src/components/middle/ChatReportPanel.tsx delete mode 100644 src/components/middle/UserReportPanel.tsx diff --git a/src/api/gramjs/apiBuilders/chats.ts b/src/api/gramjs/apiBuilders/chats.ts index 71afaee7f..700337152 100644 --- a/src/api/gramjs/apiBuilders/chats.ts +++ b/src/api/gramjs/apiBuilders/chats.ts @@ -10,6 +10,7 @@ import { ApiRestrictionReason, ApiExportedInvite, ApiChatInviteImporter, + ApiChatSettings, } from '../../types'; import { pick, pickTruthy } from '../../../util/iteratees'; import { @@ -434,3 +435,17 @@ export function buildChatInviteImporter(importer: GramJs.ChatInviteImporter): Ap isRequested: requested, }; } + +export function buildApiChatSettings({ + autoarchived, + reportSpam, + addContact, + blockContact, +}: GramJs.PeerSettings): ApiChatSettings { + return { + isAutoArchived: Boolean(autoarchived), + canReportSpam: Boolean(reportSpam), + canAddContact: Boolean(addContact), + canBlockContact: Boolean(blockContact), + }; +} diff --git a/src/api/gramjs/apiBuilders/users.ts b/src/api/gramjs/apiBuilders/users.ts index 9379e0ec2..04a58eb51 100644 --- a/src/api/gramjs/apiBuilders/users.ts +++ b/src/api/gramjs/apiBuilders/users.ts @@ -1,13 +1,13 @@ import { Api as GramJs } from '../../../lib/gramjs'; import { - ApiBotCommand, ApiUser, ApiUserSettings, ApiUserStatus, ApiUserType, + ApiBotCommand, ApiUser, ApiUserStatus, ApiUserType, } from '../../types'; import { buildApiPeerId } from './peers'; export function buildApiUserFromFull(mtpUserFull: GramJs.users.UserFull): ApiUser { const { fullUser: { - about, commonChatsCount, pinnedMsgId, botInfo, blocked, settings, + about, commonChatsCount, pinnedMsgId, botInfo, blocked, }, users, } = mtpUserFull; @@ -16,7 +16,6 @@ export function buildApiUserFromFull(mtpUserFull: GramJs.users.UserFull): ApiUse return { ...user, - settings: buildApiUserSettings(settings), fullInfo: { bio: about, commonChatsCount, @@ -112,17 +111,3 @@ export function buildApiUsersAndStatuses(mtpUsers: GramJs.TypeUser[]) { return { users, userStatusesById }; } - -export function buildApiUserSettings({ - autoarchived, - reportSpam, - addContact, - blockContact, -}: GramJs.PeerSettings): ApiUserSettings { - return { - isAutoArchived: Boolean(autoarchived), - canReportSpam: Boolean(reportSpam), - canAddContact: Boolean(addContact), - canBlockContact: Boolean(blockContact), - }; -} diff --git a/src/api/gramjs/methods/chats.ts b/src/api/gramjs/methods/chats.ts index d5fabe566..546ad1949 100644 --- a/src/api/gramjs/methods/chats.ts +++ b/src/api/gramjs/methods/chats.ts @@ -26,6 +26,7 @@ import { buildApiChatFolder, buildApiChatFolderFromSuggested, buildApiChatBotCommands, + buildApiChatSettings, } from '../apiBuilders/chats'; import { buildApiMessage, buildMessageDraft } from '../apiBuilders/messages'; import { buildApiUser, buildApiUsersAndStatuses } from '../apiBuilders/users'; @@ -179,6 +180,20 @@ export function fetchFullChat(chat: ApiChat) { : getFullChatInfo(id); } +export async function fetchChatSettings(chat: ApiChat) { + const { id, accessHash } = chat; + + const result = await invokeRequest(new GramJs.messages.GetPeerSettings({ + peer: buildInputPeer(id, accessHash), + })); + + if (!result) { + return undefined; + } + + return buildApiChatSettings(result.settings); +} + export async function searchChats({ query }: { query: string }) { const result = await invokeRequest(new GramJs.contacts.Search({ q: query })); if (!result) { diff --git a/src/api/gramjs/methods/index.ts b/src/api/gramjs/methods/index.ts index 3f468b300..c14840cd2 100644 --- a/src/api/gramjs/methods/index.ts +++ b/src/api/gramjs/methods/index.ts @@ -7,7 +7,7 @@ export { } from './auth'; export { - fetchChats, fetchFullChat, searchChats, requestChatUpdate, + fetchChats, fetchFullChat, searchChats, requestChatUpdate, fetchChatSettings, saveDraft, clearDraft, fetchChat, updateChatMutedState, createChannel, joinChannel, deleteChatUser, deleteChat, leaveChannel, deleteChannel, createGroupChat, editChatPhoto, toggleChatPinned, toggleChatArchived, toggleDialogUnread, setChatEnabledReactions, @@ -42,6 +42,7 @@ export { checkChatUsername, setChatUsername, updatePrivateLink, fetchExportedChatInvites, editExportedChatInvite, exportChatInvite, deleteExportedChatInvite, deleteRevokedExportedChatInvites, fetchChatInviteImporters, hideChatJoinRequest, hideAllChatJoinRequests, + hideChatReportPanel, } from './management'; export { diff --git a/src/api/gramjs/methods/management.ts b/src/api/gramjs/methods/management.ts index c8ca6e2da..c8ab6d693 100644 --- a/src/api/gramjs/methods/management.ts +++ b/src/api/gramjs/methods/management.ts @@ -218,3 +218,11 @@ export function hideAllChatJoinRequests({ link, }), true); } + +export function hideChatReportPanel(chat: ApiChat) { + const { id, accessHash } = chat; + + return invokeRequest(new GramJs.messages.HidePeerSettingsBar({ + peer: buildInputPeer(id, accessHash), + })); +} diff --git a/src/api/gramjs/methods/users.ts b/src/api/gramjs/methods/users.ts index ce4dcbfb2..22cfb375d 100644 --- a/src/api/gramjs/methods/users.ts +++ b/src/api/gramjs/methods/users.ts @@ -51,7 +51,6 @@ export async function fetchFullUser({ '@type': 'updateUser', id, user: { - settings: userWithFullInfo.settings, fullInfo: userWithFullInfo.fullInfo, }, }); @@ -248,8 +247,8 @@ export async function fetchProfilePhotos(user?: ApiUser, chat?: ApiChat) { }; } -export function reportSpam(user: ApiUser) { - const { id, accessHash } = user; +export function reportSpam(userOrChat: ApiUser | ApiChat) { + const { id, accessHash } = userOrChat; return invokeRequest(new GramJs.messages.ReportSpam({ peer: buildInputPeer(id, accessHash), diff --git a/src/api/gramjs/updater.ts b/src/api/gramjs/updater.ts index 36e859279..211ba1b2d 100644 --- a/src/api/gramjs/updater.ts +++ b/src/api/gramjs/updater.ts @@ -22,8 +22,9 @@ import { buildAvatarHash, buildApiChatFromPreview, buildApiChatFolder, + buildApiChatSettings, } from './apiBuilders/chats'; -import { buildApiUser, buildApiUserSettings, buildApiUserStatus } from './apiBuilders/users'; +import { buildApiUser, buildApiUserStatus } from './apiBuilders/users'; import { buildMessageFromUpdate, isMessageWithMedia, @@ -799,7 +800,7 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) { id: user.id, user: { ...user, - ...(settings && { settings: buildApiUserSettings(settings) }), + ...(settings && { settings: buildApiChatSettings(settings) }), }, }); }); diff --git a/src/api/types/chats.ts b/src/api/types/chats.ts index 4eaadfc06..d6289a0b3 100644 --- a/src/api/types/chats.ts +++ b/src/api/types/chats.ts @@ -53,6 +53,8 @@ export interface ApiChat { accessHash?: string; }; + // Obtained from GetChatSettings + settings?: ApiChatSettings; // Obtained from GetFullChat / GetFullChannel fullInfo?: ApiChatFullInfo; // Obtained with UpdateUserTyping or UpdateChatUserTyping updates @@ -161,3 +163,10 @@ export interface ApiChatFolder { includedChatIds: string[]; excludedChatIds: string[]; } + +export interface ApiChatSettings { + isAutoArchived?: boolean; + canReportSpam?: boolean; + canAddContact?: boolean; + canBlockContact?: boolean; +} diff --git a/src/api/types/users.ts b/src/api/types/users.ts index e76b53409..c723bef7b 100644 --- a/src/api/types/users.ts +++ b/src/api/types/users.ts @@ -26,14 +26,6 @@ export interface ApiUser { // Obtained from GetFullUser / UserFullInfo fullInfo?: ApiUserFullInfo; - settings?: ApiUserSettings; -} - -export interface ApiUserSettings { - isAutoArchived?: boolean; - canReportSpam?: boolean; - canAddContact?: boolean; - canBlockContact?: boolean; } export interface ApiUserFullInfo { diff --git a/src/components/mediaViewer/VideoPlayer.tsx b/src/components/mediaViewer/VideoPlayer.tsx index e7fda0a26..714132ad5 100644 --- a/src/components/mediaViewer/VideoPlayer.tsx +++ b/src/components/mediaViewer/VideoPlayer.tsx @@ -130,7 +130,7 @@ const VideoPlayer: FC = ({ }, []); useEffect(() => { - if (!isMediaViewerOpen) return; + if (!isMediaViewerOpen) return undefined; const togglePayingStateBySpace = (e: KeyboardEvent) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); diff --git a/src/components/middle/UserReportPanel.scss b/src/components/middle/ChatReportPanel.scss similarity index 97% rename from src/components/middle/UserReportPanel.scss rename to src/components/middle/ChatReportPanel.scss index 24d775a98..cab1432fb 100644 --- a/src/components/middle/UserReportPanel.scss +++ b/src/components/middle/ChatReportPanel.scss @@ -1,4 +1,4 @@ -.UserReportPanel { +.ChatReportPanel { position: absolute; left: 0; right: 0; diff --git a/src/components/middle/ChatReportPanel.tsx b/src/components/middle/ChatReportPanel.tsx new file mode 100644 index 000000000..c0c5f9194 --- /dev/null +++ b/src/components/middle/ChatReportPanel.tsx @@ -0,0 +1,186 @@ +import React, { + FC, memo, useCallback, useState, +} from '../../lib/teact/teact'; +import { withGlobal, getActions } from '../../global'; + +import { ApiChat, ApiChatSettings, ApiUser } from '../../api/types'; + +import { selectChat, selectUser } from '../../global/selectors'; +import { + getChatTitle, getUserFirstOrLastName, getUserFullName, isChatBasicGroup, isUserId, +} from '../../global/helpers'; +import buildClassName from '../../util/buildClassName'; +import useLang from '../../hooks/useLang'; +import useFlag from '../../hooks/useFlag'; + +import Button from '../ui/Button'; +import ConfirmDialog from '../ui/ConfirmDialog'; +import Checkbox from '../ui/Checkbox'; + +import './ChatReportPanel.scss'; + +type OwnProps = { + chatId: string; + className?: string; + settings?: ApiChatSettings; +}; + +type StateProps = { + currentUserId?: string; + chat?: ApiChat; + user?: ApiUser; +}; + +const ChatReportPanel: FC = ({ + chatId, className, chat, user, settings, currentUserId, +}) => { + const { + addContact, + blockContact, + reportSpam, + deleteChat, + leaveChannel, + deleteChatUser, + deleteHistory, + toggleChatArchived, + hideChatReportPanel, + } = getActions(); + + const lang = useLang(); + const [isBlockUserModalOpen, openBlockUserModal, closeBlockUserModal] = useFlag(); + const [shouldReportSpam, setShouldReportSpam] = useState(true); + const [shouldDeleteChat, setShouldDeleteChat] = useState(true); + const { accessHash } = chat || {}; + const { + isAutoArchived, canReportSpam, canAddContact, canBlockContact, + } = settings || {}; + const isBasicGroup = chat && isChatBasicGroup(chat); + + const handleAddContact = useCallback(() => { + addContact({ chatId }); + if (isAutoArchived) { + toggleChatArchived({ chatId }); + } + }, [addContact, isAutoArchived, toggleChatArchived, chatId]); + + const handleConfirmBlock = useCallback(() => { + closeBlockUserModal(); + blockContact({ contactId: chatId, accessHash }); + if (canReportSpam && shouldReportSpam) { + reportSpam({ chatId }); + } + if (shouldDeleteChat) { + deleteChat({ chatId }); + } + }, [ + accessHash, blockContact, closeBlockUserModal, deleteChat, reportSpam, canReportSpam, shouldDeleteChat, + shouldReportSpam, chatId, + ]); + + const handleCloseReportPanel = useCallback(() => { + hideChatReportPanel({ chatId }); + }, [chatId, hideChatReportPanel]); + + const handleChatReportSpam = useCallback(() => { + closeBlockUserModal(); + reportSpam({ chatId }); + if (isBasicGroup) { + deleteChatUser({ chatId, userId: currentUserId }); + deleteHistory({ chatId, shouldDeleteForAll: false }); + } else { + leaveChannel({ chatId }); + } + }, [ + chatId, closeBlockUserModal, currentUserId, deleteChatUser, deleteHistory, isBasicGroup, leaveChannel, reportSpam, + ]); + + if (!settings) { + return undefined; + } + + return ( +
+ {canAddContact && ( + + )} + {canBlockContact && ( + + )} + {canReportSpam && !canBlockContact && ( + + )} + + + {user && canReportSpam && ( + + )} + {user && ( + + )} + +
+ ); +}; + +export default memo(withGlobal( + (global, { chatId }): StateProps => ({ + currentUserId: global.currentUserId, + chat: selectChat(global, chatId), + user: isUserId(chatId) ? selectUser(global, chatId) : undefined, + }), +)(ChatReportPanel)); diff --git a/src/components/middle/MiddleColumn.tsx b/src/components/middle/MiddleColumn.tsx index 079773bb8..90c8cccf1 100644 --- a/src/components/middle/MiddleColumn.tsx +++ b/src/components/middle/MiddleColumn.tsx @@ -42,7 +42,6 @@ import { selectIsUserBlocked, selectPinnedIds, selectTheme, - selectUser, } from '../../global/selectors'; import { getCanPostInChat, getMessageSendingRestrictionReason, isChatChannel, isChatSuperGroup, isUserId, @@ -107,7 +106,7 @@ type StateProps = { currentTransitionKey: number; messageLists?: GlobalMessageList[]; isChannel?: boolean; - isUserFull?: boolean; + areChatSettingsLoaded?: boolean; canSubscribe?: boolean; canStartBot?: boolean; canRestartBot?: boolean; @@ -150,7 +149,7 @@ const MiddleColumn: FC = ({ shouldSkipHistoryAnimations, currentTransitionKey, isChannel, - isUserFull, + areChatSettingsLoaded, canSubscribe, canStartBot, canRestartBot, @@ -161,7 +160,7 @@ const MiddleColumn: FC = ({ openChat, unpinAllMessages, loadUser, - loadFullUser, + loadChatSettings, closeLocalTextSearch, exitMessageSelectMode, closePaymentModal, @@ -258,10 +257,10 @@ const MiddleColumn: FC = ({ }, [chatId, isPrivate, loadUser]); useEffect(() => { - if (isPrivate && !isUserFull && lastSyncTime) { - loadFullUser({ userId: chatId }); + if (!areChatSettingsLoaded && lastSyncTime) { + loadChatSettings({ chatId }); } - }, [chatId, isPrivate, isUserFull, lastSyncTime, loadFullUser]); + }, [chatId, isPrivate, areChatSettingsLoaded, lastSyncTime, loadChatSettings]); const handleDragEnter = useCallback((e: React.DragEvent) => { if (IS_TOUCH_ENV) { @@ -587,7 +586,6 @@ export default memo(withGlobal( const isPrivate = isUserId(chatId); const chat = selectChat(global, chatId); const bot = selectChatBot(global, chatId); - const user = isPrivate ? selectUser(global, chatId) : undefined; const pinnedIds = selectPinnedIds(global, chatId); const { chatId: audioChatId, messageId: audioMessageId } = global.audioPlayer; @@ -609,7 +607,7 @@ export default memo(withGlobal( threadId, messageListType, isPrivate, - isUserFull: Boolean(user?.settings), + areChatSettingsLoaded: Boolean(chat?.settings), canPost: !isPinnedMessageList && (!chat || canPost) && !isBotNotStarted, isPinnedMessageList, isScheduledMessageList, diff --git a/src/components/middle/MiddleHeader.tsx b/src/components/middle/MiddleHeader.tsx index 2ad433379..5dd5196b0 100644 --- a/src/components/middle/MiddleHeader.tsx +++ b/src/components/middle/MiddleHeader.tsx @@ -19,7 +19,7 @@ import { } from '../../config'; import { IS_SINGLE_COLUMN_LAYOUT, IS_TABLET_COLUMN_LAYOUT } from '../../util/environment'; import { - getChatTitle, getMessageKey, getPrivateChatUserId, getSenderTitle, isUserId, + getChatTitle, getMessageKey, getSenderTitle, isUserId, } from '../../global/helpers'; import { selectAllowedMessageActions, @@ -35,7 +35,6 @@ import { selectScheduledIds, selectThreadInfo, selectThreadTopMessageId, - selectUser, } from '../../global/selectors'; import useEnsureMessage from '../../hooks/useEnsureMessage'; import useWindowSize from '../../hooks/useWindowSize'; @@ -54,7 +53,7 @@ import HeaderActions from './HeaderActions'; import HeaderPinnedMessage from './HeaderPinnedMessage'; import AudioPlayer from './AudioPlayer'; import GroupCallTopPane from '../calls/group/GroupCallTopPane'; -import UserReportPanel from './UserReportPanel'; +import ChatReportPanel from './ChatReportPanel'; import './MiddleHeader.scss'; @@ -83,7 +82,6 @@ type StateProps = { isChatWithSelf?: boolean; isChatWithBot?: boolean; lastSyncTime?: number; - shouldShowUserReportPanel?: boolean; shouldSkipHistoryAnimations?: boolean; currentTransitionKey: number; connectionState?: GlobalState['connectionState']; @@ -109,7 +107,6 @@ const MiddleHeader: FC = ({ isChatWithSelf, isChatWithBot, lastSyncTime, - shouldShowUserReportPanel, shouldSkipHistoryAnimations, currentTransitionKey, connectionState, @@ -136,6 +133,7 @@ const MiddleHeader: FC = ({ ? pinnedMessageIds.length : (pinnedMessageIds ? 1 : undefined); const chatTitleLength = chat && getChatTitle(lang, chat).length; const topMessageTitle = topMessageSender ? getSenderTitle(lang, topMessageSender) : undefined; + const { settings } = chat || {}; useEffect(() => { if (threadId === MAIN_THREAD_ID && lastSyncTime && isReady) { @@ -237,6 +235,13 @@ const MiddleHeader: FC = ({ && windowWidth < SAFE_SCREEN_WIDTH_FOR_STATIC_RIGHT_COLUMN ); + const hasChatSettings = Boolean(settings?.canAddContact || settings?.canBlockContact || settings?.canReportSpam); + const { + shouldRender: shouldShowChatReportPanel, + transitionClassNames: chatReportPanelClassNames, + } = useShowTransition(hasChatSettings); + const renderingChatSettings = useCurrentOrPrev(hasChatSettings ? settings : undefined, true); + const { shouldRender: shouldRenderAudioPlayer, transitionClassNames: audioPlayerClassNames, @@ -400,7 +405,14 @@ const MiddleHeader: FC = ({ /> )} - {shouldShowUserReportPanel && } + {shouldShowChatReportPanel && ( + + )}
{isAudioPlayerRendered && ( @@ -425,9 +437,6 @@ export default memo(withGlobal( (global, { chatId, threadId, messageListType }): StateProps => { const { isLeftColumnShown, lastSyncTime, shouldSkipHistoryAnimations } = global; const chat = selectChat(global, chatId); - const userId = chat && getPrivateChatUserId(chat); - const user = userId ? selectUser(global, userId) : undefined; - const { typingStatus } = chat || {}; const { chatId: audioChatId, messageId: audioMessageId } = global.audioPlayer; @@ -455,7 +464,6 @@ export default memo(withGlobal( audioMessage, chat, messagesCount, - shouldShowUserReportPanel: Boolean(user?.settings?.canAddContact || user?.settings?.canBlockContact), isChatWithSelf: selectIsChatWithSelf(global, chatId), isChatWithBot: chat && selectIsChatWithBot(global, chat), lastSyncTime, diff --git a/src/components/middle/UserReportPanel.tsx b/src/components/middle/UserReportPanel.tsx deleted file mode 100644 index ece8e229e..000000000 --- a/src/components/middle/UserReportPanel.tsx +++ /dev/null @@ -1,125 +0,0 @@ -import React, { - FC, memo, useCallback, useState, -} from '../../lib/teact/teact'; -import { withGlobal, getActions } from '../../global'; - -import { ApiUser } from '../../api/types'; - -import { selectUser } from '../../global/selectors'; -import { getUserFirstOrLastName, getUserFullName } from '../../global/helpers'; -import useLang from '../../hooks/useLang'; -import useFlag from '../../hooks/useFlag'; - -import Button from '../ui/Button'; -import ConfirmDialog from '../ui/ConfirmDialog'; -import Checkbox from '../ui/Checkbox'; - -import './UserReportPanel.scss'; - -type OwnProps = { - userId: string; -}; - -type StateProps = { - user?: ApiUser; -}; - -const UserReportPanel: FC = ({ userId, user }) => { - const { - addContact, - blockContact, - reportSpam, - deleteChat, - toggleChatArchived, - } = getActions(); - - const lang = useLang(); - const [isBlockUserModalOpen, openBlockUserModal, closeBlockUserModal] = useFlag(); - const [shouldReportSpam, setShouldReportSpam] = useState(true); - const [shouldDeleteChat, setShouldDeleteChat] = useState(true); - const { settings, accessHash } = user || {}; - const { - isAutoArchived, canReportSpam, canAddContact, canBlockContact, - } = settings || {}; - const handleAddContact = useCallback(() => { - addContact({ userId }); - if (isAutoArchived) { - toggleChatArchived({ chatId: userId }); - } - }, [addContact, isAutoArchived, toggleChatArchived, userId]); - - const handleConfirmBlock = useCallback(() => { - closeBlockUserModal(); - blockContact({ contactId: userId, accessHash }); - if (canReportSpam && shouldReportSpam) { - reportSpam({ userId }); - } - if (shouldDeleteChat) { - deleteChat({ chatId: userId }); - } - }, [ - accessHash, blockContact, closeBlockUserModal, deleteChat, reportSpam, canReportSpam, shouldDeleteChat, - shouldReportSpam, userId, - ]); - - if (!settings) { - return undefined; - } - - return ( -
- {canAddContact && ( - - )} - {canBlockContact && ( - - )} - - {canReportSpam && ( - - )} - - -
- ); -}; - -export default memo(withGlobal( - (global, { userId }): StateProps => ({ user: selectUser(global, userId) }), -)(UserReportPanel)); diff --git a/src/global/actions/api/chats.ts b/src/global/actions/api/chats.ts index fc8cc0cfe..af26e8d2a 100644 --- a/src/global/actions/api/chats.ts +++ b/src/global/actions/api/chats.ts @@ -981,6 +981,17 @@ addActionHandler('setChatEnabledReactions', async (global, actions, payload) => void loadFullChat(chat); }); +addActionHandler('loadChatSettings', async (global, actions, payload) => { + const { chatId } = payload!; + const chat = selectChat(global, chatId); + if (!chat) return undefined; + + const settings = await callApi('fetchChatSettings', chat); + if (!settings) return undefined; + + return updateChat(getGlobal(), chat.id, { settings }); +}); + async function loadChats( listType: 'active' | 'archived', offsetId?: string, offsetDate?: number, shouldReplace = false, ) { diff --git a/src/global/actions/api/management.ts b/src/global/actions/api/management.ts index f2f36fae7..66afb86d5 100644 --- a/src/global/actions/api/management.ts +++ b/src/global/actions/api/management.ts @@ -357,3 +357,16 @@ addActionHandler('hideAllChatJoinRequests', async (global, actions, payload) => }, }); }); + +addActionHandler('hideChatReportPanel', async (global, actions, payload) => { + const { chatId } = payload!; + const chat = selectChat(global, chatId); + if (!chat) return undefined; + + const result = await callApi('hideChatReportPanel', chat); + if (!result) return undefined; + + return updateChat(getGlobal(), chatId, { + settings: undefined, + }); +}); diff --git a/src/global/actions/api/users.ts b/src/global/actions/api/users.ts index 1f870839a..49d3cc639 100644 --- a/src/global/actions/api/users.ts +++ b/src/global/actions/api/users.ts @@ -268,13 +268,13 @@ addActionHandler('addContact', (global, actions, payload) => { }); addActionHandler('reportSpam', (global, actions, payload) => { - const { userId } = payload!; - const user = selectUser(global, userId); - if (!user) { + const { chatId } = payload!; + const userOrChat = isUserId(chatId) ? selectUser(global, chatId) : selectChat(global, chatId); + if (!userOrChat) { return; } - void callApi('reportSpam', user); + void callApi('reportSpam', userOrChat); }); async function searchUsers(query: string) { diff --git a/src/global/reducers/users.ts b/src/global/reducers/users.ts index 53d116279..cae162cf5 100644 --- a/src/global/reducers/users.ts +++ b/src/global/reducers/users.ts @@ -3,6 +3,7 @@ import { ApiUser, ApiUserStatus } from '../../api/types'; import { omit, pick } from '../../util/iteratees'; import { MEMO_EMPTY_ARRAY } from '../../util/memo'; +import { updateChat } from './chats'; export function replaceUsers(global: GlobalState, newById: Record): GlobalState { return { @@ -133,13 +134,17 @@ export function deleteContact(global: GlobalState, userId: string): GlobalState }, }; - return replaceUsers(global, { + global = replaceUsers(global, { ...byId, [userId]: { ...byId[userId], isContact: undefined, }, }); + + return updateChat(global, userId, { + settings: undefined, + }); } export function updateUserSearch( diff --git a/src/global/types.ts b/src/global/types.ts index a91f90838..a0466956a 100644 --- a/src/global/types.ts +++ b/src/global/types.ts @@ -533,7 +533,7 @@ export type NonTypedActionNames = ( // chats 'preloadTopChatMessages' | 'loadAllChats' | 'openChatWithInfo' | 'openLinkedChat' | 'openSupportChat' | 'openTipsChat' | 'focusMessageInComments' | 'openChatByPhoneNumber' | - 'loadFullChat' | 'loadTopChats' | 'requestChatUpdate' | 'updateChatMutedState' | + 'loadChatSettings' | 'loadFullChat' | 'loadTopChats' | 'requestChatUpdate' | 'updateChatMutedState' | 'joinChannel' | 'leaveChannel' | 'deleteChannel' | 'toggleChatPinned' | 'toggleChatArchived' | 'toggleChatUnread' | 'loadChatFolders' | 'loadRecommendedChatFolders' | 'editChatFolder' | 'addChatFolder' | 'deleteChatFolder' | 'updateChat' | 'toggleSignatures' | 'loadGroupsForDiscussion' | 'linkDiscussionGroup' | 'unlinkDiscussionGroup' | @@ -571,7 +571,7 @@ export type NonTypedActionNames = ( 'setEditingExportedInvite' | 'loadExportedChatInvites' | 'editExportedChatInvite' | 'exportChatInvite' | 'deleteExportedChatInvite' | 'deleteRevokedExportedChatInvites' | 'setOpenedInviteInfo' | 'loadChatInviteImporters' | 'loadChatJoinRequests' | 'hideChatJoinRequest' | 'hideAllChatJoinRequests' | 'requestNextManagementScreen' | - 'loadChatInviteRequesters' | + 'loadChatInviteRequesters' | 'hideChatReportPanel' | // groups 'togglePreHistoryHidden' | 'updateChatDefaultBannedRights' | 'updateChatMemberBannedRights' | 'updateChatAdmin' | 'acceptInviteConfirmation' | diff --git a/src/lib/gramjs/tl/apiTl.js b/src/lib/gramjs/tl/apiTl.js index affa1e955..b66f1fdbb 100644 --- a/src/lib/gramjs/tl/apiTl.js +++ b/src/lib/gramjs/tl/apiTl.js @@ -1028,6 +1028,7 @@ messages.sendMessage#d9d75a4 flags:# no_webpage:flags.1?true silent:flags.5?true messages.sendMedia#e25ff8e0 flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true noforwards:flags.14?true peer:InputPeer reply_to_msg_id:flags.0?int media:InputMedia message:string random_id:long reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector schedule_date:flags.10?int send_as:flags.13?InputPeer = Updates; messages.forwardMessages#cc30290b 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 from_peer:InputPeer id:Vector random_id:Vector to_peer:InputPeer schedule_date:flags.10?int send_as:flags.13?InputPeer = Updates; messages.reportSpam#cf1592db peer:InputPeer = Bool; +messages.getPeerSettings#efd9a6a2 peer:InputPeer = messages.PeerSettings; messages.report#8953ab4e peer:InputPeer id:Vector reason:ReportReason message:string = Bool; messages.getChats#49e9528f id:Vector = messages.Chats; messages.getFullChat#aeb00b34 chat_id:long = messages.ChatFull; @@ -1078,6 +1079,7 @@ messages.getOnlines#6e2be050 peer:InputPeer = ChatOnlines; messages.editChatAbout#def60797 peer:InputPeer about:string = Bool; messages.editChatDefaultBannedRights#a5866b41 peer:InputPeer banned_rights:ChatBannedRights = Updates; messages.getEmojiKeywordsDifference#1508b6af lang_code:string from_version:int = EmojiKeywordsDifference; +messages.hidePeerSettingsBar#4facb138 peer:InputPeer = Bool; messages.getScheduledHistory#f516760b peer:InputPeer hash:long = messages.Messages; messages.sendScheduledMessages#bd38850a peer:InputPeer id:Vector = Updates; messages.deleteScheduledMessages#59ae2b16 peer:InputPeer id:Vector = Updates; diff --git a/src/lib/gramjs/tl/static/api.json b/src/lib/gramjs/tl/static/api.json index 646d9e4f3..e9d4605db 100644 --- a/src/lib/gramjs/tl/static/api.json +++ b/src/lib/gramjs/tl/static/api.json @@ -69,6 +69,7 @@ "messages.sendMedia", "messages.forwardMessages", "messages.reportSpam", + "messages.getPeerSettings", "messages.report", "messages.getChats", "messages.getFullChat", @@ -124,6 +125,7 @@ "messages.editChatAbout", "messages.editChatDefaultBannedRights", "messages.getEmojiKeywordsDifference", + "messages.hidePeerSettingsBar", "messages.getScheduledHistory", "messages.sendScheduledMessages", "messages.deleteScheduledMessages",