mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios
This commit is contained in:
commit
4a89668a10
@ -650,9 +650,9 @@ class CallListCallItemNode: ItemListRevealOptionsItemNode {
|
||||
self.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration * 0.3, removeOnCompletion: false)
|
||||
}
|
||||
|
||||
override public func header() -> ListViewItemHeader? {
|
||||
override public func headers() -> [ListViewItemHeader]? {
|
||||
if let (item, _, _, _, _) = self.layoutParams {
|
||||
return item.header
|
||||
return item.header.flatMap { [$0] }
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
@ -467,9 +467,9 @@ class CallListGroupCallItemNode: ItemListRevealOptionsItemNode {
|
||||
self.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration * 0.3, removeOnCompletion: false)
|
||||
}
|
||||
|
||||
override public func header() -> ListViewItemHeader? {
|
||||
override public func headers() -> [ListViewItemHeader]? {
|
||||
if let (item, _, _, _, _) = self.layoutParams {
|
||||
return item.header
|
||||
return item.header.flatMap { [$0] }
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
@ -151,9 +151,10 @@ private enum ChatListSearchItemHeaderId: Int32 {
|
||||
}
|
||||
|
||||
public final class ChatListSearchItemHeader: ListViewItemHeader {
|
||||
public let id: Int64
|
||||
public let id: ListViewItemNode.HeaderId
|
||||
public let type: ChatListSearchItemHeaderType
|
||||
public let stickDirection: ListViewItemHeaderStickDirection = .top
|
||||
public let stickOverInsets: Bool = true
|
||||
public let theme: PresentationTheme
|
||||
public let strings: PresentationStrings
|
||||
public let actionTitle: String?
|
||||
@ -163,14 +164,14 @@ public final class ChatListSearchItemHeader: ListViewItemHeader {
|
||||
|
||||
public init(type: ChatListSearchItemHeaderType, theme: PresentationTheme, strings: PresentationStrings, actionTitle: String? = nil, action: (() -> Void)? = nil) {
|
||||
self.type = type
|
||||
self.id = Int64(self.type.id.rawValue)
|
||||
self.id = ListViewItemNode.HeaderId(space: 0, id: Int64(self.type.id.rawValue))
|
||||
self.theme = theme
|
||||
self.strings = strings
|
||||
self.actionTitle = actionTitle
|
||||
self.action = action
|
||||
}
|
||||
|
||||
public func node() -> ListViewItemHeaderNode {
|
||||
public func node(synchronousLoad: Bool) -> ListViewItemHeaderNode {
|
||||
return ChatListSearchItemHeaderNode(type: self.type, theme: self.theme, strings: self.strings, actionTitle: self.actionTitle, action: self.action)
|
||||
}
|
||||
|
||||
|
@ -363,9 +363,9 @@ public class ChatListAdditionalCategoryItemNode: ItemListRevealOptionsItemNode {
|
||||
self.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration * 0.5, removeOnCompletion: false)
|
||||
}
|
||||
|
||||
override public func header() -> ListViewItemHeader? {
|
||||
override public func headers() -> [ListViewItemHeader]? {
|
||||
if let item = self.item {
|
||||
return item.header
|
||||
return item.header.flatMap { [$0] }
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
@ -465,7 +465,7 @@ class ChatListFilterPresetCategoryItemNode: ItemListRevealOptionsItemNode, ItemL
|
||||
}
|
||||
}
|
||||
|
||||
override func header() -> ListViewItemHeader? {
|
||||
override func headers() -> [ListViewItemHeader]? {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
@ -154,9 +154,9 @@ class ChatListRecentPeersListItemNode: ListViewItemNode {
|
||||
self.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration * 0.5, removeOnCompletion: false)
|
||||
}
|
||||
|
||||
override public func header() -> ListViewItemHeader? {
|
||||
override public func headers() -> [ListViewItemHeader]? {
|
||||
if let item = self.item {
|
||||
return item.header
|
||||
return item.header.flatMap { [$0] }
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
@ -1893,9 +1893,9 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
}
|
||||
}
|
||||
|
||||
override public func header() -> ListViewItemHeader? {
|
||||
override public func headers() -> [ListViewItemHeader]? {
|
||||
if let item = self.layoutParams?.0 {
|
||||
return item.header
|
||||
return item.header.flatMap { [$0] }
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
@ -245,9 +245,9 @@ class ContactsAddItemNode: ListViewItemNode {
|
||||
self.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration * 0.5, removeOnCompletion: false)
|
||||
}
|
||||
|
||||
override public func header() -> ListViewItemHeader? {
|
||||
override public func headers() -> [ListViewItemHeader]? {
|
||||
if let (item, _, _, _, _) = self.layoutParams {
|
||||
return item.header
|
||||
return item.header.flatMap { [$0] }
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
@ -325,9 +325,9 @@ class ContactListActionItemNode: ListViewItemNode {
|
||||
self.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false)
|
||||
}
|
||||
|
||||
override public func header() -> ListViewItemHeader? {
|
||||
override public func headers() -> [ListViewItemHeader]? {
|
||||
if let item = self.item {
|
||||
return item.header
|
||||
return item.header.flatMap { [$0] }
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
@ -5,20 +5,21 @@ import TelegramPresentationData
|
||||
import ListSectionHeaderNode
|
||||
|
||||
final class ContactListNameIndexHeader: Equatable, ListViewItemHeader {
|
||||
let id: Int64
|
||||
let id: ListViewItemNode.HeaderId
|
||||
let theme: PresentationTheme
|
||||
let letter: unichar
|
||||
let stickDirection: ListViewItemHeaderStickDirection = .top
|
||||
public let stickOverInsets: Bool = true
|
||||
|
||||
let height: CGFloat = 29.0
|
||||
|
||||
init(theme: PresentationTheme, letter: unichar) {
|
||||
self.theme = theme
|
||||
self.letter = letter
|
||||
self.id = Int64(letter)
|
||||
self.id = ListViewItemNode.HeaderId(space: 0, id: Int64(letter))
|
||||
}
|
||||
|
||||
func node() -> ListViewItemHeaderNode {
|
||||
func node(synchronousLoad: Bool) -> ListViewItemHeaderNode {
|
||||
return ContactListNameIndexHeaderNode(theme: self.theme, letter: self.letter)
|
||||
}
|
||||
|
||||
|
@ -1182,9 +1182,9 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
||||
self.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration * 0.5, removeOnCompletion: false)
|
||||
}
|
||||
|
||||
override public func header() -> ListViewItemHeader? {
|
||||
override public func headers() -> [ListViewItemHeader]? {
|
||||
if let (item, _, _, _, _, _) = self.layoutParams {
|
||||
return item.header
|
||||
return item.header.flatMap { [$0] }
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
@ -41,6 +41,8 @@ private func cancelOtherGestures(gesture: ContextGesture, view: UIView) {
|
||||
for recognizer in gestureRecognizers {
|
||||
if let recognizer = recognizer as? ContextGesture, recognizer !== gesture {
|
||||
recognizer.cancel()
|
||||
} else if let recognizer = recognizer as? ListViewTapGestureRecognizer {
|
||||
recognizer.cancel()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,11 @@ import UIKitRuntimeUtils
|
||||
private let infiniteScrollSize: CGFloat = 10000.0
|
||||
private let insertionAnimationDuration: Double = 0.4
|
||||
|
||||
private struct VisibleHeaderNodeId: Hashable {
|
||||
var id: ListViewItemNode.HeaderId
|
||||
var affinity: Int
|
||||
}
|
||||
|
||||
private final class ListViewBackingLayer: CALayer {
|
||||
override func setNeedsLayout() {
|
||||
}
|
||||
@ -275,7 +280,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
||||
|
||||
private final var items: [ListViewItem] = []
|
||||
private final var itemNodes: [ListViewItemNode] = []
|
||||
private final var itemHeaderNodes: [Int64: ListViewItemHeaderNode] = [:]
|
||||
private final var itemHeaderNodes: [VisibleHeaderNodeId: ListViewItemHeaderNode] = [:]
|
||||
|
||||
public final var itemHeaderNodesAlpha: CGFloat = 1.0
|
||||
|
||||
@ -846,7 +851,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
||||
}
|
||||
self.updateScroller(transition: .immediate)
|
||||
|
||||
self.updateItemHeaders(leftInset: self.insets.left, rightInset: self.insets.right)
|
||||
self.updateItemHeaders(leftInset: self.insets.left, rightInset: self.insets.right, synchronousLoad: false)
|
||||
|
||||
for (_, headerNode) in self.itemHeaderNodes {
|
||||
if self.dynamicBounceEnabled && headerNode.wantsScrollDynamics {
|
||||
@ -1366,13 +1371,6 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
||||
}
|
||||
} else if let itemHighlightOverlayBackground = self.itemHighlightOverlayBackground {
|
||||
self.itemHighlightOverlayBackground = nil
|
||||
for (_, _) in self.itemHeaderNodes {
|
||||
//self.view.bringSubview(toFront: headerNode.view)
|
||||
}
|
||||
//self.view.bringSubview(toFront: itemHighlightOverlayBackground.view)
|
||||
for _ in self.itemNodes {
|
||||
//self.view.bringSubview(toFront: itemNode.view)
|
||||
}
|
||||
transition.updateAlpha(node: itemHighlightOverlayBackground, alpha: 0.0, completion: { [weak itemHighlightOverlayBackground] _ in
|
||||
itemHighlightOverlayBackground?.removeFromSupernode()
|
||||
})
|
||||
@ -1869,7 +1867,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
||||
|
||||
let beginReplay = { [weak self] in
|
||||
if let strongSelf = self {
|
||||
strongSelf.replayOperations(animated: animated, animateAlpha: options.contains(.AnimateAlpha), animateCrossfade: options.contains(.AnimateCrossfade), synchronous: options.contains(.Synchronous), animateTopItemVerticalOrigin: options.contains(.AnimateTopItemPosition), operations: updatedOperations, requestItemInsertionAnimationsIndices: options.contains(.RequestItemInsertionAnimations) ? insertedIndexSet : Set(), scrollToItem: scrollToItem, additionalScrollDistance: additionalScrollDistance, updateSizeAndInsets: updateSizeAndInsets, stationaryItemIndex: stationaryItemIndex, updateOpaqueState: updateOpaqueState, completion: {
|
||||
strongSelf.replayOperations(animated: animated, animateAlpha: options.contains(.AnimateAlpha), animateCrossfade: options.contains(.AnimateCrossfade), synchronous: options.contains(.Synchronous), synchronousLoads: options.contains(.PreferSynchronousResourceLoading), animateTopItemVerticalOrigin: options.contains(.AnimateTopItemPosition), operations: updatedOperations, requestItemInsertionAnimationsIndices: options.contains(.RequestItemInsertionAnimations) ? insertedIndexSet : Set(), scrollToItem: scrollToItem, additionalScrollDistance: additionalScrollDistance, updateSizeAndInsets: updateSizeAndInsets, stationaryItemIndex: stationaryItemIndex, updateOpaqueState: updateOpaqueState, completion: {
|
||||
if options.contains(.PreferSynchronousDrawing) {
|
||||
self?.recursivelyEnsureDisplaySynchronously(true)
|
||||
}
|
||||
@ -2318,7 +2316,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
||||
}
|
||||
}
|
||||
|
||||
private func replayOperations(animated: Bool, animateAlpha: Bool, animateCrossfade: Bool, synchronous: Bool, animateTopItemVerticalOrigin: Bool, operations: [ListViewStateOperation], requestItemInsertionAnimationsIndices: Set<Int>, scrollToItem originalScrollToItem: ListViewScrollToItem?, additionalScrollDistance: CGFloat, updateSizeAndInsets: ListViewUpdateSizeAndInsets?, stationaryItemIndex: Int?, updateOpaqueState: Any?, completion: () -> Void) {
|
||||
private func replayOperations(animated: Bool, animateAlpha: Bool, animateCrossfade: Bool, synchronous: Bool, synchronousLoads: Bool, animateTopItemVerticalOrigin: Bool, operations: [ListViewStateOperation], requestItemInsertionAnimationsIndices: Set<Int>, scrollToItem originalScrollToItem: ListViewScrollToItem?, additionalScrollDistance: CGFloat, updateSizeAndInsets: ListViewUpdateSizeAndInsets?, stationaryItemIndex: Int?, updateOpaqueState: Any?, completion: () -> Void) {
|
||||
var scrollToItem: ListViewScrollToItem?
|
||||
var isExperimentalSnapToScrollToItem = false
|
||||
if let originalScrollToItem = originalScrollToItem {
|
||||
@ -3039,7 +3037,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
||||
previousItemHeaderNodes.append(headerNode)
|
||||
}
|
||||
|
||||
self.updateItemHeaders(leftInset: listInsets.left, rightInset: listInsets.right, transition: headerNodesTransition, animateInsertion: animated || !requestItemInsertionAnimationsIndices.isEmpty)
|
||||
self.updateItemHeaders(leftInset: listInsets.left, rightInset: listInsets.right, synchronousLoad: synchronousLoads, transition: headerNodesTransition, animateInsertion: animated || !requestItemInsertionAnimationsIndices.isEmpty)
|
||||
|
||||
if let offset = offset, !offset.isZero {
|
||||
//self.didScrollWithOffset?(-offset, headerNodesTransition.0, nil)
|
||||
@ -3215,7 +3213,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
||||
|
||||
completion()
|
||||
} else {
|
||||
self.updateItemHeaders(leftInset: listInsets.left, rightInset: listInsets.right, transition: headerNodesTransition, animateInsertion: animated || !requestItemInsertionAnimationsIndices.isEmpty)
|
||||
self.updateItemHeaders(leftInset: listInsets.left, rightInset: listInsets.right, synchronousLoad: synchronousLoads, transition: headerNodesTransition, animateInsertion: animated || !requestItemInsertionAnimationsIndices.isEmpty)
|
||||
self.updateItemNodesVisibilities(onlyPositive: deferredUpdateVisible)
|
||||
|
||||
if animated {
|
||||
@ -3262,15 +3260,88 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
||||
node.headerAccessoryItemNode?.removeFromSupernode()
|
||||
node.headerAccessoryItemNode = nil
|
||||
}
|
||||
|
||||
private var nextHeaderSpaceAffinity: Int = 0
|
||||
|
||||
private func assignHeaderSpaceAffinities() {
|
||||
var nextTempAffinity = 0
|
||||
|
||||
var existingAffinityIdByAffinity: [Int: Int] = [:]
|
||||
|
||||
for i in 0 ..< self.itemNodes.count {
|
||||
let currentItemNode = self.itemNodes[i]
|
||||
|
||||
if let currentItemHeaders = currentItemNode.headers() {
|
||||
currentHeadersLoop: for currentHeader in currentItemHeaders {
|
||||
let currentId = currentHeader.id
|
||||
if let currentAffinity = currentItemNode.tempHeaderSpaceAffinities[currentId] {
|
||||
if let existingAffinity = currentItemNode.headerSpaceAffinities[currentId] {
|
||||
existingAffinityIdByAffinity[currentAffinity] = existingAffinity
|
||||
}
|
||||
|
||||
continue currentHeadersLoop
|
||||
}
|
||||
|
||||
let currentAffinity = nextTempAffinity
|
||||
nextTempAffinity += 1
|
||||
|
||||
currentItemNode.tempHeaderSpaceAffinities[currentId] = currentAffinity
|
||||
|
||||
if let existingAffinity = currentItemNode.headerSpaceAffinities[currentId] {
|
||||
existingAffinityIdByAffinity[currentAffinity] = existingAffinity
|
||||
}
|
||||
|
||||
groupSearch: for nextIndex in (i + 1) ..< self.itemNodes.count {
|
||||
let nextItemNode = self.itemNodes[nextIndex]
|
||||
|
||||
var containsSameHeader = false
|
||||
if let nextHeaders = nextItemNode.headers() {
|
||||
nextHeaderSearch: for nextHeader in nextHeaders {
|
||||
if nextHeader.id == currentId {
|
||||
containsSameHeader = true
|
||||
break nextHeaderSearch
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if containsSameHeader {
|
||||
nextItemNode.tempHeaderSpaceAffinities[currentId] = currentAffinity
|
||||
} else {
|
||||
break groupSearch
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for i in 0 ..< self.itemNodes.count {
|
||||
let itemNode = self.itemNodes[i]
|
||||
for (headerId, tempAffinity) in itemNode.tempHeaderSpaceAffinities {
|
||||
let affinity: Int
|
||||
if let existing = existingAffinityIdByAffinity[tempAffinity] {
|
||||
affinity = existing
|
||||
} else {
|
||||
affinity = self.nextHeaderSpaceAffinity
|
||||
existingAffinityIdByAffinity[tempAffinity] = affinity
|
||||
self.nextHeaderSpaceAffinity += 1
|
||||
}
|
||||
|
||||
itemNode.headerSpaceAffinities[headerId] = affinity
|
||||
itemNode.tempHeaderSpaceAffinities = [:]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func updateItemHeaders(leftInset: CGFloat, rightInset: CGFloat, transition: (ContainedViewLayoutTransition, Bool, CGFloat) = (.immediate, false, 0.0), animateInsertion: Bool = false) {
|
||||
private func updateItemHeaders(leftInset: CGFloat, rightInset: CGFloat, synchronousLoad: Bool, transition: (ContainedViewLayoutTransition, Bool, CGFloat) = (.immediate, false, 0.0), animateInsertion: Bool = false) {
|
||||
self.assignHeaderSpaceAffinities()
|
||||
|
||||
let upperDisplayBound = self.headerInsets.top
|
||||
let lowerDisplayBound = self.visibleSize.height - self.insets.bottom
|
||||
var visibleHeaderNodes = Set<Int64>()
|
||||
var visibleHeaderNodes = Set<VisibleHeaderNodeId>()
|
||||
|
||||
let flashing = self.headerItemsAreFlashing()
|
||||
|
||||
func addHeader(id: Int64, upperBound: CGFloat, upperBoundEdge: CGFloat, lowerBound: CGFloat, item: ListViewItemHeader, hasValidNodes: Bool) {
|
||||
func addHeader(id: VisibleHeaderNodeId, upperBound: CGFloat, upperBoundEdge: CGFloat, lowerBound: CGFloat, item: ListViewItemHeader, hasValidNodes: Bool) {
|
||||
let itemHeaderHeight: CGFloat = item.height
|
||||
|
||||
let headerFrame: CGRect
|
||||
@ -3334,13 +3405,12 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
||||
} else if hasValidNodes && headerNode.alpha.isZero {
|
||||
headerNode.alpha = initialHeaderNodeAlpha
|
||||
if animateInsertion {
|
||||
headerNode.layer.animateAlpha(from: 0.0, to: initialHeaderNodeAlpha, duration: 0.2)
|
||||
headerNode.layer.animateScale(from: 0.2, to: 1.0, duration: 0.2)
|
||||
headerNode.animateAdded(duration: 0.2)
|
||||
}
|
||||
}
|
||||
headerNode.updateStickDistanceFactor(stickLocationDistanceFactor, transition: transition.0)
|
||||
} else {
|
||||
let headerNode = item.node()
|
||||
let headerNode = item.node(synchronousLoad: synchronousLoad)
|
||||
headerNode.alpha = initialHeaderNodeAlpha
|
||||
if headerNode.item !== item {
|
||||
item.updateNode(headerNode, previous: nil, next: nil)
|
||||
@ -3357,39 +3427,70 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
||||
self.addSubnode(headerNode)
|
||||
}
|
||||
if animateInsertion {
|
||||
headerNode.layer.animateAlpha(from: 0.0, to: initialHeaderNodeAlpha, duration: 0.3)
|
||||
headerNode.layer.animateScale(from: 0.2, to: 1.0, duration: 0.3)
|
||||
headerNode.alpha = initialHeaderNodeAlpha
|
||||
headerNode.animateAdded(duration: 0.2)
|
||||
}
|
||||
headerNode.updateStickDistanceFactor(stickLocationDistanceFactor, transition: .immediate)
|
||||
}
|
||||
}
|
||||
|
||||
var previousHeaderBySpace: [AnyHashable: (id: VisibleHeaderNodeId, upperBound: CGFloat, upperBoundEdge: CGFloat, lowerBound: CGFloat, item: ListViewItemHeader, hasValidNodes: Bool)] = [:]
|
||||
|
||||
var previousHeader: (id: Int64, upperBound: CGFloat, upperBoundEdge: CGFloat, lowerBound: CGFloat, item: ListViewItemHeader, hasValidNodes: Bool)?
|
||||
for itemNode in self.itemNodes {
|
||||
let itemFrame = itemNode.apparentFrame
|
||||
let itemTopInset = itemNode.insets.top
|
||||
if let itemHeader = itemNode.header() {
|
||||
if let (previousHeaderId, previousUpperBound, previousUpperBoundEdge, previousLowerBound, previousHeaderItem, hasValidNodes) = previousHeader {
|
||||
if previousHeaderId == itemHeader.id {
|
||||
previousHeader = (previousHeaderId, previousUpperBound, previousUpperBoundEdge, itemFrame.maxY, previousHeaderItem, hasValidNodes || itemNode.index != nil)
|
||||
} else {
|
||||
addHeader(id: previousHeaderId, upperBound: previousUpperBound, upperBoundEdge: previousUpperBoundEdge, lowerBound: previousLowerBound, item: previousHeaderItem, hasValidNodes: hasValidNodes)
|
||||
|
||||
previousHeader = (itemHeader.id, itemFrame.minY, itemFrame.minY + itemTopInset, itemFrame.maxY, itemHeader, itemNode.index != nil)
|
||||
var validItemHeaderSpaces: [AnyHashable] = []
|
||||
if let itemHeaders = itemNode.headers() {
|
||||
for itemHeader in itemHeaders {
|
||||
guard let affinity = itemNode.headerSpaceAffinities[itemHeader.id] else {
|
||||
assertionFailure()
|
||||
continue
|
||||
}
|
||||
|
||||
let headerId = VisibleHeaderNodeId(id: itemHeader.id, affinity: affinity)
|
||||
|
||||
validItemHeaderSpaces.append(itemHeader.id.space)
|
||||
|
||||
let itemMaxY: CGFloat
|
||||
if itemHeader.stickOverInsets {
|
||||
itemMaxY = itemFrame.maxY
|
||||
} else {
|
||||
itemMaxY = itemFrame.maxY - (self.rotated ? itemNode.insets.top : itemNode.insets.bottom)
|
||||
}
|
||||
|
||||
if let (previousHeaderId, previousUpperBound, previousUpperBoundEdge, previousLowerBound, previousHeaderItem, hasValidNodes) = previousHeaderBySpace[itemHeader.id.space] {
|
||||
if previousHeaderId == headerId {
|
||||
previousHeaderBySpace[itemHeader.id.space] = (previousHeaderId, previousUpperBound, previousUpperBoundEdge, itemMaxY, previousHeaderItem, hasValidNodes || itemNode.index != nil)
|
||||
} else {
|
||||
addHeader(id: previousHeaderId, upperBound: previousUpperBound, upperBoundEdge: previousUpperBoundEdge, lowerBound: previousLowerBound, item: previousHeaderItem, hasValidNodes: hasValidNodes)
|
||||
|
||||
previousHeaderBySpace[itemHeader.id.space] = (headerId, itemFrame.minY, itemFrame.minY + itemTopInset, itemMaxY, itemHeader, itemNode.index != nil)
|
||||
}
|
||||
} else {
|
||||
previousHeaderBySpace[itemHeader.id.space] = (headerId, itemFrame.minY, itemFrame.minY + itemTopInset, itemMaxY, itemHeader, itemNode.index != nil)
|
||||
}
|
||||
} else {
|
||||
previousHeader = (itemHeader.id, itemFrame.minY, itemFrame.minY + itemTopInset, itemFrame.maxY, itemHeader, itemNode.index != nil)
|
||||
}
|
||||
} else {
|
||||
if let (previousHeaderId, previousUpperBound, previousUpperBoundEdge, previousLowerBound, previousHeaderItem, hasValidNodes) = previousHeader {
|
||||
addHeader(id: previousHeaderId, upperBound: previousUpperBound, upperBoundEdge: previousUpperBoundEdge, lowerBound: previousLowerBound, item: previousHeaderItem, hasValidNodes: hasValidNodes)
|
||||
}
|
||||
|
||||
for (space, previousHeader) in previousHeaderBySpace {
|
||||
if validItemHeaderSpaces.contains(space) {
|
||||
continue
|
||||
}
|
||||
previousHeader = nil
|
||||
|
||||
let (previousHeaderId, previousUpperBound, previousUpperBoundEdge, previousLowerBound, previousHeaderItem, hasValidNodes) = previousHeader
|
||||
|
||||
addHeader(id: previousHeaderId, upperBound: previousUpperBound, upperBoundEdge: previousUpperBoundEdge, lowerBound: previousLowerBound, item: previousHeaderItem, hasValidNodes: hasValidNodes)
|
||||
|
||||
previousHeaderBySpace.removeValue(forKey: space)
|
||||
}
|
||||
}
|
||||
|
||||
if let (previousHeaderId, previousUpperBound, previousUpperBoundEdge, previousLowerBound, previousHeaderItem, hasValidNodes) = previousHeader {
|
||||
|
||||
for (space, previousHeader) in previousHeaderBySpace {
|
||||
let (previousHeaderId, previousUpperBound, previousUpperBoundEdge, previousLowerBound, previousHeaderItem, hasValidNodes) = previousHeader
|
||||
|
||||
addHeader(id: previousHeaderId, upperBound: previousUpperBound, upperBoundEdge: previousUpperBoundEdge, lowerBound: previousLowerBound, item: previousHeaderItem, hasValidNodes: hasValidNodes)
|
||||
|
||||
previousHeaderBySpace.removeValue(forKey: space)
|
||||
}
|
||||
|
||||
let currentIds = Set(self.itemHeaderNodes.keys)
|
||||
@ -3709,10 +3810,10 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
||||
var updatedOperations = operations
|
||||
updatedState.removeInvisibleNodes(&updatedOperations)
|
||||
if synchronous {
|
||||
self.replayOperations(animated: false, animateAlpha: false, animateCrossfade: false, synchronous: false, animateTopItemVerticalOrigin: false, operations: updatedOperations, requestItemInsertionAnimationsIndices: Set(), scrollToItem: nil, additionalScrollDistance: 0.0, updateSizeAndInsets: nil, stationaryItemIndex: nil, updateOpaqueState: nil, completion: completion)
|
||||
self.replayOperations(animated: false, animateAlpha: false, animateCrossfade: false, synchronous: false, synchronousLoads: false, animateTopItemVerticalOrigin: false, operations: updatedOperations, requestItemInsertionAnimationsIndices: Set(), scrollToItem: nil, additionalScrollDistance: 0.0, updateSizeAndInsets: nil, stationaryItemIndex: nil, updateOpaqueState: nil, completion: completion)
|
||||
} else {
|
||||
self.dispatchOnVSync {
|
||||
self.replayOperations(animated: false, animateAlpha: false, animateCrossfade: false, synchronous: false, animateTopItemVerticalOrigin: false, operations: updatedOperations, requestItemInsertionAnimationsIndices: Set(), scrollToItem: nil, additionalScrollDistance: 0.0, updateSizeAndInsets: nil, stationaryItemIndex: nil, updateOpaqueState: nil, completion: completion)
|
||||
self.replayOperations(animated: false, animateAlpha: false, animateCrossfade: false, synchronous: false, synchronousLoads: false, animateTopItemVerticalOrigin: false, operations: updatedOperations, requestItemInsertionAnimationsIndices: Set(), scrollToItem: nil, additionalScrollDistance: 0.0, updateSizeAndInsets: nil, stationaryItemIndex: nil, updateOpaqueState: nil, completion: completion)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,14 +8,13 @@ public enum ListViewItemHeaderStickDirection {
|
||||
case bottom
|
||||
}
|
||||
|
||||
public typealias ListViewItemHeaderId = Int64
|
||||
|
||||
public protocol ListViewItemHeader: class {
|
||||
var id: ListViewItemHeaderId { get }
|
||||
public protocol ListViewItemHeader: AnyObject {
|
||||
var id: ListViewItemNode.HeaderId { get }
|
||||
var stickDirection: ListViewItemHeaderStickDirection { get }
|
||||
var height: CGFloat { get }
|
||||
var stickOverInsets: Bool { get }
|
||||
|
||||
func node() -> ListViewItemHeaderNode
|
||||
func node(synchronousLoad: Bool) -> ListViewItemHeaderNode
|
||||
func updateNode(_ node: ListViewItemHeaderNode, previous: ListViewItemHeader?, next: ListViewItemHeader?)
|
||||
}
|
||||
|
||||
@ -114,6 +113,11 @@ open class ListViewItemHeaderNode: ASDisplayNode {
|
||||
self.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration, removeOnCompletion: false)
|
||||
self.layer.animateScale(from: 1.0, to: 0.2, duration: duration, removeOnCompletion: false)
|
||||
}
|
||||
|
||||
open func animateAdded(duration: Double) {
|
||||
self.layer.animateAlpha(from: 0.0, to: self.alpha, duration: 0.2)
|
||||
self.layer.animateScale(from: 0.2, to: 1.0, duration: 0.2)
|
||||
}
|
||||
|
||||
private var cachedLayout: (CGSize, CGFloat, CGFloat)?
|
||||
|
||||
|
@ -84,6 +84,16 @@ public struct ListViewItemLayoutParams {
|
||||
}
|
||||
|
||||
open class ListViewItemNode: ASDisplayNode, AccessibilityFocusableNode {
|
||||
public struct HeaderId: Hashable {
|
||||
public var space: AnyHashable
|
||||
public var id: AnyHashable
|
||||
|
||||
public init(space: AnyHashable, id: AnyHashable) {
|
||||
self.space = space
|
||||
self.id = id
|
||||
}
|
||||
}
|
||||
|
||||
let rotated: Bool
|
||||
final var index: Int?
|
||||
|
||||
@ -116,6 +126,9 @@ open class ListViewItemNode: ASDisplayNode, AccessibilityFocusableNode {
|
||||
|
||||
private final var spring: ListViewItemSpring?
|
||||
private final var animations: [(String, ListViewAnimation)] = []
|
||||
|
||||
final var tempHeaderSpaceAffinities: [ListViewItemNode.HeaderId: Int] = [:]
|
||||
final var headerSpaceAffinities: [ListViewItemNode.HeaderId: Int] = [:]
|
||||
|
||||
final let wantsScrollDynamics: Bool
|
||||
|
||||
@ -533,7 +546,7 @@ open class ListViewItemNode: ASDisplayNode, AccessibilityFocusableNode {
|
||||
return false
|
||||
}
|
||||
|
||||
open func header() -> ListViewItemHeader? {
|
||||
open func headers() -> [ListViewItemHeader]? {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -2,5 +2,7 @@ import Foundation
|
||||
import UIKit
|
||||
|
||||
public final class ListViewTapGestureRecognizer: UITapGestureRecognizer {
|
||||
|
||||
public func cancel() {
|
||||
self.state = .failed
|
||||
}
|
||||
}
|
||||
|
@ -1328,8 +1328,12 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo
|
||||
}
|
||||
}
|
||||
|
||||
override public func header() -> ListViewItemHeader? {
|
||||
return self.layoutParams?.0.header
|
||||
override public func headers() -> [ListViewItemHeader]? {
|
||||
if let item = self.layoutParams?.0 {
|
||||
return item.header.flatMap { [$0] }
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
override public func updateAbsoluteRect(_ rect: CGRect, within containerSize: CGSize) {
|
||||
@ -1350,10 +1354,11 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo
|
||||
}
|
||||
|
||||
public final class ItemListPeerItemHeader: ListViewItemHeader {
|
||||
public let id: Int64
|
||||
public let id: ListViewItemNode.HeaderId
|
||||
public let text: String
|
||||
public let additionalText: String
|
||||
public let stickDirection: ListViewItemHeaderStickDirection = .topEdge
|
||||
public let stickOverInsets: Bool = true
|
||||
public let theme: PresentationTheme
|
||||
public let strings: PresentationStrings
|
||||
public let actionTitle: String?
|
||||
@ -1364,14 +1369,14 @@ public final class ItemListPeerItemHeader: ListViewItemHeader {
|
||||
public init(theme: PresentationTheme, strings: PresentationStrings, text: String, additionalText: String, actionTitle: String? = nil, id: Int64, action: (() -> Void)? = nil) {
|
||||
self.text = text
|
||||
self.additionalText = additionalText
|
||||
self.id = id
|
||||
self.id = ListViewItemNode.HeaderId(space: 0, id: id)
|
||||
self.theme = theme
|
||||
self.strings = strings
|
||||
self.actionTitle = actionTitle
|
||||
self.action = action
|
||||
}
|
||||
|
||||
public func node() -> 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)
|
||||
}
|
||||
|
||||
|
@ -457,7 +457,11 @@ public class ItemListVenueItemNode: ListViewItemNode, ItemListItemNode {
|
||||
self.item?.infoAction?()
|
||||
}
|
||||
|
||||
override public func header() -> ListViewItemHeader? {
|
||||
return self.item?.header
|
||||
override public func headers() -> [ListViewItemHeader]? {
|
||||
if let item = self.item {
|
||||
return item.header.flatMap { [$0] }
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ final class ListMessageDateHeader: ListViewItemHeader {
|
||||
private let month: Int32
|
||||
private let year: Int32
|
||||
|
||||
let id: Int64
|
||||
let id: ListViewItemNode.HeaderId
|
||||
let theme: PresentationTheme
|
||||
let strings: PresentationStrings
|
||||
let fontSize: PresentationFontSize
|
||||
@ -61,14 +61,15 @@ final class ListMessageDateHeader: ListViewItemHeader {
|
||||
self.month = timeinfo.tm_mon
|
||||
self.year = timeinfo.tm_year
|
||||
|
||||
self.id = Int64(self.roundedTimestamp)
|
||||
self.id = ListViewItemNode.HeaderId(space: 0, id: Int64(self.roundedTimestamp))
|
||||
}
|
||||
|
||||
let stickDirection: ListViewItemHeaderStickDirection = .top
|
||||
let stickOverInsets: Bool = true
|
||||
|
||||
let height: CGFloat = 28.0
|
||||
|
||||
func node() -> 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)
|
||||
}
|
||||
|
||||
|
@ -1118,8 +1118,8 @@ public final class ListMessageFileItemNode: ListMessageNode {
|
||||
}
|
||||
}
|
||||
|
||||
override public func header() -> ListViewItemHeader? {
|
||||
return self.item?.header
|
||||
override public func headers() -> [ListViewItemHeader]? {
|
||||
return self.item?.header.flatMap { [$0] }
|
||||
}
|
||||
|
||||
override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
||||
|
@ -759,8 +759,12 @@ public final class ListMessageSnippetItemNode: ListMessageNode {
|
||||
}
|
||||
}
|
||||
|
||||
override public func header() -> ListViewItemHeader? {
|
||||
return self.item?.header
|
||||
override public func headers() -> [ListViewItemHeader]? {
|
||||
if let item = self.item {
|
||||
return item.header.flatMap { [$0] }
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
||||
|
@ -2055,7 +2055,7 @@ static NSString *dumpHexString(NSData *data, int maxLength) {
|
||||
[self getAuthKeyForCurrentScheme:scheme createIfNeeded:false authInfoSelector:&authInfoSelector];
|
||||
|
||||
if (MTLogEnabled()) {
|
||||
MTLog(@"[MTProto#%p@%p missing key %lld selector %d]", self, _context, _validAuthInfo.authInfo.authKeyId, authInfoSelector);
|
||||
MTLog(@"[MTProto#%p@%p missing key %lld selector %d useExplicitAuthKey: %lld, canResetAuthData: %s]", self, _context, _validAuthInfo.authInfo.authKeyId, authInfoSelector, _useExplicitAuthKey.authKeyId, _canResetAuthData ? "true" : "false");
|
||||
}
|
||||
|
||||
if (_useExplicitAuthKey != nil) {
|
||||
|
@ -247,7 +247,7 @@ private final class BubbleSettingsControllerNode: ASDisplayNode, UIScrollViewDel
|
||||
dateHeaderNode = currentDateHeaderNode
|
||||
headerItem.updateNode(dateHeaderNode, previous: nil, next: headerItem)
|
||||
} else {
|
||||
dateHeaderNode = headerItem.node()
|
||||
dateHeaderNode = headerItem.node(synchronousLoad: true)
|
||||
dateHeaderNode.subnodeTransform = CATransform3DMakeScale(-1.0, 1.0, 1.0)
|
||||
self.messagesContainerNode.addSubnode(dateHeaderNode)
|
||||
self.dateHeaderNode = dateHeaderNode
|
||||
|
@ -243,9 +243,9 @@ class SettingsSearchRecentItemNode: ItemListRevealOptionsItemNode {
|
||||
self.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration * 0.5, removeOnCompletion: false)
|
||||
}
|
||||
|
||||
override public func header() -> ListViewItemHeader? {
|
||||
override public func headers() -> [ListViewItemHeader]? {
|
||||
if let item = self.item {
|
||||
return item.header
|
||||
return item.header.flatMap { [$0] }
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
@ -386,7 +386,7 @@ private final class TextSizeSelectionControllerNode: ASDisplayNode, UIScrollView
|
||||
dateHeaderNode = currentDateHeaderNode
|
||||
headerItem.updateNode(dateHeaderNode, previous: nil, next: headerItem)
|
||||
} else {
|
||||
dateHeaderNode = headerItem.node()
|
||||
dateHeaderNode = headerItem.node(synchronousLoad: true)
|
||||
dateHeaderNode.subnodeTransform = CATransform3DMakeScale(-1.0, 1.0, 1.0)
|
||||
self.messagesContainerNode.addSubnode(dateHeaderNode)
|
||||
self.dateHeaderNode = dateHeaderNode
|
||||
|
@ -970,7 +970,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
|
||||
dateHeaderNode = currentDateHeaderNode
|
||||
headerItem.updateNode(dateHeaderNode, previous: nil, next: headerItem)
|
||||
} else {
|
||||
dateHeaderNode = headerItem.node()
|
||||
dateHeaderNode = headerItem.node(synchronousLoad: true)
|
||||
//dateHeaderNode.subnodeTransform = CATransform3DMakeScale(-1.0, 1.0, 1.0)
|
||||
self.messagesContainerNode.addSubnode(dateHeaderNode)
|
||||
self.dateHeaderNode = dateHeaderNode
|
||||
|
@ -249,9 +249,9 @@ class ThemeGridSearchColorsItemNode: ListViewItemNode {
|
||||
self.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration * 0.5, removeOnCompletion: false)
|
||||
}
|
||||
|
||||
override public func header() -> ListViewItemHeader? {
|
||||
override public func headers() -> [ListViewItemHeader]? {
|
||||
if let item = self.item {
|
||||
return item.header
|
||||
return item.header.flatMap { [$0] }
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
@ -550,7 +550,7 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
dateHeaderNode = currentDateHeaderNode
|
||||
headerItem.updateNode(dateHeaderNode, previous: nil, next: headerItem)
|
||||
} else {
|
||||
dateHeaderNode = headerItem.node()
|
||||
dateHeaderNode = headerItem.node(synchronousLoad: true)
|
||||
dateHeaderNode.subnodeTransform = CATransform3DMakeScale(-1.0, 1.0, 1.0)
|
||||
self.messagesContainerNode.addSubnode(dateHeaderNode)
|
||||
self.dateHeaderNode = dateHeaderNode
|
||||
|
@ -1082,7 +1082,7 @@ final class MessageStoryRenderer {
|
||||
dateHeaderNode = currentDateHeaderNode
|
||||
headerItem.updateNode(dateHeaderNode, previous: nil, next: headerItem)
|
||||
} else {
|
||||
dateHeaderNode = headerItem.node()
|
||||
dateHeaderNode = headerItem.node(synchronousLoad: true)
|
||||
dateHeaderNode.subnodeTransform = CATransform3DMakeScale(-1.0, 1.0, 1.0)
|
||||
self.messagesContainerNode.addSubnode(dateHeaderNode)
|
||||
self.dateHeaderNode = dateHeaderNode
|
||||
|
@ -281,7 +281,7 @@ class VoiceChatActionItemNode: ListViewItemNode {
|
||||
self.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false)
|
||||
}
|
||||
|
||||
override public func header() -> ListViewItemHeader? {
|
||||
override public func headers() -> [ListViewItemHeader]? {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
@ -990,7 +990,7 @@ class VoiceChatFullscreenParticipantItemNode: ItemListRevealOptionsItemNode {
|
||||
self.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false)
|
||||
}
|
||||
|
||||
override func header() -> ListViewItemHeader? {
|
||||
override func headers() -> [ListViewItemHeader]? {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -1273,7 +1273,7 @@ class VoiceChatParticipantItemNode: ItemListRevealOptionsItemNode {
|
||||
self.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false)
|
||||
}
|
||||
|
||||
override func header() -> ListViewItemHeader? {
|
||||
override func headers() -> [ListViewItemHeader]? {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -7927,6 +7927,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
itemNode.updateSelectionState(animated: animated)
|
||||
}
|
||||
}
|
||||
|
||||
self.chatDisplayNode.historyNode.forEachItemHeaderNode{ itemHeaderNode in
|
||||
if let avatarNode = itemHeaderNode as? ChatMessageAvatarHeaderNode {
|
||||
avatarNode.updateSelectionState(animated: animated)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func updatePollTooltipMessageState(animated: Bool) {
|
||||
|
@ -1086,6 +1086,8 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
||||
strongSelf.forEachItemHeaderNode { itemHeaderNode in
|
||||
if let dateNode = itemHeaderNode as? ChatMessageDateHeaderNode {
|
||||
dateNode.updatePresentationData(chatPresentationData, context: context)
|
||||
} else if let avatarNode = itemHeaderNode as? ChatMessageAvatarHeaderNode {
|
||||
avatarNode.updatePresentationData(chatPresentationData, context: context)
|
||||
} else if let dateNode = itemHeaderNode as? ListMessageDateHeaderNode {
|
||||
dateNode.updateThemeAndStrings(theme: presentationData.theme, strings: presentationData.strings)
|
||||
}
|
||||
|
@ -108,14 +108,6 @@ class ChatHoleItemNode: ListViewItemNode {
|
||||
}
|
||||
}
|
||||
|
||||
/*override public func header() -> ListViewItemHeader? {
|
||||
if let item = self.item {
|
||||
return item.header
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}*/
|
||||
|
||||
override public func animateAdded(_ currentTimestamp: Double, duration: Double) {
|
||||
self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||
}
|
||||
|
@ -150,7 +150,7 @@ class ChatMessageShareButton: HighlightableButtonNode {
|
||||
textNode.removeFromSupernode()
|
||||
}
|
||||
self.backgroundNode.frame = CGRect(origin: CGPoint(), size: size)
|
||||
self.backgroundNode.update(size: self.backgroundNode.bounds.size, cornerRadius: self.backgroundNode.bounds.height / 2.0, transition: .immediate)
|
||||
self.backgroundNode.update(size: self.backgroundNode.bounds.size, cornerRadius: min(self.backgroundNode.bounds.width, self.backgroundNode.bounds.height) / 2.0, transition: .immediate)
|
||||
if let image = self.iconNode.image {
|
||||
self.iconNode.frame = CGRect(origin: CGPoint(x: floor((size.width - image.size.width) / 2.0) + self.iconOffset.x, y: floor((size.width - image.size.width) / 2.0) - (offsetIcon ? 1.0 : 0.0) + self.iconOffset.y), size: image.size)
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import TelegramPresentationData
|
||||
import Postbox
|
||||
import SyncCore
|
||||
import AccountContext
|
||||
import AvatarNode
|
||||
|
||||
private let timezoneOffset: Int32 = {
|
||||
let nowTimestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970)
|
||||
@ -22,7 +23,7 @@ final class ChatMessageDateHeader: ListViewItemHeader {
|
||||
private let roundedTimestamp: Int32
|
||||
private let scheduled: Bool
|
||||
|
||||
let id: Int64
|
||||
let id: ListViewItemNode.HeaderId
|
||||
let presentationData: ChatPresentationData
|
||||
let context: AccountContext
|
||||
let action: ((Int32) -> Void)?
|
||||
@ -33,21 +34,16 @@ final class ChatMessageDateHeader: ListViewItemHeader {
|
||||
self.presentationData = presentationData
|
||||
self.context = context
|
||||
self.action = action
|
||||
if timestamp == scheduleWhenOnlineTimestamp {
|
||||
self.roundedTimestamp = scheduleWhenOnlineTimestamp
|
||||
} else if timestamp == Int32.max {
|
||||
self.roundedTimestamp = timestamp / (granularity) * (granularity)
|
||||
} else {
|
||||
self.roundedTimestamp = ((timestamp + timezoneOffset) / (granularity)) * (granularity)
|
||||
}
|
||||
self.id = Int64(self.roundedTimestamp)
|
||||
self.roundedTimestamp = dateHeaderTimestampId(timestamp: timestamp)
|
||||
self.id = ListViewItemNode.HeaderId(space: 0, id: Int64(self.roundedTimestamp))
|
||||
}
|
||||
|
||||
let stickDirection: ListViewItemHeaderStickDirection = .bottom
|
||||
let stickOverInsets: Bool = true
|
||||
|
||||
let height: CGFloat = 34.0
|
||||
|
||||
func node() -> ListViewItemHeaderNode {
|
||||
func node(synchronousLoad: Bool) -> ListViewItemHeaderNode {
|
||||
return ChatMessageDateHeaderNode(localTimestamp: self.roundedTimestamp, scheduled: self.scheduled, presentationData: self.presentationData, context: self.context, action: self.action)
|
||||
}
|
||||
|
||||
@ -90,6 +86,16 @@ private func monthAtIndex(_ index: Int, strings: PresentationStrings) -> String
|
||||
}
|
||||
}
|
||||
|
||||
private func dateHeaderTimestampId(timestamp: Int32) -> Int32 {
|
||||
if timestamp == scheduleWhenOnlineTimestamp {
|
||||
return timestamp
|
||||
} else if timestamp == Int32.max {
|
||||
return timestamp / (granularity) * (granularity)
|
||||
} else {
|
||||
return ((timestamp + timezoneOffset) / (granularity)) * (granularity)
|
||||
}
|
||||
}
|
||||
|
||||
final class ChatMessageDateHeaderNode: ListViewItemHeaderNode {
|
||||
let labelNode: TextNode
|
||||
let backgroundNode: NavigationBackgroundNode
|
||||
@ -164,12 +170,11 @@ final class ChatMessageDateHeaderNode: ListViewItemHeaderNode {
|
||||
self.transform = CATransform3DMakeRotation(CGFloat.pi, 0.0, 0.0, 1.0)
|
||||
|
||||
let graphics = PresentationResourcesChat.principalGraphics(theme: presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper, bubbleCorners: presentationData.chatBubbleCorners)
|
||||
|
||||
//self.backgroundNode.image = graphics.dateStaticBackground
|
||||
|
||||
self.backgroundNode.updateColor(color: selectDateFillStaticColor(theme: presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper), enableBlur: dateFillNeedsBlur(theme: presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper), transition: .immediate)
|
||||
self.stickBackgroundNode.image = graphics.dateFloatingBackground
|
||||
self.stickBackgroundNode.alpha = 0.0
|
||||
//self.backgroundNode.addSubnode(self.stickBackgroundNode)
|
||||
|
||||
self.addSubnode(self.backgroundNode)
|
||||
self.addSubnode(self.labelNode)
|
||||
|
||||
@ -198,8 +203,7 @@ final class ChatMessageDateHeaderNode: ListViewItemHeaderNode {
|
||||
self.presentationData = presentationData
|
||||
|
||||
let graphics = PresentationResourcesChat.principalGraphics(theme: presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper, bubbleCorners: presentationData.chatBubbleCorners)
|
||||
|
||||
//self.backgroundNode.image = graphics.dateStaticBackground
|
||||
|
||||
self.backgroundNode.updateColor(color: selectDateFillStaticColor(theme: presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper), enableBlur: dateFillNeedsBlur(theme: presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper), transition: .immediate)
|
||||
self.stickBackgroundNode.image = graphics.dateFloatingBackground
|
||||
|
||||
@ -220,12 +224,6 @@ final class ChatMessageDateHeaderNode: ListViewItemHeaderNode {
|
||||
|
||||
func updateBackgroundColor(color: UIColor, enableBlur: Bool) {
|
||||
self.backgroundNode.updateColor(color: color, enableBlur: enableBlur, transition: .immediate)
|
||||
/*let chatDateSize: CGFloat = 20.0
|
||||
self.backgroundNode.image = generateImage(CGSize(width: chatDateSize, height: chatDateSize), contextGenerator: { size, context -> Void in
|
||||
context.clear(CGRect(origin: CGPoint(), size: size))
|
||||
context.setFillColor(color.cgColor)
|
||||
context.fillEllipse(in: CGRect(origin: CGPoint(), size: size))
|
||||
})!.stretchableImage(withLeftCapWidth: Int(chatDateSize) / 2, topCapHeight: Int(chatDateSize) / 2)*/
|
||||
}
|
||||
|
||||
override func updateLayout(size: CGSize, leftInset: CGFloat, rightInset: CGFloat) {
|
||||
@ -307,3 +305,173 @@ final class ChatMessageDateHeaderNode: ListViewItemHeaderNode {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final class ChatMessageAvatarHeader: ListViewItemHeader {
|
||||
struct Id: Hashable {
|
||||
var peerId: PeerId
|
||||
var timestampId: Int32
|
||||
}
|
||||
|
||||
let id: ListViewItemNode.HeaderId
|
||||
let peerId: PeerId
|
||||
let peer: Peer?
|
||||
let messageReference: MessageReference?
|
||||
let presentationData: ChatPresentationData
|
||||
let context: AccountContext
|
||||
let controllerInteraction: ChatControllerInteraction
|
||||
|
||||
init(timestamp: Int32, peerId: PeerId, peer: Peer?, messageReference: MessageReference?, presentationData: ChatPresentationData, context: AccountContext, controllerInteraction: ChatControllerInteraction) {
|
||||
self.peerId = peerId
|
||||
self.peer = peer
|
||||
self.messageReference = messageReference
|
||||
self.presentationData = presentationData
|
||||
self.context = context
|
||||
self.controllerInteraction = controllerInteraction
|
||||
self.id = ListViewItemNode.HeaderId(space: 1, id: Id(peerId: peerId, timestampId: dateHeaderTimestampId(timestamp: timestamp)))
|
||||
}
|
||||
|
||||
let stickDirection: ListViewItemHeaderStickDirection = .top
|
||||
let stickOverInsets: Bool = false
|
||||
|
||||
let height: CGFloat = 38.0
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
func updateNode(_ node: ListViewItemHeaderNode, previous: ListViewItemHeader?, next: ListViewItemHeader?) {
|
||||
guard let node = node as? ChatMessageAvatarHeaderNode, let next = next as? ChatMessageAvatarHeader else {
|
||||
return
|
||||
}
|
||||
node.updatePresentationData(next.presentationData, context: next.context)
|
||||
}
|
||||
}
|
||||
|
||||
private let avatarFont = avatarPlaceholderFont(size: 16.0)
|
||||
|
||||
final class ChatMessageAvatarHeaderNode: ListViewItemHeaderNode {
|
||||
private let peerId: PeerId
|
||||
private let messageReference: MessageReference?
|
||||
private let peer: Peer?
|
||||
|
||||
private let containerNode: ContextControllerSourceNode
|
||||
private let avatarNode: AvatarNode
|
||||
private var presentationData: ChatPresentationData
|
||||
private let context: AccountContext
|
||||
private let controllerInteraction: ChatControllerInteraction
|
||||
|
||||
init(peerId: PeerId, peer: Peer?, messageReference: MessageReference?, presentationData: ChatPresentationData, context: AccountContext, controllerInteraction: ChatControllerInteraction, synchronousLoad: Bool) {
|
||||
self.peerId = peerId
|
||||
self.peer = peer
|
||||
self.messageReference = messageReference
|
||||
self.presentationData = presentationData
|
||||
self.context = context
|
||||
self.controllerInteraction = controllerInteraction
|
||||
|
||||
self.containerNode = ContextControllerSourceNode()
|
||||
|
||||
self.avatarNode = AvatarNode(font: avatarFont)
|
||||
|
||||
super.init(layerBacked: false, dynamicBounce: true, isRotated: true, seeThrough: false)
|
||||
|
||||
self.transform = CATransform3DMakeRotation(CGFloat.pi, 0.0, 0.0, 1.0)
|
||||
|
||||
self.addSubnode(self.containerNode)
|
||||
self.containerNode.addSubnode(self.avatarNode)
|
||||
|
||||
if let peer = peer {
|
||||
self.setPeer(context: context, theme: presentationData.theme.theme, synchronousLoad: synchronousLoad, peer: peer, authorOfMessage: messageReference, emptyColor: .black)
|
||||
}
|
||||
|
||||
self.containerNode.activated = { [weak self] gesture, _ in
|
||||
guard let strongSelf = self, let peer = strongSelf.peer else {
|
||||
return
|
||||
}
|
||||
var messageId: MessageId?
|
||||
if let messageReference = messageReference, case let .message(m) = messageReference.content {
|
||||
messageId = m.id
|
||||
}
|
||||
strongSelf.controllerInteraction.openPeerContextMenu(peer, messageId, strongSelf.containerNode, strongSelf.containerNode.bounds, gesture)
|
||||
}
|
||||
|
||||
self.updateSelectionState(animated: false)
|
||||
}
|
||||
|
||||
func setCustomLetters(context: AccountContext, theme: PresentationTheme, synchronousLoad: Bool, letters: [String], emptyColor: UIColor) {
|
||||
self.containerNode.isGestureEnabled = false
|
||||
|
||||
self.avatarNode.setCustomLetters(letters, icon: !letters.isEmpty ? nil : .phone)
|
||||
}
|
||||
|
||||
func setPeer(context: AccountContext, theme: PresentationTheme, synchronousLoad: Bool, peer: Peer, authorOfMessage: MessageReference?, emptyColor: UIColor) {
|
||||
self.containerNode.isGestureEnabled = peer.smallProfileImage != nil
|
||||
|
||||
var overrideImage: AvatarNodeImageOverride?
|
||||
if peer.isDeleted {
|
||||
overrideImage = .deletedIcon
|
||||
}
|
||||
self.avatarNode.setPeer(context: context, theme: theme, peer: peer, authorOfMessage: authorOfMessage, overrideImage: overrideImage, emptyColor: emptyColor, synchronousLoad: synchronousLoad, displayDimensions: CGSize(width: 38.0, height: 38.0))
|
||||
}
|
||||
|
||||
override func didLoad() {
|
||||
super.didLoad()
|
||||
|
||||
self.avatarNode.view.addGestureRecognizer(ListViewTapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:))))
|
||||
}
|
||||
|
||||
func updatePresentationData(_ presentationData: ChatPresentationData, context: AccountContext) {
|
||||
self.presentationData = presentationData
|
||||
|
||||
self.setNeedsLayout()
|
||||
}
|
||||
|
||||
override func updateLayout(size: CGSize, leftInset: CGFloat, rightInset: CGFloat) {
|
||||
self.containerNode.frame = CGRect(origin: CGPoint(x: leftInset + 3.0, y: 0.0), size: CGSize(width: 38.0, height: 38.0))
|
||||
self.avatarNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: 38.0, height: 38.0))
|
||||
}
|
||||
|
||||
override func animateRemoved(duration: Double) {
|
||||
self.alpha = 0.0
|
||||
self.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration, removeOnCompletion: false)
|
||||
self.avatarNode.layer.animateScale(from: 1.0, to: 0.2, duration: duration, removeOnCompletion: false)
|
||||
}
|
||||
|
||||
override func animateAdded(duration: Double) {
|
||||
self.layer.animateAlpha(from: 0.0, to: self.alpha, duration: 0.2)
|
||||
self.avatarNode.layer.animateScale(from: 0.2, to: 1.0, duration: 0.2)
|
||||
}
|
||||
|
||||
override func updateStickDistanceFactor(_ factor: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||
}
|
||||
|
||||
override func updateFlashingOnScrolling(_ isFlashingOnScrolling: Bool, animated: Bool) {
|
||||
}
|
||||
|
||||
func updateSelectionState(animated: Bool) {
|
||||
let offset: CGFloat = self.controllerInteraction.selectionState != nil ? 42.0 : 0.0
|
||||
|
||||
let previousSubnodeTransform = self.subnodeTransform
|
||||
self.subnodeTransform = CATransform3DMakeTranslation(offset, 0.0, 0.0);
|
||||
if animated {
|
||||
self.layer.animate(from: NSValue(caTransform3D: previousSubnodeTransform), to: NSValue(caTransform3D: self.subnodeTransform), keyPath: "sublayerTransform", timingFunction: CAMediaTimingFunctionName.easeOut.rawValue, duration: 0.2)
|
||||
}
|
||||
}
|
||||
|
||||
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
||||
if !self.bounds.contains(point) {
|
||||
return nil
|
||||
}
|
||||
let result = self.containerNode.view.hitTest(self.view.convert(point, to: self.containerNode.view), with: event)
|
||||
return result
|
||||
}
|
||||
|
||||
override func touchesCancelled(_ touches: Set<UITouch>?, with event: UIEvent?) {
|
||||
super.touchesCancelled(touches, with: event)
|
||||
}
|
||||
|
||||
@objc func tapGesture(_ recognizer: ListViewTapGestureRecognizer) {
|
||||
if case .ended = recognizer.state {
|
||||
self.controllerInteraction.openPeer(self.peerId, .info, nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -192,9 +192,8 @@ func chatItemsHaveCommonDateHeader(_ lhs: ListViewItem, _ rhs: ListViewItem?) -
|
||||
let lhsHeader: ChatMessageDateHeader?
|
||||
let rhsHeader: ChatMessageDateHeader?
|
||||
if let lhs = lhs as? ChatMessageItem {
|
||||
lhsHeader = lhs.header
|
||||
lhsHeader = lhs.dateHeader
|
||||
} else if let _ = lhs as? ChatHoleItem {
|
||||
//lhsHeader = lhs.header
|
||||
lhsHeader = nil
|
||||
} else if let lhs = lhs as? ChatUnreadItem {
|
||||
lhsHeader = lhs.header
|
||||
@ -205,7 +204,7 @@ func chatItemsHaveCommonDateHeader(_ lhs: ListViewItem, _ rhs: ListViewItem?) -
|
||||
}
|
||||
if let rhs = rhs {
|
||||
if let rhs = rhs as? ChatMessageItem {
|
||||
rhsHeader = rhs.header
|
||||
rhsHeader = rhs.dateHeader
|
||||
} else if let _ = rhs as? ChatHoleItem {
|
||||
//rhsHeader = rhs.header
|
||||
rhsHeader = nil
|
||||
@ -257,8 +256,11 @@ public final class ChatMessageItem: ListViewItem, CustomStringConvertible {
|
||||
let effectiveAuthorId: PeerId?
|
||||
let additionalContent: ChatMessageItemAdditionalContent?
|
||||
|
||||
public let accessoryItem: ListViewAccessoryItem?
|
||||
let header: ChatMessageDateHeader
|
||||
//public let accessoryItem: ListViewAccessoryItem?
|
||||
let dateHeader: ChatMessageDateHeader
|
||||
let avatarHeader: ChatMessageAvatarHeader?
|
||||
|
||||
let headers: [ListViewItemHeader]
|
||||
|
||||
var message: Message {
|
||||
switch self.content {
|
||||
@ -288,7 +290,7 @@ public final class ChatMessageItem: ListViewItem, CustomStringConvertible {
|
||||
self.disableDate = disableDate
|
||||
self.additionalContent = additionalContent
|
||||
|
||||
var accessoryItem: ListViewAccessoryItem?
|
||||
var avatarHeader: ChatMessageAvatarHeader?
|
||||
let incoming = content.effectivelyIncoming(self.context.account.peerId)
|
||||
|
||||
var effectiveAuthor: Peer?
|
||||
@ -325,7 +327,7 @@ public final class ChatMessageItem: ListViewItem, CustomStringConvertible {
|
||||
isScheduledMessages = true
|
||||
}
|
||||
|
||||
self.header = ChatMessageDateHeader(timestamp: content.index.timestamp, scheduled: isScheduledMessages, presentationData: presentationData, context: context, action: { timestamp in
|
||||
self.dateHeader = ChatMessageDateHeader(timestamp: content.index.timestamp, scheduled: isScheduledMessages, presentationData: presentationData, context: context, action: { timestamp in
|
||||
var calendar = NSCalendar.current
|
||||
calendar.timeZone = TimeZone(abbreviation: "UTC")!
|
||||
let date = Date(timeIntervalSince1970: TimeInterval(timestamp))
|
||||
@ -355,11 +357,18 @@ public final class ChatMessageItem: ListViewItem, CustomStringConvertible {
|
||||
}
|
||||
if !hasActionMedia && !isBroadcastChannel {
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
self.accessoryItem = accessoryItem
|
||||
self.avatarHeader = avatarHeader
|
||||
|
||||
var headers: [ListViewItemHeader] = [self.dateHeader]
|
||||
if let avatarHeader = self.avatarHeader {
|
||||
headers.append(avatarHeader)
|
||||
}
|
||||
self.headers = headers
|
||||
}
|
||||
|
||||
public func nodeConfiguredForParams(async: @escaping (@escaping () -> Void) -> Void, params: ListViewItemLayoutParams, synchronousLoads: Bool, previousItem: ListViewItem?, nextItem: ListViewItem?, completion: @escaping (ListViewItemNode, @escaping () -> (Signal<Void, NoError>?, (ListViewItemApply) -> Void)) -> Void) {
|
||||
@ -467,25 +476,25 @@ public final class ChatMessageItem: ListViewItem, CustomStringConvertible {
|
||||
var mergedBottom: ChatMessageMerge = .none
|
||||
var dateAtBottom = false
|
||||
if let top = top as? ChatMessageItem {
|
||||
if top.header.id != self.header.id {
|
||||
if top.dateHeader.id != self.dateHeader.id {
|
||||
mergedBottom = .none
|
||||
} else {
|
||||
mergedBottom = messagesShouldBeMerged(accountPeerId: self.context.account.peerId, message, top.message)
|
||||
}
|
||||
}
|
||||
if let bottom = bottom as? ChatMessageItem {
|
||||
if bottom.header.id != self.header.id {
|
||||
if bottom.dateHeader.id != self.dateHeader.id {
|
||||
mergedTop = .none
|
||||
dateAtBottom = true
|
||||
} else {
|
||||
mergedTop = messagesShouldBeMerged(accountPeerId: self.context.account.peerId, bottom.message, message)
|
||||
}
|
||||
} else if let bottom = bottom as? ChatUnreadItem {
|
||||
if bottom.header.id != self.header.id {
|
||||
if bottom.header.id != self.dateHeader.id {
|
||||
dateAtBottom = true
|
||||
}
|
||||
} else if let bottom = bottom as? ChatReplyCountItem {
|
||||
if bottom.header.id != self.header.id {
|
||||
if bottom.header.id != self.dateHeader.id {
|
||||
dateAtBottom = true
|
||||
}
|
||||
} else if let _ = bottom as? ChatHoleItem {
|
||||
|
@ -801,9 +801,9 @@ public class ChatMessageItemView: ListViewItemNode {
|
||||
return nil
|
||||
}
|
||||
|
||||
override public func header() -> ListViewItemHeader? {
|
||||
override public func headers() -> [ListViewItemHeader]? {
|
||||
if let item = self.item {
|
||||
return item.header
|
||||
return item.headers
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
@ -211,9 +211,9 @@ class ChatReplyCountItemNode: ListViewItemNode {
|
||||
}
|
||||
}
|
||||
|
||||
override public func header() -> ListViewItemHeader? {
|
||||
override public func headers() -> [ListViewItemHeader]? {
|
||||
if let item = self.item {
|
||||
return item.header
|
||||
return [item.header]
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
@ -147,9 +147,9 @@ class ChatUnreadItemNode: ListViewItemNode {
|
||||
}
|
||||
}
|
||||
|
||||
override public func header() -> ListViewItemHeader? {
|
||||
override public func headers() -> [ListViewItemHeader]? {
|
||||
if let item = self.item {
|
||||
return item.header
|
||||
return [item.header]
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
@ -347,7 +347,7 @@ final class PeerInfoSelectionPanelNode: ASDisplayNode {
|
||||
|
||||
let selectionPanel: ChatMessageSelectionInputPanelNode
|
||||
let separatorNode: ASDisplayNode
|
||||
let backgroundNode: ASDisplayNode
|
||||
let backgroundNode: NavigationBackgroundNode
|
||||
|
||||
init(context: AccountContext, peerId: PeerId, deleteMessages: @escaping () -> Void, shareMessages: @escaping () -> Void, forwardMessages: @escaping () -> Void, reportMessages: @escaping () -> Void) {
|
||||
self.context = context
|
||||
@ -360,11 +360,10 @@ final class PeerInfoSelectionPanelNode: ASDisplayNode {
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
||||
self.separatorNode = ASDisplayNode()
|
||||
self.backgroundNode = ASDisplayNode()
|
||||
self.backgroundNode = NavigationBackgroundNode(color: presentationData.theme.rootController.navigationBar.blurredBackgroundColor)
|
||||
|
||||
self.selectionPanel = ChatMessageSelectionInputPanelNode(theme: presentationData.theme, strings: presentationData.strings, peerMedia: true)
|
||||
self.selectionPanel.context = context
|
||||
self.selectionPanel.backgroundColor = presentationData.theme.chat.inputPanel.panelBackgroundColor
|
||||
|
||||
let interfaceInteraction = ChatPanelInterfaceInteraction(setupReplyMessage: { _, _ in
|
||||
}, setupEditMessage: { _, _ in
|
||||
@ -466,7 +465,7 @@ final class PeerInfoSelectionPanelNode: ASDisplayNode {
|
||||
}
|
||||
|
||||
func update(layout: ContainerViewLayout, presentationData: PresentationData, transition: ContainedViewLayoutTransition) -> CGFloat {
|
||||
self.backgroundNode.backgroundColor = presentationData.theme.rootController.navigationBar.blurredBackgroundColor
|
||||
self.backgroundNode.updateColor(color: presentationData.theme.rootController.navigationBar.blurredBackgroundColor, transition: .immediate)
|
||||
self.separatorNode.backgroundColor = presentationData.theme.rootController.navigationBar.separatorColor
|
||||
|
||||
let interfaceState = ChatPresentationInterfaceState(chatWallpaper: .color(0), theme: presentationData.theme, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, limitsConfiguration: .defaultValue, fontSize: .regular, bubbleCorners: PresentationChatBubbleCorners(mainRadius: 16.0, auxiliaryRadius: 8.0, mergeBubbleCorners: true), accountPeerId: self.context.account.peerId, mode: .standard(previewing: false), chatLocation: .peer(self.peerId), subject: nil, peerNearbyData: nil, greetingData: nil, pendingUnpinnedAllMessages: false, activeGroupCallInfo: nil, hasActiveGroupCall: false, importState: nil)
|
||||
@ -477,6 +476,7 @@ final class PeerInfoSelectionPanelNode: ASDisplayNode {
|
||||
let panelHeightWithInset = panelHeight + layout.intrinsicInsets.bottom
|
||||
|
||||
transition.updateFrame(node: self.backgroundNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: layout.size.width, height: panelHeightWithInset)))
|
||||
self.backgroundNode.update(size: self.backgroundNode.bounds.size, transition: transition)
|
||||
transition.updateFrame(node: self.separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel), size: CGSize(width: layout.size.width, height: UIScreenPixel)))
|
||||
|
||||
return panelHeightWithInset
|
||||
|
@ -200,9 +200,9 @@ class WebSearchRecentQueryItemNode: ItemListRevealOptionsItemNode {
|
||||
self.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration * 0.5, removeOnCompletion: false)
|
||||
}
|
||||
|
||||
override public func header() -> ListViewItemHeader? {
|
||||
override public func headers() -> [ListViewItemHeader]? {
|
||||
if let item = self.item {
|
||||
return item.header
|
||||
return item.header.flatMap { [$0] }
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user