mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Floating avatar bug fixes
This commit is contained in:
parent
6f808d95a9
commit
fc778ceb5d
@ -171,6 +171,14 @@ public final class ChatListSearchItemHeader: ListViewItemHeader {
|
|||||||
self.action = action
|
self.action = action
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func combinesWith(other: ListViewItemHeader) -> Bool {
|
||||||
|
if let other = other as? ChatListSearchItemHeader, other.id == self.id {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public func node(synchronousLoad: Bool) -> ListViewItemHeaderNode {
|
public func node(synchronousLoad: Bool) -> ListViewItemHeaderNode {
|
||||||
return ChatListSearchItemHeaderNode(type: self.type, theme: self.theme, strings: self.strings, actionTitle: self.actionTitle, action: self.action)
|
return ChatListSearchItemHeaderNode(type: self.type, theme: self.theme, strings: self.strings, actionTitle: self.actionTitle, action: self.action)
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,14 @@ final class ContactListNameIndexHeader: Equatable, ListViewItemHeader {
|
|||||||
self.id = ListViewItemNode.HeaderId(space: 0, id: Int64(letter))
|
self.id = ListViewItemNode.HeaderId(space: 0, id: Int64(letter))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func combinesWith(other: ListViewItemHeader) -> Bool {
|
||||||
|
if let other = other as? ContactListNameIndexHeader, self.id == other.id {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func node(synchronousLoad: Bool) -> ListViewItemHeaderNode {
|
func node(synchronousLoad: Bool) -> ListViewItemHeaderNode {
|
||||||
return ContactListNameIndexHeaderNode(theme: self.theme, letter: self.letter)
|
return ContactListNameIndexHeaderNode(theme: self.theme, letter: self.letter)
|
||||||
}
|
}
|
||||||
|
@ -3297,7 +3297,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
|||||||
var containsSameHeader = false
|
var containsSameHeader = false
|
||||||
if let nextHeaders = nextItemNode.headers() {
|
if let nextHeaders = nextItemNode.headers() {
|
||||||
nextHeaderSearch: for nextHeader in nextHeaders {
|
nextHeaderSearch: for nextHeader in nextHeaders {
|
||||||
if nextHeader.id == currentId {
|
if nextHeader.id == currentId && nextHeader.combinesWith(other: currentHeader) {
|
||||||
containsSameHeader = true
|
containsSameHeader = true
|
||||||
break nextHeaderSearch
|
break nextHeaderSearch
|
||||||
}
|
}
|
||||||
@ -3341,7 +3341,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
|||||||
|
|
||||||
let flashing = self.headerItemsAreFlashing()
|
let flashing = self.headerItemsAreFlashing()
|
||||||
|
|
||||||
func addHeader(id: VisibleHeaderNodeId, upperBound: CGFloat, upperBoundEdge: CGFloat, lowerBound: CGFloat, item: ListViewItemHeader, hasValidNodes: Bool) {
|
func addHeader(id: VisibleHeaderNodeId, upperBound: CGFloat, upperIndex: Int, upperBoundEdge: CGFloat, lowerBound: CGFloat, lowerIndex: Int, item: ListViewItemHeader, hasValidNodes: Bool) {
|
||||||
let itemHeaderHeight: CGFloat = item.height
|
let itemHeaderHeight: CGFloat = item.height
|
||||||
|
|
||||||
let headerFrame: CGRect
|
let headerFrame: CGRect
|
||||||
@ -3364,7 +3364,9 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
|||||||
visibleHeaderNodes.insert(id)
|
visibleHeaderNodes.insert(id)
|
||||||
|
|
||||||
let initialHeaderNodeAlpha = self.itemHeaderNodesAlpha
|
let initialHeaderNodeAlpha = self.itemHeaderNodesAlpha
|
||||||
if let headerNode = self.itemHeaderNodes[id] {
|
let headerNode: ListViewItemHeaderNode
|
||||||
|
if let current = self.itemHeaderNodes[id] {
|
||||||
|
headerNode = current
|
||||||
switch transition.0 {
|
switch transition.0 {
|
||||||
case .immediate:
|
case .immediate:
|
||||||
headerNode.frame = headerFrame
|
headerNode.frame = headerFrame
|
||||||
@ -3410,7 +3412,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
|||||||
}
|
}
|
||||||
headerNode.updateStickDistanceFactor(stickLocationDistanceFactor, transition: transition.0)
|
headerNode.updateStickDistanceFactor(stickLocationDistanceFactor, transition: transition.0)
|
||||||
} else {
|
} else {
|
||||||
let headerNode = item.node(synchronousLoad: synchronousLoad)
|
headerNode = item.node(synchronousLoad: synchronousLoad)
|
||||||
headerNode.alpha = initialHeaderNodeAlpha
|
headerNode.alpha = initialHeaderNodeAlpha
|
||||||
if headerNode.item !== item {
|
if headerNode.item !== item {
|
||||||
item.updateNode(headerNode, previous: nil, next: nil)
|
item.updateNode(headerNode, previous: nil, next: nil)
|
||||||
@ -3432,11 +3434,52 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
|||||||
}
|
}
|
||||||
headerNode.updateStickDistanceFactor(stickLocationDistanceFactor, transition: .immediate)
|
headerNode.updateStickDistanceFactor(stickLocationDistanceFactor, transition: .immediate)
|
||||||
}
|
}
|
||||||
|
var maxIntersectionHeight: (CGFloat, Int)?
|
||||||
|
for i in upperIndex ... lowerIndex {
|
||||||
|
let itemNode = self.itemNodes[i]
|
||||||
|
let itemNodeFrame = itemNode.apparentFrame
|
||||||
|
let intersectionHeight: CGFloat = itemNodeFrame.intersection(headerFrame).height
|
||||||
|
|
||||||
|
if let (currentMaxIntersectionHeight, _) = maxIntersectionHeight {
|
||||||
|
if currentMaxIntersectionHeight < intersectionHeight {
|
||||||
|
maxIntersectionHeight = (intersectionHeight, i)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
maxIntersectionHeight = (intersectionHeight, i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let (_, i) = maxIntersectionHeight {
|
||||||
|
let itemNode = self.itemNodes[i]
|
||||||
|
let itemNodeFrame = itemNode.apparentFrame
|
||||||
|
|
||||||
|
if itemNodeFrame.intersects(headerFrame) {
|
||||||
|
var updated = false
|
||||||
|
if let previousItemNode = headerNode.attachedToItemNode {
|
||||||
|
if previousItemNode !== itemNode {
|
||||||
|
previousItemNode.attachedHeaderNodes.removeAll(where: { $0 === headerNode })
|
||||||
|
updated = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
updated = true
|
||||||
|
}
|
||||||
|
if updated {
|
||||||
|
headerNode.attachedToItemNode = itemNode
|
||||||
|
itemNode.attachedHeaderNodes.append(headerNode)
|
||||||
|
itemNode.attachedHeaderNodesUpdated()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if let previousItemNode = headerNode.attachedToItemNode {
|
||||||
|
previousItemNode.attachedHeaderNodes.removeAll(where: { $0 === headerNode })
|
||||||
|
headerNode.attachedToItemNode = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var previousHeaderBySpace: [AnyHashable: (id: VisibleHeaderNodeId, upperBound: CGFloat, upperBoundEdge: CGFloat, lowerBound: CGFloat, item: ListViewItemHeader, hasValidNodes: Bool)] = [:]
|
var previousHeaderBySpace: [AnyHashable: (id: VisibleHeaderNodeId, upperBound: CGFloat, upperBoundIndex: Int, upperBoundEdge: CGFloat, lowerBound: CGFloat, lowerBoundIndex: Int, item: ListViewItemHeader, hasValidNodes: Bool)] = [:]
|
||||||
|
|
||||||
for itemNode in self.itemNodes {
|
for i in 0 ..< self.itemNodes.count {
|
||||||
|
let itemNode = self.itemNodes[i]
|
||||||
let itemFrame = itemNode.apparentFrame
|
let itemFrame = itemNode.apparentFrame
|
||||||
let itemTopInset = itemNode.insets.top
|
let itemTopInset = itemNode.insets.top
|
||||||
var validItemHeaderSpaces: [AnyHashable] = []
|
var validItemHeaderSpaces: [AnyHashable] = []
|
||||||
@ -3458,16 +3501,16 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
|||||||
itemMaxY = itemFrame.maxY - (self.rotated ? itemNode.insets.top : itemNode.insets.bottom)
|
itemMaxY = itemFrame.maxY - (self.rotated ? itemNode.insets.top : itemNode.insets.bottom)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let (previousHeaderId, previousUpperBound, previousUpperBoundEdge, previousLowerBound, previousHeaderItem, hasValidNodes) = previousHeaderBySpace[itemHeader.id.space] {
|
if let (previousHeaderId, previousUpperBound, previousUpperIndex, previousUpperBoundEdge, previousLowerBound, previousLowerIndex, previousHeaderItem, hasValidNodes) = previousHeaderBySpace[itemHeader.id.space] {
|
||||||
if previousHeaderId == headerId {
|
if previousHeaderId == headerId {
|
||||||
previousHeaderBySpace[itemHeader.id.space] = (previousHeaderId, previousUpperBound, previousUpperBoundEdge, itemMaxY, previousHeaderItem, hasValidNodes || itemNode.index != nil)
|
previousHeaderBySpace[itemHeader.id.space] = (previousHeaderId, previousUpperBound, previousUpperIndex, previousUpperBoundEdge, itemMaxY, i, previousHeaderItem, hasValidNodes || itemNode.index != nil)
|
||||||
} else {
|
} else {
|
||||||
addHeader(id: previousHeaderId, upperBound: previousUpperBound, upperBoundEdge: previousUpperBoundEdge, lowerBound: previousLowerBound, item: previousHeaderItem, hasValidNodes: hasValidNodes)
|
addHeader(id: previousHeaderId, upperBound: previousUpperBound, upperIndex: previousUpperIndex, upperBoundEdge: previousUpperBoundEdge, lowerBound: previousLowerBound, lowerIndex: previousLowerIndex, item: previousHeaderItem, hasValidNodes: hasValidNodes)
|
||||||
|
|
||||||
previousHeaderBySpace[itemHeader.id.space] = (headerId, itemFrame.minY, itemFrame.minY + itemTopInset, itemMaxY, itemHeader, itemNode.index != nil)
|
previousHeaderBySpace[itemHeader.id.space] = (headerId, itemFrame.minY, i, itemFrame.minY + itemTopInset, itemMaxY, i, itemHeader, itemNode.index != nil)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
previousHeaderBySpace[itemHeader.id.space] = (headerId, itemFrame.minY, itemFrame.minY + itemTopInset, itemMaxY, itemHeader, itemNode.index != nil)
|
previousHeaderBySpace[itemHeader.id.space] = (headerId, itemFrame.minY, i, itemFrame.minY + itemTopInset, itemMaxY, i, itemHeader, itemNode.index != nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3477,18 +3520,18 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
let (previousHeaderId, previousUpperBound, previousUpperBoundEdge, previousLowerBound, previousHeaderItem, hasValidNodes) = previousHeader
|
let (previousHeaderId, previousUpperBound, previousUpperIndex, previousUpperBoundEdge, previousLowerBound, previousLowerIndex, previousHeaderItem, hasValidNodes) = previousHeader
|
||||||
|
|
||||||
addHeader(id: previousHeaderId, upperBound: previousUpperBound, upperBoundEdge: previousUpperBoundEdge, lowerBound: previousLowerBound, item: previousHeaderItem, hasValidNodes: hasValidNodes)
|
addHeader(id: previousHeaderId, upperBound: previousUpperBound, upperIndex: previousUpperIndex, upperBoundEdge: previousUpperBoundEdge, lowerBound: previousLowerBound, lowerIndex: previousLowerIndex, item: previousHeaderItem, hasValidNodes: hasValidNodes)
|
||||||
|
|
||||||
previousHeaderBySpace.removeValue(forKey: space)
|
previousHeaderBySpace.removeValue(forKey: space)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (space, previousHeader) in previousHeaderBySpace {
|
for (space, previousHeader) in previousHeaderBySpace {
|
||||||
let (previousHeaderId, previousUpperBound, previousUpperBoundEdge, previousLowerBound, previousHeaderItem, hasValidNodes) = previousHeader
|
let (previousHeaderId, previousUpperBound, previousUpperIndex, previousUpperBoundEdge, previousLowerBound, previousLowerIndex, previousHeaderItem, hasValidNodes) = previousHeader
|
||||||
|
|
||||||
addHeader(id: previousHeaderId, upperBound: previousUpperBound, upperBoundEdge: previousUpperBoundEdge, lowerBound: previousLowerBound, item: previousHeaderItem, hasValidNodes: hasValidNodes)
|
addHeader(id: previousHeaderId, upperBound: previousUpperBound, upperIndex: previousUpperIndex, upperBoundEdge: previousUpperBoundEdge, lowerBound: previousLowerBound, lowerIndex: previousLowerIndex, item: previousHeaderItem, hasValidNodes: hasValidNodes)
|
||||||
|
|
||||||
previousHeaderBySpace.removeValue(forKey: space)
|
previousHeaderBySpace.removeValue(forKey: space)
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,8 @@ public protocol ListViewItemHeader: AnyObject {
|
|||||||
var height: CGFloat { get }
|
var height: CGFloat { get }
|
||||||
var stickOverInsets: Bool { get }
|
var stickOverInsets: Bool { get }
|
||||||
|
|
||||||
|
func combinesWith(other: ListViewItemHeader) -> Bool
|
||||||
|
|
||||||
func node(synchronousLoad: Bool) -> ListViewItemHeaderNode
|
func node(synchronousLoad: Bool) -> ListViewItemHeaderNode
|
||||||
func updateNode(_ node: ListViewItemHeaderNode, previous: ListViewItemHeader?, next: ListViewItemHeader?)
|
func updateNode(_ node: ListViewItemHeaderNode, previous: ListViewItemHeader?, next: ListViewItemHeader?)
|
||||||
}
|
}
|
||||||
@ -25,6 +27,7 @@ open class ListViewItemHeaderNode: ASDisplayNode {
|
|||||||
final private(set) var internalStickLocationDistanceFactor: CGFloat = 0.0
|
final private(set) var internalStickLocationDistanceFactor: CGFloat = 0.0
|
||||||
final var internalStickLocationDistance: CGFloat = 0.0
|
final var internalStickLocationDistance: CGFloat = 0.0
|
||||||
private var isFlashingOnScrolling = false
|
private var isFlashingOnScrolling = false
|
||||||
|
weak var attachedToItemNode: ListViewItemNode?
|
||||||
|
|
||||||
var item: ListViewItemHeader?
|
var item: ListViewItemHeader?
|
||||||
|
|
||||||
|
@ -130,6 +130,11 @@ open class ListViewItemNode: ASDisplayNode, AccessibilityFocusableNode {
|
|||||||
final var tempHeaderSpaceAffinities: [ListViewItemNode.HeaderId: Int] = [:]
|
final var tempHeaderSpaceAffinities: [ListViewItemNode.HeaderId: Int] = [:]
|
||||||
final var headerSpaceAffinities: [ListViewItemNode.HeaderId: Int] = [:]
|
final var headerSpaceAffinities: [ListViewItemNode.HeaderId: Int] = [:]
|
||||||
|
|
||||||
|
public internal(set) var attachedHeaderNodes: [ListViewItemHeaderNode] = []
|
||||||
|
|
||||||
|
open func attachedHeaderNodesUpdated() {
|
||||||
|
}
|
||||||
|
|
||||||
final let wantsScrollDynamics: Bool
|
final let wantsScrollDynamics: Bool
|
||||||
|
|
||||||
open var preferredAnimationCurve: (CGFloat) -> CGFloat {
|
open var preferredAnimationCurve: (CGFloat) -> CGFloat {
|
||||||
|
@ -1375,6 +1375,14 @@ public final class ItemListPeerItemHeader: ListViewItemHeader {
|
|||||||
self.action = action
|
self.action = action
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func combinesWith(other: ListViewItemHeader) -> Bool {
|
||||||
|
if let other = other as? ItemListPeerItemHeader, other.id == self.id {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public func node(synchronousLoad: Bool) -> ListViewItemHeaderNode {
|
public func node(synchronousLoad: Bool) -> ListViewItemHeaderNode {
|
||||||
return ItemListPeerItemHeaderNode(theme: self.theme, strings: self.strings, text: self.text, additionalText: self.additionalText, actionTitle: self.actionTitle, action: self.action)
|
return ItemListPeerItemHeaderNode(theme: self.theme, strings: self.strings, text: self.text, additionalText: self.additionalText, actionTitle: self.actionTitle, action: self.action)
|
||||||
}
|
}
|
||||||
|
@ -68,6 +68,14 @@ final class ListMessageDateHeader: ListViewItemHeader {
|
|||||||
|
|
||||||
let height: CGFloat = 28.0
|
let height: CGFloat = 28.0
|
||||||
|
|
||||||
|
public func combinesWith(other: ListViewItemHeader) -> Bool {
|
||||||
|
if let other = other as? ListMessageDateHeader, other.id == self.id {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func node(synchronousLoad: Bool) -> ListViewItemHeaderNode {
|
func node(synchronousLoad: Bool) -> ListViewItemHeaderNode {
|
||||||
return ListMessageDateHeaderNode(theme: self.theme, strings: self.strings, fontSize: self.fontSize, roundedTimestamp: self.roundedTimestamp, month: self.month, year: self.year)
|
return ListMessageDateHeaderNode(theme: self.theme, strings: self.strings, fontSize: self.fontSize, roundedTimestamp: self.roundedTimestamp, month: self.month, year: self.year)
|
||||||
}
|
}
|
||||||
|
@ -1498,6 +1498,8 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
bounds.origin.x = -translation.x
|
bounds.origin.x = -translation.x
|
||||||
self.bounds = bounds
|
self.bounds = bounds
|
||||||
|
|
||||||
|
self.updateAttachedAvatarNodeOffset(offset: translation.x, transition: .immediate)
|
||||||
|
|
||||||
if let swipeToReplyNode = self.swipeToReplyNode {
|
if let swipeToReplyNode = self.swipeToReplyNode {
|
||||||
swipeToReplyNode.frame = CGRect(origin: CGPoint(x: bounds.size.width, y: floor((self.contentSize.height - 33.0) / 2.0)), size: CGSize(width: 33.0, height: 33.0))
|
swipeToReplyNode.frame = CGRect(origin: CGPoint(x: bounds.size.width, y: floor((self.contentSize.height - 33.0) / 2.0)), size: CGSize(width: 33.0, height: 33.0))
|
||||||
if animateReplyNodeIn {
|
if animateReplyNodeIn {
|
||||||
@ -1532,6 +1534,9 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
bounds.origin.x = 0.0
|
bounds.origin.x = 0.0
|
||||||
self.bounds = bounds
|
self.bounds = bounds
|
||||||
self.layer.animateBounds(from: previousBounds, to: bounds, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring)
|
self.layer.animateBounds(from: previousBounds, to: bounds, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring)
|
||||||
|
|
||||||
|
self.updateAttachedAvatarNodeOffset(offset: 0.0, transition: .animated(duration: 0.3, curve: .spring))
|
||||||
|
|
||||||
if let swipeToReplyNode = self.swipeToReplyNode {
|
if let swipeToReplyNode = self.swipeToReplyNode {
|
||||||
self.swipeToReplyNode = nil
|
self.swipeToReplyNode = nil
|
||||||
swipeToReplyNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak swipeToReplyNode] _ in
|
swipeToReplyNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak swipeToReplyNode] _ in
|
||||||
|
@ -3658,6 +3658,8 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
|||||||
shadowBounds.origin.x = -translation.x
|
shadowBounds.origin.x = -translation.x
|
||||||
self.shadowNode.bounds = shadowBounds
|
self.shadowNode.bounds = shadowBounds
|
||||||
|
|
||||||
|
self.updateAttachedAvatarNodeOffset(offset: translation.x, transition: .immediate)
|
||||||
|
|
||||||
if let swipeToReplyNode = self.swipeToReplyNode {
|
if let swipeToReplyNode = self.swipeToReplyNode {
|
||||||
swipeToReplyNode.frame = CGRect(origin: CGPoint(x: bounds.size.width, y: floor((self.contentSize.height - 33.0) / 2.0)), size: CGSize(width: 33.0, height: 33.0))
|
swipeToReplyNode.frame = CGRect(origin: CGPoint(x: bounds.size.width, y: floor((self.contentSize.height - 33.0) / 2.0)), size: CGSize(width: 33.0, height: 33.0))
|
||||||
if animateReplyNodeIn {
|
if animateReplyNodeIn {
|
||||||
@ -3696,6 +3698,9 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
|||||||
shadowBounds.origin.x = 0.0
|
shadowBounds.origin.x = 0.0
|
||||||
self.shadowNode.bounds = shadowBounds
|
self.shadowNode.bounds = shadowBounds
|
||||||
self.layer.animateBounds(from: previousBounds, to: bounds, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring)
|
self.layer.animateBounds(from: previousBounds, to: bounds, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring)
|
||||||
|
|
||||||
|
self.updateAttachedAvatarNodeOffset(offset: 0.0, transition: .animated(duration: 0.3, curve: .spring))
|
||||||
|
|
||||||
self.shadowNode.layer.animateBounds(from: previousShadowBounds, to: shadowBounds, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring)
|
self.shadowNode.layer.animateBounds(from: previousShadowBounds, to: shadowBounds, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring)
|
||||||
if let swipeToReplyNode = self.swipeToReplyNode {
|
if let swipeToReplyNode = self.swipeToReplyNode {
|
||||||
self.swipeToReplyNode = nil
|
self.swipeToReplyNode = nil
|
||||||
|
@ -43,6 +43,14 @@ final class ChatMessageDateHeader: ListViewItemHeader {
|
|||||||
|
|
||||||
let height: CGFloat = 34.0
|
let height: CGFloat = 34.0
|
||||||
|
|
||||||
|
public func combinesWith(other: ListViewItemHeader) -> Bool {
|
||||||
|
if let other = other as? ChatMessageDateHeader, other.id == self.id {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func node(synchronousLoad: Bool) -> ListViewItemHeaderNode {
|
func node(synchronousLoad: Bool) -> ListViewItemHeaderNode {
|
||||||
return ChatMessageDateHeaderNode(localTimestamp: self.roundedTimestamp, scheduled: self.scheduled, presentationData: self.presentationData, context: self.context, action: self.action)
|
return ChatMessageDateHeaderNode(localTimestamp: self.roundedTimestamp, scheduled: self.scheduled, presentationData: self.presentationData, context: self.context, action: self.action)
|
||||||
}
|
}
|
||||||
@ -316,14 +324,22 @@ final class ChatMessageAvatarHeader: ListViewItemHeader {
|
|||||||
let peerId: PeerId
|
let peerId: PeerId
|
||||||
let peer: Peer?
|
let peer: Peer?
|
||||||
let messageReference: MessageReference?
|
let messageReference: MessageReference?
|
||||||
|
let effectiveTimestamp: Int32
|
||||||
let presentationData: ChatPresentationData
|
let presentationData: ChatPresentationData
|
||||||
let context: AccountContext
|
let context: AccountContext
|
||||||
let controllerInteraction: ChatControllerInteraction
|
let controllerInteraction: ChatControllerInteraction
|
||||||
|
|
||||||
init(timestamp: Int32, peerId: PeerId, peer: Peer?, messageReference: MessageReference?, presentationData: ChatPresentationData, context: AccountContext, controllerInteraction: ChatControllerInteraction) {
|
init(timestamp: Int32, peerId: PeerId, peer: Peer?, messageReference: MessageReference?, message: Message, presentationData: ChatPresentationData, context: AccountContext, controllerInteraction: ChatControllerInteraction) {
|
||||||
self.peerId = peerId
|
self.peerId = peerId
|
||||||
self.peer = peer
|
self.peer = peer
|
||||||
self.messageReference = messageReference
|
self.messageReference = messageReference
|
||||||
|
|
||||||
|
var effectiveTimestamp = message.timestamp
|
||||||
|
if let forwardInfo = message.forwardInfo, forwardInfo.flags.contains(.isImported) {
|
||||||
|
effectiveTimestamp = forwardInfo.date
|
||||||
|
}
|
||||||
|
self.effectiveTimestamp = effectiveTimestamp
|
||||||
|
|
||||||
self.presentationData = presentationData
|
self.presentationData = presentationData
|
||||||
self.context = context
|
self.context = context
|
||||||
self.controllerInteraction = controllerInteraction
|
self.controllerInteraction = controllerInteraction
|
||||||
@ -335,6 +351,17 @@ final class ChatMessageAvatarHeader: ListViewItemHeader {
|
|||||||
|
|
||||||
let height: CGFloat = 38.0
|
let height: CGFloat = 38.0
|
||||||
|
|
||||||
|
public func combinesWith(other: ListViewItemHeader) -> Bool {
|
||||||
|
if let other = other as? ChatMessageAvatarHeader, other.id == self.id {
|
||||||
|
if abs(self.effectiveTimestamp - other.effectiveTimestamp) >= 10 * 60 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func node(synchronousLoad: Bool) -> ListViewItemHeaderNode {
|
func node(synchronousLoad: Bool) -> ListViewItemHeaderNode {
|
||||||
return ChatMessageAvatarHeaderNode(peerId: self.peerId, peer: self.peer, messageReference: self.messageReference, presentationData: self.presentationData, context: self.context, controllerInteraction: self.controllerInteraction, synchronousLoad: synchronousLoad)
|
return ChatMessageAvatarHeaderNode(peerId: self.peerId, peer: self.peer, messageReference: self.messageReference, presentationData: self.presentationData, context: self.context, controllerInteraction: self.controllerInteraction, synchronousLoad: synchronousLoad)
|
||||||
}
|
}
|
||||||
|
@ -914,6 +914,8 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD
|
|||||||
bounds.origin.x = -translation.x
|
bounds.origin.x = -translation.x
|
||||||
self.bounds = bounds
|
self.bounds = bounds
|
||||||
|
|
||||||
|
self.updateAttachedAvatarNodeOffset(offset: translation.x, transition: .immediate)
|
||||||
|
|
||||||
if let swipeToReplyNode = self.swipeToReplyNode {
|
if let swipeToReplyNode = self.swipeToReplyNode {
|
||||||
swipeToReplyNode.frame = CGRect(origin: CGPoint(x: bounds.size.width, y: floor((self.contentSize.height - 33.0) / 2.0)), size: CGSize(width: 33.0, height: 33.0))
|
swipeToReplyNode.frame = CGRect(origin: CGPoint(x: bounds.size.width, y: floor((self.contentSize.height - 33.0) / 2.0)), size: CGSize(width: 33.0, height: 33.0))
|
||||||
if animateReplyNodeIn {
|
if animateReplyNodeIn {
|
||||||
@ -948,6 +950,9 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD
|
|||||||
bounds.origin.x = 0.0
|
bounds.origin.x = 0.0
|
||||||
self.bounds = bounds
|
self.bounds = bounds
|
||||||
self.layer.animateBounds(from: previousBounds, to: bounds, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring)
|
self.layer.animateBounds(from: previousBounds, to: bounds, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring)
|
||||||
|
|
||||||
|
self.updateAttachedAvatarNodeOffset(offset: 0.0, transition: .animated(duration: 0.3, curve: .spring))
|
||||||
|
|
||||||
if let swipeToReplyNode = self.swipeToReplyNode {
|
if let swipeToReplyNode = self.swipeToReplyNode {
|
||||||
self.swipeToReplyNode = nil
|
self.swipeToReplyNode = nil
|
||||||
swipeToReplyNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak swipeToReplyNode] _ in
|
swipeToReplyNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak swipeToReplyNode] _ in
|
||||||
|
@ -357,7 +357,7 @@ public final class ChatMessageItem: ListViewItem, CustomStringConvertible {
|
|||||||
if !hasActionMedia && !isBroadcastChannel {
|
if !hasActionMedia && !isBroadcastChannel {
|
||||||
if let effectiveAuthor = effectiveAuthor {
|
if let effectiveAuthor = effectiveAuthor {
|
||||||
//accessoryItem = ChatMessageAvatarAccessoryItem(context: context, peerId: effectiveAuthor.id, peer: effectiveAuthor, messageReference: MessageReference(message), messageTimestamp: content.index.timestamp, forwardInfo: message.forwardInfo, emptyColor: presentationData.theme.theme.chat.message.incoming.bubble.withoutWallpaper.fill, controllerInteraction: controllerInteraction)
|
//accessoryItem = ChatMessageAvatarAccessoryItem(context: context, peerId: effectiveAuthor.id, peer: effectiveAuthor, messageReference: MessageReference(message), messageTimestamp: content.index.timestamp, forwardInfo: message.forwardInfo, emptyColor: presentationData.theme.theme.chat.message.incoming.bubble.withoutWallpaper.fill, controllerInteraction: controllerInteraction)
|
||||||
avatarHeader = ChatMessageAvatarHeader(timestamp: content.index.timestamp, peerId: effectiveAuthor.id, peer: effectiveAuthor, messageReference: MessageReference(message), presentationData: presentationData, context: context, controllerInteraction: controllerInteraction)
|
avatarHeader = ChatMessageAvatarHeader(timestamp: content.index.timestamp, peerId: effectiveAuthor.id, peer: effectiveAuthor, messageReference: MessageReference(message), message: message, presentationData: presentationData, context: context, controllerInteraction: controllerInteraction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -874,4 +874,18 @@ public class ChatMessageItemView: ListViewItemNode {
|
|||||||
func getStatusNode() -> ASDisplayNode? {
|
func getStatusNode() -> ASDisplayNode? {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var attachedAvatarNodeOffset: CGFloat = 0.0
|
||||||
|
|
||||||
|
override public func attachedHeaderNodesUpdated() {
|
||||||
|
self.updateAttachedAvatarNodeOffset(offset: self.attachedAvatarNodeOffset, transition: .immediate)
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateAttachedAvatarNodeOffset(offset: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||||
|
for headerNode in self.attachedHeaderNodes {
|
||||||
|
if let headerNode = headerNode as? ChatMessageAvatarHeaderNode {
|
||||||
|
transition.updateSublayerTransformOffset(layer: headerNode.layer, offset: CGPoint(x: offset, y: 0.0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1018,6 +1018,8 @@ class ChatMessageStickerItemNode: ChatMessageItemView {
|
|||||||
bounds.origin.x = -translation.x
|
bounds.origin.x = -translation.x
|
||||||
self.bounds = bounds
|
self.bounds = bounds
|
||||||
|
|
||||||
|
self.updateAttachedAvatarNodeOffset(offset: translation.x, transition: .immediate)
|
||||||
|
|
||||||
if let swipeToReplyNode = self.swipeToReplyNode {
|
if let swipeToReplyNode = self.swipeToReplyNode {
|
||||||
swipeToReplyNode.frame = CGRect(origin: CGPoint(x: bounds.size.width, y: floor((self.contentSize.height - 33.0) / 2.0)), size: CGSize(width: 33.0, height: 33.0))
|
swipeToReplyNode.frame = CGRect(origin: CGPoint(x: bounds.size.width, y: floor((self.contentSize.height - 33.0) / 2.0)), size: CGSize(width: 33.0, height: 33.0))
|
||||||
if animateReplyNodeIn {
|
if animateReplyNodeIn {
|
||||||
@ -1052,6 +1054,9 @@ class ChatMessageStickerItemNode: ChatMessageItemView {
|
|||||||
bounds.origin.x = 0.0
|
bounds.origin.x = 0.0
|
||||||
self.bounds = bounds
|
self.bounds = bounds
|
||||||
self.layer.animateBounds(from: previousBounds, to: bounds, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring)
|
self.layer.animateBounds(from: previousBounds, to: bounds, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring)
|
||||||
|
|
||||||
|
self.updateAttachedAvatarNodeOffset(offset: 0.0, transition: .animated(duration: 0.3, curve: .spring))
|
||||||
|
|
||||||
if let swipeToReplyNode = self.swipeToReplyNode {
|
if let swipeToReplyNode = self.swipeToReplyNode {
|
||||||
self.swipeToReplyNode = nil
|
self.swipeToReplyNode = nil
|
||||||
swipeToReplyNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak swipeToReplyNode] _ in
|
swipeToReplyNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak swipeToReplyNode] _ in
|
||||||
|
Loading…
x
Reference in New Issue
Block a user