import Foundation import UIKit import Display import SwiftSignalKit import TelegramCore import TelegramPresentationData import ItemListUI import PresentationDataUtils import AccountContext import ContextUI import AlertUI import PresentationDataUtils import UndoUI import AppBundle import TelegramPermissionsUI import Markdown public enum PeerReportSubject { case peer(EnginePeer.Id) case messages([EngineMessage.Id]) case profilePhoto(EnginePeer.Id, Int64) case story(EnginePeer.Id, Int32) } public enum PeerReportOption { case spam case fake case violence case copyright case pornography case childAbuse case illegalDrugs case personalDetails case other } public func presentPeerReportOptions( context: AccountContext, parent: ViewController, contextController: ContextControllerProtocol?, backAction: ((ContextControllerProtocol) -> Void)? = nil, subject: PeerReportSubject, options: [PeerReportOption] = [.spam, .violence, .pornography, .childAbuse, .copyright, .other], passthrough: Bool = false, forceTheme: PresentationTheme? = nil, isDetailedReportingVisible: ((Bool) -> Void)? = nil, completion: @escaping (ReportReason?, Bool) -> Void ) { if let contextController = contextController { var presentationData = context.sharedContext.currentPresentationData.with { $0 } if let forceTheme { presentationData = presentationData.withUpdated(theme: forceTheme) } var items: [ContextMenuItem] = [] if let _ = backAction { items.append(.action(ContextMenuActionItem(text: presentationData.strings.Common_Back, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Back"), color: theme.actionSheet.primaryTextColor) }, iconPosition: .left, action: { (c, _) in c?.popItems() }))) items.append(.separator) } for option in options { let title: String let color: ContextMenuActionItemTextColor = .primary var icon: UIImage? switch option { case .spam: title = presentationData.strings.ReportPeer_ReasonSpam icon = UIImage(bundleImageName: "Chat/Context Menu/Delete") case .fake: title = presentationData.strings.ReportPeer_ReasonFake icon = UIImage(bundleImageName: "Chat/Context Menu/ReportFake") case .violence: title = presentationData.strings.ReportPeer_ReasonViolence icon = UIImage(bundleImageName: "Chat/Context Menu/ReportViolence") case .pornography: title = presentationData.strings.ReportPeer_ReasonPornography icon = UIImage(bundleImageName: "Chat/Context Menu/ReportXxx") case .childAbuse: title = presentationData.strings.ReportPeer_ReasonChildAbuse icon = UIImage(bundleImageName: "Chat/Context Menu/Restrict") case .copyright: title = presentationData.strings.ReportPeer_ReasonCopyright icon = UIImage(bundleImageName: "Chat/Context Menu/ReportCopyright") case .illegalDrugs: title = presentationData.strings.ReportPeer_ReasonIllegalDrugs icon = UIImage(bundleImageName: "Chat/Context Menu/ReportDrugs") case .personalDetails: title = presentationData.strings.ReportPeer_ReasonPersonalDetails icon = UIImage(bundleImageName: "Chat/Context Menu/ReportPersonal") case .other: title = presentationData.strings.ReportPeer_ReasonOther icon = UIImage(bundleImageName: "Chat/Context Menu/Report") } items.append(.action(ContextMenuActionItem(text: title, textColor: color, icon: { theme in return generateTintedImage(image: icon, color: theme.contextMenu.primaryColor) }, action: { [weak parent] _, f in let reportReason: ReportReason switch option { case .spam: reportReason = .spam case .fake: reportReason = .fake case .violence: reportReason = .violence case .pornography: reportReason = .porno case .childAbuse: reportReason = .childAbuse case .copyright: reportReason = .copyright case .illegalDrugs: reportReason = .illegalDrugs case .personalDetails: reportReason = .personalDetails case .other: reportReason = .custom } var passthrough = passthrough if [.fake, .custom].contains(reportReason) { passthrough = false } let displaySuccess = { parent?.present(UndoOverlayController(presentationData: presentationData, content: .emoji(name: "PoliceCar", text: presentationData.strings.Report_Succeed), elevatedLayout: false, action: { _ in return false }), in: .current) } if passthrough { completion(reportReason, true) } else { let action: (String) -> Void = { message in if passthrough { completion(reportReason, true) } else { switch subject { case let .peer(peerId): let _ = (context.engine.peers.reportPeer(peerId: peerId, reason: reportReason, message: "") |> deliverOnMainQueue).start(completed: { displaySuccess() completion(nil, false) }) case let .messages(messageIds): let _ = (context.engine.peers.reportPeerMessages(messageIds: messageIds, reason: reportReason, message: "") |> deliverOnMainQueue).start(completed: { displaySuccess() completion(nil, false) }) case let .profilePhoto(peerId, _): let _ = (context.engine.peers.reportPeerPhoto(peerId: peerId, reason: reportReason, message: "") |> deliverOnMainQueue).start(completed: { displaySuccess() completion(nil, false) }) case let .story(peerId, storyId): let _ = (context.engine.peers.reportPeerStory(peerId: peerId, storyId: storyId, reason: reportReason, message: "") |> deliverOnMainQueue).start(completed: { displaySuccess() completion(nil, false) }) } } } isDetailedReportingVisible?(true) let controller = ActionSheetController(presentationData: presentationData, allowInputInset: true) controller.dismissed = { _ in isDetailedReportingVisible?(false) } let dismissAction: () -> Void = { [weak controller] in controller?.dismissAnimated() } var message = "" var items: [ActionSheetItem] = [] items.append(ReportPeerHeaderActionSheetItem(context: context, text: presentationData.strings.Report_AdditionalDetailsText)) items.append(ReportPeerDetailsActionSheetItem(context: context, theme: presentationData.theme, placeholderText: presentationData.strings.Report_AdditionalDetailsPlaceholder, textUpdated: { text in message = text })) items.append(ActionSheetButtonItem(title: presentationData.strings.Report_Report, color: .accent, font: .bold, enabled: true, action: { dismissAction() action(message) })) controller.setItemGroups([ ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, action: { dismissAction() })]) ]) parent?.present(controller, in: .window(.root)) } f(.dismissWithoutContent) }))) } contextController.pushItems(items: .single(ContextController.Items(content: .list(items)))) } else { contextController?.dismiss(completion: nil) parent.view.endEditing(true) parent.present(peerReportOptionsController(context: context, subject: subject, passthrough: passthrough, present: { [weak parent] c, a in parent?.present(c, in: .window(.root), with: a) }, push: { [weak parent] c in parent?.push(c) }, completion: completion), in: .window(.root)) } } public func peerReportOptionsController(context: AccountContext, subject: PeerReportSubject, options: [PeerReportOption] = [.spam, .violence, .pornography, .childAbuse, .copyright, .other], passthrough: Bool, present: @escaping (ViewController, Any?) -> Void, push: @escaping (ViewController) -> Void, completion: @escaping (ReportReason?, Bool) -> Void) -> ViewController { let presentationData = context.sharedContext.currentPresentationData.with { $0 } let controller = ActionSheetController(theme: ActionSheetControllerTheme(presentationData: presentationData)) var items: [ActionSheetItem] = [] for option in options { let title: String let color: ActionSheetButtonColor = .accent switch option { case .spam: title = presentationData.strings.ReportPeer_ReasonSpam case .fake: title = presentationData.strings.ReportPeer_ReasonFake case .violence: title = presentationData.strings.ReportPeer_ReasonViolence case .pornography: title = presentationData.strings.ReportPeer_ReasonPornography case .childAbuse: title = presentationData.strings.ReportPeer_ReasonChildAbuse case .copyright: title = presentationData.strings.ReportPeer_ReasonCopyright case .illegalDrugs: title = presentationData.strings.ReportPeer_ReasonIllegalDrugs case .personalDetails: title = presentationData.strings.ReportPeer_ReasonPersonalDetails case .other: title = presentationData.strings.ReportPeer_ReasonOther } items.append(ActionSheetButtonItem(title: title, color: color, action: { [weak controller] in var reportReason: ReportReason? switch option { case .spam: reportReason = .spam case .fake: reportReason = .fake case .violence: reportReason = .violence case .pornography: reportReason = .porno case .childAbuse: reportReason = .childAbuse case .copyright: reportReason = .copyright case .illegalDrugs: reportReason = .illegalDrugs case .personalDetails: reportReason = .personalDetails case .other: reportReason = .custom } if let reportReason = reportReason { var passthrough = passthrough if [.fake, .custom].contains(reportReason) { passthrough = false } let displaySuccess = { present(UndoOverlayController(presentationData: presentationData, content: .emoji(name: "PoliceCar", text: presentationData.strings.Report_Succeed), elevatedLayout: false, action: { _ in return false }), nil) } let action: (String) -> Void = { message in if passthrough { completion(reportReason, true) } else { switch subject { case let .peer(peerId): let _ = (context.engine.peers.reportPeer(peerId: peerId, reason: reportReason, message: message) |> deliverOnMainQueue).start(completed: { displaySuccess() completion(nil, true) }) case let .messages(messageIds): let _ = (context.engine.peers.reportPeerMessages(messageIds: messageIds, reason: reportReason, message: message) |> deliverOnMainQueue).start(completed: { displaySuccess() completion(nil, true) }) case let .profilePhoto(peerId, _): let _ = (context.engine.peers.reportPeerPhoto(peerId: peerId, reason: reportReason, message: message) |> deliverOnMainQueue).start(completed: { displaySuccess() completion(nil, true) }) case let .story(peerId, storyId): let _ = (context.engine.peers.reportPeerStory(peerId: peerId, storyId: storyId, reason: reportReason, message: message) |> deliverOnMainQueue).start(completed: { displaySuccess() completion(nil, true) }) } } } if [.fake, .custom].contains(reportReason) { let controller = ActionSheetController(presentationData: presentationData, allowInputInset: true) let dismissAction: () -> Void = { [weak controller] in controller?.dismissAnimated() } var message = "" var items: [ActionSheetItem] = [] items.append(ReportPeerHeaderActionSheetItem(context: context, text: presentationData.strings.Report_AdditionalDetailsText)) items.append(ReportPeerDetailsActionSheetItem(context: context, theme: presentationData.theme, placeholderText: presentationData.strings.Report_AdditionalDetailsPlaceholder, textUpdated: { text in message = text })) items.append(ActionSheetButtonItem(title: presentationData.strings.Report_Report, color: .accent, font: .bold, enabled: true, action: { dismissAction() action(message) })) controller.setItemGroups([ ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, action: { dismissAction() })]) ]) present(controller, nil) } else { action("") } } controller?.dismissAnimated() })) } controller.setItemGroups([ ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [ ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, action: { [weak controller] in controller?.dismissAnimated() completion(nil, false) }) ]) ]) return controller }