Report messages
This commit is contained in:
parent
8ccf8b3879
commit
0478be1603
@ -26,6 +26,7 @@ import cancelSelection from "../../helpers/dom/cancelSelection";
|
|||||||
import { attachClickEvent } from "../../helpers/dom/clickEvent";
|
import { attachClickEvent } from "../../helpers/dom/clickEvent";
|
||||||
import isSelectionEmpty from "../../helpers/dom/isSelectionEmpty";
|
import isSelectionEmpty from "../../helpers/dom/isSelectionEmpty";
|
||||||
import { Message } from "../../layer";
|
import { Message } from "../../layer";
|
||||||
|
import PopupReportMessages from "../popups/reportMessages";
|
||||||
|
|
||||||
export default class ChatContextMenu {
|
export default class ChatContextMenu {
|
||||||
private buttons: (ButtonMenuItemOptions & {verify: () => boolean, notDirect?: () => boolean, withSelection?: true})[];
|
private buttons: (ButtonMenuItemOptions & {verify: () => boolean, notDirect?: () => boolean, withSelection?: true})[];
|
||||||
@ -322,6 +323,15 @@ export default class ChatContextMenu {
|
|||||||
!this.chat.selection.selectionForwardBtn.hasAttribute('disabled'),
|
!this.chat.selection.selectionForwardBtn.hasAttribute('disabled'),
|
||||||
notDirect: () => true,
|
notDirect: () => true,
|
||||||
withSelection: true
|
withSelection: true
|
||||||
|
}, {
|
||||||
|
icon: 'flag',
|
||||||
|
text: 'ReportChat',
|
||||||
|
onClick: () => {
|
||||||
|
new PopupReportMessages(this.peerId, [this.mid]);
|
||||||
|
},
|
||||||
|
verify: () => !this.message.pFlags.out && !this.message.pFlags.is_outgoing && this.appPeersManager.isChannel(this.peerId),
|
||||||
|
notDirect: () => true,
|
||||||
|
withSelection: true
|
||||||
}, {
|
}, {
|
||||||
icon: 'select',
|
icon: 'select',
|
||||||
text: 'Message.Context.Select',
|
text: 'Message.Context.Select',
|
||||||
|
@ -95,7 +95,7 @@ class InputField {
|
|||||||
this.container.classList.add('input-field');
|
this.container.classList.add('input-field');
|
||||||
|
|
||||||
if(options.maxLength) {
|
if(options.maxLength) {
|
||||||
options.showLengthOn = Math.round(options.maxLength / 3);
|
options.showLengthOn = Math.min(40, Math.round(options.maxLength / 3));
|
||||||
}
|
}
|
||||||
|
|
||||||
const {placeholder, maxLength, showLengthOn, name, plainText} = options;
|
const {placeholder, maxLength, showLengthOn, name, plainText} = options;
|
||||||
|
@ -36,6 +36,7 @@ export default class PopupElement {
|
|||||||
protected btnClose: HTMLElement;
|
protected btnClose: HTMLElement;
|
||||||
protected btnConfirm: HTMLElement;
|
protected btnConfirm: HTMLElement;
|
||||||
protected body: HTMLElement;
|
protected body: HTMLElement;
|
||||||
|
protected buttons: HTMLElement;
|
||||||
|
|
||||||
protected onClose: () => void;
|
protected onClose: () => void;
|
||||||
protected onCloseAfterTimeout: () => void;
|
protected onCloseAfterTimeout: () => void;
|
||||||
@ -91,7 +92,7 @@ export default class PopupElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(buttons && buttons.length) {
|
if(buttons && buttons.length) {
|
||||||
const buttonsDiv = document.createElement('div');
|
const buttonsDiv = this.buttons = document.createElement('div');
|
||||||
buttonsDiv.classList.add('popup-buttons');
|
buttonsDiv.classList.add('popup-buttons');
|
||||||
|
|
||||||
if(buttons.length === 2) {
|
if(buttons.length === 2) {
|
||||||
|
@ -18,15 +18,16 @@ export type PopupPeerOptions = PopupOptions & Partial<{
|
|||||||
title: string,
|
title: string,
|
||||||
titleLangKey?: LangPackKey,
|
titleLangKey?: LangPackKey,
|
||||||
titleLangArgs?: any[],
|
titleLangArgs?: any[],
|
||||||
|
noTitle?: boolean,
|
||||||
description: string,
|
description: string,
|
||||||
descriptionLangKey?: LangPackKey,
|
descriptionLangKey?: LangPackKey,
|
||||||
descriptionLangArgs?: any[],
|
descriptionLangArgs?: any[],
|
||||||
buttons: Array<Omit<PopupButton, 'callback'> & Partial<{callback: PopupPeerButtonCallback}>>,
|
buttons?: Array<Omit<PopupButton, 'callback'> & Partial<{callback: PopupPeerButtonCallback}>>,
|
||||||
checkboxes: Array<PopupPeerCheckboxOptions>
|
checkboxes: Array<PopupPeerCheckboxOptions>
|
||||||
}>;
|
}>;
|
||||||
export default class PopupPeer extends PopupElement {
|
export default class PopupPeer extends PopupElement {
|
||||||
constructor(private className: string, options: PopupPeerOptions = {}) {
|
constructor(private className: string, options: PopupPeerOptions = {}) {
|
||||||
super('popup-peer' + (className ? ' ' + className : ''), addCancelButton(options.buttons), {overlayClosable: true, ...options});
|
super('popup-peer' + (className ? ' ' + className : ''), options.buttons && addCancelButton(options.buttons), {overlayClosable: true, ...options});
|
||||||
|
|
||||||
if(options.peerId) {
|
if(options.peerId) {
|
||||||
let avatarEl = new AvatarElement();
|
let avatarEl = new AvatarElement();
|
||||||
@ -36,16 +37,21 @@ export default class PopupPeer extends PopupElement {
|
|||||||
this.header.prepend(avatarEl);
|
this.header.prepend(avatarEl);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(options.titleLangKey || !options.title) this.title.append(i18n(options.titleLangKey || 'AppName', options.titleLangArgs));
|
if(!options.noTitle) {
|
||||||
else this.title.innerText = options.title || '';
|
if(options.titleLangKey || !options.title) this.title.append(i18n(options.titleLangKey || 'AppName', options.titleLangArgs));
|
||||||
|
else this.title.innerText = options.title || '';
|
||||||
let p = document.createElement('p');
|
}
|
||||||
p.classList.add('popup-description');
|
|
||||||
if(options.descriptionLangKey) p.append(i18n(options.descriptionLangKey, options.descriptionLangArgs));
|
|
||||||
else p.innerHTML = options.description;
|
|
||||||
|
|
||||||
const fragment = document.createDocumentFragment();
|
const fragment = document.createDocumentFragment();
|
||||||
fragment.append(p);
|
|
||||||
|
if(options.descriptionLangKey || options.description) {
|
||||||
|
const p = document.createElement('p');
|
||||||
|
p.classList.add('popup-description');
|
||||||
|
if(options.descriptionLangKey) p.append(i18n(options.descriptionLangKey, options.descriptionLangArgs));
|
||||||
|
else if(options.description) p.innerHTML = options.description;
|
||||||
|
|
||||||
|
fragment.append(p);
|
||||||
|
}
|
||||||
|
|
||||||
if(options.checkboxes) {
|
if(options.checkboxes) {
|
||||||
this.container.classList.add('have-checkbox');
|
this.container.classList.add('have-checkbox');
|
||||||
|
54
src/components/popups/reportMessages.ts
Normal file
54
src/components/popups/reportMessages.ts
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* https://github.com/morethanwords/tweb
|
||||||
|
* Copyright (C) 2019-2021 Eduard Kuzmenko
|
||||||
|
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
import findUpClassName from "../../helpers/dom/findUpClassName";
|
||||||
|
import whichChild from "../../helpers/dom/whichChild";
|
||||||
|
import { ReportReason } from "../../layer";
|
||||||
|
import appStickersManager from "../../lib/appManagers/appStickersManager";
|
||||||
|
import { LangPackKey } from "../../lib/langPack";
|
||||||
|
import Button from "../button";
|
||||||
|
import PopupPeer from "./peer";
|
||||||
|
import PopupReportMessagesConfirm from "./reportMessagesConfirm";
|
||||||
|
|
||||||
|
export default class PopupReportMessages extends PopupPeer {
|
||||||
|
constructor(peerId: number, mids: number[], onConfirm?: () => void) {
|
||||||
|
super('popup-report-messages', {titleLangKey: 'ChatTitle.ReportMessages', buttons: [], body: true});
|
||||||
|
|
||||||
|
mids = mids.slice();
|
||||||
|
|
||||||
|
const buttons: [LangPackKey, ReportReason['_']][] = [
|
||||||
|
['ReportChatSpam', 'inputReportReasonSpam'],
|
||||||
|
['ReportChatViolence', 'inputReportReasonViolence'],
|
||||||
|
['ReportChatChild', 'inputReportReasonChildAbuse'],
|
||||||
|
['ReportChatPornography', 'inputReportReasonPornography'],
|
||||||
|
['ReportChatOther', 'inputReportReasonOther']
|
||||||
|
];
|
||||||
|
|
||||||
|
const className = 'btn-primary btn-transparent';
|
||||||
|
buttons.forEach(b => {
|
||||||
|
const button = Button(className, {/* icon: 'edit', */text: b[0]});
|
||||||
|
this.body.append(button);
|
||||||
|
});
|
||||||
|
|
||||||
|
const preloadStickerPromise = appStickersManager.preloadAnimatedEmojiSticker(PopupReportMessagesConfirm.STICKER_EMOJI);
|
||||||
|
|
||||||
|
this.body.addEventListener('click', (e) => {
|
||||||
|
const target = findUpClassName(e.target, 'btn-primary');
|
||||||
|
const reason = buttons[whichChild(target)][1];
|
||||||
|
|
||||||
|
preloadStickerPromise.then(() => {
|
||||||
|
this.hide();
|
||||||
|
|
||||||
|
new PopupReportMessagesConfirm(peerId, mids, reason, onConfirm);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
this.body.style.margin = '0 -1rem';
|
||||||
|
this.buttons.style.marginTop = '.5rem';
|
||||||
|
|
||||||
|
this.show();
|
||||||
|
}
|
||||||
|
}
|
66
src/components/popups/reportMessagesConfirm.ts
Normal file
66
src/components/popups/reportMessagesConfirm.ts
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* https://github.com/morethanwords/tweb
|
||||||
|
* Copyright (C) 2019-2021 Eduard Kuzmenko
|
||||||
|
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { ReportReason } from "../../layer";
|
||||||
|
import appMessagesManager from "../../lib/appManagers/appMessagesManager";
|
||||||
|
import appStickersManager from "../../lib/appManagers/appStickersManager";
|
||||||
|
import InputField from "../inputField";
|
||||||
|
import { toastNew } from "../toast";
|
||||||
|
import { wrapSticker } from "../wrappers";
|
||||||
|
import PopupPeer from "./peer";
|
||||||
|
|
||||||
|
export default class PopupReportMessagesConfirm extends PopupPeer {
|
||||||
|
public static STICKER_EMOJI = '👮♀️';
|
||||||
|
constructor(peerId: number, mids: number[], reason: ReportReason['_'], onConfirm?: () => void) {
|
||||||
|
super('popup-report-messages-confirm', {
|
||||||
|
noTitle: true,
|
||||||
|
descriptionLangKey: 'ReportInfo',
|
||||||
|
buttons: [{
|
||||||
|
langKey: 'ReportChat',
|
||||||
|
callback: () => {
|
||||||
|
if(!inputField.isValid()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
onConfirm && onConfirm();
|
||||||
|
appMessagesManager.reportMessages(peerId, mids, reason, inputField.value).then(bool => {
|
||||||
|
if(!bool) return;
|
||||||
|
|
||||||
|
toastNew({
|
||||||
|
langPackKey: 'ReportSentInfo'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
body: true
|
||||||
|
});
|
||||||
|
|
||||||
|
const div = document.createElement('div');
|
||||||
|
const doc = appStickersManager.getAnimatedEmojiSticker(PopupReportMessagesConfirm.STICKER_EMOJI);
|
||||||
|
const size = 100;
|
||||||
|
wrapSticker({
|
||||||
|
doc,
|
||||||
|
div,
|
||||||
|
emoji: PopupReportMessagesConfirm.STICKER_EMOJI,
|
||||||
|
width: size,
|
||||||
|
height: size,
|
||||||
|
loop: false,
|
||||||
|
play: true
|
||||||
|
}).finally(() => {
|
||||||
|
this.show();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.header.append(div);
|
||||||
|
|
||||||
|
const inputField = new InputField({
|
||||||
|
label: 'ReportHint',
|
||||||
|
maxLength: 512,
|
||||||
|
placeholder: 'ReportChatDescription'
|
||||||
|
});
|
||||||
|
|
||||||
|
this.body.append(inputField.container);
|
||||||
|
}
|
||||||
|
}
|
12
src/lang.ts
12
src/lang.ts
@ -549,6 +549,17 @@ const lang = {
|
|||||||
"Create": "Create",
|
"Create": "Create",
|
||||||
"ViewDiscussion": "View discussion",
|
"ViewDiscussion": "View discussion",
|
||||||
"MessageScheduledUntilOnline": "Scheduled until online",
|
"MessageScheduledUntilOnline": "Scheduled until online",
|
||||||
|
"ReportChat": "Report",
|
||||||
|
"ReportChatSpam": "Spam",
|
||||||
|
// "ReportChatFakeAccount": "Fake Account",
|
||||||
|
"ReportChatViolence": "Violence",
|
||||||
|
"ReportChatPornography": "Pornography",
|
||||||
|
"ReportChatChild": "Child Abuse",
|
||||||
|
"ReportChatOther": "Other",
|
||||||
|
"ReportChatDescription": "Description",
|
||||||
|
"ReportInfo": "Please enter any additional details relevant to your report.",
|
||||||
|
"ReportSentInfo": "Telegram moderators will review your report.\nThank you for your cooperation!",
|
||||||
|
"ReportHint": "Additional details...",
|
||||||
|
|
||||||
// * macos
|
// * macos
|
||||||
"AccountSettings.Filters": "Chat Folders",
|
"AccountSettings.Filters": "Chat Folders",
|
||||||
@ -609,6 +620,7 @@ const lang = {
|
|||||||
"one_value": "%d Comment",
|
"one_value": "%d Comment",
|
||||||
"other_value": "%d Comments"
|
"other_value": "%d Comments"
|
||||||
},
|
},
|
||||||
|
"ChatTitle.ReportMessages": "Report Messages",
|
||||||
"Chat.Send.WithoutSound": "Send Without Sound",
|
"Chat.Send.WithoutSound": "Send Without Sound",
|
||||||
"Chat.Send.SetReminder": "Set a Reminder",
|
"Chat.Send.SetReminder": "Set a Reminder",
|
||||||
"Chat.Send.ScheduledMessage": "Schedule Message",
|
"Chat.Send.ScheduledMessage": "Schedule Message",
|
||||||
|
@ -17,7 +17,7 @@ import { createPosterForVideo } from "../../helpers/files";
|
|||||||
import { copy, getObjectKeysAndSort } from "../../helpers/object";
|
import { copy, getObjectKeysAndSort } from "../../helpers/object";
|
||||||
import { randomLong } from "../../helpers/random";
|
import { randomLong } from "../../helpers/random";
|
||||||
import { splitStringByLength, limitSymbols, escapeRegExp } from "../../helpers/string";
|
import { splitStringByLength, limitSymbols, escapeRegExp } from "../../helpers/string";
|
||||||
import { Chat, ChatFull, Dialog as MTDialog, DialogPeer, DocumentAttribute, InputMedia, InputMessage, InputPeerNotifySettings, InputSingleMedia, Message, MessageAction, MessageEntity, MessageFwdHeader, MessageMedia, MessageReplies, MessageReplyHeader, MessagesDialogs, MessagesFilter, MessagesMessages, MethodDeclMap, NotifyPeer, PeerNotifySettings, PhotoSize, SendMessageAction, Update, Photo, Updates, ReplyMarkup, InputPeer, InputPhoto, InputDocument, InputGeoPoint, WebPage, GeoPoint } from "../../layer";
|
import { Chat, ChatFull, Dialog as MTDialog, DialogPeer, DocumentAttribute, InputMedia, InputMessage, InputPeerNotifySettings, InputSingleMedia, Message, MessageAction, MessageEntity, MessageFwdHeader, MessageMedia, MessageReplies, MessageReplyHeader, MessagesDialogs, MessagesFilter, MessagesMessages, MethodDeclMap, NotifyPeer, PeerNotifySettings, PhotoSize, SendMessageAction, Update, Photo, Updates, ReplyMarkup, InputPeer, InputPhoto, InputDocument, InputGeoPoint, WebPage, GeoPoint, ReportReason } from "../../layer";
|
||||||
import { InvokeApiOptions } from "../../types";
|
import { InvokeApiOptions } from "../../types";
|
||||||
import I18n, { i18n, join, langPack, LangPackKey, _i18n } from "../langPack";
|
import I18n, { i18n, join, langPack, LangPackKey, _i18n } from "../langPack";
|
||||||
import { logger, LogTypes } from "../logger";
|
import { logger, LogTypes } from "../logger";
|
||||||
@ -2866,6 +2866,17 @@ export class AppMessagesManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public reportMessages(peerId: number, mids: number[], reason: ReportReason['_'], message?: string) {
|
||||||
|
return apiManager.invokeApiSingle('messages.report', {
|
||||||
|
peer: appPeersManager.getInputPeerById(peerId),
|
||||||
|
id: mids.map(mid => appMessagesIdsManager.getServerMessageId(mid)),
|
||||||
|
reason: {
|
||||||
|
_: reason
|
||||||
|
},
|
||||||
|
message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public startBot(botId: number, chatId: number, startParam: string) {
|
public startBot(botId: number, chatId: number, startParam: string) {
|
||||||
const peerId = chatId ? -chatId : botId;
|
const peerId = chatId ? -chatId : botId;
|
||||||
if(startParam) {
|
if(startParam) {
|
||||||
|
@ -32,7 +32,7 @@ export class AppStickersManager {
|
|||||||
private getGreetingStickersPromise: Promise<void>;
|
private getGreetingStickersPromise: Promise<void>;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.getStickerSet({id: 'emoji'}, {saveById: true});
|
this.getAnimatedEmojiStickerSet();
|
||||||
|
|
||||||
rootScope.addMultipleEventsListeners({
|
rootScope.addMultipleEventsListeners({
|
||||||
updateNewStickerSet: (update) => {
|
updateNewStickerSet: (update) => {
|
||||||
@ -121,6 +121,10 @@ export class AppStickersManager {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getAnimatedEmojiStickerSet() {
|
||||||
|
return this.getStickerSet({id: 'emoji'}, {saveById: true});
|
||||||
|
}
|
||||||
|
|
||||||
public async getRecentStickers(): Promise<Modify<MessagesRecentStickers.messagesRecentStickers, {
|
public async getRecentStickers(): Promise<Modify<MessagesRecentStickers.messagesRecentStickers, {
|
||||||
stickers: Document[]
|
stickers: Document[]
|
||||||
}>> {
|
}>> {
|
||||||
@ -140,6 +144,15 @@ export class AppStickersManager {
|
|||||||
return pack ? appDocsManager.getDoc(pack.documents[0]) : undefined;
|
return pack ? appDocsManager.getDoc(pack.documents[0]) : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public preloadAnimatedEmojiSticker(emoji: string) {
|
||||||
|
return this.getAnimatedEmojiStickerSet().then(() => {
|
||||||
|
const doc = this.getAnimatedEmojiSticker(emoji);
|
||||||
|
if(doc) {
|
||||||
|
return appDocsManager.downloadDoc(doc);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public saveStickerSet(res: Omit<MessagesStickerSet.messagesStickerSet, '_'>, id: string) {
|
public saveStickerSet(res: Omit<MessagesStickerSet.messagesStickerSet, '_'>, id: string) {
|
||||||
//console.log('stickers save set', res);w
|
//console.log('stickers save set', res);w
|
||||||
|
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
/*
|
||||||
|
* https://github.com/morethanwords/tweb
|
||||||
|
* Copyright (C) 2019-2021 Eduard Kuzmenko
|
||||||
|
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
.popup-instance-deactivated {
|
.popup-instance-deactivated {
|
||||||
background-color: rgba(0, 0, 0, .6);
|
background-color: rgba(0, 0, 0, .6);
|
||||||
|
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
/*
|
||||||
|
* https://github.com/morethanwords/tweb
|
||||||
|
* Copyright (C) 2019-2021 Eduard Kuzmenko
|
||||||
|
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
.popup-join-chat-invite {
|
.popup-join-chat-invite {
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
|
||||||
|
28
src/scss/partials/popups/_reportMessages.scss
Normal file
28
src/scss/partials/popups/_reportMessages.scss
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
.popup-report-messages-confirm {
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
|
.media-sticker-wrapper {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
position: relative;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-body {
|
||||||
|
margin: 1em -.5rem .375rem -.5rem;
|
||||||
|
overflow: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-description {
|
||||||
|
font-size: .875rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-buttons {
|
||||||
|
margin-top: .625rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-field {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
@ -276,6 +276,7 @@ html.night {
|
|||||||
@import "partials/popups/forward";
|
@import "partials/popups/forward";
|
||||||
@import "partials/popups/instanceDeactivated";
|
@import "partials/popups/instanceDeactivated";
|
||||||
@import "partials/popups/joinChatInvite";
|
@import "partials/popups/joinChatInvite";
|
||||||
|
@import "partials/popups/reportMessages";
|
||||||
|
|
||||||
@import "partials/pages/pages";
|
@import "partials/pages/pages";
|
||||||
@import "partials/pages/authCode";
|
@import "partials/pages/authCode";
|
||||||
|
Loading…
x
Reference in New Issue
Block a user