mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2026-02-14 23:09:38 +00:00
283 lines
20 KiB
Swift
283 lines
20 KiB
Swift
import Foundation
|
|
import UIKit
|
|
import Display
|
|
import AccountContext
|
|
import SwiftSignalKit
|
|
import Postbox
|
|
import TelegramCore
|
|
import TextFormat
|
|
import UndoUI
|
|
import ChatInterfaceState
|
|
|
|
extension PeerInfoScreenNode {
|
|
func deleteMessages(messageIds: Set<MessageId>?) {
|
|
if let messageIds = messageIds ?? self.state.selectedMessageIds, !messageIds.isEmpty {
|
|
self.activeActionDisposable.set((self.context.sharedContext.chatAvailableMessageActions(engine: self.context.engine, accountPeerId: self.context.account.peerId, messageIds: messageIds, keepUpdated: false)
|
|
|> deliverOnMainQueue).startStrict(next: { [weak self] actions in
|
|
if let strongSelf = self, let peer = strongSelf.data?.peer, !actions.options.isEmpty {
|
|
let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData)
|
|
var items: [ActionSheetItem] = []
|
|
var personalPeerName: String?
|
|
var isChannel = false
|
|
if let user = peer as? TelegramUser {
|
|
personalPeerName = EnginePeer(user).compactDisplayTitle
|
|
} else if let channel = peer as? TelegramChannel, case .broadcast = channel.info {
|
|
isChannel = true
|
|
}
|
|
|
|
if actions.options.contains(.deleteGlobally) {
|
|
let globalTitle: String
|
|
if isChannel {
|
|
globalTitle = strongSelf.presentationData.strings.Conversation_DeleteMessagesForMe
|
|
} else if let personalPeerName = personalPeerName {
|
|
globalTitle = strongSelf.presentationData.strings.Conversation_DeleteMessagesFor(personalPeerName).string
|
|
} else {
|
|
globalTitle = strongSelf.presentationData.strings.Conversation_DeleteMessagesForEveryone
|
|
}
|
|
items.append(ActionSheetButtonItem(title: globalTitle, color: .destructive, action: { [weak actionSheet] in
|
|
actionSheet?.dismissAnimated()
|
|
if let strongSelf = self {
|
|
strongSelf.headerNode.navigationButtonContainer.performAction?(.selectionDone, nil, nil)
|
|
let _ = strongSelf.context.engine.messages.deleteMessagesInteractively(messageIds: Array(messageIds), type: .forEveryone).startStandalone()
|
|
}
|
|
}))
|
|
}
|
|
if actions.options.contains(.deleteLocally) {
|
|
var localOptionText = strongSelf.presentationData.strings.Conversation_DeleteMessagesForMe
|
|
if strongSelf.context.account.peerId == strongSelf.peerId {
|
|
if messageIds.count == 1 {
|
|
localOptionText = strongSelf.presentationData.strings.Conversation_Moderate_Delete
|
|
} else {
|
|
localOptionText = strongSelf.presentationData.strings.Conversation_DeleteManyMessages
|
|
}
|
|
}
|
|
items.append(ActionSheetButtonItem(title: localOptionText, color: .destructive, action: { [weak actionSheet] in
|
|
actionSheet?.dismissAnimated()
|
|
if let strongSelf = self {
|
|
strongSelf.headerNode.navigationButtonContainer.performAction?(.selectionDone, nil, nil)
|
|
let _ = strongSelf.context.engine.messages.deleteMessagesInteractively(messageIds: Array(messageIds), type: .forLocalPeer).startStandalone()
|
|
}
|
|
}))
|
|
}
|
|
actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [
|
|
ActionSheetButtonItem(title: strongSelf.presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in
|
|
actionSheet?.dismissAnimated()
|
|
})
|
|
])])
|
|
strongSelf.view.endEditing(true)
|
|
strongSelf.controller?.present(actionSheet, in: .window(.root))
|
|
}
|
|
}))
|
|
}
|
|
}
|
|
|
|
func forwardMessages(messageIds: Set<MessageId>?) {
|
|
if let messageIds = messageIds ?? self.state.selectedMessageIds, !messageIds.isEmpty {
|
|
let peerSelectionController = self.context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: self.context, updatedPresentationData: self.controller?.updatedPresentationData, filter: [.onlyWriteable, .excludeDisabled], hasFilters: true, multipleSelection: true, selectForumThreads: true))
|
|
peerSelectionController.multiplePeersSelected = { [weak self, weak peerSelectionController] peers, peerMap, messageText, mode, forwardOptions, _ in
|
|
guard let strongSelf = self, let strongController = peerSelectionController else {
|
|
return
|
|
}
|
|
strongController.dismiss()
|
|
|
|
var result: [EnqueueMessage] = []
|
|
if messageText.string.count > 0 {
|
|
let inputText = convertMarkdownToAttributes(messageText)
|
|
for text in breakChatInputText(trimChatInputText(inputText)) {
|
|
if text.length != 0 {
|
|
var attributes: [MessageAttribute] = []
|
|
let entities = generateTextEntities(text.string, enabledTypes: .all, currentEntities: generateChatInputTextEntities(text))
|
|
if !entities.isEmpty {
|
|
attributes.append(TextEntitiesMessageAttribute(entities: entities))
|
|
}
|
|
result.append(.message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: nil, threadId: nil, replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
|
}
|
|
}
|
|
}
|
|
|
|
var attributes: [MessageAttribute] = []
|
|
attributes.append(ForwardOptionsMessageAttribute(hideNames: forwardOptions?.hideNames == true, hideCaptions: forwardOptions?.hideCaptions == true))
|
|
|
|
result.append(contentsOf: messageIds.map { messageId -> EnqueueMessage in
|
|
return .forward(source: messageId, threadId: nil, grouping: .auto, attributes: attributes, correlationId: nil)
|
|
})
|
|
|
|
var displayPeers: [EnginePeer] = []
|
|
for peer in peers {
|
|
let _ = (enqueueMessages(account: strongSelf.context.account, peerId: peer.id, messages: result)
|
|
|> deliverOnMainQueue).startStandalone(next: { messageIds in
|
|
if let strongSelf = self {
|
|
let signals: [Signal<Bool, NoError>] = messageIds.compactMap({ id -> Signal<Bool, NoError>? in
|
|
guard let id = id else {
|
|
return nil
|
|
}
|
|
return strongSelf.context.account.pendingMessageManager.pendingMessageStatus(id)
|
|
|> mapToSignal { status, _ -> Signal<Bool, NoError> in
|
|
if status != nil {
|
|
return .never()
|
|
} else {
|
|
return .single(true)
|
|
}
|
|
}
|
|
|> take(1)
|
|
})
|
|
if strongSelf.shareStatusDisposable == nil {
|
|
strongSelf.shareStatusDisposable = MetaDisposable()
|
|
}
|
|
strongSelf.shareStatusDisposable?.set((combineLatest(signals)
|
|
|> deliverOnMainQueue).startStrict())
|
|
}
|
|
})
|
|
|
|
if case let .secretChat(secretPeer) = peer {
|
|
if let peer = peerMap[secretPeer.regularPeerId] {
|
|
displayPeers.append(peer)
|
|
}
|
|
} else {
|
|
displayPeers.append(peer)
|
|
}
|
|
}
|
|
|
|
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
|
|
let text: String
|
|
var savedMessages = false
|
|
if displayPeers.count == 1, let peerId = displayPeers.first?.id, peerId == strongSelf.context.account.peerId {
|
|
text = messageIds.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_SavedMessages_One : presentationData.strings.Conversation_ForwardTooltip_SavedMessages_Many
|
|
savedMessages = true
|
|
} else {
|
|
if displayPeers.count == 1, let peer = displayPeers.first {
|
|
var peerName = peer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
|
|
peerName = peerName.replacingOccurrences(of: "**", with: "")
|
|
text = messageIds.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_Chat_One(peerName).string : presentationData.strings.Conversation_ForwardTooltip_Chat_Many(peerName).string
|
|
} else if displayPeers.count == 2, let firstPeer = displayPeers.first, let secondPeer = displayPeers.last {
|
|
var firstPeerName = firstPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : firstPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
|
|
firstPeerName = firstPeerName.replacingOccurrences(of: "**", with: "")
|
|
var secondPeerName = secondPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : secondPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
|
|
secondPeerName = secondPeerName.replacingOccurrences(of: "**", with: "")
|
|
text = messageIds.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_TwoChats_One(firstPeerName, secondPeerName).string : presentationData.strings.Conversation_ForwardTooltip_TwoChats_Many(firstPeerName, secondPeerName).string
|
|
} else if let peer = displayPeers.first {
|
|
var peerName = peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
|
|
peerName = peerName.replacingOccurrences(of: "**", with: "")
|
|
text = messageIds.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_ManyChats_One(peerName, "\(displayPeers.count - 1)").string : presentationData.strings.Conversation_ForwardTooltip_ManyChats_Many(peerName, "\(displayPeers.count - 1)").string
|
|
} else {
|
|
text = ""
|
|
}
|
|
}
|
|
|
|
strongSelf.controller?.present(UndoOverlayController(presentationData: presentationData, content: .forward(savedMessages: savedMessages, text: text), elevatedLayout: false, animateInAsReplacement: true, action: { action in
|
|
if savedMessages, let self, action == .info {
|
|
let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: self.context.account.peerId))
|
|
|> deliverOnMainQueue).start(next: { [weak self] peer in
|
|
guard let self, let peer else {
|
|
return
|
|
}
|
|
guard let navigationController = self.controller?.navigationController as? NavigationController else {
|
|
return
|
|
}
|
|
self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(peer), forceOpenChat: true))
|
|
})
|
|
}
|
|
return false
|
|
}), in: .current)
|
|
}
|
|
peerSelectionController.peerSelected = { [weak self, weak peerSelectionController] peer, threadId in
|
|
let peerId = peer.id
|
|
|
|
if let strongSelf = self, let _ = peerSelectionController {
|
|
if peerId == strongSelf.context.account.peerId {
|
|
Queue.mainQueue().after(0.88) {
|
|
strongSelf.hapticFeedback.success()
|
|
}
|
|
|
|
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
|
|
strongSelf.controller?.present(UndoOverlayController(presentationData: presentationData, content: .forward(savedMessages: true, text: messageIds.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_SavedMessages_One : presentationData.strings.Conversation_ForwardTooltip_SavedMessages_Many), elevatedLayout: false, animateInAsReplacement: true, action: { action in
|
|
if let self, action == .info {
|
|
let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: self.context.account.peerId))
|
|
|> deliverOnMainQueue).start(next: { [weak self] peer in
|
|
guard let self, let peer else {
|
|
return
|
|
}
|
|
guard let navigationController = self.controller?.navigationController as? NavigationController else {
|
|
return
|
|
}
|
|
self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(peer)))
|
|
})
|
|
}
|
|
return false
|
|
}), in: .current)
|
|
|
|
strongSelf.headerNode.navigationButtonContainer.performAction?(.selectionDone, nil, nil)
|
|
|
|
let _ = (enqueueMessages(account: strongSelf.context.account, peerId: peerId, messages: messageIds.map { id -> EnqueueMessage in
|
|
return .forward(source: id, threadId: nil, grouping: .auto, attributes: [], correlationId: nil)
|
|
})
|
|
|> deliverOnMainQueue).startStandalone(next: { [weak self] messageIds in
|
|
if let strongSelf = self {
|
|
let signals: [Signal<Bool, NoError>] = messageIds.compactMap({ id -> Signal<Bool, NoError>? in
|
|
guard let id = id else {
|
|
return nil
|
|
}
|
|
return strongSelf.context.account.pendingMessageManager.pendingMessageStatus(id)
|
|
|> mapToSignal { status, _ -> Signal<Bool, NoError> in
|
|
if status != nil {
|
|
return .never()
|
|
} else {
|
|
return .single(true)
|
|
}
|
|
}
|
|
|> take(1)
|
|
})
|
|
strongSelf.activeActionDisposable.set((combineLatest(signals)
|
|
|> deliverOnMainQueue).startStrict())
|
|
}
|
|
})
|
|
if let peerSelectionController = peerSelectionController {
|
|
peerSelectionController.dismiss()
|
|
}
|
|
} else {
|
|
let _ = (ChatInterfaceState.update(engine: strongSelf.context.engine, peerId: peerId, threadId: threadId, { currentState in
|
|
return currentState.withUpdatedForwardMessageIds(Array(messageIds))
|
|
})
|
|
|> deliverOnMainQueue).startStandalone(completed: {
|
|
if let strongSelf = self {
|
|
let proceed: (ChatController) -> Void = { chatController in
|
|
strongSelf.headerNode.navigationButtonContainer.performAction?(.selectionDone, nil, nil)
|
|
|
|
if let navigationController = strongSelf.controller?.navigationController as? NavigationController {
|
|
var viewControllers = navigationController.viewControllers
|
|
if threadId != nil {
|
|
viewControllers.insert(chatController, at: viewControllers.count - 2)
|
|
} else {
|
|
viewControllers.insert(chatController, at: viewControllers.count - 1)
|
|
}
|
|
navigationController.setViewControllers(viewControllers, animated: false)
|
|
|
|
strongSelf.activeActionDisposable.set((chatController.ready.get()
|
|
|> filter { $0 }
|
|
|> take(1)
|
|
|> deliverOnMainQueue).startStrict(next: { [weak navigationController] _ in
|
|
viewControllers.removeAll(where: { $0 is PeerSelectionController })
|
|
navigationController?.setViewControllers(viewControllers, animated: true)
|
|
}))
|
|
}
|
|
}
|
|
|
|
if let threadId = threadId {
|
|
let _ = (strongSelf.context.sharedContext.chatControllerForForumThread(context: strongSelf.context, peerId: peerId, threadId: threadId)
|
|
|> deliverOnMainQueue).startStandalone(next: { chatController in
|
|
proceed(chatController)
|
|
})
|
|
} else {
|
|
let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(id: peerId), subject: .none, botStart: nil, mode: .standard(.default), params: nil)
|
|
proceed(chatController)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
}
|
|
self.controller?.push(peerSelectionController)
|
|
}
|
|
}
|
|
}
|