Middle Header: Add "Report Spam and Leave" button, fix animations (#1759)
This commit is contained in:
parent
ab78137640
commit
fc9b679a66
@ -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),
|
||||
};
|
||||
}
|
||||
|
||||
@ -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),
|
||||
};
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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),
|
||||
}));
|
||||
}
|
||||
|
||||
@ -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),
|
||||
|
||||
@ -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) }),
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
.UserReportPanel {
|
||||
.ChatReportPanel {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
186
src/components/middle/ChatReportPanel.tsx
Normal file
186
src/components/middle/ChatReportPanel.tsx
Normal 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));
|
||||
@ -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,
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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));
|
||||
@ -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,
|
||||
) {
|
||||
|
||||
@ -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,
|
||||
});
|
||||
});
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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' |
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user