mirror of
https://github.com/TelegramMessenger/Telegram-iOS.git
synced 2026-07-06 03:33:41 +02:00
When the user long-presses Send in the main chat and the composed text passes the same rich-markdown gate used at send time (richMarkdownAttributeIfNeeded), the send-options preview bubble renders the message as rich InstantPage content, crossfading from the raw text as the menu animates in. Plain text and custom chat contents / edit previews are unchanged. ChatSendMessageActionUI cannot depend on InstantPageUI (it closes a dependency cycle via LocationUI -> AttachmentUI -> ... -> ChatTextInputActionButtonsNode), so the rich view is built in TelegramUI (ChatSendMessageRichTextPreview, wrapping InstantPageV2View + the outgoing message theme) and injected into the screen via a new ChatSendMessageContextScreenRichTextPreview protocol, mirroring the existing media-preview pattern. The main-chat send call site classifies the compose text and injects the preview; MessageItemView lays it out within the send-button-bounded bubble envelope and crossfades between the raw text and the rich layout. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
118 lines
4.9 KiB
Swift
118 lines
4.9 KiB
Swift
import Foundation
|
|
import UIKit
|
|
import Display
|
|
import AsyncDisplayKit
|
|
import SwiftSignalKit
|
|
import TelegramPresentationData
|
|
import AccountContext
|
|
import ContextUI
|
|
import TelegramCore
|
|
import TextFormat
|
|
import ReactionSelectionNode
|
|
import WallpaperBackgroundNode
|
|
|
|
public enum SendMessageActionSheetControllerParams {
|
|
public final class SendMessage {
|
|
public let isScheduledMessages: Bool
|
|
public let mediaPreview: ChatSendMessageContextScreenMediaPreview?
|
|
public let mediaCaptionIsAbove: (Bool, (Bool) -> Void)?
|
|
public let messageEffect: (ChatSendMessageActionSheetControllerSendParameters.Effect?, (ChatSendMessageActionSheetControllerSendParameters.Effect?) -> Void)?
|
|
public let attachment: Bool
|
|
public let canSendWhenOnline: Bool
|
|
public let forwardMessageIds: [EngineMessage.Id]
|
|
public let canMakePaidContent: Bool
|
|
public let currentPrice: Int64?
|
|
public let hasTimers: Bool
|
|
public let sendPaidMessageStars: StarsAmount?
|
|
public let isMonoforum: Bool
|
|
|
|
public init(
|
|
isScheduledMessages: Bool,
|
|
mediaPreview: ChatSendMessageContextScreenMediaPreview?,
|
|
mediaCaptionIsAbove: (Bool, (Bool) -> Void)?,
|
|
messageEffect: (ChatSendMessageActionSheetControllerSendParameters.Effect?, (ChatSendMessageActionSheetControllerSendParameters.Effect?) -> Void)?,
|
|
attachment: Bool,
|
|
canSendWhenOnline: Bool,
|
|
forwardMessageIds: [EngineMessage.Id],
|
|
canMakePaidContent: Bool,
|
|
currentPrice: Int64?,
|
|
hasTimers: Bool,
|
|
sendPaidMessageStars: StarsAmount?,
|
|
isMonoforum: Bool
|
|
) {
|
|
self.isScheduledMessages = isScheduledMessages
|
|
self.mediaPreview = mediaPreview
|
|
self.mediaCaptionIsAbove = mediaCaptionIsAbove
|
|
self.messageEffect = messageEffect
|
|
self.attachment = attachment
|
|
self.canSendWhenOnline = canSendWhenOnline
|
|
self.forwardMessageIds = forwardMessageIds
|
|
self.canMakePaidContent = canMakePaidContent
|
|
self.currentPrice = currentPrice
|
|
self.hasTimers = hasTimers
|
|
self.sendPaidMessageStars = sendPaidMessageStars
|
|
self.isMonoforum = isMonoforum
|
|
}
|
|
}
|
|
|
|
public final class EditMessage {
|
|
public let messages: [EngineMessage]
|
|
public let mediaPreview: ChatSendMessageContextScreenMediaPreview?
|
|
public let mediaCaptionIsAbove: (Bool, (Bool) -> Void)?
|
|
|
|
public init(messages: [EngineMessage], mediaPreview: ChatSendMessageContextScreenMediaPreview?, mediaCaptionIsAbove: (Bool, (Bool) -> Void)?) {
|
|
self.messages = messages
|
|
self.mediaPreview = mediaPreview
|
|
self.mediaCaptionIsAbove = mediaCaptionIsAbove
|
|
}
|
|
}
|
|
|
|
case sendMessage(SendMessage)
|
|
case editMessage(EditMessage)
|
|
}
|
|
|
|
public func makeChatSendMessageActionSheetController(
|
|
initialData: ChatSendMessageContextScreen.InitialData,
|
|
context: AccountContext,
|
|
updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil,
|
|
peerId: EnginePeer.Id?,
|
|
params: SendMessageActionSheetControllerParams,
|
|
hasEntityKeyboard: Bool,
|
|
gesture: ContextGesture?,
|
|
sourceSendButton: UIView,
|
|
textInputView: UITextView?,
|
|
emojiViewProvider: ((ChatTextInputTextCustomEmojiAttribute) -> UIView)?,
|
|
wallpaperBackgroundNode: WallpaperBackgroundNode? = nil,
|
|
completion: @escaping () -> Void,
|
|
sendMessage: @escaping (ChatSendMessageActionSheetController.SendMode, ChatSendMessageActionSheetController.SendParameters?) -> Void,
|
|
schedule: @escaping (ChatSendMessageActionSheetController.SendParameters?) -> Void,
|
|
editPrice: @escaping (Int64) -> Void,
|
|
openPremiumPaywall: @escaping (ViewController) -> Void,
|
|
reactionItems: [ReactionItem]? = nil,
|
|
availableMessageEffects: AvailableMessageEffects? = nil,
|
|
isPremium: Bool = false,
|
|
richTextPreview: ChatSendMessageContextScreenRichTextPreview? = nil
|
|
) -> ChatSendMessageActionSheetController {
|
|
return ChatSendMessageContextScreen(
|
|
initialData: initialData,
|
|
context: context,
|
|
updatedPresentationData: updatedPresentationData,
|
|
peerId: peerId,
|
|
params: params,
|
|
hasEntityKeyboard: hasEntityKeyboard,
|
|
gesture: gesture,
|
|
sourceSendButton: sourceSendButton,
|
|
textInputView: textInputView,
|
|
emojiViewProvider: emojiViewProvider,
|
|
wallpaperBackgroundNode: wallpaperBackgroundNode,
|
|
completion: completion,
|
|
sendMessage: sendMessage,
|
|
schedule: schedule,
|
|
editPrice: editPrice,
|
|
openPremiumPaywall: openPremiumPaywall,
|
|
reactionItems: reactionItems,
|
|
availableMessageEffects: availableMessageEffects,
|
|
isPremium: isPremium,
|
|
richTextPreview: richTextPreview
|
|
)
|
|
}
|