This commit is contained in:
Ilya Laktyushin 2026-05-14 12:45:26 +02:00
parent 7a7333edab
commit 91eb779ae2
614 changed files with 33270 additions and 37190 deletions

View file

@ -1,6 +1,5 @@
import Foundation
import UIKit
import Postbox
import TelegramCore
import AsyncDisplayKit
import Display
@ -48,11 +47,11 @@ private struct MessageContextMenuData {
let messageActions: ChatAvailableMessageActions
}
func canEditMessage(context: AccountContext, limitsConfiguration: EngineConfiguration.Limits, message: Message) -> Bool {
func canEditMessage(context: AccountContext, limitsConfiguration: EngineConfiguration.Limits, message: EngineRawMessage) -> Bool {
return canEditMessage(accountPeerId: context.account.peerId, limitsConfiguration: limitsConfiguration, message: message)
}
private func canEditMessage(accountPeerId: PeerId, limitsConfiguration: EngineConfiguration.Limits, message: Message, reschedule: Bool = false) -> Bool {
private func canEditMessage(accountPeerId: EnginePeer.Id, limitsConfiguration: EngineConfiguration.Limits, message: EngineRawMessage, reschedule: Bool = false) -> Bool {
var hasEditRights = false
var unlimitedInterval = reschedule
@ -190,7 +189,7 @@ private func canEditFactCheck(appConfig: AppConfiguration) -> Bool {
return false
}
private func canViewReadStats(message: Message, participantCount: Int?, isMessageRead: Bool, isPremium: Bool, appConfig: AppConfiguration) -> Bool {
private func canViewReadStats(message: EngineRawMessage, participantCount: Int?, isMessageRead: Bool, isPremium: Bool, appConfig: AppConfiguration) -> Bool {
guard let peer = message.peers[message.id.peerId] else {
return false
}
@ -285,7 +284,7 @@ private func canViewReadStats(message: Message, participantCount: Int?, isMessag
return true
}
func canReplyInChat(_ chatPresentationInterfaceState: ChatPresentationInterfaceState, accountPeerId: PeerId) -> Bool {
func canReplyInChat(_ chatPresentationInterfaceState: ChatPresentationInterfaceState, accountPeerId: EnginePeer.Id) -> Bool {
if case let .customChatContents(contents) = chatPresentationInterfaceState.subject, case .hashTagSearch = contents.kind {
return true
}
@ -383,7 +382,7 @@ enum ChatMessageContextMenuAction {
case sheet(ChatMessageContextMenuSheetAction)
}
func messageMediaEditingOptions(message: Message) -> MessageMediaEditingOptions {
func messageMediaEditingOptions(message: EngineRawMessage) -> MessageMediaEditingOptions {
if message.id.peerId.namespace == Namespaces.Peer.SecretChat {
return []
}
@ -436,7 +435,7 @@ func messageMediaEditingOptions(message: Message) -> MessageMediaEditingOptions
return options
}
func updatedChatEditInterfaceMessageState(context: AccountContext, state: ChatPresentationInterfaceState, message: Message) -> (ChatPresentationInterfaceState, (UrlPreviewState?, Disposable)?) {
func updatedChatEditInterfaceMessageState(context: AccountContext, state: ChatPresentationInterfaceState, message: EngineRawMessage) -> (ChatPresentationInterfaceState, (UrlPreviewState?, Disposable)?) {
var updated = state
for media in message.media {
if let webpage = media as? TelegramMediaWebpage, case let .Loaded(content) = webpage.content {
@ -480,7 +479,7 @@ func updatedChatEditInterfaceMessageState(context: AccountContext, state: ChatPr
)
}
func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState: ChatPresentationInterfaceState, context: AccountContext, messages: [Message], controllerInteraction: ChatControllerInteraction?, selectAll: Bool, interfaceInteraction: ChatPanelInterfaceInteraction?, readStats: MessageReadStats? = nil, messageNode: ChatMessageItemView? = nil) -> Signal<ContextController.Items, NoError> {
func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState: ChatPresentationInterfaceState, context: AccountContext, messages: [EngineRawMessage], controllerInteraction: ChatControllerInteraction?, selectAll: Bool, interfaceInteraction: ChatPanelInterfaceInteraction?, readStats: MessageReadStats? = nil, messageNode: ChatMessageItemView? = nil) -> Signal<ContextController.Items, NoError> {
guard let interfaceInteraction = interfaceInteraction, let controllerInteraction = controllerInteraction else {
return .single(ContextController.Items(content: .list([])))
}
@ -695,8 +694,8 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
return .single(ContextController.Items(content: .list(actions)))
}
var loadStickerSaveStatus: MediaId?
var loadCopyMediaResource: MediaResource?
var loadStickerSaveStatus: EngineMedia.Id?
var loadCopyMediaResource: TelegramMediaResource?
var isAction = false
var isGiveawayServiceMessage = false
var diceEmoji: String?
@ -872,7 +871,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
let isScheduled = chatPresentationInterfaceState.subject == .scheduledMessages
let dataSignal: Signal<(MessageContextMenuData, [MessageId: ChatUpdatingMessageMedia], InfoSummaryData, AppConfiguration, Bool, Int32, AvailableReactions?, TranslationSettings, LoggingSettings, NotificationSoundList?, EnginePeer?), NoError> = combineLatest(
let dataSignal: Signal<(MessageContextMenuData, [EngineMessage.Id: ChatUpdatingMessageMedia], InfoSummaryData, AppConfiguration, Bool, Int32, AvailableReactions?, TranslationSettings, LoggingSettings, NotificationSoundList?, EnginePeer?), NoError> = combineLatest(
loadLimits,
loadStickerSaveStatusSignal,
loadResourceStatusSignal,
@ -887,7 +886,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
context.engine.peers.notificationSoundList() |> take(1),
context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId))
)
|> map { limitsAndAppConfig, stickerSaveStatus, resourceStatus, messageActions, updatingMessageMedia, infoSummaryData, isMessageRead, messageViewsPrivacyTips, availableReactions, sharedData, notificationSoundList, accountPeer -> (MessageContextMenuData, [MessageId: ChatUpdatingMessageMedia], InfoSummaryData, AppConfiguration, Bool, Int32, AvailableReactions?, TranslationSettings, LoggingSettings, NotificationSoundList?, EnginePeer?) in
|> map { limitsAndAppConfig, stickerSaveStatus, resourceStatus, messageActions, updatingMessageMedia, infoSummaryData, isMessageRead, messageViewsPrivacyTips, availableReactions, sharedData, notificationSoundList, accountPeer -> (MessageContextMenuData, [EngineMessage.Id: ChatUpdatingMessageMedia], InfoSummaryData, AppConfiguration, Bool, Int32, AvailableReactions?, TranslationSettings, LoggingSettings, NotificationSoundList?, EnginePeer?) in
let (limitsConfiguration, appConfig) = limitsAndAppConfig
var canEdit = false
if !isAction {
@ -1003,7 +1002,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
strongController.dismiss()
let id = Int64.random(in: Int64.min ... Int64.max)
let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: LocalFileReferenceMediaResource(localFilePath: logPath, randomId: id), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: nil, attributes: [.FileName(fileName: "CallStats.log")], alternativeRepresentations: [])
let file = TelegramMediaFile(fileId: EngineMedia.Id(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: LocalFileReferenceMediaResource(localFilePath: logPath, randomId: id), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: nil, attributes: [.FileName(fileName: "CallStats.log")], alternativeRepresentations: [])
let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), threadId: nil, replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [message]).startStandalone()
@ -1640,7 +1639,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
}
if canPin {
var pinnedSelectedMessageId: MessageId?
var pinnedSelectedMessageId: EngineMessage.Id?
for message in messages {
if message.tags.contains(.pinned) {
pinnedSelectedMessageId = message.id
@ -1709,7 +1708,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
actions.append(.action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.Conversation_ContextMenuCopyLink, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Link"), color: theme.actionSheet.primaryTextColor)
}, action: { _, f in
var threadMessageId: MessageId?
var threadMessageId: EngineMessage.Id?
if case let .replyThread(replyThreadMessage) = chatPresentationInterfaceState.chatLocation {
threadMessageId = replyThreadMessage.effectiveMessageId
}
@ -2355,7 +2354,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
}
}
func canPerformEditingActions(limits: LimitsConfiguration, accountPeerId: PeerId, message: Message, unlimitedInterval: Bool) -> Bool {
func canPerformEditingActions(limits: LimitsConfiguration, accountPeerId: EnginePeer.Id, message: EngineRawMessage, unlimitedInterval: Bool) -> Bool {
if message.id.peerId == accountPeerId {
return true
}
@ -2372,7 +2371,7 @@ func canPerformEditingActions(limits: LimitsConfiguration, accountPeerId: PeerId
return false
}
private func canPerformDeleteActions(limits: LimitsConfiguration, accountPeerId: PeerId, message: Message) -> Bool {
private func canPerformDeleteActions(limits: LimitsConfiguration, accountPeerId: EnginePeer.Id, message: EngineRawMessage) -> Bool {
if message.id.peerId == accountPeerId {
return true
}
@ -2396,7 +2395,7 @@ private func canPerformDeleteActions(limits: LimitsConfiguration, accountPeerId:
return false
}
func chatAvailableMessageActionsImpl(engine: TelegramEngine, accountPeerId: PeerId, messageIds: Set<MessageId>, messages: [MessageId: Message] = [:], peers: [PeerId: Peer] = [:], keepUpdated: Bool) -> Signal<ChatAvailableMessageActions, NoError> {
func chatAvailableMessageActionsImpl(engine: TelegramEngine, accountPeerId: EnginePeer.Id, messageIds: Set<EngineMessage.Id>, messages: [EngineMessage.Id: EngineRawMessage] = [:], peers: [EnginePeer.Id: EngineRawPeer] = [:], keepUpdated: Bool) -> Signal<ChatAvailableMessageActions, NoError> {
return engine.data.subscribe(
TelegramEngine.EngineData.Item.Configuration.Limits(),
EngineDataMap(Set(messageIds.map(\.peerId)).map(TelegramEngine.EngineData.Item.Peer.Peer.init)),
@ -2414,9 +2413,9 @@ func chatAvailableMessageActionsImpl(engine: TelegramEngine, accountPeerId: Peer
isPremium = false
}
var optionsMap: [MessageId: ChatAvailableMessageActionOptions] = [:]
var banPeer: Peer?
var banPeers: [Peer] = []
var optionsMap: [EngineMessage.Id: ChatAvailableMessageActionOptions] = [:]
var banPeer: EngineRawPeer?
var banPeers: [EngineRawPeer] = []
var hadPersonalIncoming = false
var hadBanPeerId = false
var disableDelete = false
@ -2427,7 +2426,7 @@ func chatAvailableMessageActionsImpl(engine: TelegramEngine, accountPeerId: Peer
var setTag = false
var commonTags: Set<MessageReaction.Reaction>?
func getPeer(_ peerId: PeerId) -> Peer? {
func getPeer(_ peerId: EnginePeer.Id) -> EngineRawPeer? {
if let maybePeer = peerMap[peerId], let peer = maybePeer {
return peer._asPeer()
} else if let peer = peers[peerId] {
@ -2437,7 +2436,7 @@ func chatAvailableMessageActionsImpl(engine: TelegramEngine, accountPeerId: Peer
}
}
func getMessage(_ messageId: MessageId) -> Message? {
func getMessage(_ messageId: EngineMessage.Id) -> EngineRawMessage? {
if let maybeMessage = messageMap[messageId], let message = maybeMessage {
return message._asMessage()
} else if let message = messages[messageId] {
@ -2447,7 +2446,7 @@ func chatAvailableMessageActionsImpl(engine: TelegramEngine, accountPeerId: Peer
}
}
func isPeerCopyProtected(_ peerId: PeerId) -> Bool? {
func isPeerCopyProtected(_ peerId: EnginePeer.Id) -> Bool? {
let copyProtection = copyProtectionMap[peerId]
let myCopyProtection = myCopyProtectionMap[peerId]
if copyProtection == true || myCopyProtection == true {
@ -2914,10 +2913,10 @@ private final class ChatDeleteMessageContextItemNode: ASDisplayNode, ContextMenu
final class ChatMessageAuthorContextItem: ContextMenuCustomItem {
fileprivate let context: AccountContext
fileprivate let message: Message
fileprivate let message: EngineRawMessage
fileprivate let action: ((ContextControllerProtocol, @escaping (ContextMenuActionResult) -> Void, EnginePeer) -> Void)?
init(context: AccountContext, message: Message, action: ((ContextControllerProtocol, @escaping (ContextMenuActionResult) -> Void, EnginePeer) -> Void)?) {
init(context: AccountContext, message: EngineRawMessage, action: ((ContextControllerProtocol, @escaping (ContextMenuActionResult) -> Void, EnginePeer) -> Void)?) {
self.context = context
self.message = message
self.action = action
@ -3158,13 +3157,13 @@ private final class ChatMessageAuthorContextItemNode: ASDisplayNode, ContextMenu
final class ChatReadReportContextItem: ContextMenuCustomItem {
fileprivate let context: AccountContext
fileprivate let message: Message
fileprivate let message: EngineRawMessage
fileprivate let hasReadReports: Bool
fileprivate let isEdit: Bool
fileprivate let stats: MessageReadStats?
fileprivate let action: ((ContextControllerProtocol, @escaping (ContextMenuActionResult) -> Void, MessageReadStats?, [StickerPackCollectionInfo], TelegramMediaFile?) -> Void)?
init(context: AccountContext, message: Message, hasReadReports: Bool, isEdit: Bool, stats: MessageReadStats?, action: ((ContextControllerProtocol, @escaping (ContextMenuActionResult) -> Void, MessageReadStats?, [StickerPackCollectionInfo], TelegramMediaFile?) -> Void)?) {
init(context: AccountContext, message: EngineRawMessage, hasReadReports: Bool, isEdit: Bool, stats: MessageReadStats?, action: ((ContextControllerProtocol, @escaping (ContextMenuActionResult) -> Void, MessageReadStats?, [StickerPackCollectionInfo], TelegramMediaFile?) -> Void)?) {
self.context = context
self.message = message
self.hasReadReports = hasReadReports
@ -3746,10 +3745,10 @@ private func stringForRemainingTime(_ duration: Int32, strings: PresentationStri
final class ChatRateTranscriptionContextItem: ContextMenuCustomItem {
fileprivate let context: AccountContext
fileprivate let message: Message
fileprivate let message: EngineRawMessage
fileprivate let action: (Bool) -> Void
init(context: AccountContext, message: Message, action: @escaping (Bool) -> Void) {
init(context: AccountContext, message: EngineRawMessage, action: @escaping (Bool) -> Void) {
self.context = context
self.message = message
self.action = action