Refactoring

This commit is contained in:
Ali 2023-10-02 19:04:00 +04:00
parent 8b7ca5f4f7
commit 3f6d4678f5
61 changed files with 785 additions and 516 deletions

View file

@ -341,6 +341,11 @@ swift_library(
"//submodules/TelegramUI/Components/Chat/ForwardAccessoryPanelNode",
"//submodules/TelegramUI/Components/LegacyMessageInputPanel",
"//submodules/TelegramUI/Components/Chat/ChatMessageDateAndStatusNode",
"//submodules/TelegramUI/Components/Chat/ChatMessageBubbleContentNode",
"//submodules/TelegramUI/Components/Chat/ChatHistoryEntry",
"//submodules/TelegramUI/Components/Chat/ChatMessageItemCommon",
"//submodules/TelegramUI/Components/Chat/ChatMessageTextBubbleContentNode",
"//submodules/TelegramUI/Components/Chat/EditableTokenListNode",
] + select({
"@build_bazel_rules_apple//apple:ios_arm64": appcenter_targets,
"//build-system:ios_sim_arm64": [],

View file

@ -0,0 +1,23 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
swift_library(
name = "ChatHistoryEntry",
module_name = "ChatHistoryEntry",
srcs = glob([
"Sources/**/*.swift",
]),
copts = [
"-warnings-as-errors",
],
deps = [
"//submodules/Postbox",
"//submodules/TelegramCore",
"//submodules/TelegramPresentationData",
"//submodules/MergeLists",
"//submodules/TemporaryCachedPeerDataManager",
"//submodules/AccountContext",
],
visibility = [
"//visibility:public",
],
)

View file

@ -12,15 +12,15 @@ public enum ChatMessageEntryContentType {
}
public struct ChatMessageEntryAttributes: Equatable {
var rank: CachedChannelAdminRank?
var isContact: Bool
var contentTypeHint: ChatMessageEntryContentType
var updatingMedia: ChatUpdatingMessageMedia?
var isPlaying: Bool
var isCentered: Bool
var authorStoryStats: PeerStoryStats?
public var rank: CachedChannelAdminRank?
public var isContact: Bool
public var contentTypeHint: ChatMessageEntryContentType
public var updatingMedia: ChatUpdatingMessageMedia?
public var isPlaying: Bool
public var isCentered: Bool
public var authorStoryStats: PeerStoryStats?
init(rank: CachedChannelAdminRank?, isContact: Bool, contentTypeHint: ChatMessageEntryContentType, updatingMedia: ChatUpdatingMessageMedia?, isPlaying: Bool, isCentered: Bool, authorStoryStats: PeerStoryStats?) {
public init(rank: CachedChannelAdminRank?, isContact: Bool, contentTypeHint: ChatMessageEntryContentType, updatingMedia: ChatUpdatingMessageMedia?, isPlaying: Bool, isCentered: Bool, authorStoryStats: PeerStoryStats?) {
self.rank = rank
self.isContact = isContact
self.contentTypeHint = contentTypeHint
@ -41,7 +41,7 @@ public struct ChatMessageEntryAttributes: Equatable {
}
}
enum ChatHistoryEntry: Identifiable, Comparable {
public enum ChatHistoryEntry: Identifiable, Comparable {
case MessageEntry(Message, ChatPresentationData, Bool, MessageHistoryEntryLocation?, ChatHistoryMessageSelection, ChatMessageEntryAttributes)
case MessageGroupEntry(MessageGroupInfo, [(Message, Bool, ChatHistoryMessageSelection, ChatMessageEntryAttributes, MessageHistoryEntryLocation?)], ChatPresentationData)
case UnreadEntry(MessageIndex, ChatPresentationData)
@ -49,7 +49,7 @@ enum ChatHistoryEntry: Identifiable, Comparable {
case ChatInfoEntry(String, String, TelegramMediaImage?, TelegramMediaFile?, ChatPresentationData)
case SearchEntry(PresentationTheme, PresentationStrings)
var stableId: UInt64 {
public var stableId: UInt64 {
switch self {
case let .MessageEntry(message, _, _, _, _, attributes):
let type: UInt64
@ -75,7 +75,7 @@ enum ChatHistoryEntry: Identifiable, Comparable {
}
}
var index: MessageIndex {
public var index: MessageIndex {
switch self {
case let .MessageEntry(message, _, _, _, _, _):
return message.index
@ -92,7 +92,7 @@ enum ChatHistoryEntry: Identifiable, Comparable {
}
}
var firstIndex: MessageIndex {
public var firstIndex: MessageIndex {
switch self {
case let .MessageEntry(message, _, _, _, _, _):
return message.index
@ -109,7 +109,7 @@ enum ChatHistoryEntry: Identifiable, Comparable {
}
}
static func ==(lhs: ChatHistoryEntry, rhs: ChatHistoryEntry) -> Bool {
public static func ==(lhs: ChatHistoryEntry, rhs: ChatHistoryEntry) -> Bool {
switch lhs {
case let .MessageEntry(lhsMessage, lhsPresentationData, lhsRead, _, lhsSelection, lhsAttributes):
switch rhs {
@ -264,7 +264,7 @@ enum ChatHistoryEntry: Identifiable, Comparable {
}
}
static func <(lhs: ChatHistoryEntry, rhs: ChatHistoryEntry) -> Bool {
public static func <(lhs: ChatHistoryEntry, rhs: ChatHistoryEntry) -> Bool {
let lhsIndex = lhs.index
let rhsIndex = rhs.index
if lhsIndex == rhsIndex {

View file

@ -0,0 +1,28 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
swift_library(
name = "ChatMessageBubbleContentNode",
module_name = "ChatMessageBubbleContentNode",
srcs = glob([
"Sources/**/*.swift",
]),
copts = [
"-warnings-as-errors",
],
deps = [
"//submodules/AsyncDisplayKit",
"//submodules/Display",
"//submodules/Postbox",
"//submodules/TelegramCore",
"//submodules/TelegramUIPreferences",
"//submodules/TelegramPresentationData",
"//submodules/AccountContext",
"//submodules/ChatMessageBackground",
"//submodules/TelegramUI/Components/ChatControllerInteraction",
"//submodules/TelegramUI/Components/Chat/ChatHistoryEntry",
"//submodules/TelegramUI/Components/Chat/ChatMessageItemCommon",
],
visibility = [
"//visibility:public",
],
)

View file

@ -0,0 +1,269 @@
import Foundation
import UIKit
import AsyncDisplayKit
import Display
import Postbox
import TelegramCore
import TelegramUIPreferences
import TelegramPresentationData
import AccountContext
import ChatMessageBackground
import ChatControllerInteraction
import ChatHistoryEntry
import ChatMessageItemCommon
public enum ChatMessageBubbleContentBackgroundHiding {
case never
case emptyWallpaper
case always
}
public enum ChatMessageBubbleContentAlignment {
case none
case center
}
public struct ChatMessageBubbleContentProperties {
public let hidesSimpleAuthorHeader: Bool
public let headerSpacing: CGFloat
public let hidesBackground: ChatMessageBubbleContentBackgroundHiding
public let forceFullCorners: Bool
public let forceAlignment: ChatMessageBubbleContentAlignment
public let shareButtonOffset: CGPoint?
public let hidesHeaders: Bool
public let avatarOffset: CGFloat?
public init(
hidesSimpleAuthorHeader: Bool,
headerSpacing: CGFloat,
hidesBackground: ChatMessageBubbleContentBackgroundHiding,
forceFullCorners: Bool,
forceAlignment: ChatMessageBubbleContentAlignment,
shareButtonOffset: CGPoint? = nil,
hidesHeaders: Bool = false,
avatarOffset: CGFloat? = nil
) {
self.hidesSimpleAuthorHeader = hidesSimpleAuthorHeader
self.headerSpacing = headerSpacing
self.hidesBackground = hidesBackground
self.forceFullCorners = forceFullCorners
self.forceAlignment = forceAlignment
self.shareButtonOffset = shareButtonOffset
self.hidesHeaders = hidesHeaders
self.avatarOffset = avatarOffset
}
}
public enum ChatMessageBubbleNoneMergeStatus {
case Incoming
case Outgoing
case None
}
public enum ChatMessageBubbleMergeStatus {
case None(ChatMessageBubbleNoneMergeStatus)
case Left
case Right
case Both
}
public enum ChatMessageBubbleRelativePosition {
public enum NeighbourType {
case media
case freeform
}
public enum NeighbourSpacing {
case `default`
case condensed
case overlap(CGFloat)
}
case None(ChatMessageBubbleMergeStatus)
case BubbleNeighbour
case Neighbour(Bool, NeighbourType, NeighbourSpacing)
}
public enum ChatMessageBubbleContentMosaicNeighbor {
case merged
case mergedBubble
case none(tail: Bool)
}
public struct ChatMessageBubbleContentMosaicPosition {
public let topLeft: ChatMessageBubbleContentMosaicNeighbor
public let topRight: ChatMessageBubbleContentMosaicNeighbor
public let bottomLeft: ChatMessageBubbleContentMosaicNeighbor
public let bottomRight: ChatMessageBubbleContentMosaicNeighbor
public init(topLeft: ChatMessageBubbleContentMosaicNeighbor, topRight: ChatMessageBubbleContentMosaicNeighbor, bottomLeft: ChatMessageBubbleContentMosaicNeighbor, bottomRight: ChatMessageBubbleContentMosaicNeighbor) {
self.topLeft = topLeft
self.topRight = topRight
self.bottomLeft = bottomLeft
self.bottomRight = bottomRight
}
}
public enum ChatMessageBubbleContentPosition {
case linear(top: ChatMessageBubbleRelativePosition, bottom: ChatMessageBubbleRelativePosition)
case mosaic(position: ChatMessageBubbleContentMosaicPosition, wide: Bool)
}
public enum ChatMessageBubblePreparePosition {
case linear(top: ChatMessageBubbleRelativePosition, bottom: ChatMessageBubbleRelativePosition)
case mosaic(top: ChatMessageBubbleRelativePosition, bottom: ChatMessageBubbleRelativePosition)
}
public enum ChatMessageBubbleContentTapAction {
case none
case url(url: String, concealed: Bool)
case textMention(String)
case peerMention(peerId: PeerId, mention: String, openProfile: Bool)
case botCommand(String)
case hashtag(String?, String)
case instantPage
case wallpaper
case theme
case call(peerId: PeerId, isVideo: Bool)
case openMessage
case timecode(Double, String)
case tooltip(String, ASDisplayNode?, CGRect?)
case bankCard(String)
case ignore
case openPollResults(Data)
case copy(String)
case largeEmoji(String, String?, TelegramMediaFile)
case customEmoji(TelegramMediaFile)
}
public final class ChatMessageBubbleContentItem {
public let context: AccountContext
public let controllerInteraction: ChatControllerInteraction
public let message: Message
public let topMessage: Message
public let read: Bool
public let chatLocation: ChatLocation
public let presentationData: ChatPresentationData
public let associatedData: ChatMessageItemAssociatedData
public let attributes: ChatMessageEntryAttributes
public let isItemPinned: Bool
public let isItemEdited: Bool
public init(context: AccountContext, controllerInteraction: ChatControllerInteraction, message: Message, topMessage: Message, read: Bool, chatLocation: ChatLocation, presentationData: ChatPresentationData, associatedData: ChatMessageItemAssociatedData, attributes: ChatMessageEntryAttributes, isItemPinned: Bool, isItemEdited: Bool) {
self.context = context
self.controllerInteraction = controllerInteraction
self.message = message
self.topMessage = topMessage
self.read = read
self.chatLocation = chatLocation
self.presentationData = presentationData
self.associatedData = associatedData
self.attributes = attributes
self.isItemPinned = isItemPinned
self.isItemEdited = isItemEdited
}
}
open class ChatMessageBubbleContentNode: ASDisplayNode {
open var supportsMosaic: Bool {
return false
}
public weak var bubbleBackgroundNode: ChatMessageBackground?
public weak var bubbleBackdropNode: ChatMessageBubbleBackdrop?
open var visibility: ListViewItemNodeVisibility = .none
public var item: ChatMessageBubbleContentItem?
public var updateIsTextSelectionActive: ((Bool) -> Void)?
open var disablesClipping: Bool {
return false
}
required public override init() {
super.init()
}
open func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize, _ avatarInset: CGFloat) -> (ChatMessageBubbleContentProperties, unboundSize: CGSize?, maxWidth: CGFloat, layout: (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
preconditionFailure()
}
open func animateInsertion(_ currentTimestamp: Double, duration: Double) {
}
open func animateAdded(_ currentTimestamp: Double, duration: Double) {
}
open func animateRemoved(_ currentTimestamp: Double, duration: Double) {
}
open func animateInsertionIntoBubble(_ duration: Double) {
}
open func animateRemovalFromBubble(_ duration: Double, completion: @escaping () -> Void) {
self.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.25, removeOnCompletion: false, completion: { _ in
completion()
})
}
open func transitionNode(messageId: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
return nil
}
open func updateHiddenMedia(_ media: [Media]?) -> Bool {
return false
}
open func updateSearchTextHighlightState(text: String?, messages: [MessageIndex]?) {
}
open func updateAutomaticMediaDownloadSettings(_ settings: MediaAutoDownloadSettings) {
}
open func playMediaWithSound() -> ((Double?) -> Void, Bool, Bool, Bool, ASDisplayNode?)? {
return nil
}
open func tapActionAtPoint(_ point: CGPoint, gesture: TapLongTapOrDoubleTapGesture, isEstimating: Bool) -> ChatMessageBubbleContentTapAction {
return .none
}
open func updateTouchesAtPoint(_ point: CGPoint?) {
}
open func updateHighlightedState(animated: Bool) -> Bool {
return false
}
open func willUpdateIsExtractedToContextPreview(_ value: Bool) {
}
open func updateIsExtractedToContextPreview(_ value: Bool) {
}
open func updateAbsoluteRect(_ rect: CGRect, within containerSize: CGSize) {
}
open func applyAbsoluteOffset(value: CGPoint, animationCurve: ContainedViewLayoutTransitionCurve, duration: Double) {
}
open func applyAbsoluteOffsetSpring(value: CGFloat, duration: Double, damping: CGFloat) {
}
open func unreadMessageRangeUpdated() {
}
open func reactionTargetView(value: MessageReaction.Reaction) -> UIView? {
return nil
}
open func targetForStoryTransition(id: StoryId) -> UIView? {
return nil
}
open func getStatusNode() -> ASDisplayNode? {
return nil
}
}

View file

@ -15,9 +15,12 @@ swift_library(
"//submodules/TelegramCore",
"//submodules/Display",
"//submodules/SSignalKit/SwiftSignalKit",
"//submodules/TelegramUIPreferences",
"//submodules/TelegramPresentationData",
"//submodules/AccountContext",
"//submodules/AppBundle",
"//submodules/TelegramStringFormatting",
"//submodules/LocalizedPeerData",
"//submodules/Components/ReactionButtonListComponent",
"//submodules/Components/ReactionImageComponent",
"//submodules/TelegramUI/Components/AnimationCache",

View file

@ -7,7 +7,7 @@ import TelegramStringFormatting
import LocalizedPeerData
import AccountContext
enum MessageTimestampStatusFormat {
public enum MessageTimestampStatusFormat {
case regular
case minimal
}
@ -29,7 +29,7 @@ private func dateStringForDay(strings: PresentationStrings, dateTimeFormat: Pres
}
}
func stringForMessageTimestampStatus(accountPeerId: PeerId, message: Message, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, strings: PresentationStrings, format: MessageTimestampStatusFormat = .regular, associatedData: ChatMessageItemAssociatedData) -> String {
public func stringForMessageTimestampStatus(accountPeerId: PeerId, message: Message, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, strings: PresentationStrings, format: MessageTimestampStatusFormat = .regular, associatedData: ChatMessageItemAssociatedData) -> String {
if let adAttribute = message.adAttribute {
switch adAttribute.messageType {
case .sponsored:

View file

@ -0,0 +1,21 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
swift_library(
name = "ChatMessageItemCommon",
module_name = "ChatMessageItemCommon",
srcs = glob([
"Sources/**/*.swift",
]),
copts = [
"-warnings-as-errors",
],
deps = [
"//submodules/Display",
"//submodules/Postbox",
"//submodules/TelegramCore",
],
visibility = [
"//visibility:public",
],
)

View file

@ -0,0 +1,192 @@
import Foundation
import UIKit
import Display
import Postbox
import TelegramCore
public struct ChatMessageItemWidthFill {
public var compactInset: CGFloat
public var compactWidthBoundary: CGFloat
public var freeMaximumFillFactor: CGFloat
public func widthFor(_ width: CGFloat) -> CGFloat {
if width <= self.compactWidthBoundary {
return max(1.0, width - self.compactInset)
} else {
return max(1.0, floor(width * self.freeMaximumFillFactor))
}
}
}
public struct ChatMessageItemBubbleLayoutConstants {
public var edgeInset: CGFloat
public var defaultSpacing: CGFloat
public var mergedSpacing: CGFloat
public var maximumWidthFill: ChatMessageItemWidthFill
public var minimumSize: CGSize
public var contentInsets: UIEdgeInsets
public var borderInset: CGFloat
public var strokeInsets: UIEdgeInsets
public init(edgeInset: CGFloat, defaultSpacing: CGFloat, mergedSpacing: CGFloat, maximumWidthFill: ChatMessageItemWidthFill, minimumSize: CGSize, contentInsets: UIEdgeInsets, borderInset: CGFloat, strokeInsets: UIEdgeInsets) {
self.edgeInset = edgeInset
self.defaultSpacing = defaultSpacing
self.mergedSpacing = mergedSpacing
self.maximumWidthFill = maximumWidthFill
self.minimumSize = minimumSize
self.contentInsets = contentInsets
self.borderInset = borderInset
self.strokeInsets = strokeInsets
}
}
public struct ChatMessageItemTextLayoutConstants {
public var bubbleInsets: UIEdgeInsets
public init(bubbleInsets: UIEdgeInsets) {
self.bubbleInsets = bubbleInsets
}
}
public struct ChatMessageItemImageLayoutConstants {
public var bubbleInsets: UIEdgeInsets
public var statusInsets: UIEdgeInsets
public var defaultCornerRadius: CGFloat
public var mergedCornerRadius: CGFloat
public var contentMergedCornerRadius: CGFloat
public var maxDimensions: CGSize
public var minDimensions: CGSize
public init(bubbleInsets: UIEdgeInsets, statusInsets: UIEdgeInsets, defaultCornerRadius: CGFloat, mergedCornerRadius: CGFloat, contentMergedCornerRadius: CGFloat, maxDimensions: CGSize, minDimensions: CGSize) {
self.bubbleInsets = bubbleInsets
self.statusInsets = statusInsets
self.defaultCornerRadius = defaultCornerRadius
self.mergedCornerRadius = mergedCornerRadius
self.contentMergedCornerRadius = contentMergedCornerRadius
self.maxDimensions = maxDimensions
self.minDimensions = minDimensions
}
}
public struct ChatMessageItemVideoLayoutConstants {
public var maxHorizontalHeight: CGFloat
public var maxVerticalHeight: CGFloat
public init(maxHorizontalHeight: CGFloat, maxVerticalHeight: CGFloat) {
self.maxHorizontalHeight = maxHorizontalHeight
self.maxVerticalHeight = maxVerticalHeight
}
}
public struct ChatMessageItemInstantVideoConstants {
public var insets: UIEdgeInsets
public var dimensions: CGSize
public init(insets: UIEdgeInsets, dimensions: CGSize) {
self.insets = insets
self.dimensions = dimensions
}
}
public struct ChatMessageItemFileLayoutConstants {
public var bubbleInsets: UIEdgeInsets
public init(bubbleInsets: UIEdgeInsets) {
self.bubbleInsets = bubbleInsets
}
}
public struct ChatMessageItemWallpaperLayoutConstants {
public var maxTextWidth: CGFloat
public init(maxTextWidth: CGFloat) {
self.maxTextWidth = maxTextWidth
}
}
public struct ChatMessageItemLayoutConstants {
public var avatarDiameter: CGFloat
public var timestampHeaderHeight: CGFloat
public var bubble: ChatMessageItemBubbleLayoutConstants
public var image: ChatMessageItemImageLayoutConstants
public var video: ChatMessageItemVideoLayoutConstants
public var text: ChatMessageItemTextLayoutConstants
public var file: ChatMessageItemFileLayoutConstants
public var instantVideo: ChatMessageItemInstantVideoConstants
public var wallpapers: ChatMessageItemWallpaperLayoutConstants
public init(avatarDiameter: CGFloat, timestampHeaderHeight: CGFloat, bubble: ChatMessageItemBubbleLayoutConstants, image: ChatMessageItemImageLayoutConstants, video: ChatMessageItemVideoLayoutConstants, text: ChatMessageItemTextLayoutConstants, file: ChatMessageItemFileLayoutConstants, instantVideo: ChatMessageItemInstantVideoConstants, wallpapers: ChatMessageItemWallpaperLayoutConstants) {
self.avatarDiameter = avatarDiameter
self.timestampHeaderHeight = timestampHeaderHeight
self.bubble = bubble
self.image = image
self.video = video
self.text = text
self.file = file
self.instantVideo = instantVideo
self.wallpapers = wallpapers
}
public static var `default`: ChatMessageItemLayoutConstants {
return self.compact
}
public static var compact: ChatMessageItemLayoutConstants {
let bubble = ChatMessageItemBubbleLayoutConstants(edgeInset: 4.0, defaultSpacing: 2.0 + UIScreenPixel, mergedSpacing: 0.0, maximumWidthFill: ChatMessageItemWidthFill(compactInset: 36.0, compactWidthBoundary: 500.0, freeMaximumFillFactor: 0.85), minimumSize: CGSize(width: 40.0, height: 35.0), contentInsets: UIEdgeInsets(top: 0.0, left: 6.0, bottom: 0.0, right: 0.0), borderInset: UIScreenPixel, strokeInsets: UIEdgeInsets(top: 1.0, left: 1.0, bottom: 1.0, right: 1.0))
let text = ChatMessageItemTextLayoutConstants(bubbleInsets: UIEdgeInsets(top: 6.0 + UIScreenPixel, left: 12.0, bottom: 6.0 - UIScreenPixel, right: 12.0))
let image = ChatMessageItemImageLayoutConstants(bubbleInsets: UIEdgeInsets(top: 2.0, left: 2.0, bottom: 2.0, right: 2.0), statusInsets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 6.0, right: 6.0), defaultCornerRadius: 16.0, mergedCornerRadius: 8.0, contentMergedCornerRadius: 0.0, maxDimensions: CGSize(width: 300.0, height: 380.0), minDimensions: CGSize(width: 170.0, height: 74.0))
let video = ChatMessageItemVideoLayoutConstants(maxHorizontalHeight: 250.0, maxVerticalHeight: 360.0)
let file = ChatMessageItemFileLayoutConstants(bubbleInsets: UIEdgeInsets(top: 15.0, left: 9.0, bottom: 15.0, right: 12.0))
let instantVideo = ChatMessageItemInstantVideoConstants(insets: UIEdgeInsets(top: 4.0, left: 0.0, bottom: 4.0, right: 0.0), dimensions: CGSize(width: 212.0, height: 212.0))
let wallpapers = ChatMessageItemWallpaperLayoutConstants(maxTextWidth: 180.0)
return ChatMessageItemLayoutConstants(avatarDiameter: 37.0, timestampHeaderHeight: 34.0, bubble: bubble, image: image, video: video, text: text, file: file, instantVideo: instantVideo, wallpapers: wallpapers)
}
public static var regular: ChatMessageItemLayoutConstants {
let bubble = ChatMessageItemBubbleLayoutConstants(edgeInset: 4.0, defaultSpacing: 2.0 + UIScreenPixel, mergedSpacing: 0.0, maximumWidthFill: ChatMessageItemWidthFill(compactInset: 36.0, compactWidthBoundary: 500.0, freeMaximumFillFactor: 0.65), minimumSize: CGSize(width: 40.0, height: 35.0), contentInsets: UIEdgeInsets(top: 0.0, left: 6.0, bottom: 0.0, right: 0.0), borderInset: UIScreenPixel, strokeInsets: UIEdgeInsets(top: 1.0, left: 1.0, bottom: 1.0, right: 1.0))
let text = ChatMessageItemTextLayoutConstants(bubbleInsets: UIEdgeInsets(top: 6.0 + UIScreenPixel, left: 12.0, bottom: 6.0 - UIScreenPixel, right: 12.0))
let image = ChatMessageItemImageLayoutConstants(bubbleInsets: UIEdgeInsets(top: 2.0, left: 2.0, bottom: 2.0, right: 2.0), statusInsets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 6.0, right: 6.0), defaultCornerRadius: 16.0, mergedCornerRadius: 8.0, contentMergedCornerRadius: 5.0, maxDimensions: CGSize(width: 440.0, height: 440.0), minDimensions: CGSize(width: 170.0, height: 74.0))
let video = ChatMessageItemVideoLayoutConstants(maxHorizontalHeight: 250.0, maxVerticalHeight: 360.0)
let file = ChatMessageItemFileLayoutConstants(bubbleInsets: UIEdgeInsets(top: 15.0, left: 9.0, bottom: 15.0, right: 12.0))
let instantVideo = ChatMessageItemInstantVideoConstants(insets: UIEdgeInsets(top: 4.0, left: 0.0, bottom: 4.0, right: 0.0), dimensions: CGSize(width: 240.0, height: 240.0))
let wallpapers = ChatMessageItemWallpaperLayoutConstants(maxTextWidth: 180.0)
return ChatMessageItemLayoutConstants(avatarDiameter: 37.0, timestampHeaderHeight: 34.0, bubble: bubble, image: image, video: video, text: text, file: file, instantVideo: instantVideo, wallpapers: wallpapers)
}
}
public func canViewMessageReactionList(message: Message) -> Bool {
var found = false
var canViewList = false
for attribute in message.attributes {
if let attribute = attribute as? ReactionsMessageAttribute {
canViewList = attribute.canViewList
found = true
break
}
}
if !found {
return false
}
if let peer = message.peers[message.id.peerId] {
if let channel = peer as? TelegramChannel {
if case .broadcast = channel.info {
return false
} else {
return canViewList
}
} else if let _ = peer as? TelegramGroup {
return canViewList
} else if let _ = peer as? TelegramUser {
return true
} else {
return false
}
} else {
return false
}
}

View file

@ -0,0 +1,41 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
swift_library(
name = "ChatMessageTextBubbleContentNode",
module_name = "ChatMessageTextBubbleContentNode",
srcs = glob([
"Sources/**/*.swift",
]),
copts = [
"-warnings-as-errors",
],
deps = [
"//submodules/AsyncDisplayKit",
"//submodules/Display",
"//submodules/TelegramCore",
"//submodules/Postbox",
"//submodules/TextFormat",
"//submodules/UrlEscaping",
"//submodules/TelegramUniversalVideoContent",
"//submodules/TextSelectionNode",
"//submodules/InvisibleInkDustNode",
"//submodules/Emoji",
"//submodules/AnimatedStickerNode",
"//submodules/TelegramAnimatedStickerNode",
"//submodules/SSignalKit/SwiftSignalKit",
"//submodules/AccountContext",
"//submodules/YuvConversion",
"//submodules/TelegramUI/Components/AnimationCache",
"//submodules/TelegramUI/Components/LottieAnimationCache",
"//submodules/TelegramUI/Components/MultiAnimationRenderer",
"//submodules/TelegramUI/Components/EmojiTextAttachmentView",
"//submodules/TelegramUI/Components/TextNodeWithEntities",
"//submodules/TelegramUI/Components/Chat/ChatMessageDateAndStatusNode",
"//submodules/TelegramUI/Components/Chat/ChatMessageBubbleContentNode",
"//submodules/TelegramUI/Components/Chat/ShimmeringLinkNode",
"//submodules/TelegramUI/Components/Chat/ChatMessageItemCommon",
],
visibility = [
"//visibility:public",
],
)

View file

@ -21,6 +21,9 @@ import MultiAnimationRenderer
import EmojiTextAttachmentView
import TextNodeWithEntities
import ChatMessageDateAndStatusNode
import ChatMessageBubbleContentNode
import ShimmeringLinkNode
import ChatMessageItemCommon
private final class CachedChatMessageText {
let text: String
@ -48,7 +51,7 @@ private final class CachedChatMessageText {
}
}
class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
public class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
private let textNode: TextNodeWithEntities
private var spoilerTextNode: TextNodeWithEntities?
private var dustNode: InvisibleInkDustNode?
@ -63,7 +66,7 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
private var cachedChatMessageText: CachedChatMessageText?
override var visibility: ListViewItemNodeVisibility {
override public var visibility: ListViewItemNodeVisibility {
didSet {
if oldValue != self.visibility {
switch self.visibility {
@ -81,7 +84,7 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
}
}
required init() {
required public init() {
self.textNode = TextNodeWithEntities()
self.statusNode = ChatMessageDateAndStatusNode()
@ -118,11 +121,11 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
}
}
required init?(coder aDecoder: NSCoder) {
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize, _ avatarInset: CGFloat) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
override public func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize, _ avatarInset: CGFloat) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
let textLayout = TextNodeWithEntities.asyncLayout(self.textNode)
let spoilerTextLayout = TextNodeWithEntities.asyncLayout(self.spoilerTextNode)
let statusLayout = self.statusNode.asyncLayout()
@ -566,22 +569,22 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
}
}
override func animateInsertion(_ currentTimestamp: Double, duration: Double) {
override public func animateInsertion(_ currentTimestamp: Double, duration: Double) {
self.textNode.textNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
self.statusNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
}
override func animateAdded(_ currentTimestamp: Double, duration: Double) {
override public func animateAdded(_ currentTimestamp: Double, duration: Double) {
self.textNode.textNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
self.statusNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
}
override func animateRemoved(_ currentTimestamp: Double, duration: Double) {
override public func animateRemoved(_ currentTimestamp: Double, duration: Double) {
self.textNode.textNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false)
self.statusNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false)
}
override func tapActionAtPoint(_ point: CGPoint, gesture: TapLongTapOrDoubleTapGesture, isEstimating: Bool) -> ChatMessageBubbleContentTapAction {
override public func tapActionAtPoint(_ point: CGPoint, gesture: TapLongTapOrDoubleTapGesture, isEstimating: Bool) -> ChatMessageBubbleContentTapAction {
let textNodeFrame = self.textNode.textNode.frame
if let (index, attributes) = self.textNode.textNode.attributesAtPoint(CGPoint(x: point.x - textNodeFrame.minX, y: point.y - textNodeFrame.minY)) {
if let _ = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.Spoiler)], !(self.dustNode?.isRevealed ?? true) {
@ -635,7 +638,7 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
}
}
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
if self.statusNode.supernode != nil, let result = self.statusNode.hitTest(self.view.convert(point, to: self.statusNode.view), with: event) {
return result
}
@ -668,7 +671,7 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
})
}
}
override func updateTouchesAtPoint(_ point: CGPoint?) {
override public func updateTouchesAtPoint(_ point: CGPoint?) {
if let item = self.item {
var rects: [CGRect]?
var spoilerRects: [CGRect]?
@ -718,29 +721,7 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
}
}
override func peekPreviewContent(at point: CGPoint) -> (Message, ChatMessagePeekPreviewContent)? {
if let item = self.item {
let textNodeFrame = self.textNode.textNode.frame
if let (index, attributes) = self.textNode.textNode.attributesAtPoint(CGPoint(x: point.x - textNodeFrame.minX, y: point.y - textNodeFrame.minY)) {
if let value = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)] as? String {
if let rects = self.textNode.textNode.attributeRects(name: TelegramTextAttributes.URL, at: index), !rects.isEmpty {
var rect = rects[0]
for i in 1 ..< rects.count {
rect = rect.union(rects[i])
}
var concealed = true
if let (attributeText, fullText) = self.textNode.textNode.attributeSubstring(name: TelegramTextAttributes.URL, index: index) {
concealed = !doesUrlMatchText(url: value, text: attributeText, fullText: fullText)
}
return (item.message, .url(self, rect, value, concealed))
}
}
}
}
return nil
}
override func updateSearchTextHighlightState(text: String?, messages: [MessageIndex]?) {
override public func updateSearchTextHighlightState(text: String?, messages: [MessageIndex]?) {
guard let item = self.item else {
return
}
@ -769,7 +750,7 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
}
}
override func willUpdateIsExtractedToContextPreview(_ value: Bool) {
override public func willUpdateIsExtractedToContextPreview(_ value: Bool) {
if !value {
if let textSelectionNode = self.textSelectionNode {
self.textSelectionNode = nil
@ -782,7 +763,7 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
}
}
override func updateIsExtractedToContextPreview(_ value: Bool) {
override public func updateIsExtractedToContextPreview(_ value: Bool) {
if value {
if self.textSelectionNode == nil, let item = self.item, !item.associatedData.isCopyProtectionEnabled && !item.message.isCopyProtected(), let rootNode = item.controllerInteraction.chatControllerNode() {
let selectionColor: UIColor
@ -840,18 +821,18 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
}
}
override func reactionTargetView(value: MessageReaction.Reaction) -> UIView? {
override public func reactionTargetView(value: MessageReaction.Reaction) -> UIView? {
if !self.statusNode.isHidden {
return self.statusNode.reactionView(value: value)
}
return nil
}
override func getStatusNode() -> ASDisplayNode? {
override public func getStatusNode() -> ASDisplayNode? {
return self.statusNode
}
func animateFrom(sourceView: UIView, scrollOffset: CGFloat, widthDifference: CGFloat, transition: CombinedTransition) {
public func animateFrom(sourceView: UIView, scrollOffset: CGFloat, widthDifference: CGFloat, transition: CombinedTransition) {
self.view.addSubview(sourceView)
sourceView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.1, removeOnCompletion: false, completion: { [weak sourceView] _ in

View file

@ -0,0 +1,23 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
swift_library(
name = "EditableTokenListNode",
module_name = "EditableTokenListNode",
srcs = glob([
"Sources/**/*.swift",
]),
copts = [
"-warnings-as-errors",
],
deps = [
"//submodules/AsyncDisplayKit",
"//submodules/Display",
"//submodules/TelegramCore",
"//submodules/TelegramPresentationData",
"//submodules/AvatarNode",
"//submodules/AccountContext",
],
visibility = [
"//visibility:public",
],
)

View file

@ -7,16 +7,23 @@ import TelegramPresentationData
import AvatarNode
import AccountContext
struct EditableTokenListToken {
enum Subject {
public struct EditableTokenListToken {
public enum Subject {
case peer(EnginePeer)
case category(UIImage?)
}
let id: AnyHashable
let title: String
let fixedPosition: Int?
let subject: Subject
public let id: AnyHashable
public let title: String
public let fixedPosition: Int?
public let subject: Subject
public init(id: AnyHashable, title: String, fixedPosition: Int?, subject: Subject) {
self.id = id
self.title = title
self.fixedPosition = fixedPosition
self.subject = subject
}
}
private let caretIndicatorImage = generateVerticallyStretchableFilledCircleImage(radius: 1.0, color: UIColor(rgb: 0x3350ee))
@ -54,18 +61,18 @@ private func generateRemoveIcon(_ color: UIColor) -> UIImage? {
})
}
final class EditableTokenListNodeTheme {
let backgroundColor: UIColor
let separatorColor: UIColor
let placeholderTextColor: UIColor
let primaryTextColor: UIColor
let tokenBackgroundColor: UIColor
let selectedTextColor: UIColor
let selectedBackgroundColor: UIColor
let accentColor: UIColor
let keyboardColor: PresentationThemeKeyboardColor
public final class EditableTokenListNodeTheme {
public let backgroundColor: UIColor
public let separatorColor: UIColor
public let placeholderTextColor: UIColor
public let primaryTextColor: UIColor
public let tokenBackgroundColor: UIColor
public let selectedTextColor: UIColor
public let selectedBackgroundColor: UIColor
public let accentColor: UIColor
public let keyboardColor: PresentationThemeKeyboardColor
init(backgroundColor: UIColor, separatorColor: UIColor, placeholderTextColor: UIColor, primaryTextColor: UIColor, tokenBackgroundColor: UIColor, selectedTextColor: UIColor, selectedBackgroundColor: UIColor, accentColor: UIColor, keyboardColor: PresentationThemeKeyboardColor) {
public init(backgroundColor: UIColor, separatorColor: UIColor, placeholderTextColor: UIColor, primaryTextColor: UIColor, tokenBackgroundColor: UIColor, selectedTextColor: UIColor, selectedBackgroundColor: UIColor, accentColor: UIColor, keyboardColor: PresentationThemeKeyboardColor) {
self.backgroundColor = backgroundColor
self.separatorColor = separatorColor
self.placeholderTextColor = placeholderTextColor
@ -245,7 +252,7 @@ private final class CaretIndicatorNode: ASImageNode {
}
}
final class EditableTokenListNode: ASDisplayNode, UITextFieldDelegate {
public final class EditableTokenListNode: ASDisplayNode, UITextFieldDelegate {
private let context: AccountContext
private let presentationTheme: PresentationTheme
@ -260,11 +267,11 @@ final class EditableTokenListNode: ASDisplayNode, UITextFieldDelegate {
private let caretIndicatorNode: CaretIndicatorNode
private var selectedTokenId: AnyHashable?
var textUpdated: ((String) -> Void)?
var deleteToken: ((AnyHashable) -> Void)?
var textReturned: (() -> Void)?
public var textUpdated: ((String) -> Void)?
public var deleteToken: ((AnyHashable) -> Void)?
public var textReturned: (() -> Void)?
init(context: AccountContext, presentationTheme: PresentationTheme, theme: EditableTokenListNodeTheme, placeholder: String) {
public init(context: AccountContext, presentationTheme: PresentationTheme, theme: EditableTokenListNodeTheme, placeholder: String) {
self.context = context
self.presentationTheme = presentationTheme
self.theme = theme
@ -326,7 +333,7 @@ final class EditableTokenListNode: ASDisplayNode, UITextFieldDelegate {
self.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:))))
}
func updateLayout(tokens: [EditableTokenListToken], width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, transition: ContainedViewLayoutTransition) -> CGFloat {
public func updateLayout(tokens: [EditableTokenListToken], width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, transition: ContainedViewLayoutTransition) -> CGFloat {
let validTokens = Set<AnyHashable>(tokens.map { $0.id })
for i in (0 ..< self.tokenNodes.count).reversed() {
@ -466,7 +473,7 @@ final class EditableTokenListNode: ASDisplayNode, UITextFieldDelegate {
return nodeHeight
}
@objc func textFieldChanged(_ textField: UITextField) {
@objc private func textFieldChanged(_ textField: UITextField) {
let text = textField.text ?? ""
self.placeholderNode.isHidden = !text.isEmpty
self.updateSelectedTokenId(nil)
@ -476,24 +483,24 @@ final class EditableTokenListNode: ASDisplayNode, UITextFieldDelegate {
}
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
public func textFieldShouldReturn(_ textField: UITextField) -> Bool {
self.textReturned?()
return false
}
func textFieldDidBeginEditing(_ textField: UITextField) {
public func textFieldDidBeginEditing(_ textField: UITextField) {
/*if self.caretIndicatorNode.supernode == self {
self.caretIndicatorNode.removeFromSupernode()
}*/
}
func textFieldDidEndEditing(_ textField: UITextField) {
public func textFieldDidEndEditing(_ textField: UITextField) {
/*if self.caretIndicatorNode.supernode != self.scrollNode {
self.scrollNode.addSubnode(self.caretIndicatorNode)
}*/
}
func setText(_ text: String) {
public func setText(_ text: String) {
self.textFieldNode.textField.text = text
self.textFieldChanged(self.textFieldNode.textField)
}

View file

@ -0,0 +1,20 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
swift_library(
name = "ShimmeringLinkNode",
module_name = "ShimmeringLinkNode",
srcs = glob([
"Sources/**/*.swift",
]),
copts = [
"-warnings-as-errors",
],
deps = [
"//submodules/AsyncDisplayKit",
"//submodules/Display",
"//submodules/ShimmerEffect",
],
visibility = [
"//visibility:public",
],
)

View file

@ -4,7 +4,7 @@ import AsyncDisplayKit
import Display
import ShimmerEffect
final class ShimmeringLinkNode: ASDisplayNode {
public final class ShimmeringLinkNode: ASDisplayNode {
private let shimmerEffectNode: ShimmerEffectForegroundNode
private let borderShimmerEffectNode: ShimmerEffectForegroundNode
@ -12,17 +12,17 @@ final class ShimmeringLinkNode: ASDisplayNode {
private let borderMaskNode: ASImageNode
private(set) var rects: [CGRect] = []
var color: UIColor {
public var color: UIColor {
didSet {
self.backgroundColor = color
}
}
var innerRadius: CGFloat = 4.0
var outerRadius: CGFloat = 4.0
var inset: CGFloat = 2.0
public var innerRadius: CGFloat = 4.0
public var outerRadius: CGFloat = 4.0
public var inset: CGFloat = 2.0
init(color: UIColor) {
public init(color: UIColor) {
self.color = color
self.shimmerEffectNode = ShimmerEffectForegroundNode()
@ -46,14 +46,14 @@ final class ShimmeringLinkNode: ASDisplayNode {
//self.addSubnode(self.borderShimmerEffectNode)
}
override func didLoad() {
override public func didLoad() {
super.didLoad()
self.shimmerEffectNode.layer.mask = self.maskNode.layer
self.borderShimmerEffectNode.layer.mask = self.borderMaskNode.layer
}
func updateRects(_ rects: [CGRect], color: UIColor? = nil) {
public func updateRects(_ rects: [CGRect], color: UIColor? = nil) {
var updated = false
if self.rects != rects {
updated = true
@ -86,7 +86,7 @@ final class ShimmeringLinkNode: ASDisplayNode {
}
}
func updateLayout(_ size: CGSize) {
public func updateLayout(_ size: CGSize) {
self.shimmerEffectNode.frame = CGRect(origin: .zero, size: size)
self.borderShimmerEffectNode.frame = CGRect(origin: .zero, size: size)

View file

@ -14,6 +14,7 @@ import UniversalMediaPlayer
import TelegramUniversalVideoContent
import WallpaperBackgroundNode
import ChatControllerInteraction
import ChatMessageBubbleContentNode
private let messageFont = Font.regular(17.0)
private let messageBoldFont = Font.semibold(17.0)

View file

@ -5,6 +5,7 @@ import TemporaryCachedPeerDataManager
import Emoji
import AccountContext
import TelegramPresentationData
import ChatHistoryEntry
func chatHistoryEntriesForView(
location: ChatLocation,

View file

@ -23,6 +23,7 @@ import ChatPresentationInterfaceState
import TelegramNotices
import ChatControllerInteraction
import TranslateUI
import ChatHistoryEntry
extension ChatReplyThreadMessage {
var effectiveTopId: MessageId {

View file

@ -5,6 +5,7 @@ import AsyncDisplayKit
import Display
import SwiftSignalKit
import TelegramPresentationData
import ChatMessageItemCommon
private let titleFont = UIFont.systemFont(ofSize: 13.0)

View file

@ -19,6 +19,8 @@ import GalleryUI
import WallpaperBackgroundNode
import InvisibleInkDustNode
import TextNodeWithEntities
import ChatMessageBubbleContentNode
import ChatMessageItemCommon
private func attributedServiceMessageString(theme: ChatPresentationThemeData, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, message: Message, accountPeerId: PeerId, forForumOverview: Bool) -> NSAttributedString? {
return universalServiceMessageString(presentationData: (theme.theme, theme.wallpaper), strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, message: EngineMessage(message), accountPeerId: accountPeerId, forChatList: false, forForumOverview: forForumOverview)

View file

@ -30,6 +30,8 @@ import TextNodeWithEntities
import ChatControllerInteraction
import ChatMessageForwardInfoNode
import ChatMessageDateAndStatusNode
import ChatMessageItemCommon
import ChatMessageBubbleContentNode
private let nameFont = Font.medium(14.0)
private let inlineBotPrefixFont = Font.regular(14.0)

View file

@ -20,6 +20,9 @@ import MultiAnimationRenderer
import ChatControllerInteraction
import ShimmerEffect
import ChatMessageDateAndStatusNode
import ChatHistoryEntry
import ChatMessageItemCommon
import ChatMessageBubbleContentNode
private let buttonFont = Font.semibold(13.0)

View file

@ -2,6 +2,8 @@ import Foundation
import UIKit
import Display
import TelegramPresentationData
import ChatMessageBubbleContentNode
import ChatMessageItemCommon
func chatMessageBubbleImageContentCorners(relativeContentPosition position: ChatMessageBubbleContentPosition, normalRadius: CGFloat, mergedRadius: CGFloat, mergedWithAnotherContentRadius: CGFloat, layoutConstants: ChatMessageItemLayoutConstants, chatPresentationData: ChatPresentationData) -> ImageCorners {
let topLeftCorner: ImageCorner

View file

@ -1,264 +0,0 @@
import Foundation
import UIKit
import AsyncDisplayKit
import Display
import Postbox
import TelegramCore
import TelegramUIPreferences
import TelegramPresentationData
import AccountContext
import ChatMessageBackground
import ChatControllerInteraction
enum ChatMessageBubbleContentBackgroundHiding {
case never
case emptyWallpaper
case always
}
enum ChatMessageBubbleContentAlignment {
case none
case center
}
struct ChatMessageBubbleContentProperties {
let hidesSimpleAuthorHeader: Bool
let headerSpacing: CGFloat
let hidesBackground: ChatMessageBubbleContentBackgroundHiding
let forceFullCorners: Bool
let forceAlignment: ChatMessageBubbleContentAlignment
let shareButtonOffset: CGPoint?
let hidesHeaders: Bool
let avatarOffset: CGFloat?
init(
hidesSimpleAuthorHeader: Bool,
headerSpacing: CGFloat,
hidesBackground: ChatMessageBubbleContentBackgroundHiding,
forceFullCorners: Bool,
forceAlignment: ChatMessageBubbleContentAlignment,
shareButtonOffset: CGPoint? = nil,
hidesHeaders: Bool = false,
avatarOffset: CGFloat? = nil
) {
self.hidesSimpleAuthorHeader = hidesSimpleAuthorHeader
self.headerSpacing = headerSpacing
self.hidesBackground = hidesBackground
self.forceFullCorners = forceFullCorners
self.forceAlignment = forceAlignment
self.shareButtonOffset = shareButtonOffset
self.hidesHeaders = hidesHeaders
self.avatarOffset = avatarOffset
}
}
enum ChatMessageBubbleNoneMergeStatus {
case Incoming
case Outgoing
case None
}
enum ChatMessageBubbleMergeStatus {
case None(ChatMessageBubbleNoneMergeStatus)
case Left
case Right
case Both
}
enum ChatMessageBubbleRelativePosition {
enum NeighbourType {
case media
case freeform
}
enum NeighbourSpacing {
case `default`
case condensed
case overlap(CGFloat)
}
case None(ChatMessageBubbleMergeStatus)
case BubbleNeighbour
case Neighbour(Bool, NeighbourType, NeighbourSpacing)
}
enum ChatMessageBubbleContentMosaicNeighbor {
case merged
case mergedBubble
case none(tail: Bool)
}
struct ChatMessageBubbleContentMosaicPosition {
let topLeft: ChatMessageBubbleContentMosaicNeighbor
let topRight: ChatMessageBubbleContentMosaicNeighbor
let bottomLeft: ChatMessageBubbleContentMosaicNeighbor
let bottomRight: ChatMessageBubbleContentMosaicNeighbor
}
enum ChatMessageBubbleContentPosition {
case linear(top: ChatMessageBubbleRelativePosition, bottom: ChatMessageBubbleRelativePosition)
case mosaic(position: ChatMessageBubbleContentMosaicPosition, wide: Bool)
}
enum ChatMessageBubblePreparePosition {
case linear(top: ChatMessageBubbleRelativePosition, bottom: ChatMessageBubbleRelativePosition)
case mosaic(top: ChatMessageBubbleRelativePosition, bottom: ChatMessageBubbleRelativePosition)
}
enum ChatMessageBubbleContentTapAction {
case none
case url(url: String, concealed: Bool)
case textMention(String)
case peerMention(peerId: PeerId, mention: String, openProfile: Bool)
case botCommand(String)
case hashtag(String?, String)
case instantPage
case wallpaper
case theme
case call(peerId: PeerId, isVideo: Bool)
case openMessage
case timecode(Double, String)
case tooltip(String, ASDisplayNode?, CGRect?)
case bankCard(String)
case ignore
case openPollResults(Data)
case copy(String)
case largeEmoji(String, String?, TelegramMediaFile)
case customEmoji(TelegramMediaFile)
}
final class ChatMessageBubbleContentItem {
let context: AccountContext
let controllerInteraction: ChatControllerInteraction
let message: Message
let topMessage: Message
let read: Bool
let chatLocation: ChatLocation
let presentationData: ChatPresentationData
let associatedData: ChatMessageItemAssociatedData
let attributes: ChatMessageEntryAttributes
let isItemPinned: Bool
let isItemEdited: Bool
init(context: AccountContext, controllerInteraction: ChatControllerInteraction, message: Message, topMessage: Message, read: Bool, chatLocation: ChatLocation, presentationData: ChatPresentationData, associatedData: ChatMessageItemAssociatedData, attributes: ChatMessageEntryAttributes, isItemPinned: Bool, isItemEdited: Bool) {
self.context = context
self.controllerInteraction = controllerInteraction
self.message = message
self.topMessage = topMessage
self.read = read
self.chatLocation = chatLocation
self.presentationData = presentationData
self.associatedData = associatedData
self.attributes = attributes
self.isItemPinned = isItemPinned
self.isItemEdited = isItemEdited
}
}
class ChatMessageBubbleContentNode: ASDisplayNode {
var supportsMosaic: Bool {
return false
}
weak var bubbleBackgroundNode: ChatMessageBackground?
weak var bubbleBackdropNode: ChatMessageBubbleBackdrop?
var visibility: ListViewItemNodeVisibility = .none
var item: ChatMessageBubbleContentItem?
var updateIsTextSelectionActive: ((Bool) -> Void)?
var disablesClipping: Bool {
return false
}
required override init() {
super.init()
}
func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize, _ avatarInset: CGFloat) -> (ChatMessageBubbleContentProperties, unboundSize: CGSize?, maxWidth: CGFloat, layout: (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
preconditionFailure()
}
func animateInsertion(_ currentTimestamp: Double, duration: Double) {
}
func animateAdded(_ currentTimestamp: Double, duration: Double) {
}
func animateRemoved(_ currentTimestamp: Double, duration: Double) {
}
func animateInsertionIntoBubble(_ duration: Double) {
}
func animateRemovalFromBubble(_ duration: Double, completion: @escaping () -> Void) {
self.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.25, removeOnCompletion: false, completion: { _ in
completion()
})
}
func transitionNode(messageId: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
return nil
}
func peekPreviewContent(at point: CGPoint) -> (Message, ChatMessagePeekPreviewContent)? {
return nil
}
func updateHiddenMedia(_ media: [Media]?) -> Bool {
return false
}
func updateSearchTextHighlightState(text: String?, messages: [MessageIndex]?) {
}
func updateAutomaticMediaDownloadSettings(_ settings: MediaAutoDownloadSettings) {
}
func playMediaWithSound() -> ((Double?) -> Void, Bool, Bool, Bool, ASDisplayNode?)? {
return nil
}
func tapActionAtPoint(_ point: CGPoint, gesture: TapLongTapOrDoubleTapGesture, isEstimating: Bool) -> ChatMessageBubbleContentTapAction {
return .none
}
func updateTouchesAtPoint(_ point: CGPoint?) {
}
func updateHighlightedState(animated: Bool) -> Bool {
return false
}
func willUpdateIsExtractedToContextPreview(_ value: Bool) {
}
func updateIsExtractedToContextPreview(_ value: Bool) {
}
func updateAbsoluteRect(_ rect: CGRect, within containerSize: CGSize) {
}
func applyAbsoluteOffset(value: CGPoint, animationCurve: ContainedViewLayoutTransitionCurve, duration: Double) {
}
func applyAbsoluteOffsetSpring(value: CGFloat, duration: Double, damping: CGFloat) {
}
func unreadMessageRangeUpdated() {
}
func reactionTargetView(value: MessageReaction.Reaction) -> UIView? {
return nil
}
func targetForStoryTransition(id: StoryId) -> UIView? {
return nil
}
func getStatusNode() -> ASDisplayNode? {
return nil
}
}

View file

@ -31,6 +31,10 @@ import EmojiStatusComponent
import ChatControllerInteraction
import ChatMessageForwardInfoNode
import ChatMessageDateAndStatusNode
import ChatMessageBubbleContentNode
import ChatHistoryEntry
import ChatMessageTextBubbleContentNode
import ChatMessageItemCommon
enum InternalBubbleTapAction {
case action(() -> Void)
@ -4157,16 +4161,6 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
return nil
}
override func peekPreviewContent(at point: CGPoint) -> (Message, ChatMessagePeekPreviewContent)? {
for contentNode in self.contentNodes {
let frame = contentNode.frame
if let result = contentNode.peekPreviewContent(at: point.offsetBy(dx: -frame.minX, dy: -frame.minY)) {
return result
}
}
return nil
}
override func updateHiddenMedia() {
var hasHiddenMosaicStatus = false
var hasHiddenBackground = false

View file

@ -6,6 +6,9 @@ import TelegramCore
import Postbox
import TelegramPresentationData
import AppBundle
import ChatMessageBubbleContentNode
import ChatMessageItemCommon
import ChatMessageDateAndStatusNode
private let titleFont: UIFont = Font.medium(16.0)
private let labelFont: UIFont = Font.regular(13.0)

View file

@ -9,6 +9,8 @@ import TelegramPresentationData
import RadialStatusNode
import AnimatedCountLabelNode
import AnimatedAvatarSetNode
import ChatMessageBubbleContentNode
import ChatMessageItemCommon
final class ChatMessageCommentFooterContentNode: ChatMessageBubbleContentNode {
private let separatorNode: ASDisplayNode

View file

@ -10,6 +10,8 @@ import AvatarNode
import AccountContext
import PhoneNumberFormat
import ChatMessageDateAndStatusNode
import ChatMessageBubbleContentNode
import ChatMessageItemCommon
private let avatarFont = avatarPlaceholderFont(size: 16.0)

View file

@ -5,6 +5,8 @@ import Display
import AsyncDisplayKit
import SwiftSignalKit
import TelegramCore
import ChatMessageBubbleContentNode
import ChatMessageItemCommon
final class ChatMessageEventLogPreviousDescriptionContentNode: ChatMessageBubbleContentNode {
private let contentNode: ChatMessageAttachedContentNode

View file

@ -5,6 +5,8 @@ import Display
import AsyncDisplayKit
import SwiftSignalKit
import TelegramCore
import ChatMessageBubbleContentNode
import ChatMessageItemCommon
final class ChatMessageEventLogPreviousLinkContentNode: ChatMessageBubbleContentNode {
private let contentNode: ChatMessageAttachedContentNode

View file

@ -5,6 +5,8 @@ import Display
import AsyncDisplayKit
import SwiftSignalKit
import TelegramCore
import ChatMessageBubbleContentNode
import ChatMessageItemCommon
final class ChatMessageEventLogPreviousMessageContentNode: ChatMessageBubbleContentNode {
private let contentNode: ChatMessageAttachedContentNode

View file

@ -9,6 +9,8 @@ import TelegramUIPreferences
import ComponentFlow
import AudioTranscriptionButtonComponent
import ChatMessageDateAndStatusNode
import ChatMessageBubbleContentNode
import ChatMessageItemCommon
class ChatMessageFileBubbleContentNode: ChatMessageBubbleContentNode {
let interactiveFileNode: ChatMessageInteractiveFileNode

View file

@ -5,6 +5,8 @@ import Display
import AsyncDisplayKit
import SwiftSignalKit
import TelegramCore
import ChatMessageBubbleContentNode
import ChatMessageItemCommon
final class ChatMessageGameBubbleContentNode: ChatMessageBubbleContentNode {
private var game: TelegramMediaGame?

View file

@ -18,6 +18,8 @@ import TelegramAnimatedStickerNode
import ChatControllerInteraction
import ShimmerEffect
import Markdown
import ChatMessageBubbleContentNode
import ChatMessageItemCommon
private func attributedServiceMessageString(theme: ChatPresentationThemeData, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, message: EngineMessage, accountPeerId: EnginePeer.Id) -> NSAttributedString? {
return universalServiceMessageString(presentationData: (theme.theme, theme.wallpaper), strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, message: message, accountPeerId: accountPeerId, forChatList: false, forForumOverview: false)

View file

@ -15,6 +15,8 @@ import ShimmerEffect
import AnimatedStickerNode
import TelegramAnimatedStickerNode
import ChatMessageDateAndStatusNode
import ChatMessageBubbleContentNode
import ChatMessageItemCommon
private let titleFont = Font.medium(15.0)
private let textFont = Font.regular(13.0)

View file

@ -9,6 +9,8 @@ import TelegramUIPreferences
import ComponentFlow
import AudioTranscriptionButtonComponent
import ChatMessageDateAndStatusNode
import ChatMessageBubbleContentNode
import ChatMessageItemCommon
class ChatMessageInstantVideoBubbleContentNode: ChatMessageBubbleContentNode {
let interactiveFileNode: ChatMessageInteractiveFileNode

View file

@ -15,6 +15,8 @@ import Markdown
import ChatControllerInteraction
import ChatMessageForwardInfoNode
import ChatMessageDateAndStatusNode
import ChatMessageItemCommon
import ChatMessageBubbleContentNode
private let nameFont = Font.medium(14.0)

View file

@ -30,6 +30,8 @@ import UndoUI
import TelegramNotices
import ChatControllerInteraction
import ChatMessageDateAndStatusNode
import ChatHistoryEntry
import ChatMessageItemCommon
private struct FetchControls {
let fetch: (Bool) -> Void

View file

@ -21,6 +21,8 @@ import Markdown
import TextFormat
import ChatMessageForwardInfoNode
import ChatMessageDateAndStatusNode
import ChatMessageItemCommon
import ChatMessageBubbleContentNode
struct ChatMessageInstantVideoItemLayoutResult {
let contentSize: CGSize

View file

@ -26,6 +26,8 @@ import InvisibleInkDustNode
import ChatControllerInteraction
import StoryContainerScreen
import ChatMessageDateAndStatusNode
import ChatHistoryEntry
import ChatMessageItemCommon
private struct FetchControls {
let fetch: (Bool) -> Void

View file

@ -7,6 +7,8 @@ import SwiftSignalKit
import TelegramCore
import TelegramUIPreferences
import TelegramStringFormatting
import ChatMessageBubbleContentNode
import ChatMessageItemCommon
private let titleFont: UIFont = Font.semibold(15.0)
private let textFont: UIFont = Font.regular(15.0)

View file

@ -11,6 +11,7 @@ import AccountContext
import Emoji
import PersistentStringHash
import ChatControllerInteraction
import ChatHistoryEntry
public enum ChatMessageItemContent: Sequence {
case message(message: Message, read: Bool, selection: ChatHistoryMessageSelection, attributes: ChatMessageEntryAttributes, location: MessageHistoryEntryLocation?)

View file

@ -11,104 +11,7 @@ import ChatListUI
import TelegramPresentationData
import SwiftSignalKit
import ChatControllerInteraction
struct ChatMessageItemWidthFill {
var compactInset: CGFloat
var compactWidthBoundary: CGFloat
var freeMaximumFillFactor: CGFloat
func widthFor(_ width: CGFloat) -> CGFloat {
if width <= self.compactWidthBoundary {
return max(1.0, width - self.compactInset)
} else {
return max(1.0, floor(width * self.freeMaximumFillFactor))
}
}
}
struct ChatMessageItemBubbleLayoutConstants {
var edgeInset: CGFloat
var defaultSpacing: CGFloat
var mergedSpacing: CGFloat
var maximumWidthFill: ChatMessageItemWidthFill
var minimumSize: CGSize
var contentInsets: UIEdgeInsets
var borderInset: CGFloat
var strokeInsets: UIEdgeInsets
}
struct ChatMessageItemTextLayoutConstants {
var bubbleInsets: UIEdgeInsets
}
struct ChatMessageItemImageLayoutConstants {
var bubbleInsets: UIEdgeInsets
var statusInsets: UIEdgeInsets
var defaultCornerRadius: CGFloat
var mergedCornerRadius: CGFloat
var contentMergedCornerRadius: CGFloat
var maxDimensions: CGSize
var minDimensions: CGSize
}
struct ChatMessageItemVideoLayoutConstants {
var maxHorizontalHeight: CGFloat
var maxVerticalHeight: CGFloat
}
struct ChatMessageItemInstantVideoConstants {
var insets: UIEdgeInsets
var dimensions: CGSize
}
struct ChatMessageItemFileLayoutConstants {
var bubbleInsets: UIEdgeInsets
}
struct ChatMessageItemWallpaperLayoutConstants {
var maxTextWidth: CGFloat
}
struct ChatMessageItemLayoutConstants {
var avatarDiameter: CGFloat
var timestampHeaderHeight: CGFloat
var bubble: ChatMessageItemBubbleLayoutConstants
var image: ChatMessageItemImageLayoutConstants
var video: ChatMessageItemVideoLayoutConstants
var text: ChatMessageItemTextLayoutConstants
var file: ChatMessageItemFileLayoutConstants
var instantVideo: ChatMessageItemInstantVideoConstants
var wallpapers: ChatMessageItemWallpaperLayoutConstants
static var `default`: ChatMessageItemLayoutConstants {
return self.compact
}
fileprivate static var compact: ChatMessageItemLayoutConstants {
let bubble = ChatMessageItemBubbleLayoutConstants(edgeInset: 4.0, defaultSpacing: 2.0 + UIScreenPixel, mergedSpacing: 0.0, maximumWidthFill: ChatMessageItemWidthFill(compactInset: 36.0, compactWidthBoundary: 500.0, freeMaximumFillFactor: 0.85), minimumSize: CGSize(width: 40.0, height: 35.0), contentInsets: UIEdgeInsets(top: 0.0, left: 6.0, bottom: 0.0, right: 0.0), borderInset: UIScreenPixel, strokeInsets: UIEdgeInsets(top: 1.0, left: 1.0, bottom: 1.0, right: 1.0))
let text = ChatMessageItemTextLayoutConstants(bubbleInsets: UIEdgeInsets(top: 6.0 + UIScreenPixel, left: 12.0, bottom: 6.0 - UIScreenPixel, right: 12.0))
let image = ChatMessageItemImageLayoutConstants(bubbleInsets: UIEdgeInsets(top: 2.0, left: 2.0, bottom: 2.0, right: 2.0), statusInsets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 6.0, right: 6.0), defaultCornerRadius: 16.0, mergedCornerRadius: 8.0, contentMergedCornerRadius: 0.0, maxDimensions: CGSize(width: 300.0, height: 380.0), minDimensions: CGSize(width: 170.0, height: 74.0))
let video = ChatMessageItemVideoLayoutConstants(maxHorizontalHeight: 250.0, maxVerticalHeight: 360.0)
let file = ChatMessageItemFileLayoutConstants(bubbleInsets: UIEdgeInsets(top: 15.0, left: 9.0, bottom: 15.0, right: 12.0))
let instantVideo = ChatMessageItemInstantVideoConstants(insets: UIEdgeInsets(top: 4.0, left: 0.0, bottom: 4.0, right: 0.0), dimensions: CGSize(width: 212.0, height: 212.0))
let wallpapers = ChatMessageItemWallpaperLayoutConstants(maxTextWidth: 180.0)
return ChatMessageItemLayoutConstants(avatarDiameter: 37.0, timestampHeaderHeight: 34.0, bubble: bubble, image: image, video: video, text: text, file: file, instantVideo: instantVideo, wallpapers: wallpapers)
}
fileprivate static var regular: ChatMessageItemLayoutConstants {
let bubble = ChatMessageItemBubbleLayoutConstants(edgeInset: 4.0, defaultSpacing: 2.0 + UIScreenPixel, mergedSpacing: 0.0, maximumWidthFill: ChatMessageItemWidthFill(compactInset: 36.0, compactWidthBoundary: 500.0, freeMaximumFillFactor: 0.65), minimumSize: CGSize(width: 40.0, height: 35.0), contentInsets: UIEdgeInsets(top: 0.0, left: 6.0, bottom: 0.0, right: 0.0), borderInset: UIScreenPixel, strokeInsets: UIEdgeInsets(top: 1.0, left: 1.0, bottom: 1.0, right: 1.0))
let text = ChatMessageItemTextLayoutConstants(bubbleInsets: UIEdgeInsets(top: 6.0 + UIScreenPixel, left: 12.0, bottom: 6.0 - UIScreenPixel, right: 12.0))
let image = ChatMessageItemImageLayoutConstants(bubbleInsets: UIEdgeInsets(top: 2.0, left: 2.0, bottom: 2.0, right: 2.0), statusInsets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 6.0, right: 6.0), defaultCornerRadius: 16.0, mergedCornerRadius: 8.0, contentMergedCornerRadius: 5.0, maxDimensions: CGSize(width: 440.0, height: 440.0), minDimensions: CGSize(width: 170.0, height: 74.0))
let video = ChatMessageItemVideoLayoutConstants(maxHorizontalHeight: 250.0, maxVerticalHeight: 360.0)
let file = ChatMessageItemFileLayoutConstants(bubbleInsets: UIEdgeInsets(top: 15.0, left: 9.0, bottom: 15.0, right: 12.0))
let instantVideo = ChatMessageItemInstantVideoConstants(insets: UIEdgeInsets(top: 4.0, left: 0.0, bottom: 4.0, right: 0.0), dimensions: CGSize(width: 240.0, height: 240.0))
let wallpapers = ChatMessageItemWallpaperLayoutConstants(maxTextWidth: 180.0)
return ChatMessageItemLayoutConstants(avatarDiameter: 37.0, timestampHeaderHeight: 34.0, bubble: bubble, image: image, video: video, text: text, file: file, instantVideo: instantVideo, wallpapers: wallpapers)
}
}
import ChatMessageItemCommon
func chatMessageItemLayoutConstants(_ constants: (ChatMessageItemLayoutConstants, ChatMessageItemLayoutConstants), params: ListViewItemLayoutParams, presentationData: ChatPresentationData) -> ChatMessageItemLayoutConstants {
var result: ChatMessageItemLayoutConstants
@ -136,11 +39,6 @@ enum ChatMessageItemBottomNeighbor {
case merged(semi: Bool)
}
enum ChatMessagePeekPreviewContent {
case media(Media)
case url(ASDisplayNode, CGRect, String, Bool)
}
private let voiceMessageDurationFormatter: DateComponentsFormatter = {
let formatter = DateComponentsFormatter()
formatter.unitsStyle = .spellOut
@ -790,10 +688,6 @@ public class ChatMessageItemView: ListViewItemNode, ChatMessageItemNodeProtocol
return nil
}
func peekPreviewContent(at point: CGPoint) -> (Message, ChatMessagePeekPreviewContent)? {
return nil
}
func updateHiddenMedia() {
}

View file

@ -11,6 +11,8 @@ import MediaResources
import LocationResources
import LiveLocationPositionNode
import ChatMessageDateAndStatusNode
import ChatMessageBubbleContentNode
import ChatMessageItemCommon
private let titleFont = Font.medium(14.0)
private let liveTitleFont = Font.medium(16.0)

View file

@ -11,6 +11,8 @@ import AccountContext
import GridMessageSelectionNode
import ChatControllerInteraction
import ChatMessageDateAndStatusNode
import ChatMessageBubbleContentNode
import ChatMessageItemCommon
class ChatMessageMediaBubbleContentNode: ChatMessageBubbleContentNode {
override var supportsMosaic: Bool {
@ -411,15 +413,6 @@ class ChatMessageMediaBubbleContentNode: ChatMessageBubbleContentNode {
return nil
}
override func peekPreviewContent(at point: CGPoint) -> (Message, ChatMessagePeekPreviewContent)? {
if let message = self.item?.message, let currentMedia = self.media, !message.containsSecretMedia {
if self.interactiveImageNode.frame.contains(point), self.interactiveImageNode.isReadyForInteractivePreview() {
return (message, .media(currentMedia))
}
}
return nil
}
override func updateHiddenMedia(_ media: [Media]?) -> Bool {
var mediaHidden = false

View file

@ -12,6 +12,8 @@ import AvatarNode
import TelegramPresentationData
import ChatMessageBackground
import ChatMessageDateAndStatusNode
import ChatMessageBubbleContentNode
import ChatMessageItemCommon
func isPollEffectivelyClosed(message: Message, poll: TelegramMediaPoll) -> Bool {
if poll.isClosed {

View file

@ -18,6 +18,8 @@ import UniversalMediaPlayer
import TelegramUniversalVideoContent
import GalleryUI
import Markdown
import ChatMessageBubbleContentNode
import ChatMessageItemCommon
class ChatMessageProfilePhotoSuggestionContentNode: ChatMessageBubbleContentNode {
private var mediaBackgroundContent: WallpaperBubbleBackgroundNode?

View file

@ -13,40 +13,8 @@ import ReactionButtonListComponent
import AccountContext
import WallpaperBackgroundNode
import ChatControllerInteraction
func canViewMessageReactionList(message: Message) -> Bool {
var found = false
var canViewList = false
for attribute in message.attributes {
if let attribute = attribute as? ReactionsMessageAttribute {
canViewList = attribute.canViewList
found = true
break
}
}
if !found {
return false
}
if let peer = message.peers[message.id.peerId] {
if let channel = peer as? TelegramChannel {
if case .broadcast = channel.info {
return false
} else {
return canViewList
}
} else if let _ = peer as? TelegramGroup {
return canViewList
} else if let _ = peer as? TelegramUser {
return true
} else {
return false
}
} else {
return false
}
}
import ChatMessageBubbleContentNode
import ChatMessageItemCommon
final class MessageReactionButtonsNode: ASDisplayNode {
enum DisplayType {

View file

@ -8,6 +8,8 @@ import TelegramCore
import TelegramPresentationData
import TextFormat
import ChatMessageDateAndStatusNode
import ChatMessageBubbleContentNode
import ChatMessageItemCommon
class ChatMessageRestrictedBubbleContentNode: ChatMessageBubbleContentNode {
private let textNode: TextNode

View file

@ -16,6 +16,7 @@ import WallpaperBackgroundNode
import ChatControllerInteraction
import ChatMessageForwardInfoNode
import ChatMessageDateAndStatusNode
import ChatMessageItemCommon
private let nameFont = Font.medium(14.0)
private let inlineBotPrefixFont = Font.regular(14.0)

View file

@ -21,6 +21,8 @@ import Markdown
import ComponentFlow
import AvatarStoryIndicatorComponent
import AvatarNode
import ChatMessageBubbleContentNode
import ChatMessageItemCommon
class ChatMessageStoryMentionContentNode: ChatMessageBubbleContentNode {
private var mediaBackgroundContent: WallpaperBubbleBackgroundNode?

View file

@ -6,6 +6,8 @@ import AsyncDisplayKit
import SwiftSignalKit
import TelegramCore
import TelegramPresentationData
import ChatMessageBubbleContentNode
import ChatMessageItemCommon
final class ChatMessageUnsupportedBubbleContentNode: ChatMessageBubbleContentNode {
private var buttonNode: ChatMessageAttachedContentButtonNode

View file

@ -18,6 +18,8 @@ import Markdown
import RadialStatusNode
import ComponentFlow
import AudioTranscriptionPendingIndicatorComponent
import ChatMessageBubbleContentNode
import ChatMessageItemCommon
class ChatMessageWallpaperBubbleContentNode: ChatMessageBubbleContentNode {
private var mediaBackgroundContent: WallpaperBubbleBackgroundNode?

View file

@ -13,6 +13,8 @@ import InstantPageUI
import UrlHandling
import GalleryData
import TelegramPresentationData
import ChatMessageBubbleContentNode
import ChatMessageItemCommon
private let titleFont: UIFont = Font.semibold(15.0)

View file

@ -7,6 +7,7 @@ import TelegramPresentationData
import MergeLists
import AccountContext
import ChatControllerInteraction
import ChatHistoryEntry
enum ChatRecentActionsEntryContentIndex: Int32 {
case header = 0

View file

@ -8,6 +8,7 @@ import TelegramPresentationData
import AccountContext
import WallpaperBackgroundNode
import ChatControllerInteraction
import ChatMessageItemCommon
private let titleFont = UIFont.systemFont(ofSize: 13.0)

View file

@ -8,6 +8,7 @@ import TelegramPresentationData
import AccountContext
import WallpaperBackgroundNode
import ChatControllerInteraction
import ChatMessageItemCommon
private let titleFont = UIFont.systemFont(ofSize: 13.0)

View file

@ -13,6 +13,7 @@ import AlertUI
import PresentationDataUtils
import ContactListUI
import CounterContollerTitleView
import EditableTokenListNode
private func peerTokenTitle(accountPeerId: PeerId, peer: Peer, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder) -> String {
if peer.id == accountPeerId {

View file

@ -11,6 +11,7 @@ import ContactListUI
import ChatListUI
import AnimationCache
import MultiAnimationRenderer
import EditableTokenListNode
private struct SearchResultEntry: Identifiable {
let index: Int

View file

@ -6,6 +6,7 @@ import Display
import MergeLists
import AccountContext
import ChatControllerInteraction
import ChatHistoryEntry
func preparedChatHistoryViewTransition(from fromView: ChatHistoryView?, to toView: ChatHistoryView, reason: ChatHistoryViewTransitionReason, reverse: Bool, chatLocation: ChatLocation, controllerInteraction: ChatControllerInteraction, scrollPosition: ChatHistoryViewScrollPosition?, scrollAnimationCurve: ListViewAnimationCurve?, initialData: InitialMessageHistoryData?, keyboardButtonsMessage: Message?, cachedData: CachedPeerData?, cachedDataMessages: [MessageId: Message]?, readStateData: [PeerId: ChatHistoryCombinedInitialReadStateData]?, flashIndicators: Bool, updatedMessageSelection: Bool, messageTransitionNode: ChatMessageTransitionNode?, allUpdated: Bool) -> ChatHistoryViewTransition {
var mergeResult: (deleteIndices: [Int], indicesAndItems: [(Int, ChatHistoryEntry, Int?)], updateIndices: [(Int, ChatHistoryEntry, Int)])

View file

@ -42,6 +42,7 @@ import PeerInfoStoryGridScreen
import TelegramAccountAuxiliaryMethods
import PeerSelectionController
import LegacyMessageInputPanel
import ChatHistoryEntry
private final class AccountUserInterfaceInUseContext {
let subscribers = Bag<(Bool) -> Void>()