Middle Header: Add "Report Spam and Leave" button, fix animations (#1759)

This commit is contained in:
Alexander Zinchuk 2022-03-19 21:19:29 +01:00
parent ab78137640
commit fc9b679a66
22 changed files with 309 additions and 184 deletions

View File

@ -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),
};
}

View File

@ -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),
};
}

View File

@ -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) {

View File

@ -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 {

View File

@ -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),
}));
}

View File

@ -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),

View File

@ -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) }),
},
});
});

View File

@ -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;
}

View File

@ -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 {

View File

@ -130,7 +130,7 @@ const VideoPlayer: FC<OwnProps> = ({
}, []);
useEffect(() => {
if (!isMediaViewerOpen) return;
if (!isMediaViewerOpen) return undefined;
const togglePayingStateBySpace = (e: KeyboardEvent) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();

View File

@ -1,4 +1,4 @@
.UserReportPanel {
.ChatReportPanel {
position: absolute;
left: 0;
right: 0;

View File

@ -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<OwnProps & StateProps> = ({
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<boolean>(true);
const [shouldDeleteChat, setShouldDeleteChat] = useState<boolean>(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 (
<div className={buildClassName('ChatReportPanel', className)} dir={lang.isRtl ? 'rtl' : undefined}>
{canAddContact && (
<Button
isText
ripple
fluid
size="tiny"
className="UserReportPanel--Button"
onClick={handleAddContact}
>
{lang('lng_new_contact_add')}
</Button>
)}
{canBlockContact && (
<Button
color="danger"
isText
fluid
size="tiny"
className="UserReportPanel--Button"
onClick={openBlockUserModal}
>
{lang('lng_new_contact_block')}
</Button>
)}
{canReportSpam && !canBlockContact && (
<Button
color="danger"
isText
fluid
size="tiny"
className="UserReportPanel--Button"
onClick={openBlockUserModal}
>
{lang('lng_report_spam_and_leave')}
</Button>
)}
<Button
round
ripple
size="tiny"
color="translucent"
onClick={handleCloseReportPanel}
ariaLabel={lang('Close')}
>
<i className="icon-close" />
</Button>
<ConfirmDialog
isOpen={isBlockUserModalOpen}
onClose={closeBlockUserModal}
title={lang('BlockUserTitle', user ? getUserFirstOrLastName(user) : getChatTitle(lang, chat!))}
text={user
? lang('UserInfo.BlockConfirmationTitle', getUserFullName(user))
: lang('Chat.Confirm.ReportSpam.Group')}
isButtonsInOneRow
confirmIsDestructive
confirmLabel={lang('Block')}
confirmHandler={user ? handleConfirmBlock : handleChatReportSpam}
>
{user && canReportSpam && (
<Checkbox
label={lang('DeleteReportSpam')}
checked={shouldReportSpam}
onCheck={setShouldReportSpam}
/>
)}
{user && (
<Checkbox
label={lang('DeleteThisChat')}
checked={shouldDeleteChat}
onCheck={setShouldDeleteChat}
/>
)}
</ConfirmDialog>
</div>
);
};
export default memo(withGlobal<OwnProps>(
(global, { chatId }): StateProps => ({
currentUserId: global.currentUserId,
chat: selectChat(global, chatId),
user: isUserId(chatId) ? selectUser(global, chatId) : undefined,
}),
)(ChatReportPanel));

View File

@ -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<StateProps> = ({
shouldSkipHistoryAnimations,
currentTransitionKey,
isChannel,
isUserFull,
areChatSettingsLoaded,
canSubscribe,
canStartBot,
canRestartBot,
@ -161,7 +160,7 @@ const MiddleColumn: FC<StateProps> = ({
openChat,
unpinAllMessages,
loadUser,
loadFullUser,
loadChatSettings,
closeLocalTextSearch,
exitMessageSelectMode,
closePaymentModal,
@ -258,10 +257,10 @@ const MiddleColumn: FC<StateProps> = ({
}, [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<HTMLDivElement>) => {
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,

View File

@ -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<OwnProps & StateProps> = ({
isChatWithSelf,
isChatWithBot,
lastSyncTime,
shouldShowUserReportPanel,
shouldSkipHistoryAnimations,
currentTransitionKey,
connectionState,
@ -136,6 +133,7 @@ const MiddleHeader: FC<OwnProps & StateProps> = ({
? 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<OwnProps & StateProps> = ({
&& 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<OwnProps & StateProps> = ({
/>
)}
{shouldShowUserReportPanel && <UserReportPanel key={chatId} userId={chatId} />}
{shouldShowChatReportPanel && (
<ChatReportPanel
key={chatId}
chatId={chatId}
settings={renderingChatSettings}
className={chatReportPanelClassNames}
/>
)}
<div className="header-tools">
{isAudioPlayerRendered && (
@ -425,9 +437,6 @@ export default memo(withGlobal<OwnProps>(
(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<OwnProps>(
audioMessage,
chat,
messagesCount,
shouldShowUserReportPanel: Boolean(user?.settings?.canAddContact || user?.settings?.canBlockContact),
isChatWithSelf: selectIsChatWithSelf(global, chatId),
isChatWithBot: chat && selectIsChatWithBot(global, chat),
lastSyncTime,

View File

@ -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<OwnProps & StateProps> = ({ userId, user }) => {
const {
addContact,
blockContact,
reportSpam,
deleteChat,
toggleChatArchived,
} = getActions();
const lang = useLang();
const [isBlockUserModalOpen, openBlockUserModal, closeBlockUserModal] = useFlag();
const [shouldReportSpam, setShouldReportSpam] = useState<boolean>(true);
const [shouldDeleteChat, setShouldDeleteChat] = useState<boolean>(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 (
<div className="UserReportPanel">
{canAddContact && (
<Button
isText
ripple
fluid
size="tiny"
className="UserReportPanel--Button"
onClick={handleAddContact}
>
{lang('lng_new_contact_add')}
</Button>
)}
{canBlockContact && (
<Button
color="danger"
isText
ripple
fluid
size="tiny"
className="UserReportPanel--Button"
onClick={openBlockUserModal}
>
{lang('lng_new_contact_block')}
</Button>
)}
<ConfirmDialog
isOpen={isBlockUserModalOpen}
onClose={closeBlockUserModal}
title={lang('BlockUserTitle', getUserFirstOrLastName(user))}
text={lang('UserInfo.BlockConfirmationTitle', getUserFullName(user))}
isButtonsInOneRow
confirmIsDestructive
confirmLabel={lang('Block')}
confirmHandler={handleConfirmBlock}
>
{canReportSpam && (
<Checkbox
label={lang('DeleteReportSpam')}
checked={shouldReportSpam}
onCheck={setShouldReportSpam}
/>
)}
<Checkbox
label={lang('DeleteThisChat')}
checked={shouldDeleteChat}
onCheck={setShouldDeleteChat}
/>
</ConfirmDialog>
</div>
);
};
export default memo(withGlobal<OwnProps>(
(global, { userId }): StateProps => ({ user: selectUser(global, userId) }),
)(UserReportPanel));

View File

@ -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,
) {

View File

@ -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,
});
});

View File

@ -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) {

View File

@ -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<string, ApiUser>): 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(

View File

@ -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' |

View File

@ -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<MessageEntity> 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<int> random_id:Vector<long> 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<int> reason:ReportReason message:string = Bool;
messages.getChats#49e9528f id:Vector<long> = 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<int> = Updates;
messages.deleteScheduledMessages#59ae2b16 peer:InputPeer id:Vector<int> = Updates;

View File

@ -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",