Middle Header: Introduce Add Contact and Block User buttons (#1735)
This commit is contained in:
parent
531c2de36c
commit
a215aa1083
@ -1,13 +1,13 @@
|
|||||||
import { Api as GramJs } from '../../../lib/gramjs';
|
import { Api as GramJs } from '../../../lib/gramjs';
|
||||||
import {
|
import {
|
||||||
ApiBotCommand, ApiUser, ApiUserStatus, ApiUserType,
|
ApiBotCommand, ApiUser, ApiUserSettings, ApiUserStatus, ApiUserType,
|
||||||
} from '../../types';
|
} from '../../types';
|
||||||
import { buildApiPeerId } from './peers';
|
import { buildApiPeerId } from './peers';
|
||||||
|
|
||||||
export function buildApiUserFromFull(mtpUserFull: GramJs.users.UserFull): ApiUser {
|
export function buildApiUserFromFull(mtpUserFull: GramJs.users.UserFull): ApiUser {
|
||||||
const {
|
const {
|
||||||
fullUser: {
|
fullUser: {
|
||||||
about, commonChatsCount, pinnedMsgId, botInfo, blocked,
|
about, commonChatsCount, pinnedMsgId, botInfo, blocked, settings,
|
||||||
},
|
},
|
||||||
users,
|
users,
|
||||||
} = mtpUserFull;
|
} = mtpUserFull;
|
||||||
@ -16,6 +16,7 @@ export function buildApiUserFromFull(mtpUserFull: GramJs.users.UserFull): ApiUse
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
...user,
|
...user,
|
||||||
|
settings: buildApiUserSettings(settings),
|
||||||
fullInfo: {
|
fullInfo: {
|
||||||
bio: about,
|
bio: about,
|
||||||
commonChatsCount,
|
commonChatsCount,
|
||||||
@ -111,3 +112,17 @@ export function buildApiUsersAndStatuses(mtpUsers: GramJs.TypeUser[]) {
|
|||||||
|
|
||||||
return { users, userStatusesById };
|
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),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
@ -28,7 +28,7 @@ export {
|
|||||||
|
|
||||||
export {
|
export {
|
||||||
fetchFullUser, fetchNearestCountry, fetchTopUsers, fetchContactList, fetchUsers,
|
fetchFullUser, fetchNearestCountry, fetchTopUsers, fetchContactList, fetchUsers,
|
||||||
addContact, updateContact, deleteContact, fetchProfilePhotos, fetchCommonChats,
|
addContact, updateContact, deleteContact, fetchProfilePhotos, fetchCommonChats, reportSpam,
|
||||||
} from './users';
|
} from './users';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
|||||||
@ -51,6 +51,7 @@ export async function fetchFullUser({
|
|||||||
'@type': 'updateUser',
|
'@type': 'updateUser',
|
||||||
id,
|
id,
|
||||||
user: {
|
user: {
|
||||||
|
settings: userWithFullInfo.settings,
|
||||||
fullInfo: userWithFullInfo.fullInfo,
|
fullInfo: userWithFullInfo.fullInfo,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -247,6 +248,14 @@ export async function fetchProfilePhotos(user?: ApiUser, chat?: ApiChat) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function reportSpam(user: ApiUser) {
|
||||||
|
const { id, accessHash } = user;
|
||||||
|
|
||||||
|
return invokeRequest(new GramJs.messages.ReportSpam({
|
||||||
|
peer: buildInputPeer(id, accessHash),
|
||||||
|
}), true);
|
||||||
|
}
|
||||||
|
|
||||||
function updateLocalDb(result: (GramJs.photos.Photos | GramJs.photos.PhotosSlice | GramJs.messages.Chats)) {
|
function updateLocalDb(result: (GramJs.photos.Photos | GramJs.photos.PhotosSlice | GramJs.messages.Chats)) {
|
||||||
if ('chats' in result) {
|
if ('chats' in result) {
|
||||||
addEntitiesWithPhotosToLocalDb(result.chats);
|
addEntitiesWithPhotosToLocalDb(result.chats);
|
||||||
|
|||||||
@ -23,7 +23,7 @@ import {
|
|||||||
buildApiChatFromPreview,
|
buildApiChatFromPreview,
|
||||||
buildApiChatFolder,
|
buildApiChatFolder,
|
||||||
} from './apiBuilders/chats';
|
} from './apiBuilders/chats';
|
||||||
import { buildApiUser, buildApiUserStatus } from './apiBuilders/users';
|
import { buildApiUser, buildApiUserSettings, buildApiUserStatus } from './apiBuilders/users';
|
||||||
import {
|
import {
|
||||||
buildMessageFromUpdate,
|
buildMessageFromUpdate,
|
||||||
isMessageWithMedia,
|
isMessageWithMedia,
|
||||||
@ -771,11 +771,12 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) {
|
|||||||
});
|
});
|
||||||
} else if (update instanceof GramJs.UpdatePeerSettings) {
|
} else if (update instanceof GramJs.UpdatePeerSettings) {
|
||||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||||
const { _entities } = update;
|
const { _entities, settings } = update;
|
||||||
if (!_entities) {
|
if (!_entities) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (_entities?.length) {
|
if (_entities?.length) {
|
||||||
_entities
|
_entities
|
||||||
.filter((e) => e instanceof GramJs.User && !e.contact)
|
.filter((e) => e instanceof GramJs.User && !e.contact)
|
||||||
@ -797,7 +798,10 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) {
|
|||||||
onUpdate({
|
onUpdate({
|
||||||
'@type': 'updateUser',
|
'@type': 'updateUser',
|
||||||
id: user.id,
|
id: user.id,
|
||||||
user,
|
user: {
|
||||||
|
...user,
|
||||||
|
...(settings && { settings: buildApiUserSettings(settings) }),
|
||||||
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,6 +26,14 @@ export interface ApiUser {
|
|||||||
|
|
||||||
// Obtained from GetFullUser / UserFullInfo
|
// Obtained from GetFullUser / UserFullInfo
|
||||||
fullInfo?: ApiUserFullInfo;
|
fullInfo?: ApiUserFullInfo;
|
||||||
|
settings?: ApiUserSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ApiUserSettings {
|
||||||
|
isAutoArchived?: boolean;
|
||||||
|
canReportSpam?: boolean;
|
||||||
|
canAddContact?: boolean;
|
||||||
|
canBlockContact?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ApiUserFullInfo {
|
export interface ApiUserFullInfo {
|
||||||
|
|||||||
@ -42,6 +42,7 @@ import {
|
|||||||
selectIsUserBlocked,
|
selectIsUserBlocked,
|
||||||
selectPinnedIds,
|
selectPinnedIds,
|
||||||
selectTheme,
|
selectTheme,
|
||||||
|
selectUser,
|
||||||
} from '../../modules/selectors';
|
} from '../../modules/selectors';
|
||||||
import {
|
import {
|
||||||
getCanPostInChat, getMessageSendingRestrictionReason, isChatChannel, isChatSuperGroup, isUserId,
|
getCanPostInChat, getMessageSendingRestrictionReason, isChatChannel, isChatSuperGroup, isUserId,
|
||||||
@ -106,10 +107,12 @@ type StateProps = {
|
|||||||
currentTransitionKey: number;
|
currentTransitionKey: number;
|
||||||
messageLists?: GlobalMessageList[];
|
messageLists?: GlobalMessageList[];
|
||||||
isChannel?: boolean;
|
isChannel?: boolean;
|
||||||
|
isUserFull?: boolean;
|
||||||
canSubscribe?: boolean;
|
canSubscribe?: boolean;
|
||||||
canStartBot?: boolean;
|
canStartBot?: boolean;
|
||||||
canRestartBot?: boolean;
|
canRestartBot?: boolean;
|
||||||
activeEmojiInteractions?: ActiveEmojiInteraction[];
|
activeEmojiInteractions?: ActiveEmojiInteraction[];
|
||||||
|
lastSyncTime?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
const CLOSE_ANIMATION_DURATION = IS_SINGLE_COLUMN_LAYOUT ? 450 + ANIMATION_END_DELAY : undefined;
|
const CLOSE_ANIMATION_DURATION = IS_SINGLE_COLUMN_LAYOUT ? 450 + ANIMATION_END_DELAY : undefined;
|
||||||
@ -147,15 +150,18 @@ const MiddleColumn: FC<StateProps> = ({
|
|||||||
shouldSkipHistoryAnimations,
|
shouldSkipHistoryAnimations,
|
||||||
currentTransitionKey,
|
currentTransitionKey,
|
||||||
isChannel,
|
isChannel,
|
||||||
|
isUserFull,
|
||||||
canSubscribe,
|
canSubscribe,
|
||||||
canStartBot,
|
canStartBot,
|
||||||
canRestartBot,
|
canRestartBot,
|
||||||
activeEmojiInteractions,
|
activeEmojiInteractions,
|
||||||
|
lastSyncTime,
|
||||||
}) => {
|
}) => {
|
||||||
const {
|
const {
|
||||||
openChat,
|
openChat,
|
||||||
unpinAllMessages,
|
unpinAllMessages,
|
||||||
loadUser,
|
loadUser,
|
||||||
|
loadFullUser,
|
||||||
closeLocalTextSearch,
|
closeLocalTextSearch,
|
||||||
exitMessageSelectMode,
|
exitMessageSelectMode,
|
||||||
closePaymentModal,
|
closePaymentModal,
|
||||||
@ -251,6 +257,12 @@ const MiddleColumn: FC<StateProps> = ({
|
|||||||
}
|
}
|
||||||
}, [chatId, isPrivate, loadUser]);
|
}, [chatId, isPrivate, loadUser]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (isPrivate && !isUserFull && lastSyncTime) {
|
||||||
|
loadFullUser({ userId: chatId });
|
||||||
|
}
|
||||||
|
}, [chatId, isPrivate, isUserFull, lastSyncTime, loadFullUser]);
|
||||||
|
|
||||||
const handleDragEnter = useCallback((e: React.DragEvent<HTMLDivElement>) => {
|
const handleDragEnter = useCallback((e: React.DragEvent<HTMLDivElement>) => {
|
||||||
if (IS_TOUCH_ENV) {
|
if (IS_TOUCH_ENV) {
|
||||||
return;
|
return;
|
||||||
@ -540,7 +552,9 @@ export default memo(withGlobal(
|
|||||||
|
|
||||||
const { messageLists } = global.messages;
|
const { messageLists } = global.messages;
|
||||||
const currentMessageList = selectCurrentMessageList(global);
|
const currentMessageList = selectCurrentMessageList(global);
|
||||||
const { isLeftColumnShown, chats: { listIds }, activeEmojiInteractions } = global;
|
const {
|
||||||
|
isLeftColumnShown, chats: { listIds }, activeEmojiInteractions, lastSyncTime,
|
||||||
|
} = global;
|
||||||
|
|
||||||
const state: StateProps = {
|
const state: StateProps = {
|
||||||
theme,
|
theme,
|
||||||
@ -559,6 +573,7 @@ export default memo(withGlobal(
|
|||||||
animationLevel: global.settings.byKey.animationLevel,
|
animationLevel: global.settings.byKey.animationLevel,
|
||||||
currentTransitionKey: Math.max(0, global.messages.messageLists.length - 1),
|
currentTransitionKey: Math.max(0, global.messages.messageLists.length - 1),
|
||||||
activeEmojiInteractions,
|
activeEmojiInteractions,
|
||||||
|
lastSyncTime,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!currentMessageList || !listIds.active) {
|
if (!currentMessageList || !listIds.active) {
|
||||||
@ -566,8 +581,10 @@ export default memo(withGlobal(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { chatId, threadId, type: messageListType } = currentMessageList;
|
const { chatId, threadId, type: messageListType } = currentMessageList;
|
||||||
|
const isPrivate = isUserId(chatId);
|
||||||
const chat = selectChat(global, chatId);
|
const chat = selectChat(global, chatId);
|
||||||
const bot = selectChatBot(global, chatId);
|
const bot = selectChatBot(global, chatId);
|
||||||
|
const user = isPrivate ? selectUser(global, chatId) : undefined;
|
||||||
const pinnedIds = selectPinnedIds(global, chatId);
|
const pinnedIds = selectPinnedIds(global, chatId);
|
||||||
const { chatId: audioChatId, messageId: audioMessageId } = global.audioPlayer;
|
const { chatId: audioChatId, messageId: audioMessageId } = global.audioPlayer;
|
||||||
|
|
||||||
@ -588,7 +605,8 @@ export default memo(withGlobal(
|
|||||||
chatId,
|
chatId,
|
||||||
threadId,
|
threadId,
|
||||||
messageListType,
|
messageListType,
|
||||||
isPrivate: isUserId(chatId),
|
isPrivate,
|
||||||
|
isUserFull: Boolean(user?.settings),
|
||||||
canPost: !isPinnedMessageList && (!chat || canPost) && !isBotNotStarted,
|
canPost: !isPinnedMessageList && (!chat || canPost) && !isBotNotStarted,
|
||||||
isPinnedMessageList,
|
isPinnedMessageList,
|
||||||
isScheduledMessageList,
|
isScheduledMessageList,
|
||||||
|
|||||||
@ -19,7 +19,7 @@ import {
|
|||||||
} from '../../config';
|
} from '../../config';
|
||||||
import { IS_SINGLE_COLUMN_LAYOUT, IS_TABLET_COLUMN_LAYOUT } from '../../util/environment';
|
import { IS_SINGLE_COLUMN_LAYOUT, IS_TABLET_COLUMN_LAYOUT } from '../../util/environment';
|
||||||
import {
|
import {
|
||||||
getChatTitle, getMessageKey, getSenderTitle, isUserId,
|
getChatTitle, getMessageKey, getPrivateChatUserId, getSenderTitle, isUserId,
|
||||||
} from '../../modules/helpers';
|
} from '../../modules/helpers';
|
||||||
import {
|
import {
|
||||||
selectAllowedMessageActions,
|
selectAllowedMessageActions,
|
||||||
@ -35,6 +35,7 @@ import {
|
|||||||
selectScheduledIds,
|
selectScheduledIds,
|
||||||
selectThreadInfo,
|
selectThreadInfo,
|
||||||
selectThreadTopMessageId,
|
selectThreadTopMessageId,
|
||||||
|
selectUser,
|
||||||
} from '../../modules/selectors';
|
} from '../../modules/selectors';
|
||||||
import useEnsureMessage from '../../hooks/useEnsureMessage';
|
import useEnsureMessage from '../../hooks/useEnsureMessage';
|
||||||
import useWindowSize from '../../hooks/useWindowSize';
|
import useWindowSize from '../../hooks/useWindowSize';
|
||||||
@ -53,6 +54,7 @@ import HeaderActions from './HeaderActions';
|
|||||||
import HeaderPinnedMessage from './HeaderPinnedMessage';
|
import HeaderPinnedMessage from './HeaderPinnedMessage';
|
||||||
import AudioPlayer from './AudioPlayer';
|
import AudioPlayer from './AudioPlayer';
|
||||||
import GroupCallTopPane from '../calls/group/GroupCallTopPane';
|
import GroupCallTopPane from '../calls/group/GroupCallTopPane';
|
||||||
|
import UserReportPanel from './UserReportPanel';
|
||||||
|
|
||||||
import './MiddleHeader.scss';
|
import './MiddleHeader.scss';
|
||||||
|
|
||||||
@ -81,6 +83,7 @@ type StateProps = {
|
|||||||
isChatWithSelf?: boolean;
|
isChatWithSelf?: boolean;
|
||||||
isChatWithBot?: boolean;
|
isChatWithBot?: boolean;
|
||||||
lastSyncTime?: number;
|
lastSyncTime?: number;
|
||||||
|
shouldShowUserReportPanel?: boolean;
|
||||||
shouldSkipHistoryAnimations?: boolean;
|
shouldSkipHistoryAnimations?: boolean;
|
||||||
currentTransitionKey: number;
|
currentTransitionKey: number;
|
||||||
connectionState?: GlobalState['connectionState'];
|
connectionState?: GlobalState['connectionState'];
|
||||||
@ -106,6 +109,7 @@ const MiddleHeader: FC<OwnProps & StateProps> = ({
|
|||||||
isChatWithSelf,
|
isChatWithSelf,
|
||||||
isChatWithBot,
|
isChatWithBot,
|
||||||
lastSyncTime,
|
lastSyncTime,
|
||||||
|
shouldShowUserReportPanel,
|
||||||
shouldSkipHistoryAnimations,
|
shouldSkipHistoryAnimations,
|
||||||
currentTransitionKey,
|
currentTransitionKey,
|
||||||
connectionState,
|
connectionState,
|
||||||
@ -395,6 +399,9 @@ const MiddleHeader: FC<OwnProps & StateProps> = ({
|
|||||||
onAllPinnedClick={handleAllPinnedClick}
|
onAllPinnedClick={handleAllPinnedClick}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{shouldShowUserReportPanel && <UserReportPanel key={chatId} userId={chatId} />}
|
||||||
|
|
||||||
<div className="header-tools">
|
<div className="header-tools">
|
||||||
{isAudioPlayerRendered && (
|
{isAudioPlayerRendered && (
|
||||||
<AudioPlayer
|
<AudioPlayer
|
||||||
@ -418,6 +425,8 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
(global, { chatId, threadId, messageListType }): StateProps => {
|
(global, { chatId, threadId, messageListType }): StateProps => {
|
||||||
const { isLeftColumnShown, lastSyncTime, shouldSkipHistoryAnimations } = global;
|
const { isLeftColumnShown, lastSyncTime, shouldSkipHistoryAnimations } = global;
|
||||||
const chat = selectChat(global, chatId);
|
const chat = selectChat(global, chatId);
|
||||||
|
const userId = chat && getPrivateChatUserId(chat);
|
||||||
|
const user = userId ? selectUser(global, userId) : undefined;
|
||||||
|
|
||||||
const { typingStatus } = chat || {};
|
const { typingStatus } = chat || {};
|
||||||
|
|
||||||
@ -446,6 +455,7 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
audioMessage,
|
audioMessage,
|
||||||
chat,
|
chat,
|
||||||
messagesCount,
|
messagesCount,
|
||||||
|
shouldShowUserReportPanel: Boolean(user?.settings?.canAddContact || user?.settings?.canBlockContact),
|
||||||
isChatWithSelf: selectIsChatWithSelf(global, chatId),
|
isChatWithSelf: selectIsChatWithSelf(global, chatId),
|
||||||
isChatWithBot: chat && selectIsChatWithBot(global, chat),
|
isChatWithBot: chat && selectIsChatWithBot(global, chat),
|
||||||
lastSyncTime,
|
lastSyncTime,
|
||||||
|
|||||||
36
src/components/middle/UserReportPanel.scss
Normal file
36
src/components/middle/UserReportPanel.scss
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
.UserReportPanel {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
top: 100%;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-left: auto;
|
||||||
|
background: var(--color-background);
|
||||||
|
padding: 0.375rem 0.8125rem 0.25rem 1rem;
|
||||||
|
box-shadow: 0 0.125rem 0.125rem var(--color-light-shadow), inset 0 0.125rem 0.125rem var(--color-light-shadow);
|
||||||
|
transform: translate3d(0, 0, 0);
|
||||||
|
transition: opacity 0.15s ease, transform var(--layer-transition);
|
||||||
|
|
||||||
|
body.animation-level-1 & {
|
||||||
|
.ripple-container {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1276px) {
|
||||||
|
transform: translate3d(0, 0, 0);
|
||||||
|
transition: opacity 0.15s ease, transform var(--layer-transition);
|
||||||
|
|
||||||
|
#Main.right-column-open & {
|
||||||
|
padding-right: calc(var(--right-column-width) + 1rem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.UserReportPanel--Button {
|
||||||
|
margin-left: 0.25rem;
|
||||||
|
flex: 1 1 50%;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
124
src/components/middle/UserReportPanel.tsx
Normal file
124
src/components/middle/UserReportPanel.tsx
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
import React, { FC, memo, useCallback, useState } from '../../lib/teact/teact';
|
||||||
|
import { withGlobal, getDispatch } from '../../lib/teact/teactn';
|
||||||
|
|
||||||
|
import { ApiUser } from '../../api/types';
|
||||||
|
|
||||||
|
import { selectUser } from '../../modules/selectors';
|
||||||
|
import { getUserFirstOrLastName, getUserFullName } from '../../modules/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,
|
||||||
|
} = getDispatch();
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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));
|
||||||
@ -561,7 +561,7 @@ export type ActionTypes = (
|
|||||||
// users
|
// users
|
||||||
'loadFullUser' | 'loadNearestCountry' | 'loadTopUsers' | 'loadContactList' |
|
'loadFullUser' | 'loadNearestCountry' | 'loadTopUsers' | 'loadContactList' |
|
||||||
'loadCurrentUser' | 'updateProfile' | 'checkUsername' | 'addContact' | 'updateContact' |
|
'loadCurrentUser' | 'updateProfile' | 'checkUsername' | 'addContact' | 'updateContact' |
|
||||||
'deleteContact' | 'loadUser' | 'setUserSearchQuery' | 'loadCommonChats' |
|
'deleteContact' | 'loadUser' | 'setUserSearchQuery' | 'loadCommonChats' | 'reportSpam' |
|
||||||
// chat creation
|
// chat creation
|
||||||
'createChannel' | 'createGroupChat' | 'resetChatCreation' |
|
'createChannel' | 'createGroupChat' | 'resetChatCreation' |
|
||||||
// settings
|
// settings
|
||||||
|
|||||||
@ -1021,6 +1021,7 @@ messages.setTyping#58943ee2 flags:# peer:InputPeer top_msg_id:flags.0?int action
|
|||||||
messages.sendMessage#d9d75a4 flags:# no_webpage:flags.1?true 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 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.sendMessage#d9d75a4 flags:# no_webpage:flags.1?true 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 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.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.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.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.report#8953ab4e peer:InputPeer id:Vector<int> reason:ReportReason message:string = Bool;
|
messages.report#8953ab4e peer:InputPeer id:Vector<int> reason:ReportReason message:string = Bool;
|
||||||
messages.getChats#49e9528f id:Vector<long> = messages.Chats;
|
messages.getChats#49e9528f id:Vector<long> = messages.Chats;
|
||||||
messages.getFullChat#aeb00b34 chat_id:long = messages.ChatFull;
|
messages.getFullChat#aeb00b34 chat_id:long = messages.ChatFull;
|
||||||
|
|||||||
@ -67,6 +67,7 @@
|
|||||||
"messages.sendMessage",
|
"messages.sendMessage",
|
||||||
"messages.sendMedia",
|
"messages.sendMedia",
|
||||||
"messages.forwardMessages",
|
"messages.forwardMessages",
|
||||||
|
"messages.reportSpam",
|
||||||
"messages.report",
|
"messages.report",
|
||||||
"messages.getChats",
|
"messages.getChats",
|
||||||
"messages.getFullChat",
|
"messages.getFullChat",
|
||||||
|
|||||||
@ -271,6 +271,16 @@ addReducer('addContact', (global, actions, payload) => {
|
|||||||
void callApi('addContact', pick(user, ['id', 'accessHash', 'firstName', 'lastName', 'phoneNumber']));
|
void callApi('addContact', pick(user, ['id', 'accessHash', 'firstName', 'lastName', 'phoneNumber']));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
addReducer('reportSpam', (global, actions, payload) => {
|
||||||
|
const { userId } = payload!;
|
||||||
|
const user = selectUser(global, userId);
|
||||||
|
if (!user) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void callApi('reportSpam', user);
|
||||||
|
});
|
||||||
|
|
||||||
async function searchUsers(query: string) {
|
async function searchUsers(query: string) {
|
||||||
const result = await callApi('searchChats', { query });
|
const result = await callApi('searchChats', { query });
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user