diff --git a/submodules/AccountContext/Sources/AccountContext.swift b/submodules/AccountContext/Sources/AccountContext.swift index 35c7b34853..d3babbae12 100644 --- a/submodules/AccountContext/Sources/AccountContext.swift +++ b/submodules/AccountContext/Sources/AccountContext.swift @@ -891,6 +891,8 @@ public protocol SharedAccountContext: AnyObject { func presentContactsWarningSuppression(context: AccountContext, present: (ViewController, Any?) -> Void) func openImagePicker(context: AccountContext, completion: @escaping (UIImage) -> Void, present: @escaping (ViewController) -> Void) func openAddPeerMembers(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)?, parentController: ViewController, groupPeer: Peer, selectAddMemberDisposable: MetaDisposable, addMemberDisposable: MetaDisposable) + func openChatInstantPage(context: AccountContext, message: Message, sourcePeerType: MediaAutoDownloadPeerType?, navigationController: NavigationController) + func openChatWallpaper(context: AccountContext, message: Message, present: @escaping (ViewController, Any?) -> Void) func makeRecentSessionsController(context: AccountContext, activeSessionsContext: ActiveSessionsContext) -> ViewController & RecentSessionsController diff --git a/submodules/AccountContext/Sources/ChatController.swift b/submodules/AccountContext/Sources/ChatController.swift index 2bd309c408..bae75268de 100644 --- a/submodules/AccountContext/Sources/ChatController.swift +++ b/submodules/AccountContext/Sources/ChatController.swift @@ -769,6 +769,32 @@ public protocol PeerInfoScreen: ViewController { var peerId: PeerId { get } } +public extension Peer { + func canSetupAutoremoveTimeout(accountPeerId: EnginePeer.Id) -> Bool { + if let _ = self as? TelegramSecretChat { + return false + } else if let group = self as? TelegramGroup { + if case .creator = group.role { + return true + } else if case let .admin(rights, _) = group.role { + if rights.rights.contains(.canDeleteMessages) { + return true + } + } + } else if let user = self as? TelegramUser { + if user.id != accountPeerId && user.botInfo == nil { + return true + } + } else if let channel = self as? TelegramChannel { + if channel.hasPermission(.deleteAllMessages) { + return true + } + } + + return false + } +} + public protocol ChatController: ViewController { var chatLocation: ChatLocation { get } var canReadHistory: ValuePromise { get } diff --git a/submodules/TelegramUI/BUILD b/submodules/TelegramUI/BUILD index 7f38a8733b..cb90bdf215 100644 --- a/submodules/TelegramUI/BUILD +++ b/submodules/TelegramUI/BUILD @@ -404,6 +404,9 @@ swift_library( "//submodules/TelegramUI/Components/Chat/ChatMessageGiftBubbleContentNode", "//submodules/TelegramUI/Components/Chat/ChatMessageGiveawayBubbleContentNode", "//submodules/TelegramUI/Components/Chat/ChatMessageBubbleItemNode", + "//submodules/TelegramUI/Components/Chat/ChatRecentActionsController", + "//submodules/TelegramUI/Components/Chat/ChatNavigationButton", + "//submodules/TelegramUI/Components/Chat/ChatLoadingNode", ] + select({ "@build_bazel_rules_apple//apple:ios_arm64": appcenter_targets, "//build-system:ios_sim_arm64": [], diff --git a/submodules/TelegramUI/Components/Chat/ChatLoadingNode/BUILD b/submodules/TelegramUI/Components/Chat/ChatLoadingNode/BUILD new file mode 100644 index 0000000000..d3a63d832d --- /dev/null +++ b/submodules/TelegramUI/Components/Chat/ChatLoadingNode/BUILD @@ -0,0 +1,34 @@ +load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") + +swift_library( + name = "ChatLoadingNode", + module_name = "ChatLoadingNode", + srcs = glob([ + "Sources/**/*.swift", + ]), + copts = [ + "-warnings-as-errors", + ], + deps = [ + "//submodules/AsyncDisplayKit", + "//submodules/SSignalKit/SwiftSignalKit", + "//submodules/Display", + "//submodules/TelegramCore", + "//submodules/TelegramPresentationData", + "//submodules/ActivityIndicator", + "//submodules/WallpaperBackgroundNode", + "//submodules/ShimmerEffect", + "//submodules/ChatPresentationInterfaceState", + "//submodules/AccountContext", + "//submodules/TelegramUI/Components/Chat/ChatMessageItem", + "//submodules/TelegramUI/Components/Chat/ChatMessageItemView", + "//submodules/TelegramUI/Components/Chat/ChatMessageStickerItemNode", + "//submodules/TelegramUI/Components/Chat/ChatMessageInstantVideoItemNode", + "//submodules/TelegramUI/Components/Chat/ChatMessageAnimatedStickerItemNode", + "//submodules/TelegramUI/Components/Chat/ChatMessageBubbleItemNode", + "//submodules/TelegramUI/Components/Chat/ChatMessageItemImpl", + ], + visibility = [ + "//visibility:public", + ], +) diff --git a/submodules/TelegramUI/Sources/ChatLoadingNode.swift b/submodules/TelegramUI/Components/Chat/ChatLoadingNode/Sources/ChatLoadingNode.swift similarity index 91% rename from submodules/TelegramUI/Sources/ChatLoadingNode.swift rename to submodules/TelegramUI/Components/Chat/ChatLoadingNode/Sources/ChatLoadingNode.swift index 2573b20227..760609e3c5 100644 --- a/submodules/TelegramUI/Sources/ChatLoadingNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatLoadingNode/Sources/ChatLoadingNode.swift @@ -16,13 +16,14 @@ import ChatMessageStickerItemNode import ChatMessageInstantVideoItemNode import ChatMessageAnimatedStickerItemNode import ChatMessageBubbleItemNode +import ChatMessageItemImpl -final class ChatLoadingNode: ASDisplayNode { +public final class ChatLoadingNode: ASDisplayNode { private let backgroundNode: NavigationBackgroundNode private let activityIndicator: ActivityIndicator private let offset: CGPoint - init(context: AccountContext, theme: PresentationTheme, chatWallpaper: TelegramWallpaper, bubbleCorners: PresentationChatBubbleCorners) { + public init(context: AccountContext, theme: PresentationTheme, chatWallpaper: TelegramWallpaper, bubbleCorners: PresentationChatBubbleCorners) { self.backgroundNode = NavigationBackgroundNode(color: selectDateFillStaticColor(theme: theme, wallpaper: chatWallpaper), enableBlur: context.sharedContext.energyUsageSettings.fullTranslucency && dateFillNeedsBlur(theme: theme, wallpaper: chatWallpaper)) let serviceColor = serviceMessageColorComponents(theme: theme, wallpaper: chatWallpaper) @@ -39,7 +40,7 @@ final class ChatLoadingNode: ASDisplayNode { self.addSubnode(self.activityIndicator) } - func updateLayout(size: CGSize, insets: UIEdgeInsets, transition: ContainedViewLayoutTransition) { + public func updateLayout(size: CGSize, insets: UIEdgeInsets, transition: ContainedViewLayoutTransition) { let displayRect = CGRect(origin: CGPoint(x: 0.0, y: insets.top), size: CGSize(width: size.width, height: size.height - insets.top - insets.bottom)) let backgroundSize: CGFloat = 30.0 @@ -50,7 +51,7 @@ final class ChatLoadingNode: ASDisplayNode { transition.updateFrame(node: self.activityIndicator, frame: CGRect(origin: CGPoint(x: displayRect.minX + floor((displayRect.width - activitySize.width) / 2.0) + self.offset.x, y: displayRect.minY + floor((displayRect.height - activitySize.height) / 2.0) + self.offset.y), size: activitySize)) } - var progressFrame: CGRect { + public var progressFrame: CGRect { return self.backgroundNode.frame } } @@ -59,22 +60,22 @@ private let avatarSize = CGSize(width: 38.0, height: 38.0) private let avatarImage = generateFilledCircleImage(diameter: avatarSize.width, color: .white) private let avatarBorderImage = generateCircleImage(diameter: avatarSize.width, lineWidth: 1.0 - UIScreenPixel, color: .white) -final class ChatLoadingPlaceholderMessageContainer { - var avatarNode: ASImageNode? - var avatarBorderNode: ASImageNode? +public final class ChatLoadingPlaceholderMessageContainer { + public var avatarNode: ASImageNode? + public var avatarBorderNode: ASImageNode? - let bubbleNode: ASImageNode - let bubbleBorderNode: ASImageNode + public let bubbleNode: ASImageNode + public let bubbleBorderNode: ASImageNode - var parentView: UIView? { + public var parentView: UIView? { return self.bubbleNode.supernode?.view } - var frame: CGRect { + public var frame: CGRect { return self.bubbleNode.frame } - init(bubbleImage: UIImage?, bubbleBorderImage: UIImage?) { + public init(bubbleImage: UIImage?, bubbleBorderImage: UIImage?) { self.bubbleNode = ASImageNode() self.bubbleNode.displaysAsynchronously = false self.bubbleNode.image = bubbleImage @@ -84,12 +85,12 @@ final class ChatLoadingPlaceholderMessageContainer { self.bubbleBorderNode.image = bubbleBorderImage } - func setup(maskNode: ASDisplayNode, borderMaskNode: ASDisplayNode) { + public func setup(maskNode: ASDisplayNode, borderMaskNode: ASDisplayNode) { maskNode.addSubnode(self.bubbleNode) borderMaskNode.addSubnode(self.bubbleBorderNode) } - func animateWith(_ listItemNode: ListViewItemNode, delay: Double, transition: ContainedViewLayoutTransition) { + public func animateWith(_ listItemNode: ListViewItemNode, delay: Double, transition: ContainedViewLayoutTransition) { listItemNode.allowsGroupOpacity = true listItemNode.alpha = 1.0 listItemNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2, delay: delay, completion: { _ in @@ -107,7 +108,7 @@ final class ChatLoadingPlaceholderMessageContainer { } } - func update(size: CGSize, hasAvatar: Bool, rect: CGRect, transition: ContainedViewLayoutTransition) { + public func update(size: CGSize, hasAvatar: Bool, rect: CGRect, transition: ContainedViewLayoutTransition) { var avatarOffset: CGFloat = 0.0 if hasAvatar && self.avatarNode == nil { @@ -139,7 +140,7 @@ final class ChatLoadingPlaceholderMessageContainer { } } -final class ChatLoadingPlaceholderNode: ASDisplayNode { +public final class ChatLoadingPlaceholderNode: ASDisplayNode { private weak var backgroundNode: WallpaperBackgroundNode? private let context: AccountContext @@ -161,7 +162,7 @@ final class ChatLoadingPlaceholderNode: ASDisplayNode { private var validLayout: (CGSize, UIEdgeInsets, LayoutMetrics)? - init(context: AccountContext, theme: PresentationTheme, chatWallpaper: TelegramWallpaper, bubbleCorners: PresentationChatBubbleCorners, backgroundNode: WallpaperBackgroundNode) { + public init(context: AccountContext, theme: PresentationTheme, chatWallpaper: TelegramWallpaper, bubbleCorners: PresentationChatBubbleCorners, backgroundNode: WallpaperBackgroundNode) { self.context = context self.backgroundNode = backgroundNode @@ -207,7 +208,7 @@ final class ChatLoadingPlaceholderNode: ASDisplayNode { } } - override func didLoad() { + override public func didLoad() { super.didLoad() self.containerNode.view.mask = self.maskNode.view @@ -223,10 +224,8 @@ final class ChatLoadingPlaceholderNode: ASDisplayNode { } private var bottomInset: (Int, CGFloat)? - func setup(_ historyNode: ChatHistoryNode, updating: Bool = false) { - guard let listNode = historyNode as? ListView else { - return - } + public func setup(_ historyNode: ListView, updating: Bool = false) { + let listNode = historyNode var listItemNodes: [ASDisplayNode] = [] var count = 0 @@ -291,10 +290,11 @@ final class ChatLoadingPlaceholderNode: ASDisplayNode { } private var didAnimateOut = false - func animateOut(_ historyNode: ChatHistoryNode, completion: @escaping () -> Void = {}) { - guard let listNode = historyNode as? ListView, let (size, _, _) = self.validLayout else { + public func animateOut(_ historyNode: ListView, completion: @escaping () -> Void = {}) { + guard let (size, _, _) = self.validLayout else { return } + let listNode = historyNode self.didAnimateOut = true self.backgroundNode?.updateIsLooping(false) @@ -378,7 +378,7 @@ final class ChatLoadingPlaceholderNode: ASDisplayNode { } } - func addContentOffset(offset: CGFloat, transition: ContainedViewLayoutTransition) { + public func addContentOffset(offset: CGFloat, transition: ContainedViewLayoutTransition) { self.maskNode.bounds = self.maskNode.bounds.offsetBy(dx: 0.0, dy: -offset) self.borderMaskNode.bounds = self.borderMaskNode.bounds.offsetBy(dx: 0.0, dy: -offset) transition.animateOffsetAdditive(node: self.maskNode, offset: offset) @@ -388,7 +388,7 @@ final class ChatLoadingPlaceholderNode: ASDisplayNode { } } - func update(rect: CGRect, within containerSize: CGSize, transition: ContainedViewLayoutTransition = .immediate) { + public func update(rect: CGRect, within containerSize: CGSize, transition: ContainedViewLayoutTransition = .immediate) { self.absolutePosition = (rect, containerSize) if let backgroundContent = self.backgroundContent { var backgroundFrame = backgroundContent.frame @@ -398,14 +398,14 @@ final class ChatLoadingPlaceholderNode: ASDisplayNode { } } - enum ChatType: Equatable { + public enum ChatType: Equatable { case generic case user case group case channel } private var chatType: ChatType = .channel - func updatePresentationInterfaceState(_ chatPresentationInterfaceState: ChatPresentationInterfaceState) { + public func updatePresentationInterfaceState(_ chatPresentationInterfaceState: ChatPresentationInterfaceState) { var chatType: ChatType = .channel if let peer = chatPresentationInterfaceState.renderedPeer?.peer { if peer is TelegramUser { @@ -429,7 +429,7 @@ final class ChatLoadingPlaceholderNode: ASDisplayNode { } } - func updateLayout(size: CGSize, insets: UIEdgeInsets, metrics: LayoutMetrics, transition: ContainedViewLayoutTransition) { + public func updateLayout(size: CGSize, insets: UIEdgeInsets, metrics: LayoutMetrics, transition: ContainedViewLayoutTransition) { self.validLayout = (size, insets, metrics) let bounds = CGRect(origin: .zero, size: size) diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageItemImpl/BUILD b/submodules/TelegramUI/Components/Chat/ChatMessageItemImpl/BUILD new file mode 100644 index 0000000000..e704fe5675 --- /dev/null +++ b/submodules/TelegramUI/Components/Chat/ChatMessageItemImpl/BUILD @@ -0,0 +1,42 @@ +load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") + +swift_library( + name = "ChatMessageItemImpl", + module_name = "ChatMessageItemImpl", + srcs = glob([ + "Sources/**/*.swift", + ]), + copts = [ + "-warnings-as-errors", + ], + deps = [ + "//submodules/Postbox", + "//submodules/AsyncDisplayKit", + "//submodules/Display", + "//submodules/SSignalKit/SwiftSignalKit", + "//submodules/TelegramCore", + "//submodules/TelegramPresentationData", + "//submodules/TelegramUIPreferences", + "//submodules/AccountContext", + "//submodules/Emoji", + "//submodules/PersistentStringHash", + "//submodules/TelegramUI/Components/ChatControllerInteraction", + "//submodules/TelegramUI/Components/Chat/ChatHistoryEntry", + "//submodules/TelegramUI/Components/Chat/ChatMessageItem", + "//submodules/TelegramUI/Components/Chat/ChatMessageItemCommon", + "//submodules/TelegramUI/Components/Chat/ChatMessageItemView", + "//submodules/TelegramUI/Components/Chat/ChatMessageStickerItemNode", + "//submodules/TelegramUI/Components/Chat/ChatMessageAnimatedStickerItemNode", + "//submodules/TelegramUI/Components/Chat/ChatMessageBubbleItemNode", + "//submodules/AvatarNode", + "//submodules/TelegramUniversalVideoContent", + "//submodules/MediaPlayer:UniversalMediaPlayer", + "//submodules/GalleryUI", + "//submodules/Components/HierarchyTrackingLayer", + "//submodules/WallpaperBackgroundNode", + "//submodules/AvatarVideoNode", + ], + visibility = [ + "//visibility:public", + ], +) diff --git a/submodules/TelegramUI/Sources/ChatMessageDateHeader.swift b/submodules/TelegramUI/Components/Chat/ChatMessageItemImpl/Sources/ChatMessageDateHeader.swift similarity index 85% rename from submodules/TelegramUI/Sources/ChatMessageDateHeader.swift rename to submodules/TelegramUI/Components/Chat/ChatMessageItemImpl/Sources/ChatMessageDateHeader.swift index da8c351f1d..9253684a1f 100644 --- a/submodules/TelegramUI/Sources/ChatMessageDateHeader.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageItemImpl/Sources/ChatMessageDateHeader.swift @@ -27,18 +27,18 @@ private let timezoneOffset: Int32 = { private let granularity: Int32 = 60 * 60 * 24 -final class ChatMessageDateHeader: ListViewItemHeader { +public final class ChatMessageDateHeader: ListViewItemHeader { private let timestamp: Int32 private let roundedTimestamp: Int32 private let scheduled: Bool - let id: ListViewItemNode.HeaderId - let presentationData: ChatPresentationData - let controllerInteraction: ChatControllerInteraction? - let context: AccountContext - let action: ((Int32, Bool) -> Void)? + public let id: ListViewItemNode.HeaderId + public let presentationData: ChatPresentationData + public let controllerInteraction: ChatControllerInteraction? + public let context: AccountContext + public let action: ((Int32, Bool) -> Void)? - init(timestamp: Int32, scheduled: Bool, presentationData: ChatPresentationData, controllerInteraction: ChatControllerInteraction?, context: AccountContext, action: ((Int32, Bool) -> Void)? = nil) { + public init(timestamp: Int32, scheduled: Bool, presentationData: ChatPresentationData, controllerInteraction: ChatControllerInteraction?, context: AccountContext, action: ((Int32, Bool) -> Void)? = nil) { self.timestamp = timestamp self.scheduled = scheduled self.presentationData = presentationData @@ -49,10 +49,10 @@ final class ChatMessageDateHeader: ListViewItemHeader { self.id = ListViewItemNode.HeaderId(space: 0, id: Int64(self.roundedTimestamp)) } - let stickDirection: ListViewItemHeaderStickDirection = .bottom - let stickOverInsets: Bool = true + public let stickDirection: ListViewItemHeaderStickDirection = .bottom + public let stickOverInsets: Bool = true - let height: CGFloat = 34.0 + public let height: CGFloat = 34.0 public func combinesWith(other: ListViewItemHeader) -> Bool { if let other = other as? ChatMessageDateHeader, other.id == self.id { @@ -62,11 +62,11 @@ final class ChatMessageDateHeader: ListViewItemHeader { } } - func node(synchronousLoad: Bool) -> ListViewItemHeaderNode { + public func node(synchronousLoad: Bool) -> ListViewItemHeaderNode { return ChatMessageDateHeaderNode(localTimestamp: self.roundedTimestamp, scheduled: self.scheduled, presentationData: self.presentationData, controllerInteraction: self.controllerInteraction, context: self.context, action: self.action) } - func updateNode(_ node: ListViewItemHeaderNode, previous: ListViewItemHeader?, next: ListViewItemHeader?) { + public func updateNode(_ node: ListViewItemHeaderNode, previous: ListViewItemHeader?, next: ListViewItemHeader?) { guard let node = node as? ChatMessageDateHeaderNode, let next = next as? ChatMessageDateHeader else { return } @@ -115,10 +115,10 @@ private func dateHeaderTimestampId(timestamp: Int32) -> Int32 { } } -final class ChatMessageDateHeaderNode: ListViewItemHeaderNode { - let labelNode: TextNode - let backgroundNode: NavigationBackgroundNode - let stickBackgroundNode: ASImageNode +public final class ChatMessageDateHeaderNode: ListViewItemHeaderNode { + public let labelNode: TextNode + public let backgroundNode: NavigationBackgroundNode + public let stickBackgroundNode: ASImageNode private var backgroundContent: WallpaperBubbleBackgroundNode? @@ -134,7 +134,7 @@ final class ChatMessageDateHeaderNode: ListViewItemHeaderNode { private var absolutePosition: (CGRect, CGSize)? - init(localTimestamp: Int32, scheduled: Bool, presentationData: ChatPresentationData, controllerInteraction: ChatControllerInteraction?, context: AccountContext, action: ((Int32, Bool) -> Void)? = nil) { + public init(localTimestamp: Int32, scheduled: Bool, presentationData: ChatPresentationData, controllerInteraction: ChatControllerInteraction?, context: AccountContext, action: ((Int32, Bool) -> Void)? = nil) { self.presentationData = presentationData self.controllerInteraction = controllerInteraction self.context = context @@ -220,13 +220,13 @@ final class ChatMessageDateHeaderNode: ListViewItemHeaderNode { self.labelNode.frame = CGRect(origin: CGPoint(), size: size.size) } - override func didLoad() { + override public func didLoad() { super.didLoad() self.view.addGestureRecognizer(ListViewTapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:)))) } - func updatePresentationData(_ presentationData: ChatPresentationData, context: AccountContext) { + public func updatePresentationData(_ presentationData: ChatPresentationData, context: AccountContext) { let previousPresentationData = self.presentationData self.presentationData = presentationData @@ -252,11 +252,11 @@ final class ChatMessageDateHeaderNode: ListViewItemHeaderNode { self.setNeedsLayout() } - func updateBackgroundColor(color: UIColor, enableBlur: Bool) { + public func updateBackgroundColor(color: UIColor, enableBlur: Bool) { self.backgroundNode.updateColor(color: color, enableBlur: enableBlur, transition: .immediate) } - override func updateAbsoluteRect(_ rect: CGRect, within containerSize: CGSize) { + override public func updateAbsoluteRect(_ rect: CGRect, within containerSize: CGSize) { self.absolutePosition = (rect, containerSize) if let backgroundContent = self.backgroundContent { var backgroundFrame = backgroundContent.frame @@ -266,7 +266,7 @@ final class ChatMessageDateHeaderNode: ListViewItemHeaderNode { } } - override func updateLayout(size: CGSize, leftInset: CGFloat, rightInset: CGFloat) { + override public func updateLayout(size: CGSize, leftInset: CGFloat, rightInset: CGFloat) { let chatDateSize: CGFloat = 20.0 let chatDateInset: CGFloat = 6.0 @@ -294,7 +294,7 @@ final class ChatMessageDateHeaderNode: ListViewItemHeaderNode { } } - override func updateStickDistanceFactor(_ factor: CGFloat, transition: ContainedViewLayoutTransition) { + override public func updateStickDistanceFactor(_ factor: CGFloat, transition: ContainedViewLayoutTransition) { if !self.stickDistanceFactor.isEqual(to: factor) { self.stickBackgroundNode.alpha = factor @@ -312,7 +312,7 @@ final class ChatMessageDateHeaderNode: ListViewItemHeaderNode { } } - override func updateFlashingOnScrolling(_ isFlashingOnScrolling: Bool, animated: Bool) { + override public func updateFlashingOnScrolling(_ isFlashingOnScrolling: Bool, animated: Bool) { self.flashingOnScrolling = isFlashingOnScrolling self.updateFlashing(animated: animated) } @@ -336,7 +336,7 @@ final class ChatMessageDateHeaderNode: ListViewItemHeaderNode { } } - override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { if !self.bounds.contains(point) { return nil } @@ -349,35 +349,35 @@ final class ChatMessageDateHeaderNode: ListViewItemHeaderNode { return nil } - override func touchesCancelled(_ touches: Set?, with event: UIEvent?) { + override public func touchesCancelled(_ touches: Set?, with event: UIEvent?) { super.touchesCancelled(touches, with: event) } - @objc func tapGesture(_ recognizer: ListViewTapGestureRecognizer) { + @objc private func tapGesture(_ recognizer: ListViewTapGestureRecognizer) { if case .ended = recognizer.state { self.action?(self.localTimestamp, self.stickDistanceFactor < 0.5) } } } -final class ChatMessageAvatarHeader: ListViewItemHeader { - struct Id: Hashable { - var peerId: PeerId - var timestampId: Int32 +public final class ChatMessageAvatarHeader: ListViewItemHeader { + public struct Id: Hashable { + public var peerId: PeerId + public var timestampId: Int32 } - let id: ListViewItemNode.HeaderId - let peerId: PeerId - let peer: Peer? - let messageReference: MessageReference? - let adMessageId: EngineMessage.Id? - let effectiveTimestamp: Int32 - let presentationData: ChatPresentationData - let context: AccountContext - let controllerInteraction: ChatControllerInteraction - let storyStats: PeerStoryStats? + public let id: ListViewItemNode.HeaderId + public let peerId: PeerId + public let peer: Peer? + public let messageReference: MessageReference? + public let adMessageId: EngineMessage.Id? + public let effectiveTimestamp: Int32 + public let presentationData: ChatPresentationData + public let context: AccountContext + public let controllerInteraction: ChatControllerInteraction + public let storyStats: PeerStoryStats? - init(timestamp: Int32, peerId: PeerId, peer: Peer?, messageReference: MessageReference?, message: Message, presentationData: ChatPresentationData, context: AccountContext, controllerInteraction: ChatControllerInteraction, storyStats: PeerStoryStats?) { + public init(timestamp: Int32, peerId: PeerId, peer: Peer?, messageReference: MessageReference?, message: Message, presentationData: ChatPresentationData, context: AccountContext, controllerInteraction: ChatControllerInteraction, storyStats: PeerStoryStats?) { self.peerId = peerId self.peer = peer self.messageReference = messageReference @@ -400,10 +400,10 @@ final class ChatMessageAvatarHeader: ListViewItemHeader { self.storyStats = storyStats } - let stickDirection: ListViewItemHeaderStickDirection = .top - let stickOverInsets: Bool = false + public let stickDirection: ListViewItemHeaderStickDirection = .top + public let stickOverInsets: Bool = false - let height: CGFloat = 38.0 + public let height: CGFloat = 38.0 public func combinesWith(other: ListViewItemHeader) -> Bool { if let other = other as? ChatMessageAvatarHeader, other.id == self.id { @@ -416,11 +416,11 @@ final class ChatMessageAvatarHeader: ListViewItemHeader { } } - func node(synchronousLoad: Bool) -> ListViewItemHeaderNode { + public func node(synchronousLoad: Bool) -> ListViewItemHeaderNode { return ChatMessageAvatarHeaderNodeImpl(peerId: self.peerId, peer: self.peer, messageReference: self.messageReference, adMessageId: self.adMessageId, presentationData: self.presentationData, context: self.context, controllerInteraction: self.controllerInteraction, storyStats: self.storyStats, synchronousLoad: synchronousLoad) } - func updateNode(_ node: ListViewItemHeaderNode, previous: ListViewItemHeader?, next: ListViewItemHeader?) { + public func updateNode(_ node: ListViewItemHeaderNode, previous: ListViewItemHeader?, next: ListViewItemHeader?) { guard let node = node as? ChatMessageAvatarHeaderNodeImpl else { return } @@ -433,7 +433,7 @@ private let avatarFont = avatarPlaceholderFont(size: 16.0) private let maxVideoLoopCount = 3 -final class ChatMessageAvatarHeaderNodeImpl: ListViewItemHeaderNode { +public final class ChatMessageAvatarHeaderNodeImpl: ListViewItemHeaderNode { private let context: AccountContext private var presentationData: ChatPresentationData private let controllerInteraction: ChatControllerInteraction @@ -445,7 +445,7 @@ final class ChatMessageAvatarHeaderNodeImpl: ListViewItemHeaderNode { private let adMessageId: EngineMessage.Id? private let containerNode: ContextControllerSourceNode - let avatarNode: AvatarNode + public let avatarNode: AvatarNode private var avatarVideoNode: AvatarVideoNode? private var cachedDataDisposable = MetaDisposable() @@ -466,7 +466,7 @@ final class ChatMessageAvatarHeaderNodeImpl: ListViewItemHeaderNode { } } - init(peerId: PeerId, peer: Peer?, messageReference: MessageReference?, adMessageId: EngineMessage.Id?, presentationData: ChatPresentationData, context: AccountContext, controllerInteraction: ChatControllerInteraction, storyStats: PeerStoryStats?, synchronousLoad: Bool) { + public init(peerId: PeerId, peer: Peer?, messageReference: MessageReference?, adMessageId: EngineMessage.Id?, presentationData: ChatPresentationData, context: AccountContext, controllerInteraction: ChatControllerInteraction, storyStats: PeerStoryStats?, synchronousLoad: Bool) { self.peerId = peerId self.peer = peer self.messageReference = messageReference @@ -513,13 +513,13 @@ final class ChatMessageAvatarHeaderNodeImpl: ListViewItemHeaderNode { self.cachedDataDisposable.dispose() } - func setCustomLetters(context: AccountContext, theme: PresentationTheme, synchronousLoad: Bool, letters: [String], emptyColor: UIColor) { + public func setCustomLetters(context: AccountContext, theme: PresentationTheme, synchronousLoad: Bool, letters: [String], emptyColor: UIColor) { self.containerNode.isGestureEnabled = false self.avatarNode.setCustomLetters(letters, icon: !letters.isEmpty ? nil : .phone) } - func setPeer(context: AccountContext, theme: PresentationTheme, synchronousLoad: Bool, peer: Peer, authorOfMessage: MessageReference?, emptyColor: UIColor) { + public func setPeer(context: AccountContext, theme: PresentationTheme, synchronousLoad: Bool, peer: Peer, authorOfMessage: MessageReference?, emptyColor: UIColor) { self.containerNode.isGestureEnabled = peer.smallProfileImage != nil var overrideImage: AvatarNodeImageOverride? @@ -608,7 +608,7 @@ final class ChatMessageAvatarHeaderNodeImpl: ListViewItemHeaderNode { } } - func updateStoryStats(storyStats: PeerStoryStats?, theme: PresentationTheme, force: Bool) { + public func updateStoryStats(storyStats: PeerStoryStats?, theme: PresentationTheme, force: Bool) { /*if storyStats != nil { var backgroundContent: WallpaperBubbleBackgroundNode? if let current = self.backgroundContent { @@ -657,42 +657,42 @@ final class ChatMessageAvatarHeaderNodeImpl: ListViewItemHeaderNode { }*/ } - override func didLoad() { + override public func didLoad() { super.didLoad() self.avatarNode.view.addGestureRecognizer(ListViewTapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:)))) } - func updatePresentationData(_ presentationData: ChatPresentationData, context: AccountContext) { + public func updatePresentationData(_ presentationData: ChatPresentationData, context: AccountContext) { if self.presentationData !== presentationData { self.presentationData = presentationData self.setNeedsLayout() } } - override func updateLayout(size: CGSize, leftInset: CGFloat, rightInset: CGFloat) { + override public func updateLayout(size: CGSize, leftInset: CGFloat, rightInset: CGFloat) { self.containerNode.frame = CGRect(origin: CGPoint(x: leftInset + 3.0, y: 0.0), size: CGSize(width: 38.0, height: 38.0)) self.avatarNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: 38.0, height: 38.0)) } - override func animateRemoved(duration: Double) { + override public func animateRemoved(duration: Double) { self.alpha = 0.0 self.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration, removeOnCompletion: false) self.avatarNode.layer.animateScale(from: 1.0, to: 0.2, duration: duration, removeOnCompletion: false) } - override func animateAdded(duration: Double) { + override public func animateAdded(duration: Double) { self.layer.animateAlpha(from: 0.0, to: self.alpha, duration: 0.2) self.avatarNode.layer.animateScale(from: 0.2, to: 1.0, duration: 0.2) } - override func updateStickDistanceFactor(_ factor: CGFloat, transition: ContainedViewLayoutTransition) { + override public func updateStickDistanceFactor(_ factor: CGFloat, transition: ContainedViewLayoutTransition) { } - override func updateFlashingOnScrolling(_ isFlashingOnScrolling: Bool, animated: Bool) { + override public func updateFlashingOnScrolling(_ isFlashingOnScrolling: Bool, animated: Bool) { } - func updateSelectionState(animated: Bool) { + public func updateSelectionState(animated: Bool) { let offset: CGFloat = self.controllerInteraction.selectionState != nil ? 42.0 : 0.0 let previousSubnodeTransform = self.subnodeTransform @@ -702,7 +702,7 @@ final class ChatMessageAvatarHeaderNodeImpl: ListViewItemHeaderNode { } } - override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { if !self.bounds.contains(point) { return nil } @@ -710,11 +710,11 @@ final class ChatMessageAvatarHeaderNodeImpl: ListViewItemHeaderNode { return result } - override func touchesCancelled(_ touches: Set?, with event: UIEvent?) { + override public func touchesCancelled(_ touches: Set?, with event: UIEvent?) { super.touchesCancelled(touches, with: event) } - @objc func tapGesture(_ recognizer: ListViewTapGestureRecognizer) { + @objc private func tapGesture(_ recognizer: ListViewTapGestureRecognizer) { if case .ended = recognizer.state { if self.peerId.namespace == Namespaces.Peer.Empty, case let .message(_, _, id, _, _, _) = self.messageReference?.content { self.controllerInteraction.displayMessageTooltip(id, self.presentationData.strings.Conversation_ForwardAuthorHiddenTooltip, self, self.avatarNode.frame) diff --git a/submodules/TelegramUI/Sources/ChatMessageItemImpl.swift b/submodules/TelegramUI/Components/Chat/ChatMessageItemImpl/Sources/ChatMessageItemImpl.swift similarity index 99% rename from submodules/TelegramUI/Sources/ChatMessageItemImpl.swift rename to submodules/TelegramUI/Components/Chat/ChatMessageItemImpl/Sources/ChatMessageItemImpl.swift index 75d7ebdeba..4ed32c279c 100644 --- a/submodules/TelegramUI/Sources/ChatMessageItemImpl.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageItemImpl/Sources/ChatMessageItemImpl.swift @@ -137,7 +137,7 @@ private func messagesShouldBeMerged(accountPeerId: PeerId, _ lhs: Message, _ rhs return .none } -func chatItemsHaveCommonDateHeader(_ lhs: ListViewItem, _ rhs: ListViewItem?) -> Bool{ +public func chatItemsHaveCommonDateHeader(_ lhs: ListViewItem, _ rhs: ListViewItem?) -> Bool{ let lhsHeader: ChatMessageDateHeader? let rhsHeader: ChatMessageDateHeader? if let lhs = lhs as? ChatMessageItemImpl { diff --git a/submodules/TelegramUI/Sources/ChatReplyCountItem.swift b/submodules/TelegramUI/Components/Chat/ChatMessageItemImpl/Sources/ChatReplyCountItem.swift similarity index 85% rename from submodules/TelegramUI/Sources/ChatReplyCountItem.swift rename to submodules/TelegramUI/Components/Chat/ChatMessageItemImpl/Sources/ChatReplyCountItem.swift index 855eb10ec8..e16d544a70 100644 --- a/submodules/TelegramUI/Sources/ChatReplyCountItem.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageItemImpl/Sources/ChatReplyCountItem.swift @@ -12,15 +12,15 @@ import ChatMessageItemCommon private let titleFont = UIFont.systemFont(ofSize: 13.0) -class ChatReplyCountItem: ListViewItem { - let index: MessageIndex - let isComments: Bool - let count: Int - let presentationData: ChatPresentationData - let header: ChatMessageDateHeader - let controllerInteraction: ChatControllerInteraction +public class ChatReplyCountItem: ListViewItem { + public let index: MessageIndex + public let isComments: Bool + public let count: Int + public let presentationData: ChatPresentationData + public let header: ChatMessageDateHeader + public let controllerInteraction: ChatControllerInteraction - init(index: MessageIndex, isComments: Bool, count: Int, presentationData: ChatPresentationData, context: AccountContext, controllerInteraction: ChatControllerInteraction) { + public init(index: MessageIndex, isComments: Bool, count: Int, presentationData: ChatPresentationData, context: AccountContext, controllerInteraction: ChatControllerInteraction) { self.index = index self.isComments = isComments self.count = count @@ -29,7 +29,7 @@ class ChatReplyCountItem: ListViewItem { self.controllerInteraction = controllerInteraction } - func nodeConfiguredForParams(async: @escaping (@escaping () -> Void) -> Void, params: ListViewItemLayoutParams, synchronousLoads: Bool, previousItem: ListViewItem?, nextItem: ListViewItem?, completion: @escaping (ListViewItemNode, @escaping () -> (Signal?, (ListViewItemApply) -> Void)) -> Void) { + public func nodeConfiguredForParams(async: @escaping (@escaping () -> Void) -> Void, params: ListViewItemLayoutParams, synchronousLoads: Bool, previousItem: ListViewItem?, nextItem: ListViewItem?, completion: @escaping (ListViewItemNode, @escaping () -> (Signal?, (ListViewItemApply) -> Void)) -> Void) { async { let node = ChatReplyCountItemNode() Queue.mainQueue().async { @@ -63,8 +63,8 @@ class ChatReplyCountItem: ListViewItem { } } -class ChatReplyCountItemNode: ListViewItemNode { - var item: ChatReplyCountItem? +public class ChatReplyCountItemNode: ListViewItemNode { + public var item: ChatReplyCountItem? private let labelNode: TextNode private var backgroundNode: WallpaperBubbleBackgroundNode? private let backgroundColorNode: ASDisplayNode @@ -75,7 +75,7 @@ class ChatReplyCountItemNode: ListViewItemNode { private var absoluteRect: (CGRect, CGSize)? - init() { + public init() { self.labelNode = TextNode() self.labelNode.isUserInteractionEnabled = false @@ -91,17 +91,17 @@ class ChatReplyCountItemNode: ListViewItemNode { self.canBeUsedAsScrollToItemAnchor = false } - override func animateInsertion(_ currentTimestamp: Double, duration: Double, short: Bool) { + override public func animateInsertion(_ currentTimestamp: Double, duration: Double, short: Bool) { super.animateInsertion(currentTimestamp, duration: duration, short: short) self.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.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) } - override func layoutForParams(_ params: ListViewItemLayoutParams, item: ListViewItem, previousItem: ListViewItem?, nextItem: ListViewItem?) { + override public func layoutForParams(_ params: ListViewItemLayoutParams, item: ListViewItem, previousItem: ListViewItem?, nextItem: ListViewItem?) { if let item = item as? ChatReplyCountItem { let dateAtBottom = !chatItemsHaveCommonDateHeader(item, nextItem) let (layout, apply) = self.asyncLayout()(item, params, dateAtBottom) @@ -111,7 +111,7 @@ class ChatReplyCountItemNode: ListViewItemNode { } } - func asyncLayout() -> (_ item: ChatReplyCountItem, _ params: ListViewItemLayoutParams, _ dateAtBottom: Bool) -> (ListViewItemNodeLayout, () -> Void) { + public func asyncLayout() -> (_ item: ChatReplyCountItem, _ params: ListViewItemLayoutParams, _ dateAtBottom: Bool) -> (ListViewItemNodeLayout, () -> Void) { let makeLabelLayout = TextNode.asyncLayout(self.labelNode) let layoutConstants = self.layoutConstants @@ -192,7 +192,7 @@ class ChatReplyCountItemNode: ListViewItemNode { } } - override func updateAbsoluteRect(_ rect: CGRect, within containerSize: CGSize) { + override public func updateAbsoluteRect(_ rect: CGRect, within containerSize: CGSize) { var rect = rect rect.origin.y = containerSize.height - rect.maxY + self.insets.top @@ -207,7 +207,7 @@ class ChatReplyCountItemNode: ListViewItemNode { } } - override func applyAbsoluteOffset(value: CGPoint, animationCurve: ContainedViewLayoutTransitionCurve, duration: Double) { + override public func applyAbsoluteOffset(value: CGPoint, animationCurve: ContainedViewLayoutTransitionCurve, duration: Double) { if let backgroundNode = self.backgroundNode { backgroundNode.offset(value: CGPoint(x: value.x, y: -value.y), animationCurve: animationCurve, duration: duration) } diff --git a/submodules/TelegramUI/Sources/ChatUnreadItem.swift b/submodules/TelegramUI/Components/Chat/ChatMessageItemImpl/Sources/ChatUnreadItem.swift similarity index 84% rename from submodules/TelegramUI/Sources/ChatUnreadItem.swift rename to submodules/TelegramUI/Components/Chat/ChatMessageItemImpl/Sources/ChatUnreadItem.swift index 87cfa3ffa8..95604423a5 100644 --- a/submodules/TelegramUI/Sources/ChatUnreadItem.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageItemImpl/Sources/ChatUnreadItem.swift @@ -12,20 +12,20 @@ import ChatMessageItemCommon private let titleFont = UIFont.systemFont(ofSize: 13.0) -class ChatUnreadItem: ListViewItem { - let index: MessageIndex - let presentationData: ChatPresentationData - let controllerInteraction: ChatControllerInteraction - let header: ChatMessageDateHeader +public class ChatUnreadItem: ListViewItem { + public let index: MessageIndex + public let presentationData: ChatPresentationData + public let controllerInteraction: ChatControllerInteraction + public let header: ChatMessageDateHeader - init(index: MessageIndex, presentationData: ChatPresentationData, controllerInteraction: ChatControllerInteraction, context: AccountContext) { + public init(index: MessageIndex, presentationData: ChatPresentationData, controllerInteraction: ChatControllerInteraction, context: AccountContext) { self.index = index self.presentationData = presentationData self.controllerInteraction = controllerInteraction self.header = ChatMessageDateHeader(timestamp: index.timestamp, scheduled: false, presentationData: presentationData, controllerInteraction: controllerInteraction, context: context) } - func nodeConfiguredForParams(async: @escaping (@escaping () -> Void) -> Void, params: ListViewItemLayoutParams, synchronousLoads: Bool, previousItem: ListViewItem?, nextItem: ListViewItem?, completion: @escaping (ListViewItemNode, @escaping () -> (Signal?, (ListViewItemApply) -> Void)) -> Void) { + public func nodeConfiguredForParams(async: @escaping (@escaping () -> Void) -> Void, params: ListViewItemLayoutParams, synchronousLoads: Bool, previousItem: ListViewItem?, nextItem: ListViewItem?, completion: @escaping (ListViewItemNode, @escaping () -> (Signal?, (ListViewItemApply) -> Void)) -> Void) { async { let node = ChatUnreadItemNode() @@ -67,12 +67,12 @@ class ChatUnreadItem: ListViewItem { } } -class ChatUnreadItemNode: ListViewItemNode { - var item: ChatUnreadItem? - let backgroundNode: ASImageNode - let labelNode: TextNode +public class ChatUnreadItemNode: ListViewItemNode { + public var item: ChatUnreadItem? + public let backgroundNode: ASImageNode + public let labelNode: TextNode - let activateArea: AccessibilityAreaNode + public let activateArea: AccessibilityAreaNode private var wallpaperBackgroundNode: WallpaperBackgroundNode? private var backgroundContent: WallpaperBubbleBackgroundNode? @@ -83,7 +83,7 @@ class ChatUnreadItemNode: ListViewItemNode { private let layoutConstants = ChatMessageItemLayoutConstants.default - init() { + public init() { self.backgroundNode = ASImageNode() self.backgroundNode.isLayerBacked = true self.backgroundNode.displayWithoutProcessing = true @@ -108,17 +108,17 @@ class ChatUnreadItemNode: ListViewItemNode { self.canBeUsedAsScrollToItemAnchor = false } - override func animateInsertion(_ currentTimestamp: Double, duration: Double, short: Bool) { + override public func animateInsertion(_ currentTimestamp: Double, duration: Double, short: Bool) { super.animateInsertion(currentTimestamp, duration: duration, short: short) self.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.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) } - override func layoutForParams(_ params: ListViewItemLayoutParams, item: ListViewItem, previousItem: ListViewItem?, nextItem: ListViewItem?) { + override public func layoutForParams(_ params: ListViewItemLayoutParams, item: ListViewItem, previousItem: ListViewItem?, nextItem: ListViewItem?) { if let item = item as? ChatUnreadItem { let dateAtBottom = !chatItemsHaveCommonDateHeader(item, nextItem) let (layout, apply) = self.asyncLayout()(item, params, dateAtBottom) @@ -128,7 +128,7 @@ class ChatUnreadItemNode: ListViewItemNode { } } - func asyncLayout() -> (_ item: ChatUnreadItem, _ params: ListViewItemLayoutParams, _ dateAtBottom: Bool) -> (ListViewItemNodeLayout, () -> Void) { + public func asyncLayout() -> (_ item: ChatUnreadItem, _ params: ListViewItemLayoutParams, _ dateAtBottom: Bool) -> (ListViewItemNodeLayout, () -> Void) { let labelLayout = TextNode.asyncLayout(self.labelNode) let layoutConstants = self.layoutConstants let currentTheme = self.theme @@ -187,7 +187,7 @@ class ChatUnreadItemNode: ListViewItemNode { } } - override func updateAbsoluteRect(_ rect: CGRect, within containerSize: CGSize) { + override public func updateAbsoluteRect(_ rect: CGRect, within containerSize: CGSize) { super.updateAbsoluteRect(rect, within: containerSize) self.absolutePosition = (rect, containerSize) diff --git a/submodules/TelegramUI/Components/Chat/ChatNavigationButton/BUILD b/submodules/TelegramUI/Components/Chat/ChatNavigationButton/BUILD new file mode 100644 index 0000000000..7c7d0d30c1 --- /dev/null +++ b/submodules/TelegramUI/Components/Chat/ChatNavigationButton/BUILD @@ -0,0 +1,17 @@ +load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") + +swift_library( + name = "ChatNavigationButton", + module_name = "ChatNavigationButton", + srcs = glob([ + "Sources/**/*.swift", + ]), + copts = [ + "-warnings-as-errors", + ], + deps = [ + ], + visibility = [ + "//visibility:public", + ], +) diff --git a/submodules/TelegramUI/Components/Chat/ChatNavigationButton/Sources/ChatNavigationButton.swift b/submodules/TelegramUI/Components/Chat/ChatNavigationButton/Sources/ChatNavigationButton.swift new file mode 100644 index 0000000000..3feb62f0d8 --- /dev/null +++ b/submodules/TelegramUI/Components/Chat/ChatNavigationButton/Sources/ChatNavigationButton.swift @@ -0,0 +1,27 @@ +import Foundation +import UIKit + +public enum ChatNavigationButtonAction: Equatable { + case openChatInfo(expandAvatar: Bool) + case clearHistory + case clearCache + case cancelMessageSelection + case search + case dismiss + case toggleInfoPanel + case spacer +} + +public struct ChatNavigationButton: Equatable { + public let action: ChatNavigationButtonAction + public let buttonItem: UIBarButtonItem + + public init(action: ChatNavigationButtonAction, buttonItem: UIBarButtonItem) { + self.action = action + self.buttonItem = buttonItem + } + + public static func ==(lhs: ChatNavigationButton, rhs: ChatNavigationButton) -> Bool { + return lhs.action == rhs.action && lhs.buttonItem === rhs.buttonItem + } +} diff --git a/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/BUILD b/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/BUILD new file mode 100644 index 0000000000..afcda60459 --- /dev/null +++ b/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/BUILD @@ -0,0 +1,54 @@ +load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") + +swift_library( + name = "ChatRecentActionsController", + module_name = "ChatRecentActionsController", + srcs = glob([ + "Sources/**/*.swift", + ]), + copts = [ + "-warnings-as-errors", + ], + deps = [ + "//submodules/AccountContext", + "//submodules/AlertUI", + "//submodules/AsyncDisplayKit", + "//submodules/BotPaymentsUI", + "//submodules/TelegramUI/Components/ChatControllerInteraction", + "//submodules/TelegramUI/Components/Chat/ChatHistoryEntry", + "//submodules/TelegramUI/Components/Chat/ChatMessageItemView", + "//submodules/TelegramUI/Components/Chat/ChatMessageItemImpl", + "//submodules/TelegramUI/Components/Chat/ChatNavigationButton", + "//submodules/TelegramUI/Components/Chat/ChatLoadingNode", + "//submodules/ChatPresentationInterfaceState", + "//submodules/ContextUI", + "//submodules/Display", + "//submodules/HashtagSearchUI", + "//submodules/InstantPageUI", + "//submodules/InviteLinksUI", + "//submodules/ItemListPeerItem", + "//submodules/ItemListUI", + "//submodules/JoinLinkPreviewUI", + "//submodules/LanguageLinkPreviewUI", + "//submodules/MergeLists", + "//submodules/OpenInExternalAppUI", + "//submodules/Pasteboard", + "//submodules/PeerInfoUI", + "//submodules/Postbox", + "//submodules/PresentationDataUtils", + "//submodules/SearchBarNode", + "//submodules/StickerPackPreviewUI", + "//submodules/SSignalKit/SwiftSignalKit", + "//submodules/TelegramBaseController", + "//submodules/TelegramCallsUI", + "//submodules/TelegramCore", + "//submodules/TelegramPresentationData", + "//submodules/TelegramUIPreferences", + "//submodules/TemporaryCachedPeerDataManager", + "//submodules/UndoUI", + "//submodules/WallpaperBackgroundNode", + ], + visibility = [ + "//visibility:public", + ], +) diff --git a/submodules/TelegramUI/Sources/ChatRecentActionsController.swift b/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsController.swift similarity index 97% rename from submodules/TelegramUI/Sources/ChatRecentActionsController.swift rename to submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsController.swift index 95c9098a72..fae2294c6b 100644 --- a/submodules/TelegramUI/Sources/ChatRecentActionsController.swift +++ b/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsController.swift @@ -10,8 +10,9 @@ import AccountContext import AlertUI import PresentationDataUtils import ChatPresentationInterfaceState +import ChatNavigationButton -final class ChatRecentActionsController: TelegramBaseController { +public final class ChatRecentActionsController: TelegramBaseController { private var controllerNode: ChatRecentActionsControllerNode { return self.displayNode as! ChatRecentActionsControllerNode } @@ -21,7 +22,7 @@ final class ChatRecentActionsController: TelegramBaseController { private let initialAdminPeerId: PeerId? private var presentationData: PresentationData private var presentationDataPromise = Promise() - override var updatedPresentationData: (PresentationData, Signal) { + override public var updatedPresentationData: (PresentationData, Signal) { return (self.presentationData, self.presentationDataPromise.get()) } private var presentationDataDisposable: Disposable? @@ -32,7 +33,7 @@ final class ChatRecentActionsController: TelegramBaseController { private let titleView: ChatRecentActionsTitleView - init(context: AccountContext, peer: Peer, adminPeerId: PeerId?) { + public init(context: AccountContext, peer: Peer, adminPeerId: PeerId?) { self.context = context self.peer = peer self.initialAdminPeerId = adminPeerId @@ -219,7 +220,7 @@ final class ChatRecentActionsController: TelegramBaseController { }) } - required init(coder aDecoder: NSCoder) { + required public init(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } @@ -240,7 +241,7 @@ final class ChatRecentActionsController: TelegramBaseController { self.controllerNode.updatePresentationData(self.presentationData) } - override func loadDisplayNode() { + override public func loadDisplayNode() { self.displayNode = ChatRecentActionsControllerNode(context: self.context, controller: self, peer: self.peer, presentationData: self.presentationData, interaction: self.interaction, pushController: { [weak self] c in (self?.navigationController as? NavigationController)?.pushViewController(c) }, presentController: { [weak self] c, t, a in @@ -267,7 +268,7 @@ final class ChatRecentActionsController: TelegramBaseController { self.controllerNode.containerLayoutUpdated(layout, navigationBarHeight: self.navigationLayout(layout: layout).navigationFrame.maxY, transition: transition) } - @objc func activateSearch() { + @objc private func activateSearch() { if let navigationBar = self.navigationBar { if !(navigationBar.contentNode is ChatRecentActionsSearchNavigationContentNode) { let searchNavigationNode = ChatRecentActionsSearchNavigationContentNode(theme: self.presentationData.theme, strings: self.presentationData.strings, cancel: { [weak self] in diff --git a/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift b/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsControllerNode.swift similarity index 98% rename from submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift rename to submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsControllerNode.swift index a3576e10e5..1fdad85bfa 100644 --- a/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsControllerNode.swift @@ -29,6 +29,7 @@ import Pasteboard import ChatControllerInteraction import ChatPresentationInterfaceState import ChatMessageItemView +import ChatLoadingNode private final class ChatRecentActionsListOpaqueState { let entries: [ChatRecentActionsEntry] @@ -279,11 +280,11 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { self?.openUrl(url) }, shareCurrentLocation: {}, shareAccountContact: {}, sendBotCommand: { _, _ in }, openInstantPage: { [weak self] message, associatedData in if let strongSelf = self, let navigationController = strongSelf.getNavigationController() { - openChatInstantPage(context: strongSelf.context, message: message, sourcePeerType: associatedData?.automaticDownloadPeerType, navigationController: navigationController) + strongSelf.context.sharedContext.openChatInstantPage(context: strongSelf.context, message: message, sourcePeerType: associatedData?.automaticDownloadPeerType, navigationController: navigationController) } }, openWallpaper: { [weak self] message in if let strongSelf = self{ - openChatWallpaper(context: strongSelf.context, message: message, present: { [weak self] c, a in + strongSelf.context.sharedContext.openChatWallpaper(context: strongSelf.context, message: message, present: { [weak self] c, a in self?.pushController(c) }) } @@ -1187,3 +1188,17 @@ final class ChatRecentActionsMessageContextExtractedContentSource: ContextExtrac return result } } + +final class ChatMessageContextLocationContentSource: ContextLocationContentSource { + private let controller: ViewController + private let location: CGPoint + + init(controller: ViewController, location: CGPoint) { + self.controller = controller + self.location = location + } + + func transitionInfo() -> ContextControllerLocationViewInfo? { + return ContextControllerLocationViewInfo(location: self.location, contentAreaInScreenSpace: UIScreen.main.bounds) + } +} diff --git a/submodules/TelegramUI/Sources/ChatRecentActionsEmptyNode.swift b/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsEmptyNode.swift similarity index 94% rename from submodules/TelegramUI/Sources/ChatRecentActionsEmptyNode.swift rename to submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsEmptyNode.swift index 3dbceb060f..0b2e4048a3 100644 --- a/submodules/TelegramUI/Sources/ChatRecentActionsEmptyNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsEmptyNode.swift @@ -10,7 +10,7 @@ import ChatPresentationInterfaceState private let titleFont = Font.medium(16.0) private let textFont = Font.regular(15.0) -final class ChatRecentActionsEmptyNode: ASDisplayNode { +public final class ChatRecentActionsEmptyNode: ASDisplayNode { private var theme: PresentationTheme private var chatWallpaper: TelegramWallpaper @@ -28,7 +28,7 @@ final class ChatRecentActionsEmptyNode: ASDisplayNode { private var title: String = "" private var text: String = "" - init(theme: PresentationTheme, chatWallpaper: TelegramWallpaper, chatBubbleCorners: PresentationChatBubbleCorners) { + public init(theme: PresentationTheme, chatWallpaper: TelegramWallpaper, chatBubbleCorners: PresentationChatBubbleCorners) { self.theme = theme self.chatWallpaper = chatWallpaper @@ -59,7 +59,7 @@ final class ChatRecentActionsEmptyNode: ASDisplayNode { } } - func updateLayout(presentationData: ChatPresentationData, backgroundNode: WallpaperBackgroundNode, size: CGSize, transition: ContainedViewLayoutTransition) { + public func updateLayout(presentationData: ChatPresentationData, backgroundNode: WallpaperBackgroundNode, size: CGSize, transition: ContainedViewLayoutTransition) { self.wallpaperBackgroundNode = backgroundNode self.layoutParams = (size, presentationData) @@ -119,7 +119,7 @@ final class ChatRecentActionsEmptyNode: ASDisplayNode { } } - func setup(title: String, text: String) { + public func setup(title: String, text: String) { if self.title != title || self.text != text { self.title = title self.text = text diff --git a/submodules/TelegramUI/Sources/ChatRecentActionsFilterController.swift b/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsFilterController.swift similarity index 100% rename from submodules/TelegramUI/Sources/ChatRecentActionsFilterController.swift rename to submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsFilterController.swift diff --git a/submodules/TelegramUI/Sources/ChatRecentActionsHistoryTransition.swift b/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsHistoryTransition.swift similarity index 99% rename from submodules/TelegramUI/Sources/ChatRecentActionsHistoryTransition.swift rename to submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsHistoryTransition.swift index c552988cbb..fa417ad0e6 100644 --- a/submodules/TelegramUI/Sources/ChatRecentActionsHistoryTransition.swift +++ b/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsHistoryTransition.swift @@ -8,6 +8,7 @@ import MergeLists import AccountContext import ChatControllerInteraction import ChatHistoryEntry +import ChatMessageItemImpl enum ChatRecentActionsEntryContentIndex: Int32 { case header = 0 diff --git a/submodules/TelegramUI/Sources/ChatRecentActionsInteraction.swift b/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsInteraction.swift similarity index 100% rename from submodules/TelegramUI/Sources/ChatRecentActionsInteraction.swift rename to submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsInteraction.swift diff --git a/submodules/TelegramUI/Sources/ChatRecentActionsSearchNavigationContentNode.swift b/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsSearchNavigationContentNode.swift similarity index 100% rename from submodules/TelegramUI/Sources/ChatRecentActionsSearchNavigationContentNode.swift rename to submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsSearchNavigationContentNode.swift diff --git a/submodules/TelegramUI/Sources/ChatRecentActionsTitleView.swift b/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsTitleView.swift similarity index 100% rename from submodules/TelegramUI/Sources/ChatRecentActionsTitleView.swift rename to submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsTitleView.swift diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 68b054a33a..81bcb43c9c 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -108,10 +108,12 @@ import ReplyAccessoryPanelNode import TextSelectionNode import ChatMessagePollBubbleContentNode import ChatMessageItem +import ChatMessageItemImpl import ChatMessageItemView import ChatMessageItemCommon import ChatMessageAnimatedStickerItemNode import ChatMessageBubbleItemNode +import ChatNavigationButton public enum ChatControllerPeekActions { case standard @@ -2862,7 +2864,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if let strongSelf = self, strongSelf.isNodeLoaded, let navigationController = strongSelf.effectiveNavigationController, let message = strongSelf.chatDisplayNode.historyNode.messageInCurrentHistoryView(message.id) { let _ = strongSelf.presentVoiceMessageDiscardAlert(action: { strongSelf.chatDisplayNode.dismissInput() - openChatInstantPage(context: strongSelf.context, message: message, sourcePeerType: associatedData?.automaticDownloadPeerType, navigationController: navigationController) + strongSelf.context.sharedContext.openChatInstantPage(context: strongSelf.context, message: message, sourcePeerType: associatedData?.automaticDownloadPeerType, navigationController: navigationController) if case .overlay = strongSelf.presentationInterfaceState.mode { strongSelf.chatDisplayNode.dismissAsOverlay() @@ -2873,7 +2875,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if let strongSelf = self, strongSelf.isNodeLoaded, let message = strongSelf.chatDisplayNode.historyNode.messageInCurrentHistoryView(message.id) { let _ = strongSelf.presentVoiceMessageDiscardAlert(action: { strongSelf.chatDisplayNode.dismissInput() - openChatWallpaper(context: strongSelf.context, message: message, present: { [weak self] c, a in + strongSelf.context.sharedContext.openChatWallpaper(context: strongSelf.context, message: message, present: { [weak self] c, a in self?.push(c) }) }) @@ -19499,33 +19501,6 @@ final class ChatControllerContextReferenceContentSource: ContextReferenceContent } } - -extension Peer { - func canSetupAutoremoveTimeout(accountPeerId: PeerId) -> Bool { - if let _ = self as? TelegramSecretChat { - return false - } else if let group = self as? TelegramGroup { - if case .creator = group.role { - return true - } else if case let .admin(rights, _) = group.role { - if rights.rights.contains(.canDeleteMessages) { - return true - } - } - } else if let user = self as? TelegramUser { - if user.id != accountPeerId && user.botInfo == nil { - return true - } - } else if let channel = self as? TelegramChannel { - if channel.hasPermission(.deleteAllMessages) { - return true - } - } - - return false - } -} - enum AllowedReactions { case set(Set) case all diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index e4dc236d50..98862f8173 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -36,6 +36,8 @@ import ChatMessageItemView import ChatMessageSelectionNode import ManagedDiceAnimationNode import ChatMessageTransitionNode +import ChatLoadingNode +import ChatRecentActionsController final class VideoNavigationControllerDropContentItem: NavigationControllerDropContentItem { let itemNode: OverlayMediaItemNode diff --git a/submodules/TelegramUI/Sources/ChatEmptyNode.swift b/submodules/TelegramUI/Sources/ChatEmptyNode.swift index 6c7c7ffe6f..f511b9dafa 100644 --- a/submodules/TelegramUI/Sources/ChatEmptyNode.swift +++ b/submodules/TelegramUI/Sources/ChatEmptyNode.swift @@ -14,6 +14,7 @@ import ChatPresentationInterfaceState import WallpaperBackgroundNode import ComponentFlow import EmojiStatusComponent +import ChatLoadingNode private protocol ChatEmptyNodeContent { func updateLayout(interfaceState: ChatPresentationInterfaceState, subject: ChatEmptyNode.Subject, size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize diff --git a/submodules/TelegramUI/Sources/ChatHistoryListNode.swift b/submodules/TelegramUI/Sources/ChatHistoryListNode.swift index 9d846edc90..bdb15fa184 100644 --- a/submodules/TelegramUI/Sources/ChatHistoryListNode.swift +++ b/submodules/TelegramUI/Sources/ChatHistoryListNode.swift @@ -27,6 +27,7 @@ import ChatHistoryEntry import ChatOverscrollControl import ChatBotInfoItem import ChatMessageItem +import ChatMessageItemImpl import ChatMessageItemView import ChatMessageTransitionNode diff --git a/submodules/TelegramUI/Sources/ChatInterfaceStateNavigationButtons.swift b/submodules/TelegramUI/Sources/ChatInterfaceStateNavigationButtons.swift index 6223fc77fb..ea75b73364 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceStateNavigationButtons.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceStateNavigationButtons.swift @@ -6,26 +6,7 @@ import TelegramCore import TelegramPresentationData import AccountContext import ChatPresentationInterfaceState - -enum ChatNavigationButtonAction: Equatable { - case openChatInfo(expandAvatar: Bool) - case clearHistory - case clearCache - case cancelMessageSelection - case search - case dismiss - case toggleInfoPanel - case spacer -} - -struct ChatNavigationButton: Equatable { - let action: ChatNavigationButtonAction - let buttonItem: UIBarButtonItem - - static func ==(lhs: ChatNavigationButton, rhs: ChatNavigationButton) -> Bool { - return lhs.action == rhs.action && lhs.buttonItem === rhs.buttonItem - } -} +import ChatNavigationButton func leftNavigationButtonForChatInterfaceState(_ presentationInterfaceState: ChatPresentationInterfaceState, subject: ChatControllerSubject?, strings: PresentationStrings, currentButton: ChatNavigationButton?, target: Any?, selector: Selector?) -> ChatNavigationButton? { if let _ = presentationInterfaceState.interfaceState.selectionState { diff --git a/submodules/TelegramUI/Sources/ChatMessageContextControllerContentSource.swift b/submodules/TelegramUI/Sources/ChatMessageContextControllerContentSource.swift index 6ecbbd7f33..67be725233 100644 --- a/submodules/TelegramUI/Sources/ChatMessageContextControllerContentSource.swift +++ b/submodules/TelegramUI/Sources/ChatMessageContextControllerContentSource.swift @@ -21,7 +21,6 @@ final class ChatMessageContextLocationContentSource: ContextLocationContentSourc } } - final class ChatMessageContextExtractedContentSource: ContextExtractedContentSource { let keepInPlace: Bool = false let ignoreContentTouches: Bool = false diff --git a/submodules/TelegramUI/Sources/OpenChatMessage.swift b/submodules/TelegramUI/Sources/OpenChatMessage.swift index 3471adcb02..4564d1a6d1 100644 --- a/submodules/TelegramUI/Sources/OpenChatMessage.swift +++ b/submodules/TelegramUI/Sources/OpenChatMessage.swift @@ -366,7 +366,7 @@ func openChatMessageImpl(_ params: OpenChatMessageParams) -> Bool { return false } -func openChatInstantPage(context: AccountContext, message: Message, sourcePeerType: MediaAutoDownloadPeerType?, navigationController: NavigationController) { +func openChatInstantPageImpl(context: AccountContext, message: Message, sourcePeerType: MediaAutoDownloadPeerType?, navigationController: NavigationController) { if let (webpage, anchor) = instantPageAndAnchor(message: message) { let sourceLocation = InstantPageSourceLocation(userLocation: .peer(message.id.peerId), peerType: sourcePeerType ?? .channel) @@ -375,7 +375,7 @@ func openChatInstantPage(context: AccountContext, message: Message, sourcePeerTy } } -func openChatWallpaper(context: AccountContext, message: Message, present: @escaping (ViewController, Any?) -> Void) { +func openChatWallpaperImpl(context: AccountContext, message: Message, present: @escaping (ViewController, Any?) -> Void) { for media in message.media { if let webpage = media as? TelegramMediaWebpage, case let .Loaded(content) = webpage.content { let _ = (context.sharedContext.resolveUrl(context: context, peerId: nil, url: content.url, skipUrlAuth: true) diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift index e389eb176a..13cad18441 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift @@ -2790,7 +2790,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro } if let foundGalleryMessage = foundGalleryMessage { - openChatInstantPage(context: strongSelf.context, message: foundGalleryMessage, sourcePeerType: associatedData?.automaticDownloadPeerType, navigationController: navigationController) + strongSelf.context.sharedContext.openChatInstantPage(context: strongSelf.context, message: foundGalleryMessage, sourcePeerType: associatedData?.automaticDownloadPeerType, navigationController: navigationController) } }, openWallpaper: { _ in }, openTheme: { _ in diff --git a/submodules/TelegramUI/Sources/SharedAccountContext.swift b/submodules/TelegramUI/Sources/SharedAccountContext.swift index a29d0fd8bc..8d416794c0 100644 --- a/submodules/TelegramUI/Sources/SharedAccountContext.swift +++ b/submodules/TelegramUI/Sources/SharedAccountContext.swift @@ -45,6 +45,8 @@ import LegacyMessageInputPanel import StatisticsUI import ChatHistoryEntry import ChatMessageItem +import ChatMessageItemImpl +import ChatRecentActionsController private final class AccountUserInterfaceInUseContext { let subscribers = Bag<(Bool) -> Void>() @@ -1601,6 +1603,14 @@ public final class SharedAccountContextImpl: SharedAccountContext { }) } + public func openChatInstantPage(context: AccountContext, message: Message, sourcePeerType: MediaAutoDownloadPeerType?, navigationController: NavigationController) { + openChatInstantPageImpl(context: context, message: message, sourcePeerType: sourcePeerType, navigationController: navigationController) + } + + public func openChatWallpaper(context: AccountContext, message: Message, present: @escaping (ViewController, Any?) -> Void) { + openChatWallpaperImpl(context: context, message: message, present: present) + } + public func makeRecentSessionsController(context: AccountContext, activeSessionsContext: ActiveSessionsContext) -> ViewController & RecentSessionsController { return recentSessionsController(context: context, activeSessionsContext: activeSessionsContext, webSessionsContext: context.engine.privacy.webSessions(), websitesOnly: false) }