mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-15 21:45:19 +00:00
Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios
This commit is contained in:
commit
9ea80ff9dc
@ -1091,6 +1091,127 @@ private struct DownloadItem: Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
private func filteredPeerSearchQueryResults(value: ([FoundPeer], [FoundPeer]), scope: TelegramSearchPeersScope) -> ([FoundPeer], [FoundPeer]) {
|
||||
switch scope {
|
||||
case .everywhere:
|
||||
return value
|
||||
case .channels:
|
||||
return (
|
||||
value.0.filter { peer in
|
||||
if let channel = peer.peer as? TelegramChannel, case .broadcast = channel.info {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
},
|
||||
value.1.filter { peer in
|
||||
if let channel = peer.peer as? TelegramChannel, case .broadcast = channel.info {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
final class GlobalPeerSearchContext {
|
||||
private struct SearchKey: Hashable {
|
||||
var query: String
|
||||
|
||||
init(query: String) {
|
||||
self.query = query
|
||||
}
|
||||
}
|
||||
|
||||
private final class QueryContext {
|
||||
var value: ([FoundPeer], [FoundPeer])?
|
||||
let subscribers = Bag<(TelegramSearchPeersScope, (([FoundPeer], [FoundPeer])) -> Void)>()
|
||||
let disposable = MetaDisposable()
|
||||
|
||||
init() {
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.disposable.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
private final class Impl {
|
||||
private let queue: Queue
|
||||
private var queryContexts: [SearchKey: QueryContext] = [:]
|
||||
|
||||
init(queue: Queue) {
|
||||
self.queue = queue
|
||||
}
|
||||
|
||||
func searchRemotePeers(engine: TelegramEngine, query: String, scope: TelegramSearchPeersScope, onNext: @escaping (([FoundPeer], [FoundPeer])) -> Void) -> Disposable {
|
||||
let searchKey = SearchKey(query: query)
|
||||
let queryContext: QueryContext
|
||||
if let current = self.queryContexts[searchKey] {
|
||||
queryContext = current
|
||||
|
||||
if let value = queryContext.value {
|
||||
onNext(filteredPeerSearchQueryResults(value: value, scope: scope))
|
||||
}
|
||||
} else {
|
||||
queryContext = QueryContext()
|
||||
self.queryContexts[searchKey] = queryContext
|
||||
queryContext.disposable.set((engine.contacts.searchRemotePeers(
|
||||
query: query,
|
||||
scope: .everywhere
|
||||
)
|
||||
|> delay(0.4, queue: Queue.mainQueue())
|
||||
|> deliverOn(self.queue)).start(next: { [weak queryContext] value in
|
||||
guard let queryContext else {
|
||||
return
|
||||
}
|
||||
queryContext.value = value
|
||||
for (scope, f) in queryContext.subscribers.copyItems() {
|
||||
f(filteredPeerSearchQueryResults(value: value, scope: scope))
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
let index = queryContext.subscribers.add((scope, onNext))
|
||||
|
||||
let queue = self.queue
|
||||
return ActionDisposable { [weak self, weak queryContext] in
|
||||
queue.async {
|
||||
guard let self, let queryContext else {
|
||||
return
|
||||
}
|
||||
guard let currentContext = self.queryContexts[searchKey], queryContext === queryContext else {
|
||||
return
|
||||
}
|
||||
currentContext.subscribers.remove(index)
|
||||
if currentContext.subscribers.isEmpty {
|
||||
currentContext.disposable.dispose()
|
||||
self.queryContexts.removeValue(forKey: searchKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private let queue: Queue
|
||||
private let impl: QueueLocalObject<Impl>
|
||||
|
||||
init() {
|
||||
let queue = Queue.mainQueue()
|
||||
self.queue = queue
|
||||
self.impl = QueueLocalObject(queue: queue, generate: {
|
||||
return Impl(queue: queue)
|
||||
})
|
||||
}
|
||||
|
||||
func searchRemotePeers(engine: TelegramEngine, query: String, scope: TelegramSearchPeersScope = .everywhere) -> Signal<([FoundPeer], [FoundPeer]), NoError> {
|
||||
return self.impl.signalWith { impl, subscriber in
|
||||
return impl.searchRemotePeers(engine: engine, query: query, scope: scope, onNext: subscriber.putNext)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
private let context: AccountContext
|
||||
private let animationCache: AnimationCache
|
||||
@ -1099,6 +1220,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
private let peersFilter: ChatListNodePeersFilter
|
||||
private let requestPeerType: [ReplyMarkupButtonRequestPeerType]?
|
||||
private var presentationData: PresentationData
|
||||
private let globalPeerSearchContext: GlobalPeerSearchContext?
|
||||
private let key: ChatListSearchPaneKey
|
||||
private let tagMask: EngineMessage.Tags?
|
||||
private let location: ChatListControllerLocation
|
||||
@ -1175,7 +1297,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
private var searchQueryDisposable: Disposable?
|
||||
private var searchOptionsDisposable: Disposable?
|
||||
|
||||
init(context: AccountContext, animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, interaction: ChatListSearchInteraction, key: ChatListSearchPaneKey, peersFilter: ChatListNodePeersFilter, requestPeerType: [ReplyMarkupButtonRequestPeerType]?, location: ChatListControllerLocation, searchQuery: Signal<String?, NoError>, searchOptions: Signal<ChatListSearchOptions?, NoError>, navigationController: NavigationController?) {
|
||||
init(context: AccountContext, animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, interaction: ChatListSearchInteraction, key: ChatListSearchPaneKey, peersFilter: ChatListNodePeersFilter, requestPeerType: [ReplyMarkupButtonRequestPeerType]?, location: ChatListControllerLocation, searchQuery: Signal<String?, NoError>, searchOptions: Signal<ChatListSearchOptions?, NoError>, navigationController: NavigationController?, globalPeerSearchContext: GlobalPeerSearchContext?) {
|
||||
self.context = context
|
||||
self.animationCache = animationCache
|
||||
self.animationRenderer = animationRenderer
|
||||
@ -1183,6 +1305,10 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
self.key = key
|
||||
self.location = location
|
||||
self.navigationController = navigationController
|
||||
|
||||
let globalPeerSearchContext = globalPeerSearchContext ?? GlobalPeerSearchContext()
|
||||
|
||||
self.globalPeerSearchContext = globalPeerSearchContext
|
||||
|
||||
var peersFilter = peersFilter
|
||||
if case .forum = location {
|
||||
@ -1788,18 +1914,16 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
foundRemotePeers = (
|
||||
.single((currentRemotePeersValue.0, currentRemotePeersValue.1, true))
|
||||
|> then(
|
||||
context.engine.contacts.searchRemotePeers(query: query)
|
||||
globalPeerSearchContext.searchRemotePeers(engine: context.engine, query: query)
|
||||
|> map { ($0.0, $0.1, false) }
|
||||
|> delay(0.4, queue: Queue.concurrentDefaultQueue())
|
||||
)
|
||||
)
|
||||
} else if let query = query, case .channels = key {
|
||||
foundRemotePeers = (
|
||||
.single((currentRemotePeersValue.0, currentRemotePeersValue.1, true))
|
||||
|> then(
|
||||
context.engine.contacts.searchRemotePeers(query: query, scope: .channels)
|
||||
globalPeerSearchContext.searchRemotePeers(engine: context.engine, query: query, scope: .channels)
|
||||
|> map { ($0.0, $0.1, false) }
|
||||
|> delay(0.4, queue: Queue.concurrentDefaultQueue())
|
||||
)
|
||||
)
|
||||
} else {
|
||||
|
@ -127,10 +127,11 @@ private final class ChatListSearchPendingPane {
|
||||
location: ChatListControllerLocation,
|
||||
searchQuery: Signal<String?, NoError>,
|
||||
searchOptions: Signal<ChatListSearchOptions?, NoError>,
|
||||
globalPeerSearchContext: GlobalPeerSearchContext?,
|
||||
key: ChatListSearchPaneKey,
|
||||
hasBecomeReady: @escaping (ChatListSearchPaneKey) -> Void
|
||||
) {
|
||||
let paneNode = ChatListSearchListPaneNode(context: context, animationCache: animationCache, animationRenderer: animationRenderer, updatedPresentationData: updatedPresentationData, interaction: interaction, key: key, peersFilter: (key == .chats || key == .topics) ? peersFilter : [], requestPeerType: requestPeerType, location: location, searchQuery: searchQuery, searchOptions: searchOptions, navigationController: navigationController)
|
||||
let paneNode = ChatListSearchListPaneNode(context: context, animationCache: animationCache, animationRenderer: animationRenderer, updatedPresentationData: updatedPresentationData, interaction: interaction, key: key, peersFilter: (key == .chats || key == .topics) ? peersFilter : [], requestPeerType: requestPeerType, location: location, searchQuery: searchQuery, searchOptions: searchOptions, navigationController: navigationController, globalPeerSearchContext: globalPeerSearchContext)
|
||||
|
||||
self.pane = ChatListSearchPaneWrapper(key: key, node: paneNode)
|
||||
self.disposable = (paneNode.isReady
|
||||
@ -156,6 +157,7 @@ final class ChatListSearchPaneContainerNode: ASDisplayNode, ASGestureRecognizerD
|
||||
private let location: ChatListControllerLocation
|
||||
private let searchQuery: Signal<String?, NoError>
|
||||
private let searchOptions: Signal<ChatListSearchOptions?, NoError>
|
||||
private let globalPeerSearchContext: GlobalPeerSearchContext
|
||||
private let navigationController: NavigationController?
|
||||
var interaction: ChatListSearchInteraction?
|
||||
|
||||
@ -198,6 +200,7 @@ final class ChatListSearchPaneContainerNode: ASDisplayNode, ASGestureRecognizerD
|
||||
self.searchQuery = searchQuery
|
||||
self.searchOptions = searchOptions
|
||||
self.navigationController = navigationController
|
||||
self.globalPeerSearchContext = GlobalPeerSearchContext()
|
||||
|
||||
super.init()
|
||||
}
|
||||
@ -432,6 +435,7 @@ final class ChatListSearchPaneContainerNode: ASDisplayNode, ASGestureRecognizerD
|
||||
location: self.location,
|
||||
searchQuery: self.searchQuery,
|
||||
searchOptions: self.searchOptions,
|
||||
globalPeerSearchContext: self.globalPeerSearchContext,
|
||||
key: key,
|
||||
hasBecomeReady: { [weak self] key in
|
||||
let apply: () -> Void = {
|
||||
|
@ -474,7 +474,7 @@ public class InvisibleInkDustNode: ASDisplayNode {
|
||||
}
|
||||
|
||||
public func update(revealed: Bool, animated: Bool = true) {
|
||||
guard self.isRevealed != revealed, let textNode = self.textNode else {
|
||||
guard self.isRevealed != revealed else {
|
||||
return
|
||||
}
|
||||
|
||||
@ -483,11 +483,15 @@ public class InvisibleInkDustNode: ASDisplayNode {
|
||||
if revealed {
|
||||
let transition: ContainedViewLayoutTransition = animated ? .animated(duration: 0.3, curve: .linear) : .immediate
|
||||
transition.updateAlpha(node: self, alpha: 0.0)
|
||||
transition.updateAlpha(node: textNode, alpha: 1.0)
|
||||
if let textNode = self.textNode {
|
||||
transition.updateAlpha(node: textNode, alpha: 1.0)
|
||||
}
|
||||
} else {
|
||||
let transition: ContainedViewLayoutTransition = animated ? .animated(duration: 0.4, curve: .linear) : .immediate
|
||||
transition.updateAlpha(node: self, alpha: 1.0)
|
||||
transition.updateAlpha(node: textNode, alpha: 0.0)
|
||||
if let textNode = self.textNode {
|
||||
transition.updateAlpha(node: textNode, alpha: 0.0)
|
||||
}
|
||||
|
||||
if self.isExploding {
|
||||
self.isExploding = false
|
||||
@ -497,7 +501,7 @@ public class InvisibleInkDustNode: ASDisplayNode {
|
||||
}
|
||||
|
||||
public func revealAtLocation(_ location: CGPoint) {
|
||||
guard let (_, _, textColor, _, _) = self.currentParams, let textNode = self.textNode, !self.isRevealed else {
|
||||
guard let (_, _, textColor, _, _) = self.currentParams, !self.isRevealed else {
|
||||
return
|
||||
}
|
||||
|
||||
@ -507,7 +511,7 @@ public class InvisibleInkDustNode: ASDisplayNode {
|
||||
self.isExploding = true
|
||||
|
||||
self.emitterLayer?.setValue(true, forKeyPath: "emitterBehaviors.fingerAttractor.enabled")
|
||||
self.emitterLayer?.setValue(position, forKeyPath: "emitterBehaviors.fingerAttractor.position")
|
||||
self.emitterLayer?.setValue(location, forKeyPath: "emitterBehaviors.fingerAttractor.position")
|
||||
|
||||
let maskSize = self.emitterNode.frame.size
|
||||
Queue.concurrentDefaultQueue().async {
|
||||
@ -520,10 +524,15 @@ public class InvisibleInkDustNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
Queue.mainQueue().after(0.1 * UIView.animationDurationFactor()) {
|
||||
textNode.alpha = 1.0
|
||||
Queue.mainQueue().after(0.1 * UIView.animationDurationFactor()) { [weak self] in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
|
||||
textNode.view.mask = self.textMaskNode.view
|
||||
if let textNode = self.textNode {
|
||||
textNode.alpha = 1.0
|
||||
textNode.view.mask = self.textMaskNode.view
|
||||
}
|
||||
self.textSpotNode.frame = CGRect(x: 0.0, y: 0.0, width: self.emitterMaskNode.frame.width * 3.0, height: self.emitterMaskNode.frame.height * 3.0)
|
||||
|
||||
let xFactor = (location.x / self.emitterNode.frame.width - 0.5) * 2.0
|
||||
@ -539,8 +548,13 @@ public class InvisibleInkDustNode: ASDisplayNode {
|
||||
|
||||
self.textSpotNode.layer.anchorPoint = CGPoint(x: location.x / self.emitterMaskNode.frame.width, y: location.y / self.emitterMaskNode.frame.height)
|
||||
self.textSpotNode.position = location
|
||||
self.textSpotNode.layer.animateScale(from: 0.3333, to: 10.5 + scaleAddition, duration: 0.55 + durationAddition, removeOnCompletion: false, completion: { _ in
|
||||
textNode.view.mask = nil
|
||||
self.textSpotNode.layer.animateScale(from: 0.3333, to: 10.5 + scaleAddition, duration: 0.55 + durationAddition, removeOnCompletion: false, completion: { [weak self] _ in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
if let textNode = self.textNode {
|
||||
textNode.view.mask = nil
|
||||
}
|
||||
})
|
||||
self.textSpotNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15)
|
||||
|
||||
@ -567,8 +581,10 @@ public class InvisibleInkDustNode: ASDisplayNode {
|
||||
self.emitterMaskFillNode.layer.removeAllAnimations()
|
||||
}
|
||||
} else {
|
||||
textNode.alpha = 1.0
|
||||
textNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25)
|
||||
if let textNode = self.textNode {
|
||||
textNode.alpha = 1.0
|
||||
textNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25)
|
||||
}
|
||||
|
||||
self.staticNode?.alpha = 0.0
|
||||
self.staticNode?.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.25)
|
||||
|
@ -111,7 +111,7 @@ public class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
|
||||
private var expandedBlockIds: Set<Int> = Set()
|
||||
private var appliedExpandedBlockIds: Set<Int>?
|
||||
private var displayContentsUnderSpoilers: Bool = false
|
||||
private var displayContentsUnderSpoilers: (value: Bool, location: CGPoint?) = (false, nil)
|
||||
|
||||
override public var visibility: ListViewItemNodeVisibility {
|
||||
didSet {
|
||||
@ -162,11 +162,15 @@ public class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
}
|
||||
item.controllerInteraction.requestMessageUpdate(item.message.id, false)
|
||||
}
|
||||
self.textNode.textNode.requestDisplayContentsUnderSpoilers = { [weak self] in
|
||||
self.textNode.textNode.requestDisplayContentsUnderSpoilers = { [weak self] location in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.updateDisplayContentsUnderSpoilers(value: true)
|
||||
var mappedLocation: CGPoint?
|
||||
if let location {
|
||||
mappedLocation = self.textNode.textNode.layer.convert(location, to: self.layer)
|
||||
}
|
||||
self.updateDisplayContentsUnderSpoilers(value: true, at: mappedLocation)
|
||||
}
|
||||
self.textNode.textNode.canHandleTapAtPoint = { [weak self] point in
|
||||
guard let self else {
|
||||
@ -586,7 +590,7 @@ public class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
cutout: nil,
|
||||
insets: textInsets,
|
||||
lineColor: messageTheme.accentControlColor,
|
||||
displayContentsUnderSpoilers: displayContentsUnderSpoilers,
|
||||
displayContentsUnderSpoilers: displayContentsUnderSpoilers.value,
|
||||
customTruncationToken: customTruncationToken,
|
||||
expandedBlocks: expandedBlockIds
|
||||
))
|
||||
@ -677,6 +681,11 @@ public class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
}
|
||||
strongSelf.appliedExpandedBlockIds = strongSelf.expandedBlockIds
|
||||
|
||||
var spoilerExpandRect: CGRect?
|
||||
if let location = strongSelf.displayContentsUnderSpoilers.location {
|
||||
spoilerExpandRect = textFrame.size.centered(around: CGPoint(x: location.x - textFrame.minX, y: location.y - textFrame.minY))
|
||||
}
|
||||
|
||||
let _ = textApply(InteractiveTextNodeWithEntities.Arguments(
|
||||
context: item.context,
|
||||
cache: item.controllerInteraction.presentationContext.animationCache,
|
||||
@ -685,7 +694,10 @@ public class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
attemptSynchronous: synchronousLoads,
|
||||
textColor: messageTheme.primaryTextColor,
|
||||
spoilerEffectColor: messageTheme.secondaryTextColor,
|
||||
animation: animation
|
||||
animation: animation,
|
||||
animationArguments: InteractiveTextNode.AnimationArguments(
|
||||
spoilerExpandRect: spoilerExpandRect
|
||||
)
|
||||
))
|
||||
animation.animator.updateFrame(layer: strongSelf.textNode.textNode.layer, frame: textFrame, completion: nil)
|
||||
|
||||
@ -853,7 +865,7 @@ public class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
let textNodeFrame = self.textNode.textNode.frame
|
||||
let textLocalPoint = CGPoint(x: point.x - textNodeFrame.minX, y: point.y - textNodeFrame.minY)
|
||||
if let (index, attributes) = self.textNode.textNode.attributesAtPoint(textLocalPoint) {
|
||||
if let _ = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.Spoiler)], !self.displayContentsUnderSpoilers {
|
||||
if let _ = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.Spoiler)], !self.displayContentsUnderSpoilers.value {
|
||||
return ChatMessageBubbleContentTapAction(content: .none)
|
||||
} else if let url = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)] as? String {
|
||||
var concealed = true
|
||||
@ -1045,7 +1057,7 @@ public class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
}
|
||||
}
|
||||
|
||||
if let spoilerRects = spoilerRects, !spoilerRects.isEmpty, !self.displayContentsUnderSpoilers {
|
||||
if let spoilerRects = spoilerRects, !spoilerRects.isEmpty, !self.displayContentsUnderSpoilers.value {
|
||||
} else if let rects = rects {
|
||||
let linkHighlightingNode: LinkHighlightingNode
|
||||
if let current = self.linkHighlightingNode {
|
||||
@ -1315,11 +1327,11 @@ public class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
if !strongSelf.displayContentsUnderSpoilers, let textLayout = strongSelf.textNode.textNode.cachedLayout, textLayout.segments.contains(where: { !$0.spoilers.isEmpty }), let selectionRange {
|
||||
if !strongSelf.displayContentsUnderSpoilers.value, let textLayout = strongSelf.textNode.textNode.cachedLayout, textLayout.segments.contains(where: { !$0.spoilers.isEmpty }), let selectionRange {
|
||||
for segment in textLayout.segments {
|
||||
for (spoilerRange, _) in segment.spoilers {
|
||||
if let intersection = selectionRange.intersection(spoilerRange), intersection.length > 0 {
|
||||
strongSelf.updateDisplayContentsUnderSpoilers(value: true)
|
||||
strongSelf.updateDisplayContentsUnderSpoilers(value: true, at: nil)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -1375,17 +1387,18 @@ public class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
})
|
||||
}
|
||||
|
||||
if self.displayContentsUnderSpoilers {
|
||||
self.updateDisplayContentsUnderSpoilers(value: false)
|
||||
if self.displayContentsUnderSpoilers.value {
|
||||
self.updateDisplayContentsUnderSpoilers(value: false, at: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func updateDisplayContentsUnderSpoilers(value: Bool) {
|
||||
if self.displayContentsUnderSpoilers == value {
|
||||
private func updateDisplayContentsUnderSpoilers(value: Bool, at location: CGPoint?) {
|
||||
if self.displayContentsUnderSpoilers.value == value {
|
||||
return
|
||||
}
|
||||
self.displayContentsUnderSpoilers = value
|
||||
self.displayContentsUnderSpoilers = (value, location)
|
||||
self.displayContentsUnderSpoilers.location = nil
|
||||
if let item = self.item {
|
||||
item.controllerInteraction.requestMessageUpdate(item.message.id, false)
|
||||
}
|
||||
|
@ -769,7 +769,8 @@ public final class ChatSendGroupMediaMessageContextPreview: UIView, ChatSendMess
|
||||
let messagesContainerFrame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: size.width, height: size.height))
|
||||
|
||||
self.messagesContainer.frame = messagesContainerFrame
|
||||
return messagesContainerFrame.size
|
||||
// 4.0 is a magic number to compensate for offset in other types of content
|
||||
return CGSize(width: messagesContainerFrame.width, height: messagesContainerFrame.height - 4.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1073,6 +1073,14 @@ private func addAttachment(attachment: UIImage, line: InteractiveTextNodeLine, a
|
||||
}
|
||||
|
||||
open class InteractiveTextNode: ASDisplayNode, TextNodeProtocol, UIGestureRecognizerDelegate {
|
||||
public final class AnimationArguments {
|
||||
public let spoilerExpandRect: CGRect?
|
||||
|
||||
public init(spoilerExpandRect: CGRect?) {
|
||||
self.spoilerExpandRect = spoilerExpandRect
|
||||
}
|
||||
}
|
||||
|
||||
public struct RenderContentTypes: OptionSet {
|
||||
public var rawValue: Int
|
||||
|
||||
@ -1106,7 +1114,7 @@ open class InteractiveTextNode: ASDisplayNode, TextNodeProtocol, UIGestureRecogn
|
||||
|
||||
public var canHandleTapAtPoint: ((CGPoint) -> Bool)?
|
||||
public var requestToggleBlockCollapsed: ((Int) -> Void)?
|
||||
public var requestDisplayContentsUnderSpoilers: (() -> Void)?
|
||||
public var requestDisplayContentsUnderSpoilers: ((CGPoint?) -> Void)?
|
||||
private var tapRecognizer: UITapGestureRecognizer?
|
||||
|
||||
public var currentText: NSAttributedString? {
|
||||
@ -1676,7 +1684,7 @@ open class InteractiveTextNode: ASDisplayNode, TextNodeProtocol, UIGestureRecogn
|
||||
return calculateLayoutV2(attributedString: attributedString, minimumNumberOfLines: minimumNumberOfLines, maximumNumberOfLines: maximumNumberOfLines, truncationType: truncationType, backgroundColor: backgroundColor, constrainedSize: constrainedSize, alignment: alignment, verticalAlignment: verticalAlignment, lineSpacingFactor: lineSpacingFactor, cutout: cutout, insets: insets, lineColor: lineColor, textShadowColor: textShadowColor, textShadowBlur: textShadowBlur, textStroke: textStroke, displayContentsUnderSpoilers: displayContentsUnderSpoilers, customTruncationToken: customTruncationToken, expandedBlocks: expandedBlocks)
|
||||
}
|
||||
|
||||
private func updateContentItems(animation: ListViewItemUpdateAnimation) {
|
||||
private func updateContentItems(animation: ListViewItemUpdateAnimation, animationArguments: AnimationArguments?) {
|
||||
guard let cachedLayout = self.cachedLayout else {
|
||||
return
|
||||
}
|
||||
@ -1729,8 +1737,15 @@ open class InteractiveTextNode: ASDisplayNode, TextNodeProtocol, UIGestureRecogn
|
||||
|
||||
var contentItemAnimation = animation
|
||||
let contentItemLayer: TextContentItemLayer
|
||||
var itemSpoilerExpandRect: CGRect?
|
||||
var itemAnimateContents = animateContents && contentItemAnimation.isAnimated
|
||||
if let current = self.contentItemLayers[itemId] {
|
||||
contentItemLayer = current
|
||||
|
||||
if animation.isAnimated, let spoilerExpandRect = animationArguments?.spoilerExpandRect {
|
||||
itemSpoilerExpandRect = spoilerExpandRect.offsetBy(dx: -contentItemFrame.minX, dy: -contentItemFrame.minY)
|
||||
itemAnimateContents = true
|
||||
}
|
||||
} else {
|
||||
contentItemAnimation = .None
|
||||
contentItemLayer = TextContentItemLayer()
|
||||
@ -1738,7 +1753,13 @@ open class InteractiveTextNode: ASDisplayNode, TextNodeProtocol, UIGestureRecogn
|
||||
self.layer.addSublayer(contentItemLayer)
|
||||
}
|
||||
|
||||
contentItemLayer.update(item: contentItem, animation: contentItemAnimation, synchronously: synchronous, animateContents: animateContents && contentItemAnimation.isAnimated)
|
||||
contentItemLayer.update(
|
||||
item: contentItem,
|
||||
animation: contentItemAnimation,
|
||||
synchronously: synchronous,
|
||||
animateContents: itemAnimateContents,
|
||||
spoilerExpandRect: itemSpoilerExpandRect
|
||||
)
|
||||
|
||||
contentItemAnimation.animator.updateFrame(layer: contentItemLayer, frame: contentItemFrame, completion: nil)
|
||||
}
|
||||
@ -1779,7 +1800,7 @@ open class InteractiveTextNode: ASDisplayNode, TextNodeProtocol, UIGestureRecogn
|
||||
let point = recognizer.location(in: self.view)
|
||||
if let cachedLayout = self.cachedLayout, !cachedLayout.displayContentsUnderSpoilers, let (_, attributes) = self.attributesAtPoint(point) {
|
||||
if attributes[NSAttributedString.Key(rawValue: "Attribute__Spoiler")] != nil || attributes[NSAttributedString.Key(rawValue: "TelegramSpoiler")] != nil {
|
||||
self.requestDisplayContentsUnderSpoilers?()
|
||||
self.requestDisplayContentsUnderSpoilers?(point)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -1789,7 +1810,7 @@ open class InteractiveTextNode: ASDisplayNode, TextNodeProtocol, UIGestureRecogn
|
||||
}
|
||||
}
|
||||
|
||||
public static func asyncLayout(_ maybeNode: InteractiveTextNode?) -> (InteractiveTextNodeLayoutArguments) -> (InteractiveTextNodeLayout, (ListViewItemUpdateAnimation) -> InteractiveTextNode) {
|
||||
public static func asyncLayout(_ maybeNode: InteractiveTextNode?) -> (InteractiveTextNodeLayoutArguments) -> (InteractiveTextNodeLayout, (ListViewItemUpdateAnimation, AnimationArguments?) -> InteractiveTextNode) {
|
||||
let existingLayout: InteractiveTextNodeLayout? = maybeNode?.cachedLayout
|
||||
|
||||
return { arguments in
|
||||
@ -1831,10 +1852,10 @@ open class InteractiveTextNode: ASDisplayNode, TextNodeProtocol, UIGestureRecogn
|
||||
|
||||
let node = maybeNode ?? InteractiveTextNode()
|
||||
|
||||
return (layout, { animation in
|
||||
return (layout, { animation, animationArguments in
|
||||
if node.cachedLayout !== layout {
|
||||
node.cachedLayout = layout
|
||||
node.updateContentItems(animation: animation)
|
||||
node.updateContentItems(animation: animation, animationArguments: animationArguments)
|
||||
}
|
||||
|
||||
return node
|
||||
@ -2202,7 +2223,13 @@ final class TextContentItemLayer: SimpleLayer {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
func update(item: TextContentItem, animation: ListViewItemUpdateAnimation, synchronously: Bool = false, animateContents: Bool = false) {
|
||||
func update(
|
||||
item: TextContentItem,
|
||||
animation: ListViewItemUpdateAnimation,
|
||||
synchronously: Bool,
|
||||
animateContents: Bool,
|
||||
spoilerExpandRect: CGRect?
|
||||
) {
|
||||
self.item = item
|
||||
|
||||
let contentFrame = CGRect(origin: CGPoint(), size: item.size)
|
||||
@ -2241,7 +2268,13 @@ final class TextContentItemLayer: SimpleLayer {
|
||||
return
|
||||
}
|
||||
self.isAnimating = false
|
||||
self.update(item: item, animation: .None, synchronously: true)
|
||||
self.update(
|
||||
item: item,
|
||||
animation: .None,
|
||||
synchronously: true,
|
||||
animateContents: false,
|
||||
spoilerExpandRect: nil
|
||||
)
|
||||
})
|
||||
} else {
|
||||
blockBackgroundView.layer.frame = blockBackgroundFrame
|
||||
@ -2362,13 +2395,61 @@ final class TextContentItemLayer: SimpleLayer {
|
||||
|
||||
self.renderNode.params = RenderParams(size: contentFrame.size, item: item, mask: staticContentMask)
|
||||
if synchronously {
|
||||
let previousContents = self.renderNode.layer.contents
|
||||
self.renderNode.displayImmediately()
|
||||
if animateContents, let previousContents {
|
||||
animation.transition.animateContents(layer: self.renderNode.layer, from: previousContents)
|
||||
if let spoilerExpandRect {
|
||||
let _ = spoilerExpandRect
|
||||
|
||||
self.renderNode.displayImmediately()
|
||||
|
||||
let maskFrame = self.renderNode.frame
|
||||
|
||||
let maskLayer = SimpleLayer()
|
||||
maskLayer.frame = maskFrame
|
||||
self.addSublayer(maskLayer)
|
||||
|
||||
let maskGradientLayer = SimpleGradientLayer()
|
||||
maskGradientLayer.frame = CGRect(origin: CGPoint(), size: maskFrame.size)
|
||||
setupSpoilerExpansionMaskGradient(
|
||||
gradientLayer: maskGradientLayer,
|
||||
centerLocation: CGPoint(
|
||||
x: 0.5,
|
||||
y: 0.5
|
||||
),
|
||||
radius: CGSize(
|
||||
width: 1.5,
|
||||
height: 1.5
|
||||
),
|
||||
inverse: false
|
||||
)
|
||||
} else {
|
||||
let previousContents = self.renderNode.layer.contents
|
||||
self.renderNode.displayImmediately()
|
||||
if animateContents, let previousContents {
|
||||
animation.transition.animateContents(layer: self.renderNode.layer, from: previousContents)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.renderNode.setNeedsDisplay()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func setupSpoilerExpansionMaskGradient(gradientLayer: SimpleGradientLayer, centerLocation: CGPoint, radius: CGSize, inverse: Bool) {
|
||||
let startAlpha: CGFloat = inverse ? 0.0 : 1.0
|
||||
let endAlpha: CGFloat = inverse ? 1.0 : 0.0
|
||||
|
||||
let locations: [CGFloat] = [0.0, 0.7, 0.95, 1.0]
|
||||
let colors: [CGColor] = [
|
||||
UIColor(rgb: 0xff0000, alpha: startAlpha).cgColor,
|
||||
UIColor(rgb: 0xff0000, alpha: startAlpha).cgColor,
|
||||
UIColor(rgb: 0xff0000, alpha: endAlpha).cgColor,
|
||||
UIColor(rgb: 0xff0000, alpha: endAlpha).cgColor
|
||||
]
|
||||
|
||||
gradientLayer.type = .radial
|
||||
gradientLayer.colors = colors
|
||||
gradientLayer.locations = locations.map { $0 as NSNumber }
|
||||
gradientLayer.startPoint = centerLocation
|
||||
|
||||
let endEndPoint = CGPoint(x: (gradientLayer.startPoint.x + radius.width) * 1.0, y: (gradientLayer.startPoint.y + radius.height) * 1.0)
|
||||
gradientLayer.endPoint = endEndPoint
|
||||
}
|
||||
|
@ -65,6 +65,7 @@ public final class InteractiveTextNodeWithEntities {
|
||||
public let textColor: UIColor
|
||||
public let spoilerEffectColor: UIColor
|
||||
public let animation: ListViewItemUpdateAnimation
|
||||
public let animationArguments: InteractiveTextNode.AnimationArguments?
|
||||
|
||||
public init(
|
||||
context: AccountContext,
|
||||
@ -74,7 +75,8 @@ public final class InteractiveTextNodeWithEntities {
|
||||
attemptSynchronous: Bool,
|
||||
textColor: UIColor,
|
||||
spoilerEffectColor: UIColor,
|
||||
animation: ListViewItemUpdateAnimation
|
||||
animation: ListViewItemUpdateAnimation,
|
||||
animationArguments: InteractiveTextNode.AnimationArguments?
|
||||
) {
|
||||
self.context = context
|
||||
self.cache = cache
|
||||
@ -84,6 +86,7 @@ public final class InteractiveTextNodeWithEntities {
|
||||
self.textColor = textColor
|
||||
self.spoilerEffectColor = spoilerEffectColor
|
||||
self.animation = animation
|
||||
self.animationArguments = animationArguments
|
||||
}
|
||||
|
||||
public func withUpdatedPlaceholderColor(_ color: UIColor) -> Arguments {
|
||||
@ -95,7 +98,8 @@ public final class InteractiveTextNodeWithEntities {
|
||||
attemptSynchronous: self.attemptSynchronous,
|
||||
textColor: self.textColor,
|
||||
spoilerEffectColor: self.spoilerEffectColor,
|
||||
animation: self.animation
|
||||
animation: self.animation,
|
||||
animationArguments: self.animationArguments
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -113,6 +117,7 @@ public final class InteractiveTextNodeWithEntities {
|
||||
|
||||
private var inlineStickerItemLayers: [InlineStickerItemLayer.Key: InlineStickerItemLayerData] = [:]
|
||||
private var dustEffectNodes: [Int: InvisibleInkDustNode] = [:]
|
||||
private var displayContentsUnderSpoilers: Bool?
|
||||
|
||||
private var enableLooping: Bool = true
|
||||
|
||||
@ -215,11 +220,22 @@ public final class InteractiveTextNodeWithEntities {
|
||||
return (layout, { applyArguments in
|
||||
let animation: ListViewItemUpdateAnimation = applyArguments?.animation ?? .None
|
||||
|
||||
let result = apply(animation)
|
||||
let result = apply(animation, applyArguments?.animationArguments)
|
||||
|
||||
if let maybeNode = maybeNode {
|
||||
if let applyArguments = applyArguments {
|
||||
maybeNode.updateInteractiveContents(context: applyArguments.context, cache: applyArguments.cache, renderer: applyArguments.renderer, textLayout: layout, placeholderColor: applyArguments.placeholderColor, attemptSynchronousLoad: false, textColor: applyArguments.textColor, spoilerEffectColor: applyArguments.spoilerEffectColor, animation: animation)
|
||||
maybeNode.updateInteractiveContents(
|
||||
context: applyArguments.context,
|
||||
cache: applyArguments.cache,
|
||||
renderer: applyArguments.renderer,
|
||||
textLayout: layout,
|
||||
placeholderColor: applyArguments.placeholderColor,
|
||||
attemptSynchronousLoad: false,
|
||||
textColor: applyArguments.textColor,
|
||||
spoilerEffectColor: applyArguments.spoilerEffectColor,
|
||||
animation: animation,
|
||||
animationArguments: applyArguments.animationArguments
|
||||
)
|
||||
}
|
||||
|
||||
return maybeNode
|
||||
@ -227,7 +243,18 @@ public final class InteractiveTextNodeWithEntities {
|
||||
let resultNode = InteractiveTextNodeWithEntities(textNode: result)
|
||||
|
||||
if let applyArguments = applyArguments {
|
||||
resultNode.updateInteractiveContents(context: applyArguments.context, cache: applyArguments.cache, renderer: applyArguments.renderer, textLayout: layout, placeholderColor: applyArguments.placeholderColor, attemptSynchronousLoad: false, textColor: applyArguments.textColor, spoilerEffectColor: applyArguments.spoilerEffectColor, animation: .None)
|
||||
resultNode.updateInteractiveContents(
|
||||
context: applyArguments.context,
|
||||
cache: applyArguments.cache,
|
||||
renderer: applyArguments.renderer,
|
||||
textLayout: layout,
|
||||
placeholderColor: applyArguments.placeholderColor,
|
||||
attemptSynchronousLoad: false,
|
||||
textColor: applyArguments.textColor,
|
||||
spoilerEffectColor: applyArguments.spoilerEffectColor,
|
||||
animation: .None,
|
||||
animationArguments: nil
|
||||
)
|
||||
}
|
||||
|
||||
return resultNode
|
||||
@ -253,7 +280,8 @@ public final class InteractiveTextNodeWithEntities {
|
||||
attemptSynchronousLoad: Bool,
|
||||
textColor: UIColor,
|
||||
spoilerEffectColor: UIColor,
|
||||
animation: ListViewItemUpdateAnimation
|
||||
animation: ListViewItemUpdateAnimation,
|
||||
animationArguments: InteractiveTextNode.AnimationArguments?
|
||||
) {
|
||||
self.enableLooping = context.sharedContext.energyUsageSettings.loopEmoji
|
||||
|
||||
@ -261,6 +289,8 @@ public final class InteractiveTextNodeWithEntities {
|
||||
if let textLayout {
|
||||
displayContentsUnderSpoilers = textLayout.displayContentsUnderSpoilers
|
||||
}
|
||||
let previousDisplayContentsUnderSpoilers = self.displayContentsUnderSpoilers
|
||||
self.displayContentsUnderSpoilers = displayContentsUnderSpoilers
|
||||
|
||||
var nextIndexById: [Int64: Int] = [:]
|
||||
var validIds: [InlineStickerItemLayer.Key] = []
|
||||
@ -345,7 +375,12 @@ public final class InteractiveTextNodeWithEntities {
|
||||
wordRects: segment.spoilerWords.map { $0.1.offsetBy(dx: segmentItem.contentOffset.x + 3.0, dy: segmentItem.contentOffset.y + 3.0).insetBy(dx: 1.0, dy: 1.0) }
|
||||
)
|
||||
|
||||
animation.transition.updateAlpha(node: dustEffectNode, alpha: displayContentsUnderSpoilers ? 0.0 : 1.0)
|
||||
if let previousDisplayContentsUnderSpoilers, previousDisplayContentsUnderSpoilers != displayContentsUnderSpoilers, displayContentsUnderSpoilers, let currentSpoilerExpandRect = animationArguments?.spoilerExpandRect {
|
||||
let spoilerLocalPosition = self.textNode.layer.convert(currentSpoilerExpandRect.center, to: dustEffectNode.layer)
|
||||
dustEffectNode.revealAtLocation(spoilerLocalPosition)
|
||||
} else {
|
||||
dustEffectNode.update(revealed: displayContentsUnderSpoilers, animated: previousDisplayContentsUnderSpoilers != nil && animation.isAnimated)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -552,7 +552,9 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
||||
}
|
||||
|
||||
transition.updateAlpha(node: self.regularContentNode, alpha: (state.isEditing || self.customNavigationContentNode != nil) ? 0.0 : 1.0)
|
||||
transition.updateAlpha(node: self.navigationButtonContainer, alpha: self.customNavigationContentNode != nil ? 0.0 : 1.0)
|
||||
if self.navigationTransition == nil {
|
||||
transition.updateAlpha(node: self.navigationButtonContainer, alpha: self.customNavigationContentNode != nil ? 0.0 : 1.0)
|
||||
}
|
||||
|
||||
self.editingContentNode.alpha = state.isEditing ? 1.0 : 0.0
|
||||
|
||||
|
@ -11043,7 +11043,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
||||
}
|
||||
let headerInset = sectionInset
|
||||
|
||||
let headerHeight = self.headerNode.update(width: layout.size.width, containerHeight: layout.size.height, containerInset: headerInset, statusBarHeight: layout.statusBarHeight ?? 0.0, navigationHeight: navigationHeight, isModalOverlay: layout.isModalOverlay, isMediaOnly: self.isMediaOnly, contentOffset: self.isMediaOnly ? 212.0 : self.scrollNode.view.contentOffset.y, paneContainerY: self.paneContainerNode.frame.minY, presentationData: self.presentationData, peer: self.data?.savedMessagesPeer ?? self.data?.peer, cachedData: self.data?.cachedData, threadData: self.data?.threadData, peerNotificationSettings: self.data?.peerNotificationSettings, threadNotificationSettings: self.data?.threadNotificationSettings, globalNotificationSettings: self.data?.globalNotificationSettings, statusData: self.data?.status, panelStatusData: self.customStatusData, isSecretChat: self.peerId.namespace == Namespaces.Peer.SecretChat, isContact: self.data?.isContact ?? false, isSettings: self.isSettings, state: self.state, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, transition: transition, additive: additive, animateHeader: transition.isAnimated)
|
||||
let headerHeight = self.headerNode.update(width: layout.size.width, containerHeight: layout.size.height, containerInset: headerInset, statusBarHeight: layout.statusBarHeight ?? 0.0, navigationHeight: navigationHeight, isModalOverlay: layout.isModalOverlay, isMediaOnly: self.isMediaOnly, contentOffset: self.isMediaOnly ? 212.0 : self.scrollNode.view.contentOffset.y, paneContainerY: self.paneContainerNode.frame.minY, presentationData: self.presentationData, peer: self.data?.savedMessagesPeer ?? self.data?.peer, cachedData: self.data?.cachedData, threadData: self.data?.threadData, peerNotificationSettings: self.data?.peerNotificationSettings, threadNotificationSettings: self.data?.threadNotificationSettings, globalNotificationSettings: self.data?.globalNotificationSettings, statusData: self.data?.status, panelStatusData: self.customStatusData, isSecretChat: self.peerId.namespace == Namespaces.Peer.SecretChat, isContact: self.data?.isContact ?? false, isSettings: self.isSettings, state: self.state, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, transition: self.headerNode.navigationTransition == nil ? transition : .immediate, additive: additive, animateHeader: transition.isAnimated && self.headerNode.navigationTransition == nil)
|
||||
let headerFrame = CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: CGSize(width: layout.size.width, height: headerHeight))
|
||||
if additive {
|
||||
transition.updateFrameAdditive(node: self.headerNode, frame: headerFrame)
|
||||
@ -11416,7 +11416,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
||||
}
|
||||
let headerInset = sectionInset
|
||||
|
||||
let _ = self.headerNode.update(width: layout.size.width, containerHeight: layout.size.height, containerInset: headerInset, statusBarHeight: layout.statusBarHeight ?? 0.0, navigationHeight: navigationHeight, isModalOverlay: layout.isModalOverlay, isMediaOnly: self.isMediaOnly, contentOffset: self.isMediaOnly ? 212.0 : offsetY, paneContainerY: self.paneContainerNode.frame.minY, presentationData: self.presentationData, peer: self.data?.savedMessagesPeer ?? self.data?.peer, cachedData: self.data?.cachedData, threadData: self.data?.threadData, peerNotificationSettings: self.data?.peerNotificationSettings, threadNotificationSettings: self.data?.threadNotificationSettings, globalNotificationSettings: self.data?.globalNotificationSettings, statusData: self.data?.status, panelStatusData: self.customStatusData, isSecretChat: self.peerId.namespace == Namespaces.Peer.SecretChat, isContact: self.data?.isContact ?? false, isSettings: self.isSettings, state: self.state, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, transition: transition, additive: additive, animateHeader: animateHeader)
|
||||
let _ = self.headerNode.update(width: layout.size.width, containerHeight: layout.size.height, containerInset: headerInset, statusBarHeight: layout.statusBarHeight ?? 0.0, navigationHeight: navigationHeight, isModalOverlay: layout.isModalOverlay, isMediaOnly: self.isMediaOnly, contentOffset: self.isMediaOnly ? 212.0 : offsetY, paneContainerY: self.paneContainerNode.frame.minY, presentationData: self.presentationData, peer: self.data?.savedMessagesPeer ?? self.data?.peer, cachedData: self.data?.cachedData, threadData: self.data?.threadData, peerNotificationSettings: self.data?.peerNotificationSettings, threadNotificationSettings: self.data?.threadNotificationSettings, globalNotificationSettings: self.data?.globalNotificationSettings, statusData: self.data?.status, panelStatusData: self.customStatusData, isSecretChat: self.peerId.namespace == Namespaces.Peer.SecretChat, isContact: self.data?.isContact ?? false, isSettings: self.isSettings, state: self.state, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, transition: self.headerNode.navigationTransition == nil ? transition : .immediate, additive: additive, animateHeader: animateHeader && self.headerNode.navigationTransition == nil)
|
||||
}
|
||||
|
||||
let paneAreaExpansionDistance: CGFloat = 32.0
|
||||
@ -12946,7 +12946,7 @@ private final class PeerInfoNavigationTransitionNode: ASDisplayNode, CustomNavig
|
||||
}
|
||||
let headerInset = sectionInset
|
||||
|
||||
topHeight = self.headerNode.update(width: layout.size.width, containerHeight: layout.size.height, containerInset: headerInset, statusBarHeight: layout.statusBarHeight ?? 0.0, navigationHeight: topNavigationBar.bounds.height, isModalOverlay: layout.isModalOverlay, isMediaOnly: false, contentOffset: 0.0, paneContainerY: 0.0, presentationData: self.presentationData, peer: self.screenNode.data?.savedMessagesPeer ?? self.screenNode.data?.peer, cachedData: self.screenNode.data?.cachedData, threadData: self.screenNode.data?.threadData, peerNotificationSettings: self.screenNode.data?.peerNotificationSettings, threadNotificationSettings: self.screenNode.data?.threadNotificationSettings, globalNotificationSettings: self.screenNode.data?.globalNotificationSettings, statusData: self.screenNode.data?.status, panelStatusData: (nil, nil, nil), isSecretChat: self.screenNode.peerId.namespace == Namespaces.Peer.SecretChat, isContact: self.screenNode.data?.isContact ?? false, isSettings: self.screenNode.isSettings, state: self.screenNode.state, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, transition: transition, additive: false, animateHeader: true)
|
||||
topHeight = self.headerNode.update(width: layout.size.width, containerHeight: layout.size.height, containerInset: headerInset, statusBarHeight: layout.statusBarHeight ?? 0.0, navigationHeight: topNavigationBar.bounds.height, isModalOverlay: layout.isModalOverlay, isMediaOnly: false, contentOffset: 0.0, paneContainerY: 0.0, presentationData: self.presentationData, peer: self.screenNode.data?.savedMessagesPeer ?? self.screenNode.data?.peer, cachedData: self.screenNode.data?.cachedData, threadData: self.screenNode.data?.threadData, peerNotificationSettings: self.screenNode.data?.peerNotificationSettings, threadNotificationSettings: self.screenNode.data?.threadNotificationSettings, globalNotificationSettings: self.screenNode.data?.globalNotificationSettings, statusData: self.screenNode.data?.status, panelStatusData: (nil, nil, nil), isSecretChat: self.screenNode.peerId.namespace == Namespaces.Peer.SecretChat, isContact: self.screenNode.data?.isContact ?? false, isSettings: self.screenNode.isSettings, state: self.screenNode.state, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, transition: transition, additive: false, animateHeader: false)
|
||||
}
|
||||
|
||||
let titleScale = (fraction * previousTitleNode.view.bounds.height + (1.0 - fraction) * self.headerNode.titleNodeRawContainer.bounds.height) / previousTitleNode.view.bounds.height
|
||||
|
Loading…
x
Reference in New Issue
Block a user