mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2026-01-26 22:11:27 +00:00
AvatarNode: react to theme changes
ChatHistoryListNode: follow to upperBound ItemListRevealOptionsNode: improve layout animations
This commit is contained in:
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 |
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user