Support "Report Peer" and "Report Profile Photo" (#126)

This commit is contained in:
Vadym Milichev 2022-04-09 02:23:35 +03:00 committed by GitHub
parent a7e2695f2e
commit 91c2015052
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 321 additions and 28 deletions

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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.',
});
});

View File

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

View File

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

View File

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

View File

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

View File

@ -43,6 +43,8 @@
"account.uploadWallPaper",
"account.setContentSettings",
"account.getContentSettings",
"account.reportPeer",
"account.reportProfilePhoto",
"users.getUsers",
"users.getFullUser",
"contacts.getContacts",

View File

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