mirror of
https://github.com/danog/telegram-tt.git
synced 2024-11-30 04:39:00 +01:00
Support "Report Peer" and "Report Profile Photo" (#126)
This commit is contained in:
parent
a7e2695f2e
commit
91c2015052
@ -11,7 +11,9 @@ import {
|
||||
ApiGroupCall,
|
||||
ApiMessageEntity,
|
||||
ApiMessageEntityTypes,
|
||||
ApiNewPoll, ApiPhoneCall,
|
||||
ApiNewPoll,
|
||||
ApiPhoto,
|
||||
ApiPhoneCall,
|
||||
ApiReportReason,
|
||||
ApiSendMessageAction,
|
||||
ApiSticker,
|
||||
@ -343,6 +345,20 @@ export function buildChatPhotoForLocalDb(photo: GramJs.TypePhoto) {
|
||||
});
|
||||
}
|
||||
|
||||
export function buildInputPhoto(photo: ApiPhoto) {
|
||||
const localPhoto = localDb.photos[photo?.id];
|
||||
|
||||
if (!localPhoto) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return new GramJs.InputPhoto(pick(localPhoto, [
|
||||
'id',
|
||||
'accessHash',
|
||||
'fileReference',
|
||||
]));
|
||||
}
|
||||
|
||||
export function buildInputContact({
|
||||
phone,
|
||||
firstName,
|
||||
|
43
src/api/gramjs/methods/account.ts
Normal file
43
src/api/gramjs/methods/account.ts
Normal file
@ -0,0 +1,43 @@
|
||||
import {
|
||||
ApiChat, ApiPhoto, ApiReportReason, ApiUser,
|
||||
} from '../../types';
|
||||
import { invokeRequest } from './client';
|
||||
import { Api as GramJs } from '../../../lib/gramjs';
|
||||
import { buildInputPeer, buildInputReportReason, buildInputPhoto } from '../gramjsBuilders';
|
||||
|
||||
export async function reportPeer({
|
||||
peer,
|
||||
reason,
|
||||
description,
|
||||
}: {
|
||||
peer: ApiChat | ApiUser; reason: ApiReportReason; description?: string;
|
||||
}) {
|
||||
const result = await invokeRequest(new GramJs.account.ReportPeer({
|
||||
peer: buildInputPeer(peer.id, peer.accessHash),
|
||||
reason: buildInputReportReason(reason),
|
||||
message: description,
|
||||
}));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export async function reportProfilePhoto({
|
||||
peer,
|
||||
photo,
|
||||
reason,
|
||||
description,
|
||||
}: {
|
||||
peer: ApiChat | ApiUser; photo: ApiPhoto; reason: ApiReportReason; description?: string;
|
||||
}) {
|
||||
const photoId = buildInputPhoto(photo);
|
||||
if (!photoId) return undefined;
|
||||
|
||||
const result = await invokeRequest(new GramJs.account.ReportProfilePhoto({
|
||||
peer: buildInputPeer(peer.id, peer.accessHash),
|
||||
photoId,
|
||||
reason: buildInputReportReason(reason),
|
||||
message: description,
|
||||
}));
|
||||
|
||||
return result;
|
||||
}
|
@ -2,6 +2,10 @@ export {
|
||||
destroy, disconnect, downloadMedia, fetchCurrentUser, repairFileReference,
|
||||
} from './client';
|
||||
|
||||
export {
|
||||
reportPeer, reportProfilePhoto,
|
||||
} from './account';
|
||||
|
||||
export {
|
||||
provideAuthPhoneNumber, provideAuthCode, provideAuthPassword, provideAuthRegistration, restartAuth, restartAuthWithQr,
|
||||
} from './auth';
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { ChangeEvent } from 'react';
|
||||
|
||||
import React, {
|
||||
FC, memo, useCallback, useState,
|
||||
FC, memo, useCallback, useMemo, useState,
|
||||
} from '../../lib/teact/teact';
|
||||
import { getActions } from '../../global';
|
||||
|
||||
import { ApiReportReason } from '../../api/types';
|
||||
import { ApiPhoto, ApiReportReason } from '../../api/types';
|
||||
|
||||
import useLang from '../../hooks/useLang';
|
||||
|
||||
@ -16,17 +16,27 @@ import InputText from '../ui/InputText';
|
||||
|
||||
export type OwnProps = {
|
||||
isOpen: boolean;
|
||||
subject?: 'peer' | 'messages' | 'media';
|
||||
chatId?: string;
|
||||
photo?: ApiPhoto;
|
||||
messageIds?: number[];
|
||||
onClose: () => void;
|
||||
onCloseAnimationEnd?: () => void;
|
||||
};
|
||||
|
||||
const ReportMessageModal: FC<OwnProps> = ({
|
||||
const ReportModal: FC<OwnProps> = ({
|
||||
isOpen,
|
||||
subject = 'messages',
|
||||
chatId,
|
||||
photo,
|
||||
messageIds,
|
||||
onClose,
|
||||
onCloseAnimationEnd,
|
||||
}) => {
|
||||
const {
|
||||
reportMessages,
|
||||
reportPeer,
|
||||
reportProfilePhoto,
|
||||
exitMessageSelectMode,
|
||||
} = getActions();
|
||||
|
||||
@ -34,10 +44,34 @@ const ReportMessageModal: FC<OwnProps> = ({
|
||||
const [description, setDescription] = useState('');
|
||||
|
||||
const handleReport = useCallback(() => {
|
||||
reportMessages({ messageIds, reason: selectedReason, description });
|
||||
exitMessageSelectMode();
|
||||
switch (subject) {
|
||||
case 'messages':
|
||||
reportMessages({ messageIds, reason: selectedReason, description });
|
||||
exitMessageSelectMode();
|
||||
break;
|
||||
case 'peer':
|
||||
reportPeer({ chatId, reason: selectedReason, description });
|
||||
break;
|
||||
case 'media':
|
||||
reportProfilePhoto({
|
||||
chatId, photo, reason: selectedReason, description,
|
||||
});
|
||||
break;
|
||||
}
|
||||
onClose();
|
||||
}, [description, exitMessageSelectMode, messageIds, onClose, reportMessages, selectedReason]);
|
||||
}, [
|
||||
description,
|
||||
exitMessageSelectMode,
|
||||
messageIds,
|
||||
photo,
|
||||
onClose,
|
||||
reportMessages,
|
||||
selectedReason,
|
||||
chatId,
|
||||
reportProfilePhoto,
|
||||
reportPeer,
|
||||
subject,
|
||||
]);
|
||||
|
||||
const handleSelectReason = useCallback((value: string) => {
|
||||
setSelectedReason(value as ApiReportReason);
|
||||
@ -49,7 +83,7 @@ const ReportMessageModal: FC<OwnProps> = ({
|
||||
|
||||
const lang = useLang();
|
||||
|
||||
const REPORT_OPTIONS: { value: ApiReportReason; label: string }[] = [
|
||||
const REPORT_OPTIONS: { value: ApiReportReason; label: string }[] = useMemo(() => [
|
||||
{ value: 'spam', label: lang('lng_report_reason_spam') },
|
||||
{ value: 'violence', label: lang('lng_report_reason_violence') },
|
||||
{ value: 'pornography', label: lang('lng_report_reason_pornography') },
|
||||
@ -58,19 +92,28 @@ const ReportMessageModal: FC<OwnProps> = ({
|
||||
{ value: 'illegalDrugs', label: 'Illegal Drugs' },
|
||||
{ value: 'personalDetails', label: 'Personal Details' },
|
||||
{ value: 'other', label: lang('lng_report_reason_other') },
|
||||
];
|
||||
], [lang]);
|
||||
|
||||
if (!messageIds) {
|
||||
if (
|
||||
(subject === 'messages' && !messageIds)
|
||||
|| (subject === 'peer' && !chatId)
|
||||
|| (subject === 'media' && (!chatId || !photo))
|
||||
) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const title = subject === 'messages'
|
||||
? lang('lng_report_message_title')
|
||||
: lang('ReportPeer.Report');
|
||||
|
||||
return (
|
||||
<Modal
|
||||
isOpen={isOpen}
|
||||
onClose={onClose}
|
||||
onEnter={isOpen ? handleReport : undefined}
|
||||
onCloseAnimationEnd={onCloseAnimationEnd}
|
||||
className="report"
|
||||
title={lang('lng_report_message_title')}
|
||||
title={title}
|
||||
>
|
||||
<RadioGroup
|
||||
name="report-message"
|
||||
@ -91,4 +134,4 @@ const ReportMessageModal: FC<OwnProps> = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(ReportMessageModal);
|
||||
export default memo(ReportModal);
|
@ -50,6 +50,7 @@ import ListItem from '../../ui/ListItem';
|
||||
import Badge from './Badge';
|
||||
import ChatFolderModal from '../ChatFolderModal.async';
|
||||
import ChatCallStatus from './ChatCallStatus';
|
||||
import ReportModal from '../../common/ReportModal';
|
||||
import FakeIcon from '../../common/FakeIcon';
|
||||
|
||||
import './Chat.scss';
|
||||
@ -116,8 +117,10 @@ const Chat: FC<OwnProps & StateProps> = ({
|
||||
|
||||
const [isDeleteModalOpen, openDeleteModal, closeDeleteModal] = useFlag();
|
||||
const [isChatFolderModalOpen, openChatFolderModal, closeChatFolderModal] = useFlag();
|
||||
const [isReportModalOpen, openReportModal, closeReportModal] = useFlag();
|
||||
const [shouldRenderDeleteModal, markRenderDeleteModal, unmarkRenderDeleteModal] = useFlag();
|
||||
const [shouldRenderChatFolderModal, markRenderChatFolderModal, unmarkRenderChatFolderModal] = useFlag();
|
||||
const [shouldRenderReportModal, markRenderReportModal, unmarkRenderReportModal] = useFlag();
|
||||
|
||||
const { lastMessage, typingStatus } = chat || {};
|
||||
const isAction = lastMessage && isActionMessage(lastMessage);
|
||||
@ -190,21 +193,27 @@ const Chat: FC<OwnProps & StateProps> = ({
|
||||
focusLastMessage,
|
||||
]);
|
||||
|
||||
function handleDelete() {
|
||||
const handleDelete = useCallback(() => {
|
||||
markRenderDeleteModal();
|
||||
openDeleteModal();
|
||||
}
|
||||
}, [markRenderDeleteModal, openDeleteModal]);
|
||||
|
||||
function handleChatFolderChange() {
|
||||
const handleChatFolderChange = useCallback(() => {
|
||||
markRenderChatFolderModal();
|
||||
openChatFolderModal();
|
||||
}
|
||||
}, [markRenderChatFolderModal, openChatFolderModal]);
|
||||
|
||||
const handleReport = useCallback(() => {
|
||||
markRenderReportModal();
|
||||
openReportModal();
|
||||
}, [markRenderReportModal, openReportModal]);
|
||||
|
||||
const contextActions = useChatContextActions({
|
||||
chat,
|
||||
user,
|
||||
handleDelete,
|
||||
handleChatFolderChange,
|
||||
handleReport,
|
||||
folderId,
|
||||
isPinned,
|
||||
isMuted,
|
||||
@ -330,6 +339,15 @@ const Chat: FC<OwnProps & StateProps> = ({
|
||||
chatId={chatId}
|
||||
/>
|
||||
)}
|
||||
{shouldRenderReportModal && (
|
||||
<ReportModal
|
||||
isOpen={isReportModalOpen}
|
||||
onClose={closeReportModal}
|
||||
onCloseAnimationEnd={unmarkRenderReportModal}
|
||||
chatId={chatId}
|
||||
subject="peer"
|
||||
/>
|
||||
)}
|
||||
</ListItem>
|
||||
);
|
||||
};
|
||||
|
@ -16,6 +16,7 @@ import { dispatchHeavyAnimationEvent } from '../../hooks/useHeavyAnimationCheck'
|
||||
import useHistoryBack from '../../hooks/useHistoryBack';
|
||||
import useLang from '../../hooks/useLang';
|
||||
import useMedia from '../../hooks/useMedia';
|
||||
import useFlag from '../../hooks/useFlag';
|
||||
import useMediaWithLoadProgress from '../../hooks/useMediaWithLoadProgress';
|
||||
import usePrevious from '../../hooks/usePrevious';
|
||||
import {
|
||||
@ -40,6 +41,7 @@ import {
|
||||
selectChatMessage,
|
||||
selectChatMessages,
|
||||
selectCurrentMediaSearch,
|
||||
selectIsChatWithSelf,
|
||||
selectListedIds,
|
||||
selectOutlyingIds,
|
||||
selectScheduledMessage,
|
||||
@ -63,6 +65,7 @@ import PanZoom from './PanZoom';
|
||||
import SenderInfo from './SenderInfo';
|
||||
import SlideTransition from './SlideTransition';
|
||||
import ZoomControls from './ZoomControls';
|
||||
import ReportModal from '../common/ReportModal';
|
||||
|
||||
import './MediaViewer.scss';
|
||||
|
||||
@ -71,6 +74,7 @@ type StateProps = {
|
||||
threadId?: number;
|
||||
messageId?: number;
|
||||
senderId?: string;
|
||||
isChatWithSelf?: boolean;
|
||||
origin?: MediaViewerOrigin;
|
||||
avatarOwner?: ApiChat | ApiUser;
|
||||
profilePhotoIndex?: number;
|
||||
@ -87,6 +91,7 @@ const MediaViewer: FC<StateProps> = ({
|
||||
threadId,
|
||||
messageId,
|
||||
senderId,
|
||||
isChatWithSelf,
|
||||
origin,
|
||||
avatarOwner,
|
||||
profilePhotoIndex,
|
||||
@ -144,6 +149,7 @@ const MediaViewer: FC<StateProps> = ({
|
||||
const isGhostAnimation = animationLevel === 2;
|
||||
|
||||
/* Controls */
|
||||
const [isReportModalOpen, openReportModal, closeReportModal] = useFlag();
|
||||
const [canPanZoomWrap, setCanPanZoomWrap] = useState(false);
|
||||
const [isZoomed, setIsZoomed] = useState<boolean>(false);
|
||||
const [zoomLevel, setZoomLevel] = useState<number>(1);
|
||||
@ -186,6 +192,8 @@ const MediaViewer: FC<StateProps> = ({
|
||||
undefined,
|
||||
isGhostAnimation && ANIMATION_DURATION,
|
||||
);
|
||||
const avatarPhoto = avatarOwner?.photos?.[profilePhotoIndex!];
|
||||
const canReport = !!avatarPhoto && profilePhotoIndex! > 0 && !isChatWithSelf;
|
||||
|
||||
const localBlobUrl = (photo || video) ? (photo || video)!.blobUrl : undefined;
|
||||
let bestImageData = (!isVideo && (localBlobUrl || fullMediaBlobUrl)) || previewBlobUrl || pictogramBlobUrl;
|
||||
@ -483,11 +491,20 @@ const MediaViewer: FC<StateProps> = ({
|
||||
isZoomed={isZoomed}
|
||||
message={message}
|
||||
fileName={fileName}
|
||||
canReport={canReport}
|
||||
onReport={openReportModal}
|
||||
onCloseMediaViewer={close}
|
||||
onForward={handleForward}
|
||||
onZoomToggle={handleZoomToggle}
|
||||
isAvatar={isAvatar}
|
||||
/>
|
||||
<ReportModal
|
||||
isOpen={isReportModalOpen}
|
||||
onClose={closeReportModal}
|
||||
subject="media"
|
||||
photo={avatarPhoto}
|
||||
chatId={avatarOwner?.id}
|
||||
/>
|
||||
</div>
|
||||
<PanZoom
|
||||
noWrap={!canPanZoomWrap}
|
||||
@ -565,6 +582,8 @@ export default memo(withGlobal(
|
||||
animationLevel,
|
||||
} = global.settings.byKey;
|
||||
|
||||
let isChatWithSelf = !!chatId && selectIsChatWithSelf(global, chatId);
|
||||
|
||||
if (origin === MediaViewerOrigin.SearchResult) {
|
||||
if (!(chatId && messageId)) {
|
||||
return { animationLevel };
|
||||
@ -579,6 +598,7 @@ export default memo(withGlobal(
|
||||
chatId,
|
||||
messageId,
|
||||
senderId: message.senderId,
|
||||
isChatWithSelf,
|
||||
origin,
|
||||
message,
|
||||
animationLevel,
|
||||
@ -587,11 +607,13 @@ export default memo(withGlobal(
|
||||
|
||||
if (avatarOwnerId) {
|
||||
const sender = selectUser(global, avatarOwnerId) || selectChat(global, avatarOwnerId);
|
||||
isChatWithSelf = selectIsChatWithSelf(global, avatarOwnerId);
|
||||
|
||||
return {
|
||||
messageId: -1,
|
||||
senderId: avatarOwnerId,
|
||||
avatarOwner: sender,
|
||||
isChatWithSelf,
|
||||
profilePhotoIndex: profilePhotoIndex || 0,
|
||||
animationLevel,
|
||||
origin,
|
||||
@ -635,6 +657,7 @@ export default memo(withGlobal(
|
||||
threadId,
|
||||
messageId,
|
||||
senderId: message.senderId,
|
||||
isChatWithSelf,
|
||||
origin,
|
||||
message,
|
||||
chatMessages,
|
||||
|
@ -33,6 +33,8 @@ type OwnProps = {
|
||||
message?: ApiMessage;
|
||||
fileName?: string;
|
||||
isAvatar?: boolean;
|
||||
canReport?: boolean;
|
||||
onReport: NoneToVoidFunction;
|
||||
onCloseMediaViewer: NoneToVoidFunction;
|
||||
onForward: NoneToVoidFunction;
|
||||
onZoomToggle: NoneToVoidFunction;
|
||||
@ -47,6 +49,8 @@ const MediaViewerActions: FC<OwnProps & StateProps> = ({
|
||||
isAvatar,
|
||||
isDownloading,
|
||||
isProtected,
|
||||
canReport,
|
||||
onReport,
|
||||
onCloseMediaViewer,
|
||||
onForward,
|
||||
onZoomToggle,
|
||||
@ -154,6 +158,14 @@ const MediaViewerActions: FC<OwnProps & StateProps> = ({
|
||||
{lang('AccActionDownload')}
|
||||
</MenuItem>
|
||||
)}
|
||||
{canReport && (
|
||||
<MenuItem
|
||||
icon="flag"
|
||||
onClick={onReport}
|
||||
>
|
||||
{lang('ReportPeer.Report')}
|
||||
</MenuItem>
|
||||
)}
|
||||
</DropdownMenu>
|
||||
{isDownloading && <ProgressSpinner progress={downloadProgress} size="s" noCross />}
|
||||
</div>
|
||||
@ -183,6 +195,17 @@ const MediaViewerActions: FC<OwnProps & StateProps> = ({
|
||||
>
|
||||
<i className={isZoomed ? 'icon-zoom-out' : 'icon-zoom-in'} />
|
||||
</Button>
|
||||
{canReport && (
|
||||
<Button
|
||||
round
|
||||
size="smaller"
|
||||
color="translucent-white"
|
||||
ariaLabel={lang(isVideo ? 'PeerInfo.ReportProfileVideo' : 'PeerInfo.ReportProfilePhoto')}
|
||||
onClick={onReport}
|
||||
>
|
||||
<i className="icon-flag" />
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
round
|
||||
size="smaller"
|
||||
|
@ -13,7 +13,7 @@ import {
|
||||
selectChat, selectNotifySettings, selectNotifyExceptions, selectUser, selectChatBot,
|
||||
} from '../../global/selectors';
|
||||
import {
|
||||
isUserId, getCanDeleteChat, selectIsChatMuted, getCanAddContact,
|
||||
isUserId, getCanDeleteChat, selectIsChatMuted, getCanAddContact, isChatChannel, isChatGroup,
|
||||
} from '../../global/helpers';
|
||||
import useShowTransition from '../../hooks/useShowTransition';
|
||||
import useLang from '../../hooks/useLang';
|
||||
@ -22,6 +22,7 @@ import Portal from '../ui/Portal';
|
||||
import Menu from '../ui/Menu';
|
||||
import MenuItem from '../ui/MenuItem';
|
||||
import DeleteChatModal from '../common/DeleteChatModal';
|
||||
import ReportModal from '../common/ReportModal';
|
||||
|
||||
import './HeaderMenuContainer.scss';
|
||||
|
||||
@ -69,6 +70,7 @@ type StateProps = {
|
||||
isPrivate?: boolean;
|
||||
isMuted?: boolean;
|
||||
canAddContact?: boolean;
|
||||
canReportChat?: boolean;
|
||||
canDeleteChat?: boolean;
|
||||
hasLinkedChat?: boolean;
|
||||
};
|
||||
@ -93,6 +95,7 @@ const HeaderMenuContainer: FC<OwnProps & StateProps> = ({
|
||||
chat,
|
||||
isPrivate,
|
||||
isMuted,
|
||||
canReportChat,
|
||||
canDeleteChat,
|
||||
hasLinkedChat,
|
||||
canAddContact,
|
||||
@ -115,10 +118,21 @@ const HeaderMenuContainer: FC<OwnProps & StateProps> = ({
|
||||
} = getActions();
|
||||
const [isMenuOpen, setIsMenuOpen] = useState(true);
|
||||
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
|
||||
const [isReportModalOpen, setIsReportModalOpen] = useState(false);
|
||||
const { x, y } = anchor;
|
||||
|
||||
useShowTransition(isOpen, onCloseAnimationEnd, undefined, false);
|
||||
|
||||
const handleReport = useCallback(() => {
|
||||
setIsMenuOpen(false);
|
||||
setIsReportModalOpen(true);
|
||||
}, []);
|
||||
|
||||
const closeReportModal = useCallback(() => {
|
||||
setIsReportModalOpen(false);
|
||||
onClose();
|
||||
}, [onClose]);
|
||||
|
||||
const handleDelete = useCallback(() => {
|
||||
setIsMenuOpen(false);
|
||||
setIsDeleteModalOpen(true);
|
||||
@ -334,6 +348,14 @@ const HeaderMenuContainer: FC<OwnProps & StateProps> = ({
|
||||
{lang('Statistics')}
|
||||
</MenuItem>
|
||||
)}
|
||||
{canReportChat && (
|
||||
<MenuItem
|
||||
icon="flag"
|
||||
onClick={handleReport}
|
||||
>
|
||||
{lang('ReportPeer.Report')}
|
||||
</MenuItem>
|
||||
)}
|
||||
{botButtons}
|
||||
{canLeave && (
|
||||
<MenuItem
|
||||
@ -354,6 +376,14 @@ const HeaderMenuContainer: FC<OwnProps & StateProps> = ({
|
||||
chat={chat}
|
||||
/>
|
||||
)}
|
||||
{canReportChat && chat?.id && (
|
||||
<ReportModal
|
||||
isOpen={isReportModalOpen}
|
||||
onClose={closeReportModal}
|
||||
subject="peer"
|
||||
chatId={chat.id}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</Portal>
|
||||
);
|
||||
@ -368,6 +398,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
const isPrivate = isUserId(chat.id);
|
||||
const user = isPrivate ? selectUser(global, chatId) : undefined;
|
||||
const canAddContact = user && getCanAddContact(user);
|
||||
const canReportChat = isChatChannel(chat) || isChatGroup(chat) || (user && !user.isSelf);
|
||||
|
||||
const chatBot = chatId !== REPLIES_USER_ID ? selectChatBot(global, chatId) : undefined;
|
||||
|
||||
@ -376,6 +407,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
isMuted: selectIsChatMuted(chat, selectNotifySettings(global), selectNotifyExceptions(global)),
|
||||
isPrivate,
|
||||
canAddContact,
|
||||
canReportChat,
|
||||
canDeleteChat: getCanDeleteChat(chat),
|
||||
hasLinkedChat: Boolean(chat?.fullInfo?.linkedChatId),
|
||||
botCommands: chatBot?.fullInfo?.botCommands,
|
||||
|
@ -23,7 +23,7 @@ import useCopySelectedMessages from './hooks/useCopySelectedMessages';
|
||||
import Button from '../ui/Button';
|
||||
|
||||
import DeleteSelectedMessageModal from './DeleteSelectedMessageModal';
|
||||
import ReportMessageModal from '../common/ReportMessageModal';
|
||||
import ReportModal from '../common/ReportModal';
|
||||
|
||||
import './MessageSelectToolbar.scss';
|
||||
|
||||
@ -157,7 +157,7 @@ const MessageSelectToolbar: FC<OwnProps & StateProps> = ({
|
||||
isSchedule={isSchedule}
|
||||
onClose={closeDeleteModal}
|
||||
/>
|
||||
<ReportMessageModal
|
||||
<ReportModal
|
||||
isOpen={isReportModalOpen}
|
||||
onClose={closeReportModal}
|
||||
messageIds={selectedMessageIds}
|
||||
|
@ -25,7 +25,7 @@ import useFlag from '../../../hooks/useFlag';
|
||||
import { REM } from '../../common/helpers/mediaDimensions';
|
||||
|
||||
import DeleteMessageModal from '../../common/DeleteMessageModal';
|
||||
import ReportMessageModal from '../../common/ReportMessageModal';
|
||||
import ReportModal from '../../common/ReportModal';
|
||||
import PinMessageModal from '../../common/PinMessageModal';
|
||||
import MessageContextMenu from './MessageContextMenu';
|
||||
import CalendarModal from '../../common/CalendarModal';
|
||||
@ -396,7 +396,7 @@ const ContextMenuContainer: FC<OwnProps & StateProps> = ({
|
||||
album={album}
|
||||
message={message}
|
||||
/>
|
||||
<ReportMessageModal
|
||||
<ReportModal
|
||||
isOpen={isReportModalOpen}
|
||||
onClose={closeReportModal}
|
||||
messageIds={reportMessageIds}
|
||||
|
@ -19,6 +19,7 @@ import './api/globalSearch';
|
||||
import './api/localSearch';
|
||||
import './api/management';
|
||||
import './api/sync';
|
||||
import './api/accounts';
|
||||
import './api/users';
|
||||
import './api/bots';
|
||||
import './api/settings';
|
||||
|
62
src/global/actions/api/accounts.ts
Normal file
62
src/global/actions/api/accounts.ts
Normal file
@ -0,0 +1,62 @@
|
||||
import { addActionHandler } from '../../index';
|
||||
import { selectChat } from '../../selectors';
|
||||
import { callApi } from '../../../api/gramjs';
|
||||
import { getTranslation } from '../../../util/langProvider';
|
||||
|
||||
addActionHandler('reportPeer', async (global, actions, payload) => {
|
||||
const {
|
||||
chatId,
|
||||
reason,
|
||||
description,
|
||||
} = payload;
|
||||
if (!chatId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const chat = selectChat(global, chatId)!;
|
||||
if (!chat) {
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await callApi('reportPeer', {
|
||||
peer: chat,
|
||||
reason,
|
||||
description,
|
||||
});
|
||||
|
||||
actions.showNotification({
|
||||
message: result
|
||||
? getTranslation('ReportPeer.AlertSuccess')
|
||||
: 'An error occurred while submitting your report. Please, try again later.',
|
||||
});
|
||||
});
|
||||
|
||||
addActionHandler('reportProfilePhoto', async (global, actions, payload) => {
|
||||
const {
|
||||
chatId,
|
||||
reason,
|
||||
description,
|
||||
photo,
|
||||
} = payload;
|
||||
if (!chatId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const chat = selectChat(global, chatId)!;
|
||||
if (!chat || !photo) {
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await callApi('reportProfilePhoto', {
|
||||
peer: chat,
|
||||
photo,
|
||||
reason,
|
||||
description,
|
||||
});
|
||||
|
||||
actions.showNotification({
|
||||
message: result
|
||||
? getTranslation('ReportPeer.AlertSuccess')
|
||||
: 'An error occurred while submitting your report. Please, try again later.',
|
||||
});
|
||||
});
|
@ -67,6 +67,7 @@ import {
|
||||
} from '../../selectors';
|
||||
import { debounce, onTickEnd, rafPromise } from '../../../util/schedulers';
|
||||
import { isServiceNotificationMessage } from '../../helpers';
|
||||
import { getTranslation } from '../../../util/langProvider';
|
||||
|
||||
const uploadProgressCallbacks = new Map<number, ApiOnProgress>();
|
||||
|
||||
@ -460,8 +461,8 @@ addActionHandler('reportMessages', async (global, actions, payload) => {
|
||||
|
||||
actions.showNotification({
|
||||
message: result
|
||||
? 'Thank you! Your report will be reviewed by our team.'
|
||||
: 'Error occured while submiting report. Please, try again later.',
|
||||
? getTranslation('ReportPeer.AlertSuccess')
|
||||
: 'An error occurred while submitting your report. Please, try again later.',
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -30,6 +30,8 @@ import {
|
||||
ApiGroupStatistics,
|
||||
ApiPaymentFormNativeParams,
|
||||
ApiUpdate,
|
||||
ApiReportReason,
|
||||
ApiPhoto,
|
||||
ApiKeyboardButton,
|
||||
ApiPhoneCall,
|
||||
} from '../api/types';
|
||||
@ -552,6 +554,19 @@ export interface ActionPayloads {
|
||||
signOut: { forceInitApi?: boolean } | undefined;
|
||||
apiUpdate: ApiUpdate;
|
||||
|
||||
// Accounts
|
||||
reportPeer: {
|
||||
chatId?: string;
|
||||
reason: ApiReportReason;
|
||||
description: string;
|
||||
};
|
||||
reportProfilePhoto: {
|
||||
chatId?: string;
|
||||
reason: ApiReportReason;
|
||||
description: string;
|
||||
photo?: ApiPhoto;
|
||||
};
|
||||
|
||||
// Chats
|
||||
openChat: {
|
||||
id: string | undefined;
|
||||
|
@ -5,7 +5,7 @@ import { ApiChat, ApiUser } from '../api/types';
|
||||
|
||||
import { SERVICE_NOTIFICATIONS_USER_ID } from '../config';
|
||||
import {
|
||||
isChatArchived, getCanDeleteChat, isUserId, isChatChannel,
|
||||
isChatArchived, getCanDeleteChat, isUserId, isChatChannel, isChatGroup,
|
||||
} from '../global/helpers';
|
||||
import { compact } from '../util/iteratees';
|
||||
import useLang from './useLang';
|
||||
@ -19,6 +19,7 @@ const useChatContextActions = ({
|
||||
canChangeFolder,
|
||||
handleDelete,
|
||||
handleChatFolderChange,
|
||||
handleReport,
|
||||
}: {
|
||||
chat: ApiChat | undefined;
|
||||
user: ApiUser | undefined;
|
||||
@ -28,6 +29,7 @@ const useChatContextActions = ({
|
||||
canChangeFolder?: boolean;
|
||||
handleDelete: () => void;
|
||||
handleChatFolderChange: () => void;
|
||||
handleReport?: () => void;
|
||||
}, isInSearch = false) => {
|
||||
const lang = useLang();
|
||||
|
||||
@ -84,6 +86,11 @@ const useChatContextActions = ({
|
||||
? { title: lang('Unarchive'), icon: 'unarchive', handler: () => toggleChatArchived({ id: chat.id }) }
|
||||
: { title: lang('Archive'), icon: 'archive', handler: () => toggleChatArchived({ id: chat.id }) };
|
||||
|
||||
const canReport = handleReport && (isChatChannel(chat) || isChatGroup(chat) || (user && !user.isSelf));
|
||||
const actionReport = canReport
|
||||
? { title: lang('ReportPeer.Report'), icon: 'flag', handler: handleReport }
|
||||
: undefined;
|
||||
|
||||
const actionDelete = {
|
||||
title: isUserId(chat.id)
|
||||
? lang('Delete')
|
||||
@ -103,11 +110,12 @@ const useChatContextActions = ({
|
||||
actionPin,
|
||||
!isSelf && actionMute,
|
||||
!isSelf && !isServiceNotifications && !isInFolder && actionArchive,
|
||||
actionReport,
|
||||
actionDelete,
|
||||
]);
|
||||
}, [
|
||||
chat, canChangeFolder, lang, handleChatFolderChange, isPinned, isInSearch, isMuted, handleDelete, folderId, isSelf,
|
||||
isServiceNotifications,
|
||||
chat, user, canChangeFolder, lang, handleChatFolderChange, isPinned, isInSearch, isMuted,
|
||||
handleDelete, handleReport, folderId, isSelf, isServiceNotifications,
|
||||
]);
|
||||
};
|
||||
|
||||
|
@ -982,6 +982,7 @@ account.getNotifySettings#12b3ad31 peer:InputNotifyPeer = PeerNotifySettings;
|
||||
account.updateProfile#78515775 flags:# first_name:flags.0?string last_name:flags.1?string about:flags.2?string = User;
|
||||
account.updateStatus#6628562c offline:Bool = Bool;
|
||||
account.getWallPapers#7967d36 hash:long = account.WallPapers;
|
||||
account.reportPeer#c5ba3d86 peer:InputPeer reason:ReportReason message:string = Bool;
|
||||
account.checkUsername#2714d86c username:string = Bool;
|
||||
account.updateUsername#3e0bdd7c username:string = User;
|
||||
account.getPrivacy#dadbc950 key:InputPrivacyKey = account.PrivacyRules;
|
||||
@ -1002,6 +1003,7 @@ account.getNotifyExceptions#53577479 flags:# compare_sound:flags.1?true peer:fla
|
||||
account.uploadWallPaper#dd853661 file:InputFile mime_type:string settings:WallPaperSettings = WallPaper;
|
||||
account.setContentSettings#b574b16b flags:# sensitive_enabled:flags.0?true = Bool;
|
||||
account.getContentSettings#8b9b4dae = account.ContentSettings;
|
||||
account.reportProfilePhoto#fa8cc6f5 peer:InputPeer photo_id:InputPhoto reason:ReportReason message:string = Bool;
|
||||
users.getUsers#d91a548 id:Vector<InputUser> = Vector<User>;
|
||||
users.getFullUser#b60f5918 id:InputUser = users.UserFull;
|
||||
contacts.getContacts#5dd69e12 hash:long = contacts.Contacts;
|
||||
|
@ -43,6 +43,8 @@
|
||||
"account.uploadWallPaper",
|
||||
"account.setContentSettings",
|
||||
"account.getContentSettings",
|
||||
"account.reportPeer",
|
||||
"account.reportProfilePhoto",
|
||||
"users.getUsers",
|
||||
"users.getFullUser",
|
||||
"contacts.getContacts",
|
||||
|
@ -197,11 +197,11 @@ $color-message-reaction-own-hover: #b5e0a4;
|
||||
}
|
||||
|
||||
--z-ui-loader-mask: 2000;
|
||||
--z-notification: 1000;
|
||||
--z-notification: 1520;
|
||||
--z-right-column: 900;
|
||||
--z-header-menu: 990;
|
||||
--z-header-menu-backdrop: 980;
|
||||
--z-modal: 1000;
|
||||
--z-modal: 1510;
|
||||
--z-media-viewer: 1500;
|
||||
--z-drop-area: 55;
|
||||
--z-animation-fade: 50;
|
||||
|
Loading…
Reference in New Issue
Block a user