AvatarNode: react to theme changes

ChatHistoryListNode: follow to upperBound
ItemListRevealOptionsNode: improve layout animations
This commit is contained in:
Peter
2019-04-22 17:26:11 +04:00
parent 6b8adfc5b0
commit 031ff5fa80
6 changed files with 76 additions and 39 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 957 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -227,7 +227,7 @@ public final class AvatarNode: ASDisplayNode {
representation = peer?.smallProfileImage
}
let updatedState: AvatarNodeState = .peerAvatar(peer?.id ?? PeerId(namespace: 0, id: 0), peer?.displayLetters ?? [], representation)
if updatedState != self.state {
if updatedState != self.state || theme !== self.theme {
self.state = updatedState
let parameters: AvatarNodeParameters

View File

@@ -293,6 +293,19 @@ private func extractAssociatedData(chatLocation: ChatLocation, view: MessageHist
return associatedData
}
private extension ChatHistoryLocationInput {
var isAtUpperBound: Bool {
switch self.content {
case .Navigation(index: .upperBound, anchorIndex: .upperBound, count: _):
return true
case .Scroll(index: .upperBound, anchorIndex: .upperBound, sourceIndex: _, scrollPosition: _, animated: _):
return true
default:
return false
}
}
}
public final class ChatHistoryListNode: ListView, ChatHistoryNode {
private let context: AccountContext
private let chatLocation: ChatLocation
@@ -337,7 +350,14 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
private var canReadHistoryValue: Bool = false
private var canReadHistoryDisposable: Disposable?
private let chatHistoryLocation = ValuePromise<ChatHistoryLocationInput>()
private var chatHistoryLocationValue: ChatHistoryLocationInput? {
didSet {
if let chatHistoryLocationValue = self.chatHistoryLocationValue, chatHistoryLocationValue != oldValue {
chatHistoryLocationPromise.set(chatHistoryLocationValue)
}
}
}
private let chatHistoryLocationPromise = ValuePromise<ChatHistoryLocationInput>()
private var nextHistoryLocationId: Int32 = 1
private func takeNextHistoryLocationId() -> Int32 {
let id = self.nextHistoryLocationId
@@ -455,7 +475,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
}
additionalData.append(.totalUnreadState)
let historyViewUpdate = self.chatHistoryLocation.get()
let historyViewUpdate = self.chatHistoryLocationPromise.get()
|> distinctUntilChanged
|> mapToSignal { location in
return chatHistoryViewForLocation(location, account: context.account, chatLocation: chatLocation, fixedCombinedReadStates: fixedCombinedReadStates.with { $0 }, tagMask: tagMask, additionalData: additionalData)
@@ -494,12 +514,12 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
if let filteredEntries = historyView?.filteredEntries, let visibleRange = displayRange.visibleRange {
let lastEntry = filteredEntries[filteredEntries.count - 1 - visibleRange.lastIndex]
strongSelf.chatHistoryLocation.set(ChatHistoryLocationInput(content: .Navigation(index: .message(lastEntry.index), anchorIndex: .message(lastEntry.index), count: historyMessageCount), id: 0))
strongSelf.chatHistoryLocationValue = ChatHistoryLocationInput(content: .Navigation(index: .message(lastEntry.index), anchorIndex: .message(lastEntry.index), count: historyMessageCount), id: 0)
} else {
if let messageId = messageId {
strongSelf.chatHistoryLocation.set(ChatHistoryLocationInput(content: .InitialSearch(location: .id(messageId), count: 60), id: 0))
strongSelf.chatHistoryLocationValue = ChatHistoryLocationInput(content: .InitialSearch(location: .id(messageId), count: 60), id: 0)
} else {
strongSelf.chatHistoryLocation.set(ChatHistoryLocationInput(content: .Initial(count: 60), id: 0))
strongSelf.chatHistoryLocationValue = ChatHistoryLocationInput(content: .Initial(count: 60), id: 0)
}
}
}
@@ -670,10 +690,11 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
})
if let messageId = messageId {
self.chatHistoryLocation.set(ChatHistoryLocationInput(content: .InitialSearch(location: .id(messageId), count: 60), id: 0))
self.chatHistoryLocationValue = ChatHistoryLocationInput(content: .InitialSearch(location: .id(messageId), count: 60), id: 0)
} else {
self.chatHistoryLocation.set(ChatHistoryLocationInput(content: .Initial(count: 60), id: 0))
self.chatHistoryLocationValue = ChatHistoryLocationInput(content: .Initial(count: 60), id: 0)
}
self.chatHistoryLocationPromise.set(self.chatHistoryLocationValue!)
self.generalScrollDirectionUpdated = { [weak self] direction in
guard let strongSelf = self else {
@@ -862,9 +883,11 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
if let loaded = displayedRange.loadedRange, let firstEntry = historyView.filteredEntries.first, let lastEntry = historyView.filteredEntries.last {
if loaded.firstIndex < 5 && historyView.originalView.laterId != nil {
strongSelf.chatHistoryLocation.set(ChatHistoryLocationInput(content: .Navigation(index: .message(lastEntry.index), anchorIndex: .message(lastEntry.index), count: historyMessageCount), id: 0))
strongSelf.chatHistoryLocationValue = ChatHistoryLocationInput(content: .Navigation(index: .message(lastEntry.index), anchorIndex: .message(lastEntry.index), count: historyMessageCount), id: 0)
} else if loaded.firstIndex < 5, historyView.originalView.laterId == nil, !historyView.originalView.holeLater, let chatHistoryLocationValue = strongSelf.chatHistoryLocationValue, !chatHistoryLocationValue.isAtUpperBound, historyView.originalView.anchorIndex != .upperBound {
strongSelf.chatHistoryLocationValue = ChatHistoryLocationInput(content: .Navigation(index: .upperBound, anchorIndex: .upperBound, count: historyMessageCount), id: 0)
} else if loaded.lastIndex >= historyView.filteredEntries.count - 5 && historyView.originalView.earlierId != nil {
strongSelf.chatHistoryLocation.set(ChatHistoryLocationInput(content: .Navigation(index: .message(firstEntry.index), anchorIndex: .message(firstEntry.index), count: historyMessageCount), id: 0))
strongSelf.chatHistoryLocationValue = ChatHistoryLocationInput(content: .Navigation(index: .message(firstEntry.index), anchorIndex: .message(firstEntry.index), count: historyMessageCount), id: 0)
}
}
@@ -992,12 +1015,12 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
}
if let currentMessage = currentMessage {
self.chatHistoryLocation.set(ChatHistoryLocationInput(content: .Scroll(index: .message(currentMessage.index), anchorIndex: .message(currentMessage.index), sourceIndex: .upperBound, scrollPosition: .top(0.0), animated: true), id: self.takeNextHistoryLocationId()))
self.chatHistoryLocationValue = ChatHistoryLocationInput(content: .Scroll(index: .message(currentMessage.index), anchorIndex: .message(currentMessage.index), sourceIndex: .upperBound, scrollPosition: .top(0.0), animated: true), id: self.takeNextHistoryLocationId())
}
}
public func scrollToStartOfHistory() {
self.chatHistoryLocation.set(ChatHistoryLocationInput(content: .Scroll(index: .lowerBound, anchorIndex: .lowerBound, sourceIndex: .upperBound, scrollPosition: .bottom(0.0), animated: true), id: self.takeNextHistoryLocationId()))
self.chatHistoryLocationValue = ChatHistoryLocationInput(content: .Scroll(index: .lowerBound, anchorIndex: .lowerBound, sourceIndex: .upperBound, scrollPosition: .bottom(0.0), animated: true), id: self.takeNextHistoryLocationId())
}
public func scrollToEndOfHistory() {
@@ -1005,12 +1028,12 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
case .known(0.0):
break
default:
self.chatHistoryLocation.set(ChatHistoryLocationInput(content: .Scroll(index: .upperBound, anchorIndex: .upperBound, sourceIndex: .lowerBound, scrollPosition: .top(0.0), animated: true), id: self.takeNextHistoryLocationId()))
self.chatHistoryLocationValue = ChatHistoryLocationInput(content: .Scroll(index: .upperBound, anchorIndex: .upperBound, sourceIndex: .lowerBound, scrollPosition: .top(0.0), animated: true), id: self.takeNextHistoryLocationId())
}
}
public func scrollToMessage(from fromIndex: MessageIndex, to toIndex: MessageIndex, animated: Bool, highlight: Bool = true, scrollPosition: ListViewScrollPosition = .center(.bottom)) {
self.chatHistoryLocation.set(ChatHistoryLocationInput(content: .Scroll(index: .message(toIndex), anchorIndex: .message(toIndex), sourceIndex: .message(fromIndex), scrollPosition: scrollPosition, animated: animated), id: self.takeNextHistoryLocationId()))
self.chatHistoryLocationValue = ChatHistoryLocationInput(content: .Scroll(index: .message(toIndex), anchorIndex: .message(toIndex), sourceIndex: .message(fromIndex), scrollPosition: scrollPosition, animated: animated), id: self.takeNextHistoryLocationId())
}
func scrollWithDeltaOffset(_ offset: CGFloat) {

View File

@@ -224,15 +224,19 @@ private final class ItemListRevealOptionNode: ASDisplayNode {
let titleIconSpacing: CGFloat = 11.0
let iconFrame = CGRect(origin: CGPoint(x: contentRect.minX + floor((baseSize.width - imageSize.width + sideInset) / 2.0), y: contentRect.midY - imageSize.height / 2.0 + iconOffset), size: imageSize)
if animateAdditive {
animationNode.frame = iconFrame
transition.animatePositionAdditive(node: animationNode, offset: CGPoint(x: deltaX, y: 0.0))
} else {
transition.updateFrame(node: animationNode, frame: iconFrame)
}
animationNode.frame = iconFrame
let titleFrame = CGRect(origin: CGPoint(x: contentRect.minX + floor((baseSize.width - titleSize.width + sideInset) / 2.0), y: contentRect.midY + titleIconSpacing), size: titleSize)
if animateAdditive {
self.titleNode.frame = titleFrame
transition.animatePositionAdditive(node: self.titleNode, offset: CGPoint(x: deltaX, y: 0.0))
} else {
transition.updateFrame(node: self.titleNode, frame: titleFrame)
}
self.titleNode.frame = titleFrame
if (abs(revealFactor) >= 0.4) {
animationNode.play()
@@ -244,17 +248,27 @@ private final class ItemListRevealOptionNode: ASDisplayNode {
let titleIconSpacing: CGFloat = 11.0
let iconFrame = CGRect(origin: CGPoint(x: contentRect.minX + floor((baseSize.width - imageSize.width + sideInset) / 2.0), y: contentRect.midY - imageSize.height / 2.0 + iconOffset), size: imageSize)
if animateAdditive {
iconNode.frame = iconFrame
transition.animatePositionAdditive(node: iconNode, offset: CGPoint(x: deltaX, y: 0.0))
} else {
transition.updateFrame(node: iconNode, frame: iconFrame)
}
iconNode.frame = iconFrame
let titleFrame = CGRect(origin: CGPoint(x: contentRect.minX + floor((baseSize.width - titleSize.width + sideInset) / 2.0), y: contentRect.midY + titleIconSpacing), size: titleSize)
if animateAdditive {
self.titleNode.frame = titleFrame
transition.animatePositionAdditive(node: self.titleNode, offset: CGPoint(x: deltaX, y: 0.0))
} else {
transition.updateFrame(node: self.titleNode, frame: titleFrame)
}
self.titleNode.frame = titleFrame
} else {
self.titleNode.frame = CGRect(origin: CGPoint(x: contentRect.minX + floor((baseSize.width - titleSize.width + sideInset) / 2.0), y: contentRect.minY + floor((baseSize.height - titleSize.height) / 2.0)), size: titleSize)
let titleFrame = CGRect(origin: CGPoint(x: contentRect.minX + floor((baseSize.width - titleSize.width + sideInset) / 2.0), y: contentRect.minY + floor((baseSize.height - titleSize.height) / 2.0)), size: titleSize)
if animateAdditive {
self.titleNode.frame = titleFrame
transition.animatePositionAdditive(node: self.titleNode, offset: CGPoint(x: deltaX, y: 0.0))
} else {
transition.updateFrame(node: self.titleNode, frame: titleFrame)
}
}
}
@@ -296,7 +310,7 @@ final class ItemListRevealOptionsNode: ASDisplayNode {
}
for node in strongSelf.optionNodes {
if node.frame.contains(location) {
node.setHighlighted(true)
//node.setHighlighted(true)
break
}
}
@@ -350,28 +364,25 @@ final class ItemListRevealOptionsNode: ASDisplayNode {
if size.width.isLessThanOrEqualTo(0.0) || self.optionNodes.isEmpty {
return
}
let basicNodeWidth = floorToScreenPixels((size.width - abs(self.sideInset)) / CGFloat(self.optionNodes.count))
let basicNodeWidth = floor((size.width - abs(self.sideInset)) / CGFloat(self.optionNodes.count))
let lastNodeWidth = size.width - basicNodeWidth * CGFloat(self.optionNodes.count - 1)
let revealFactor = self.revealOffset / size.width
let boundaryRevealFactor: CGFloat = 1.0 + basicNodeWidth / size.width * 0.7
var leftOffset: CGFloat
let boundaryRevealFactor: CGFloat = 1.0 + 16.0 / size.width
let startingOffset: CGFloat
if self.isLeft {
leftOffset = size.width + max(0.0, abs(revealFactor) - 1.0) * size.width
startingOffset = size.width + max(0.0, abs(revealFactor) - 1.0) * size.width
} else {
leftOffset = 0.0
startingOffset = 0.0
}
var i = self.isLeft ? (self.optionNodes.count - 1) : 0
while i >= 0 && i < self.optionNodes.count {
let node = self.optionNodes[i]
let nodeWidth = i == (self.optionNodes.count - 1) ? lastNodeWidth : basicNodeWidth
var extendedWidth = nodeWidth
let defaultAlignment: ItemListRevealOptionAlignment = isLeft ? .right : .left
var nodeTransition = transition
extendedWidth = floorToScreenPixels(nodeWidth * max(1.0, abs(revealFactor)))
var isExpanded = false
if (isLeft && i == 0) || (!isLeft && i == self.optionNodes.count - 1) {
if abs(revealFactor) > boundaryRevealFactor {
extendedWidth = size.width * max(1.0, abs(revealFactor))
isExpanded = true
}
}
@@ -387,31 +398,34 @@ final class ItemListRevealOptionsNode: ASDisplayNode {
sideInset = self.sideInset
}
var nodeLeftOffset = leftOffset
if self.isLeft {
nodeLeftOffset -= extendedWidth
} else {
nodeLeftOffset *= abs(revealFactor)
}
let extendedWidth: CGFloat
let nodeLeftOffset: CGFloat
if isExpanded {
nodeLeftOffset = 0.0
extendedWidth = size.width * max(1.0, abs(revealFactor))
} else if self.isLeft {
let offset = basicNodeWidth * CGFloat(self.optionNodes.count - 1 - i)
extendedWidth = size.width - offset
nodeLeftOffset = startingOffset - extendedWidth - floorToScreenPixels(offset * abs(revealFactor))
} else {
let offset = basicNodeWidth * CGFloat(i)
extendedWidth = size.width - offset
nodeLeftOffset = startingOffset + floorToScreenPixels(offset * abs(revealFactor))
}
transition.updateFrame(node: node, frame: CGRect(origin: CGPoint(x: floorToScreenPixels(nodeLeftOffset), y: 0.0), size: CGSize(width: extendedWidth, height: size.height)))
transition.updateFrame(node: node, frame: CGRect(origin: CGPoint(x: nodeLeftOffset, y: 0.0), size: CGSize(width: extendedWidth, height: size.height)))
node.updateLayout(isFirst: (self.isLeft && i == 0) || (!self.isLeft && i == self.optionNodes.count - 1), isLeft: self.isLeft, baseSize: CGSize(width: nodeWidth, height: size.height), alignment: defaultAlignment, isExpanded: isExpanded, extendedWidth: extendedWidth, sideInset: sideInset, transition: nodeTransition, additive: !transition.isAnimated, revealFactor: revealFactor)
if self.isLeft {
leftOffset -= extendedWidth
i -= 1
} else {
leftOffset += nodeWidth
i += 1
}
}
}
@objc func tapGesture(_ recognizer: TapLongTapOrDoubleTapGestureRecognizer) {
if case .ended = recognizer.state {
if case .ended = recognizer.state, let gesture = recognizer.lastRecognizedGestureAndLocation?.0, case .tap = gesture {
let location = recognizer.location(in: self.view)
var selectedOption: Int?
for i in 0 ..< self.optionNodes.count {

View File

@@ -644,7 +644,7 @@ public final class ManagedAudioSession {
case .record, .voiceCall:
options.insert(.allowBluetooth)
}
print("ManagedAudioSession setting active \(type != .none)")
print("ManagedAudioSession setting active true")
if #available(iOSApplicationExtension 11.0, *) {
try AVAudioSession.sharedInstance().setCategory(nativeCategoryForType(type, headphones: self.isHeadsetPluggedInValue), mode: type == .voiceCall ? AVAudioSessionModeVoiceChat : AVAudioSessionModeDefault, routeSharingPolicy: .default, options: options)
} else {