Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios

This commit is contained in:
Ilya Laktyushin 2023-06-21 16:54:48 +04:00
commit fc8d25851a
14 changed files with 185 additions and 108 deletions

View File

@ -1435,7 +1435,7 @@ public final class PeerInfoAvatarListContainerNode: ASDisplayNode {
transition.updateAlpha(node: self.setByYouNode, alpha: 0.7) transition.updateAlpha(node: self.setByYouNode, alpha: 0.7)
self.setByYouNode.attributedText = NSAttributedString(string: photoTitle, font: Font.regular(12.0), textColor: UIColor.white) self.setByYouNode.attributedText = NSAttributedString(string: photoTitle, font: Font.regular(12.0), textColor: UIColor.white)
let setByYouSize = self.setByYouNode.updateLayout(size) let setByYouSize = self.setByYouNode.updateLayout(size)
self.setByYouNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - setByYouSize.width) / 2.0), y: 17.0), size: setByYouSize) self.setByYouNode.frame = CGRect(origin: CGPoint(x: size.width - setByYouSize.width - 14.0, y: size.height - setByYouSize.height - 58.0), size: setByYouSize)
self.setByYouNode.isUserInteractionEnabled = hasLink self.setByYouNode.isUserInteractionEnabled = hasLink
} else { } else {
transition.updateAlpha(node: self.setByYouNode, alpha: 0.0) transition.updateAlpha(node: self.setByYouNode, alpha: 0.0)
@ -1445,7 +1445,7 @@ public final class PeerInfoAvatarListContainerNode: ASDisplayNode {
if let fallbackImageSignal = fallbackImageSignal { if let fallbackImageSignal = fallbackImageSignal {
self.setByYouImageNode.setSignal(fallbackImageSignal) self.setByYouImageNode.setSignal(fallbackImageSignal)
transition.updateAlpha(node: self.setByYouImageNode, alpha: 1.0) transition.updateAlpha(node: self.setByYouImageNode, alpha: 1.0)
self.setByYouImageNode.frame = CGRect(origin: CGPoint(x: self.setByYouNode.frame.minX - 32.0, y: 11.0), size: CGSize(width: 28.0, height: 28.0)) self.setByYouImageNode.frame = CGRect(origin: CGPoint(x: self.setByYouNode.frame.minX - 32.0, y: self.setByYouNode.frame.minY - 7.0), size: CGSize(width: 28.0, height: 28.0))
} else { } else {
transition.updateAlpha(node: self.setByYouImageNode, alpha: 0.0) transition.updateAlpha(node: self.setByYouImageNode, alpha: 0.0)
} }

View File

@ -376,6 +376,7 @@ swift_library(
"//submodules/TelegramUI/Components/Stories/AvatarStoryIndicatorComponent", "//submodules/TelegramUI/Components/Stories/AvatarStoryIndicatorComponent",
"//submodules/TelegramUI/Components/Stories/StorySetIndicatorComponent", "//submodules/TelegramUI/Components/Stories/StorySetIndicatorComponent",
"//submodules/TelegramUI/Components/Chat/ChatMessageForwardInfoNode", "//submodules/TelegramUI/Components/Chat/ChatMessageForwardInfoNode",
"//submodules/TelegramUI/Components/Chat/ChatAvatarNavigationNode",
"//submodules/Utils/VolumeButtons", "//submodules/Utils/VolumeButtons",
"//submodules/ChatContextQuery", "//submodules/ChatContextQuery",
] + select({ ] + select({

View File

@ -0,0 +1,35 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
swift_library(
name = "ChatAvatarNavigationNode",
module_name = "ChatAvatarNavigationNode",
srcs = glob([
"Sources/**/*.swift",
]),
copts = [
"-warnings-as-errors",
],
deps = [
"//submodules/AsyncDisplayKit",
"//submodules/Display",
"//submodules/SSignalKit/SwiftSignalKit",
"//submodules/Postbox",
"//submodules/TelegramCore",
"//submodules/AvatarNode",
"//submodules/ContextUI",
"//submodules/TelegramPresentationData",
"//submodules/TelegramUniversalVideoContent",
"//submodules/MediaPlayer:UniversalMediaPlayer",
"//submodules/GalleryUI",
"//submodules/Components/HierarchyTrackingLayer",
"//submodules/AccountContext",
"//submodules/ComponentFlow",
"//submodules/TelegramUI/Components/EmojiStatusComponent",
"//submodules/AvatarVideoNode",
"//submodules/TelegramUI/Components/Stories/AvatarStoryIndicatorComponent",
"//submodules/Components/ComponentDisplayAdapters",
],
visibility = [
"//visibility:public",
],
)

View File

@ -16,18 +16,23 @@ import AccountContext
import ComponentFlow import ComponentFlow
import EmojiStatusComponent import EmojiStatusComponent
import AvatarVideoNode import AvatarVideoNode
import AvatarStoryIndicatorComponent
import ComponentDisplayAdapters
private let normalFont = avatarPlaceholderFont(size: 16.0) private let normalFont = avatarPlaceholderFont(size: 16.0)
private let smallFont = avatarPlaceholderFont(size: 12.0) private let smallFont = avatarPlaceholderFont(size: 12.0)
final class ChatAvatarNavigationNode: ASDisplayNode { public final class ChatAvatarNavigationNode: ASDisplayNode {
private var context: AccountContext? private var context: AccountContext?
private let containerNode: ContextControllerSourceNode private let containerNode: ContextControllerSourceNode
let avatarNode: AvatarNode public let avatarNode: AvatarNode
private var avatarVideoNode: AvatarVideoNode? private var avatarVideoNode: AvatarVideoNode?
let statusView: ComponentView<Empty> public private(set) var avatarStoryView: ComponentView<Empty>?
public var hasUnseenStories: Bool?
public let statusView: ComponentView<Empty>
private var cachedDataDisposable = MetaDisposable() private var cachedDataDisposable = MetaDisposable()
private var hierarchyTrackingLayer: HierarchyTrackingLayer? private var hierarchyTrackingLayer: HierarchyTrackingLayer?
@ -42,8 +47,8 @@ final class ChatAvatarNavigationNode: ASDisplayNode {
} }
} }
var contextAction: ((ASDisplayNode, ContextGesture?) -> Void)? public var contextAction: ((ASDisplayNode, ContextGesture?) -> Void)?
var contextActionIsEnabled: Bool = false { public var contextActionIsEnabled: Bool = false {
didSet { didSet {
if self.contextActionIsEnabled != oldValue { if self.contextActionIsEnabled != oldValue {
self.containerNode.isGestureEnabled = self.contextActionIsEnabled self.containerNode.isGestureEnabled = self.contextActionIsEnabled
@ -51,7 +56,7 @@ final class ChatAvatarNavigationNode: ASDisplayNode {
} }
} }
override init() { override public init() {
self.containerNode = ContextControllerSourceNode() self.containerNode = ContextControllerSourceNode()
self.containerNode.isGestureEnabled = false self.containerNode.isGestureEnabled = false
self.avatarNode = AvatarNode(font: normalFont) self.avatarNode = AvatarNode(font: normalFont)
@ -71,13 +76,17 @@ final class ChatAvatarNavigationNode: ASDisplayNode {
self.containerNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: 37.0, height: 37.0)).offsetBy(dx: 10.0, dy: 1.0) self.containerNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: 37.0, height: 37.0)).offsetBy(dx: 10.0, dy: 1.0)
self.avatarNode.frame = self.containerNode.bounds self.avatarNode.frame = self.containerNode.bounds
#if DEBUG
self.hasUnseenStories = true
#endif
} }
deinit { deinit {
self.cachedDataDisposable.dispose() self.cachedDataDisposable.dispose()
} }
override func didLoad() { override public func didLoad() {
super.didLoad() super.didLoad()
self.view.isOpaque = false self.view.isOpaque = false
} }
@ -190,14 +199,49 @@ final class ChatAvatarNavigationNode: ASDisplayNode {
} }
} }
override func calculateSizeThatFits(_ constrainedSize: CGSize) -> CGSize { public func updateStoryView(transition: ContainedViewLayoutTransition, theme: PresentationTheme) {
if let hasUnseenStories = self.hasUnseenStories {
let avatarStoryView: ComponentView<Empty>
if let current = self.avatarStoryView {
avatarStoryView = current
} else {
avatarStoryView = ComponentView()
self.avatarStoryView = avatarStoryView
}
let _ = avatarStoryView.update(
transition: Transition(transition),
component: AnyComponent(AvatarStoryIndicatorComponent(
hasUnseen: hasUnseenStories,
isDarkTheme: theme.overallDarkAppearance,
activeLineWidth: 1.0,
inactiveLineWidth: 1.0
)),
environment: {},
containerSize: self.avatarNode.bounds.insetBy(dx: 2.0, dy: 2.0).size
)
if let avatarStoryComponentView = avatarStoryView.view {
if avatarStoryComponentView.superview == nil {
self.containerNode.view.insertSubview(avatarStoryComponentView, at: 0)
}
avatarStoryComponentView.frame = self.avatarNode.frame
}
} else {
if let avatarStoryView = self.avatarStoryView {
self.avatarStoryView = nil
avatarStoryView.view?.removeFromSuperview()
}
}
}
override public func calculateSizeThatFits(_ constrainedSize: CGSize) -> CGSize {
return CGSize(width: 37.0, height: 37.0) return CGSize(width: 37.0, height: 37.0)
} }
func onLayout() { public func onLayout() {
} }
final class SnapshotState { public final class SnapshotState {
fileprivate let snapshotView: UIView? fileprivate let snapshotView: UIView?
fileprivate init(snapshotView: UIView?) { fileprivate init(snapshotView: UIView?) {
@ -205,14 +249,14 @@ final class ChatAvatarNavigationNode: ASDisplayNode {
} }
} }
func prepareSnapshotState() -> SnapshotState { public func prepareSnapshotState() -> SnapshotState {
let snapshotView = self.avatarNode.view.snapshotView(afterScreenUpdates: false) let snapshotView = self.avatarNode.view.snapshotView(afterScreenUpdates: false)
return SnapshotState( return SnapshotState(
snapshotView: snapshotView snapshotView: snapshotView
) )
} }
func animateFromSnapshot(_ snapshotState: SnapshotState) { public func animateFromSnapshot(_ snapshotState: SnapshotState) {
self.avatarNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3) self.avatarNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
self.avatarNode.layer.animateScale(from: 0.1, to: 1.0, duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: true) self.avatarNode.layer.animateScale(from: 0.1, to: 1.0, duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: true)

View File

@ -11,11 +11,20 @@ swift_library(
], ],
deps = [ deps = [
"//submodules/AsyncDisplayKit", "//submodules/AsyncDisplayKit",
"//submodules/Display",
"//submodules/Postbox", "//submodules/Postbox",
"//submodules/Display",
"//submodules/TelegramCore", "//submodules/TelegramCore",
"//submodules/SSignalKit/SwiftSignalKit",
"//submodules/TelegramPresentationData", "//submodules/TelegramPresentationData",
"//submodules/AccountContext",
"//submodules/LocalizedPeerData", "//submodules/LocalizedPeerData",
"//submodules/PhotoResources",
"//submodules/TelegramStringFormatting",
"//submodules/TextFormat",
"//submodules/InvisibleInkDustNode",
"//submodules/TelegramUI/Components/TextNodeWithEntities",
"//submodules/TelegramUI/Components/AnimationCache",
"//submodules/TelegramUI/Components/MultiAnimationRenderer",
], ],
visibility = [ visibility = [
"//visibility:public", "//visibility:public",

View File

@ -429,7 +429,10 @@ public final class ChatListNavigationBar: Component {
tabsFrame.origin.y -= 46.0 tabsFrame.origin.y -= 46.0
} }
let accessoryPanelContainerFrame = CGRect(origin: CGPoint(x: 0.0, y: visibleSize.height - component.accessoryPanelContainerHeight), size: CGSize(width: visibleSize.width, height: component.accessoryPanelContainerHeight)) var accessoryPanelContainerFrame = CGRect(origin: CGPoint(x: 0.0, y: visibleSize.height), size: CGSize(width: visibleSize.width, height: component.accessoryPanelContainerHeight))
if !component.isSearchActive {
accessoryPanelContainerFrame.origin.y -= component.accessoryPanelContainerHeight
}
if let disappearingTabsView = self.disappearingTabsView { if let disappearingTabsView = self.disappearingTabsView {
disappearingTabsView.layer.anchorPoint = CGPoint() disappearingTabsView.layer.anchorPoint = CGPoint()
@ -466,6 +469,7 @@ public final class ChatListNavigationBar: Component {
var tabsNodeTransition = transition var tabsNodeTransition = transition
if accessoryPanelContainer.view.superview !== self { if accessoryPanelContainer.view.superview !== self {
accessoryPanelContainer.view.layer.anchorPoint = CGPoint() accessoryPanelContainer.view.layer.anchorPoint = CGPoint()
accessoryPanelContainer.clipsToBounds = true
tabsNodeTransition = .immediate tabsNodeTransition = .immediate
accessoryPanelContainer.view.alpha = 1.0 accessoryPanelContainer.view.alpha = 1.0
self.addSubview(accessoryPanelContainer.view) self.addSubview(accessoryPanelContainer.view)

View File

@ -1038,7 +1038,7 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
guard let self else { guard let self else {
return return
} }
self.view.insertSubview(view, aboveSubview: self.itemGrid.view) self.addToTransitionSurface(view: view)
} }
), ),
destinationRect: self.itemGrid.view.convert(itemRect, to: self.view), destinationRect: self.itemGrid.view.convert(itemRect, to: self.view),

View File

@ -552,6 +552,10 @@ private final class StoryContainerScreenComponent: Component {
focusedItemPromise.set(.single(nil)) focusedItemPromise.set(.single(nil))
}) })
} else { } else {
if let component = self.component, let stateValue = component.content.stateValue, let slice = stateValue.slice, let transitionOut = component.transitionOut(slice.peer.id, slice.item.id) {
transitionOut.completed()
}
let transition: Transition let transition: Transition
if self.dismissWithoutTransitionOut { if self.dismissWithoutTransitionOut {
transition = Transition(animation: .curve(duration: 0.5, curve: .spring)) transition = Transition(animation: .curve(duration: 0.5, curve: .spring))

View File

@ -537,6 +537,9 @@ public final class StoryContentContextImpl: StoryContentContext {
} }
var sortedItems: [EngineStorySubscriptions.Item] = [] var sortedItems: [EngineStorySubscriptions.Item] = []
if !startedWithUnseen, let accountItem = storySubscriptions.accountItem, accountItem.storyCount != 0 {
sortedItems.append(accountItem)
}
for peerId in self.fixedSubscriptionOrder { for peerId in self.fixedSubscriptionOrder {
if let index = storySubscriptions.items.firstIndex(where: { $0.peer.id == peerId }) { if let index = storySubscriptions.items.firstIndex(where: { $0.peer.id == peerId }) {
sortedItems.append(storySubscriptions.items[index]) sortedItems.append(storySubscriptions.items[index])
@ -607,13 +610,48 @@ public final class StoryContentContextImpl: StoryContentContext {
} }
} }
if let (focusedPeerId, _) = self.focusedItem, focusedPeerId == self.context.account.peerId { var centralIndex: Int?
let centralPeerContext = PeerContext(context: self.context, peerId: self.context.account.peerId, focusedId: nil, loadIds: loadIds) if let (focusedPeerId, _) = self.focusedItem {
if let index = subscriptionItems.firstIndex(where: { $0.peer.id == focusedPeerId }) {
centralIndex = index
}
}
if centralIndex == nil {
if !subscriptionItems.isEmpty {
centralIndex = 0
}
}
if let centralIndex {
let centralPeerContext: PeerContext
if let currentState = self.currentState, let existingContext = currentState.findPeerContext(id: subscriptionItems[centralIndex].peer.id) {
centralPeerContext = existingContext
} else {
centralPeerContext = PeerContext(context: self.context, peerId: subscriptionItems[centralIndex].peer.id, focusedId: nil, loadIds: loadIds)
}
var previousPeerContext: PeerContext?
if centralIndex != 0 {
if let currentState = self.currentState, let existingContext = currentState.findPeerContext(id: subscriptionItems[centralIndex - 1].peer.id) {
previousPeerContext = existingContext
} else {
previousPeerContext = PeerContext(context: self.context, peerId: subscriptionItems[centralIndex - 1].peer.id, focusedId: nil, loadIds: loadIds)
}
}
var nextPeerContext: PeerContext?
if centralIndex != subscriptionItems.count - 1 {
if let currentState = self.currentState, let existingContext = currentState.findPeerContext(id: subscriptionItems[centralIndex + 1].peer.id) {
nextPeerContext = existingContext
} else {
nextPeerContext = PeerContext(context: self.context, peerId: subscriptionItems[centralIndex + 1].peer.id, focusedId: nil, loadIds: loadIds)
}
}
let pendingState = StateContext( let pendingState = StateContext(
centralPeerContext: centralPeerContext, centralPeerContext: centralPeerContext,
previousPeerContext: nil, previousPeerContext: previousPeerContext,
nextPeerContext: nil nextPeerContext: nextPeerContext
) )
self.pendingState = pendingState self.pendingState = pendingState
self.pendingStateReadyDisposable = (pendingState.updated.get() self.pendingStateReadyDisposable = (pendingState.updated.get()
@ -638,74 +676,6 @@ public final class StoryContentContextImpl: StoryContentContext {
self.updateState() self.updateState()
}) })
}) })
} else {
var centralIndex: Int?
if let (focusedPeerId, _) = self.focusedItem {
if let index = subscriptionItems.firstIndex(where: { $0.peer.id == focusedPeerId }) {
centralIndex = index
}
}
if centralIndex == nil {
if !subscriptionItems.isEmpty {
centralIndex = 0
}
}
if let centralIndex {
let centralPeerContext: PeerContext
if let currentState = self.currentState, let existingContext = currentState.findPeerContext(id: subscriptionItems[centralIndex].peer.id) {
centralPeerContext = existingContext
} else {
centralPeerContext = PeerContext(context: self.context, peerId: subscriptionItems[centralIndex].peer.id, focusedId: nil, loadIds: loadIds)
}
var previousPeerContext: PeerContext?
if centralIndex != 0 {
if let currentState = self.currentState, let existingContext = currentState.findPeerContext(id: subscriptionItems[centralIndex - 1].peer.id) {
previousPeerContext = existingContext
} else {
previousPeerContext = PeerContext(context: self.context, peerId: subscriptionItems[centralIndex - 1].peer.id, focusedId: nil, loadIds: loadIds)
}
}
var nextPeerContext: PeerContext?
if centralIndex != subscriptionItems.count - 1 {
if let currentState = self.currentState, let existingContext = currentState.findPeerContext(id: subscriptionItems[centralIndex + 1].peer.id) {
nextPeerContext = existingContext
} else {
nextPeerContext = PeerContext(context: self.context, peerId: subscriptionItems[centralIndex + 1].peer.id, focusedId: nil, loadIds: loadIds)
}
}
let pendingState = StateContext(
centralPeerContext: centralPeerContext,
previousPeerContext: previousPeerContext,
nextPeerContext: nextPeerContext
)
self.pendingState = pendingState
self.pendingStateReadyDisposable = (pendingState.updated.get()
|> deliverOnMainQueue).start(next: { [weak self, weak pendingState] _ in
guard let self, let pendingState, self.pendingState === pendingState, pendingState.isReady else {
return
}
self.pendingState = nil
self.pendingStateReadyDisposable?.dispose()
self.pendingStateReadyDisposable = nil
self.currentState = pendingState
self.updateState()
self.currentStateUpdatedDisposable?.dispose()
self.currentStateUpdatedDisposable = (pendingState.updated.get()
|> deliverOnMainQueue).start(next: { [weak self, weak pendingState] _ in
guard let self, let pendingState, self.currentState === pendingState else {
return
}
self.updateState()
})
})
}
} }
} }
} }

View File

@ -98,6 +98,7 @@ import StoryContainerScreen
import StoryContentComponent import StoryContentComponent
import MoreHeaderButton import MoreHeaderButton
import VolumeButtons import VolumeButtons
import ChatAvatarNavigationNode
import ChatContextQuery import ChatContextQuery
#if DEBUG #if DEBUG
@ -562,6 +563,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
private var powerSavingMonitoringDisposable: Disposable? private var powerSavingMonitoringDisposable: Disposable?
private var avatarNode: ChatAvatarNavigationNode?
public init(context: AccountContext, chatLocation: ChatLocation, chatLocationContextHolder: Atomic<ChatLocationContextHolder?> = Atomic<ChatLocationContextHolder?>(value: nil), subject: ChatControllerSubject? = nil, botStart: ChatControllerInitialBotStart? = nil, attachBotStart: ChatControllerInitialAttachBotStart? = nil, botAppStart: ChatControllerInitialBotAppStart? = nil, mode: ChatControllerPresentationMode = .standard(previewing: false), peekData: ChatPeekTimeout? = nil, peerNearbyData: ChatPeerNearbyData? = nil, chatListFilter: Int32? = nil, chatNavigationStack: [ChatNavigationStackItem] = []) { public init(context: AccountContext, chatLocation: ChatLocation, chatLocationContextHolder: Atomic<ChatLocationContextHolder?> = Atomic<ChatLocationContextHolder?>(value: nil), subject: ChatControllerSubject? = nil, botStart: ChatControllerInitialBotStart? = nil, attachBotStart: ChatControllerInitialAttachBotStart? = nil, botAppStart: ChatControllerInitialBotAppStart? = nil, mode: ChatControllerPresentationMode = .standard(previewing: false), peekData: ChatPeekTimeout? = nil, peerNearbyData: ChatPeerNearbyData? = nil, chatListFilter: Int32? = nil, chatNavigationStack: [ChatNavigationStackItem] = []) {
let _ = ChatControllerCount.modify { value in let _ = ChatControllerCount.modify { value in
return value + 1 return value + 1
@ -4688,7 +4691,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
strongSelf.presentInGlobalOverlay(contextController) strongSelf.presentInGlobalOverlay(contextController)
} }
chatInfoButtonItem = UIBarButtonItem(customDisplayNode: avatarNode)! chatInfoButtonItem = UIBarButtonItem(customDisplayNode: avatarNode)!
self.avatarNode = avatarNode
avatarNode.updateStoryView(transition: .immediate, theme: self.presentationData.theme)
case .feed: case .feed:
chatInfoButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil) chatInfoButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
} }

View File

@ -24,6 +24,7 @@ import ChatTitleView
import ChatInputNode import ChatInputNode
import ChatEntityKeyboardInputNode import ChatEntityKeyboardInputNode
import ChatControllerInteraction import ChatControllerInteraction
import ChatAvatarNavigationNode
final class VideoNavigationControllerDropContentItem: NavigationControllerDropContentItem { final class VideoNavigationControllerDropContentItem: NavigationControllerDropContentItem {
let itemNode: OverlayMediaItemNode let itemNode: OverlayMediaItemNode

View File

@ -16,26 +16,26 @@ import TextNodeWithEntities
import AnimationCache import AnimationCache
import MultiAnimationRenderer import MultiAnimationRenderer
enum ChatMessageReplyInfoType { public enum ChatMessageReplyInfoType {
case bubble(incoming: Bool) case bubble(incoming: Bool)
case standalone case standalone
} }
class ChatMessageReplyInfoNode: ASDisplayNode { public class ChatMessageReplyInfoNode: ASDisplayNode {
class Arguments { public class Arguments {
let presentationData: ChatPresentationData public let presentationData: ChatPresentationData
let strings: PresentationStrings public let strings: PresentationStrings
let context: AccountContext public let context: AccountContext
let type: ChatMessageReplyInfoType public let type: ChatMessageReplyInfoType
let message: Message? public let message: Message?
let story: StoryId? public let story: StoryId?
let parentMessage: Message public let parentMessage: Message
let constrainedSize: CGSize public let constrainedSize: CGSize
let animationCache: AnimationCache? public let animationCache: AnimationCache?
let animationRenderer: MultiAnimationRenderer? public let animationRenderer: MultiAnimationRenderer?
let associatedData: ChatMessageItemAssociatedData public let associatedData: ChatMessageItemAssociatedData
init( public init(
presentationData: ChatPresentationData, presentationData: ChatPresentationData,
strings: PresentationStrings, strings: PresentationStrings,
context: AccountContext, context: AccountContext,
@ -62,7 +62,7 @@ class ChatMessageReplyInfoNode: ASDisplayNode {
} }
} }
var visibility: Bool = false { public var visibility: Bool = false {
didSet { didSet {
if self.visibility != oldValue { if self.visibility != oldValue {
self.textNode?.visibilityRect = self.visibility ? CGRect.infinite : nil self.textNode?.visibilityRect = self.visibility ? CGRect.infinite : nil
@ -79,7 +79,7 @@ class ChatMessageReplyInfoNode: ASDisplayNode {
private var previousMediaReference: AnyMediaReference? private var previousMediaReference: AnyMediaReference?
private var expiredStoryIconView: UIImageView? private var expiredStoryIconView: UIImageView?
override init() { override public init() {
self.contentNode = ASDisplayNode() self.contentNode = ASDisplayNode()
self.contentNode.isUserInteractionEnabled = false self.contentNode.isUserInteractionEnabled = false
self.contentNode.displaysAsynchronously = false self.contentNode.displaysAsynchronously = false
@ -97,7 +97,7 @@ class ChatMessageReplyInfoNode: ASDisplayNode {
self.contentNode.addSubnode(self.lineNode) self.contentNode.addSubnode(self.lineNode)
} }
class func asyncLayout(_ maybeNode: ChatMessageReplyInfoNode?) -> (_ arguments: Arguments) -> (CGSize, (Bool) -> ChatMessageReplyInfoNode) { public static func asyncLayout(_ maybeNode: ChatMessageReplyInfoNode?) -> (_ arguments: Arguments) -> (CGSize, (Bool) -> ChatMessageReplyInfoNode) {
let titleNodeLayout = TextNode.asyncLayout(maybeNode?.titleNode) let titleNodeLayout = TextNode.asyncLayout(maybeNode?.titleNode)
let textNodeLayout = TextNodeWithEntities.asyncLayout(maybeNode?.textNode) let textNodeLayout = TextNodeWithEntities.asyncLayout(maybeNode?.textNode)
let imageNodeLayout = TransformImageNode.asyncLayout(maybeNode?.imageNode) let imageNodeLayout = TransformImageNode.asyncLayout(maybeNode?.imageNode)
@ -583,7 +583,7 @@ class ChatMessageReplyInfoNode: ASDisplayNode {
} }
} }
func mediaTransitionView() -> UIView? { public func mediaTransitionView() -> UIView? {
if let imageNode = self.imageNode { if let imageNode = self.imageNode {
return imageNode.view return imageNode.view
} }

View File

@ -33,6 +33,7 @@ import AvatarVideoNode
import PeerInfoVisualMediaPaneNode import PeerInfoVisualMediaPaneNode
import AvatarStoryIndicatorComponent import AvatarStoryIndicatorComponent
import ComponentDisplayAdapters import ComponentDisplayAdapters
import ChatAvatarNavigationNode
enum PeerInfoHeaderButtonKey: Hashable { enum PeerInfoHeaderButtonKey: Hashable {
case message case message

View File

@ -90,6 +90,7 @@ import PeerInfoVisualMediaPaneNode
import PeerInfoStoryGridScreen import PeerInfoStoryGridScreen
import StoryContainerScreen import StoryContainerScreen
import StoryContentComponent import StoryContentComponent
import ChatAvatarNavigationNode
enum PeerInfoAvatarEditingMode { enum PeerInfoAvatarEditingMode {
case generic case generic