Bot previews

This commit is contained in:
Isaac
2024-07-24 01:56:34 +08:00
parent f604bc114f
commit 42a6f6e8bc
52 changed files with 3806 additions and 523 deletions

View File

@@ -43,6 +43,7 @@ import ChatInlineSearchResultsListComponent
import ComponentDisplayAdapters
import ComponentFlow
import ChatEmptyNode
import SpaceWarpView
final class VideoNavigationControllerDropContentItem: NavigationControllerDropContentItem {
let itemNode: OverlayMediaItemNode
@@ -86,6 +87,41 @@ private struct ChatControllerNodeDerivedLayoutState {
var upperInputPositionBound: CGFloat?
}
class ChatNodeContainer: ASDisplayNode {
private let contentNodeImpl: ASDisplayNode
var contentNode: ASDisplayNode {
if self.view is SpaceWarpView {
return self.contentNodeImpl
} else {
return self
}
}
override init() {
self.contentNodeImpl = ASDisplayNode()
super.init()
#if DEBUG && false
self.setViewBlock({
return SpaceWarpView(frame: CGRect())
})
#endif
(self.view as? SpaceWarpView)?.contentView.addSubnode(self.contentNodeImpl)
}
func triggerRipple(at point: CGPoint) {
(self.view as? SpaceWarpView)?.trigger(at: point)
}
func update(size: CGSize, transition: ContainedViewLayoutTransition) {
transition.updateFrame(node: self.contentNodeImpl, frame: CGRect(origin: CGPoint(), size: size))
(self.view as? SpaceWarpView)?.update(size: size, transition: ComponentTransition(transition))
}
}
class HistoryNodeContainer: ASDisplayNode {
var isSecret: Bool {
didSet {
@@ -95,7 +131,19 @@ class HistoryNodeContainer: ASDisplayNode {
}
}
private let contentNodeImpl: ASDisplayNode
var contentNode: ASDisplayNode {
if self.view is SpaceWarpView {
return self.contentNodeImpl
} else {
return self
}
}
init(isSecret: Bool) {
self.contentNodeImpl = ASDisplayNode()
self.isSecret = isSecret
super.init()
@@ -103,6 +151,23 @@ class HistoryNodeContainer: ASDisplayNode {
if self.isSecret {
setLayerDisableScreenshots(self.layer, self.isSecret)
}
#if DEBUG && false
self.setViewBlock({
return SpaceWarpView(frame: CGRect())
})
#endif
(self.view as? SpaceWarpView)?.contentView.addSubnode(self.contentNodeImpl)
}
func triggerRipple(at point: CGPoint) {
(self.view as? SpaceWarpView)?.trigger(at: point)
}
func update(size: CGSize, transition: ContainedViewLayoutTransition) {
transition.updateFrame(node: self.contentNodeImpl, frame: CGRect(origin: CGPoint(), size: size))
(self.view as? SpaceWarpView)?.update(size: size, transition: ComponentTransition(transition))
}
}
@@ -127,12 +192,12 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
}
}
let contentContainerNode: ASDisplayNode
let contentContainerNode: ChatNodeContainer
let contentDimNode: ASDisplayNode
let backgroundNode: WallpaperBackgroundNode
let historyNode: ChatHistoryListNodeImpl
var blurredHistoryNode: ASImageNode?
let historyNodeContainer: ASDisplayNode
let historyNodeContainer: HistoryNodeContainer
let loadingNode: ChatLoadingNode
private(set) var loadingPlaceholderNode: ChatLoadingPlaceholderNode?
@@ -379,7 +444,7 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
self.backgroundNode = backgroundNode
self.contentContainerNode = ASDisplayNode()
self.contentContainerNode = ChatNodeContainer()
self.contentDimNode = ASDisplayNode()
self.contentDimNode.isUserInteractionEnabled = false
self.contentDimNode.backgroundColor = UIColor(white: 0.0, alpha: 0.2)
@@ -633,7 +698,7 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
self.historyNodeContainer = HistoryNodeContainer(isSecret: chatLocation.peerId?.namespace == Namespaces.Peer.SecretChat)
self.historyNodeContainer.addSubnode(self.historyNode)
self.historyNodeContainer.contentNode.addSubnode(self.historyNode)
var getContentAreaInScreenSpaceImpl: (() -> CGRect)?
var onTransitionEventImpl: ((ContainedViewLayoutTransition) -> Void)?
@@ -787,11 +852,11 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
self.historyNode.enableExtractedBackgrounds = true
self.addSubnode(self.contentContainerNode)
self.contentContainerNode.addSubnode(self.backgroundNode)
self.contentContainerNode.addSubnode(self.historyNodeContainer)
self.contentContainerNode.contentNode.addSubnode(self.backgroundNode)
self.contentContainerNode.contentNode.addSubnode(self.historyNodeContainer)
if let navigationBar = self.navigationBar {
self.contentContainerNode.addSubnode(navigationBar)
self.contentContainerNode.contentNode.addSubnode(navigationBar)
}
self.inputPanelContainerNode.expansionUpdated = { [weak self] transition in
@@ -817,9 +882,9 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
self.inputPanelBackgroundNode.addSubnode(self.inputPanelBottomBackgroundSeparatorNode)
self.addSubnode(self.messageTransitionNode)
self.contentContainerNode.addSubnode(self.navigateButtons)
self.contentContainerNode.contentNode.addSubnode(self.navigateButtons)
self.addSubnode(self.presentationContextMarker)
self.contentContainerNode.addSubnode(self.contentDimNode)
self.contentContainerNode.contentNode.addSubnode(self.contentDimNode)
self.navigationBar?.additionalContentNode.addSubnode(self.titleAccessoryPanelContainer)
@@ -1004,9 +1069,9 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
self.emptyNode = emptyNode
if let inlineSearchResultsView = self.inlineSearchResults?.view {
self.contentContainerNode.view.insertSubview(emptyNode.view, belowSubview: inlineSearchResultsView)
self.contentContainerNode.contentNode.view.insertSubview(emptyNode.view, belowSubview: inlineSearchResultsView)
} else {
self.contentContainerNode.insertSubnode(emptyNode, aboveSubnode: self.historyNodeContainer)
self.contentContainerNode.contentNode.insertSubnode(emptyNode, aboveSubnode: self.historyNodeContainer)
}
if let (size, insets) = self.validEmptyNodeLayout {
@@ -1081,12 +1146,10 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
}
}
if let historyNodeContainer = self.historyNodeContainer as? HistoryNodeContainer {
let isSecret = self.chatPresentationInterfaceState.copyProtectionEnabled || self.chatLocation.peerId?.namespace == Namespaces.Peer.SecretChat
if historyNodeContainer.isSecret != isSecret {
historyNodeContainer.isSecret = isSecret
setLayerDisableScreenshots(self.titleAccessoryPanelContainer.layer, isSecret)
}
let isSecret = self.chatPresentationInterfaceState.copyProtectionEnabled || self.chatLocation.peerId?.namespace == Namespaces.Peer.SecretChat
if self.historyNodeContainer.isSecret != isSecret {
self.historyNodeContainer.isSecret = isSecret
setLayerDisableScreenshots(self.titleAccessoryPanelContainer.layer, isSecret)
}
var previousListBottomInset: CGFloat?
@@ -1097,6 +1160,7 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
self.messageTransitionNode.frame = CGRect(origin: CGPoint(), size: layout.size)
self.contentContainerNode.frame = CGRect(origin: CGPoint(), size: layout.size)
self.contentContainerNode.update(size: layout.size, transition: transition)
let isOverlay: Bool
switch self.chatPresentationInterfaceState.mode {
@@ -1239,10 +1303,10 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
if let containerNode = self.containerNode {
self.containerNode = nil
containerNode.removeFromSupernode()
self.contentContainerNode.insertSubnode(self.backgroundNode, at: 0)
self.contentContainerNode.insertSubnode(self.historyNodeContainer, aboveSubnode: self.backgroundNode)
self.contentContainerNode.contentNode.insertSubnode(self.backgroundNode, at: 0)
self.contentContainerNode.contentNode.insertSubnode(self.historyNodeContainer, aboveSubnode: self.backgroundNode)
if let restrictedNode = self.restrictedNode {
self.contentContainerNode.insertSubnode(restrictedNode, aboveSubnode: self.historyNodeContainer)
self.contentContainerNode.contentNode.insertSubnode(restrictedNode, aboveSubnode: self.historyNodeContainer)
}
self.navigationBar?.isHidden = false
}
@@ -1392,7 +1456,7 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
if self.chatImportStatusPanel != importStatusPanelNode {
dismissedImportStatusPanelNode = self.chatImportStatusPanel
self.chatImportStatusPanel = importStatusPanelNode
self.contentContainerNode.addSubnode(importStatusPanelNode)
self.contentContainerNode.contentNode.addSubnode(importStatusPanelNode)
}
importStatusPanelHeight = importStatusPanelNode.update(context: self.context, progress: CGFloat(importState.progress), presentationData: ChatPresentationData(theme: ChatPresentationThemeData(theme: self.chatPresentationInterfaceState.theme, wallpaper: self.chatPresentationInterfaceState.chatWallpaper), fontSize: self.chatPresentationInterfaceState.fontSize, strings: self.chatPresentationInterfaceState.strings, dateTimeFormat: self.chatPresentationInterfaceState.dateTimeFormat, nameDisplayOrder: self.chatPresentationInterfaceState.nameDisplayOrder, disableAnimations: false, largeEmoji: false, chatBubbleCorners: PresentationChatBubbleCorners(mainRadius: 0.0, auxiliaryRadius: 0.0, mergeBubbleCorners: false)), width: layout.size.width)
@@ -1732,6 +1796,7 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
transition.updateBounds(node: self.historyNodeContainer, bounds: contentBounds)
transition.updatePosition(node: self.historyNodeContainer, position: contentBounds.center)
self.historyNodeContainer.update(size: contentBounds.size, transition: transition)
transition.updateBounds(node: self.historyNode, bounds: CGRect(origin: CGPoint(), size: contentBounds.size))
transition.updatePosition(node: self.historyNode, position: CGPoint(x: contentBounds.size.width / 2.0, y: contentBounds.size.height / 2.0))
@@ -1779,7 +1844,7 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
dismissedOverlayContextPanelNode = self.overlayContextPanelNode
self.overlayContextPanelNode = overlayContextPanelNode
self.contentContainerNode.addSubnode(overlayContextPanelNode)
self.contentContainerNode.contentNode.addSubnode(overlayContextPanelNode)
immediatelyLayoutOverlayContextPanelAndAnimateAppearance = true
}
} else if let overlayContextPanelNode = self.overlayContextPanelNode {
@@ -1999,7 +2064,7 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
expandedInputDimNode.backgroundColor = UIColor(white: 0.0, alpha: 0.5)
expandedInputDimNode.alpha = 0.0
self.expandedInputDimNode = expandedInputDimNode
self.contentContainerNode.insertSubnode(expandedInputDimNode, aboveSubnode: self.historyNodeContainer)
self.contentContainerNode.contentNode.insertSubnode(expandedInputDimNode, aboveSubnode: self.historyNodeContainer)
transition.updateAlpha(node: expandedInputDimNode, alpha: 1.0)
expandedInputDimNode.frame = exandedFrame
transition.animatePositionAdditive(node: expandedInputDimNode, offset: CGPoint(x: 0.0, y: previousInputPanelOrigin.y - inputPanelOrigin))
@@ -2831,9 +2896,9 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
self.skippedShowSearchResultsAsListAnimationOnce = true
inlineSearchResultsView.layer.allowsGroupOpacity = true
if let emptyNode = self.emptyNode {
self.contentContainerNode.view.insertSubview(inlineSearchResultsView, aboveSubview: emptyNode.view)
self.contentContainerNode.contentNode.view.insertSubview(inlineSearchResultsView, aboveSubview: emptyNode.view)
} else {
self.contentContainerNode.view.insertSubview(inlineSearchResultsView, aboveSubview: self.historyNodeContainer.view)
self.contentContainerNode.contentNode.view.insertSubview(inlineSearchResultsView, aboveSubview: self.historyNodeContainer.view)
}
}
inlineSearchResultsTransition.setFrame(view: inlineSearchResultsView, frame: CGRect(origin: CGPoint(), size: layout.size))
@@ -3269,15 +3334,20 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
@objc func tapGesture(_ recognizer: UITapGestureRecognizer) {
if recognizer.state == .ended {
self.dismissInput()
self.dismissInput(view: self.view, location: recognizer.location(in: self.contentContainerNode.view))
}
}
func dismissInput() {
func dismissInput(view: UIView? = nil, location: CGPoint? = nil) {
if let _ = self.chatPresentationInterfaceState.inputTextPanelState.mediaRecordingState {
return
}
if let view, let location {
self.contentContainerNode.triggerRipple(at: self.contentContainerNode.view.convert(location, from: view))
self.historyNodeContainer.triggerRipple(at: self.historyNodeContainer.view.convert(location, from: view))
}
switch self.chatPresentationInterfaceState.inputMode {
case .none:
break
@@ -3739,7 +3809,7 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
let dropDimNode = ASDisplayNode()
dropDimNode.backgroundColor = self.chatPresentationInterfaceState.theme.chatList.backgroundColor.withAlphaComponent(0.35)
self.dropDimNode = dropDimNode
self.contentContainerNode.addSubnode(dropDimNode)
self.contentContainerNode.contentNode.addSubnode(dropDimNode)
if let (layout, _) = self.validLayout {
dropDimNode.frame = CGRect(origin: CGPoint(), size: layout.size)
dropDimNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25)