mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-07-16 08:19:23 +00:00
Monoforums
This commit is contained in:
parent
c2052b559a
commit
c264378b6a
@ -881,16 +881,6 @@ open class NavigationBar: ASDisplayNode {
|
||||
|
||||
if needsLeftButton {
|
||||
if animated {
|
||||
if self.leftButtonNode.view.superview != nil {
|
||||
if let snapshotView = self.leftButtonNode.view.snapshotContentTree() {
|
||||
snapshotView.frame = self.leftButtonNode.frame
|
||||
self.leftButtonNode.view.superview?.insertSubview(snapshotView, aboveSubview: self.leftButtonNode.view)
|
||||
snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false, completion: { [weak snapshotView] _ in
|
||||
snapshotView?.removeFromSuperview()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if self.backButtonNode.view.superview != nil {
|
||||
if let snapshotView = self.backButtonNode.view.snapshotContentTree() {
|
||||
snapshotView.frame = self.backButtonNode.frame
|
||||
@ -927,9 +917,11 @@ open class NavigationBar: ASDisplayNode {
|
||||
self.badgeNode.removeFromSupernode()
|
||||
|
||||
if let leftBarButtonItem = item.leftBarButtonItem {
|
||||
self.leftButtonNode.updateItems([leftBarButtonItem])
|
||||
self.leftButtonNode.updateItems([], animated: animated)
|
||||
self.leftButtonNode.updateItems([leftBarButtonItem], animated: animated)
|
||||
} else {
|
||||
self.leftButtonNode.updateItems([UIBarButtonItem(title: self.presentationData.strings.close, style: .plain, target: nil, action: nil)])
|
||||
self.leftButtonNode.updateItems([], animated: animated)
|
||||
self.leftButtonNode.updateItems([UIBarButtonItem(title: self.presentationData.strings.close, style: .plain, target: nil, action: nil)], animated: animated)
|
||||
}
|
||||
|
||||
if self.leftButtonNode.supernode == nil {
|
||||
@ -994,9 +986,6 @@ open class NavigationBar: ASDisplayNode {
|
||||
}
|
||||
|
||||
self.updateAccessibilityElements()
|
||||
if animated {
|
||||
self.hintAnimateTitleNodeOnNextLayout = true
|
||||
}
|
||||
}
|
||||
|
||||
private func updateRightButton(animated: Bool) {
|
||||
@ -1008,23 +997,14 @@ open class NavigationBar: ASDisplayNode {
|
||||
items = [rightBarButtonItem]
|
||||
}
|
||||
|
||||
self.rightButtonNodeUpdated = true
|
||||
|
||||
if !items.isEmpty {
|
||||
if animated, self.rightButtonNode.view.superview != nil {
|
||||
if let snapshotView = self.rightButtonNode.view.snapshotContentTree() {
|
||||
snapshotView.frame = self.rightButtonNode.frame
|
||||
self.rightButtonNode.view.superview?.insertSubview(snapshotView, aboveSubview: self.rightButtonNode.view)
|
||||
snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false, completion: { [weak snapshotView] _ in
|
||||
snapshotView?.removeFromSuperview()
|
||||
})
|
||||
}
|
||||
}
|
||||
self.rightButtonNode.updateItems(items)
|
||||
self.rightButtonNode.updateItems([], animated: animated)
|
||||
self.rightButtonNode.updateItems(items, animated: animated)
|
||||
if self.rightButtonNode.supernode == nil {
|
||||
self.buttonsContainerNode.addSubnode(self.rightButtonNode)
|
||||
}
|
||||
if animated {
|
||||
self.rightButtonNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15)
|
||||
}
|
||||
} else {
|
||||
if animated, self.rightButtonNode.view.superview != nil {
|
||||
if let snapshotView = self.rightButtonNode.view.snapshotContentTree() {
|
||||
@ -1050,9 +1030,6 @@ open class NavigationBar: ASDisplayNode {
|
||||
self.rightButtonNode.removeFromSupernode()
|
||||
}
|
||||
|
||||
if animated {
|
||||
self.hintAnimateTitleNodeOnNextLayout = true
|
||||
}
|
||||
self.updateAccessibilityElements()
|
||||
}
|
||||
|
||||
@ -1062,6 +1039,7 @@ open class NavigationBar: ASDisplayNode {
|
||||
public let backButtonArrow: ASImageNode
|
||||
public let leftButtonNode: NavigationButtonNode
|
||||
public let rightButtonNode: NavigationButtonNode
|
||||
private var rightButtonNodeUpdated: Bool = false
|
||||
public let additionalContentNode: SparseNode
|
||||
|
||||
private let navigationBackgroundCutoutView: NavigationBackgroundCutoutView
|
||||
@ -1359,7 +1337,7 @@ open class NavigationBar: ASDisplayNode {
|
||||
var leftTitleInset: CGFloat = leftInset + 1.0
|
||||
var rightTitleInset: CGFloat = rightInset + 1.0
|
||||
if self.backButtonNode.supernode != nil {
|
||||
let backButtonSize = self.backButtonNode.updateLayout(constrainedSize: CGSize(width: size.width, height: nominalHeight), isLandscape: isLandscape)
|
||||
let backButtonSize = self.backButtonNode.updateLayout(constrainedSize: CGSize(width: size.width, height: nominalHeight), isLandscape: isLandscape, isLeftAligned: true)
|
||||
leftTitleInset = backButtonSize.width + backButtonInset + 1.0
|
||||
|
||||
let topHitTestSlop = (nominalHeight - backButtonSize.height) * 0.5
|
||||
@ -1411,7 +1389,7 @@ open class NavigationBar: ASDisplayNode {
|
||||
self.badgeNode.alpha = 1.0
|
||||
}
|
||||
} else if self.leftButtonNode.supernode != nil {
|
||||
let leftButtonSize = self.leftButtonNode.updateLayout(constrainedSize: CGSize(width: size.width, height: nominalHeight), isLandscape: isLandscape)
|
||||
let leftButtonSize = self.leftButtonNode.updateLayout(constrainedSize: CGSize(width: size.width, height: nominalHeight), isLandscape: isLandscape, isLeftAligned: true)
|
||||
leftTitleInset = leftButtonSize.width + leftButtonInset + 1.0
|
||||
|
||||
var transition = transition
|
||||
@ -1428,16 +1406,18 @@ open class NavigationBar: ASDisplayNode {
|
||||
transition.updateFrame(node: self.badgeNode, frame: CGRect(origin: backButtonArrowFrame.origin.offsetBy(dx: 16.0, dy: 2.0), size: badgeSize))
|
||||
|
||||
if self.rightButtonNode.supernode != nil {
|
||||
let rightButtonSize = self.rightButtonNode.updateLayout(constrainedSize: (CGSize(width: size.width, height: nominalHeight)), isLandscape: isLandscape)
|
||||
let rightButtonSize = self.rightButtonNode.updateLayout(constrainedSize: (CGSize(width: size.width, height: nominalHeight)), isLandscape: isLandscape, isLeftAligned: false)
|
||||
rightTitleInset = rightButtonSize.width + leftButtonInset + 1.0
|
||||
self.rightButtonNode.alpha = 1.0
|
||||
|
||||
var transition = transition
|
||||
if self.rightButtonNode.frame.width.isZero {
|
||||
if self.rightButtonNode.frame.width.isZero || self.rightButtonNodeUpdated {
|
||||
transition = .immediate
|
||||
}
|
||||
|
||||
transition.updateFrame(node: self.rightButtonNode, frame: CGRect(origin: CGPoint(x: size.width - leftButtonInset - rightButtonSize.width, y: contentVerticalOrigin + floor((nominalHeight - rightButtonSize.height) / 2.0)), size: rightButtonSize))
|
||||
}
|
||||
self.rightButtonNodeUpdated = false
|
||||
|
||||
if let transitionState = self.transitionState {
|
||||
let progress = transitionState.progress
|
||||
@ -1447,7 +1427,7 @@ open class NavigationBar: ASDisplayNode {
|
||||
break
|
||||
case .bottom:
|
||||
if let transitionBackButtonNode = self.transitionBackButtonNode {
|
||||
let transitionBackButtonSize = transitionBackButtonNode.updateLayout(constrainedSize: CGSize(width: size.width, height: nominalHeight), isLandscape: isLandscape)
|
||||
let transitionBackButtonSize = transitionBackButtonNode.updateLayout(constrainedSize: CGSize(width: size.width, height: nominalHeight), isLandscape: isLandscape, isLeftAligned: true)
|
||||
let initialX: CGFloat = backButtonInset + size.width * 0.3
|
||||
let finalX: CGFloat = floor((size.width - transitionBackButtonSize.width) / 2.0)
|
||||
|
||||
@ -1592,7 +1572,7 @@ open class NavigationBar: ASDisplayNode {
|
||||
node.updateManualText(self.backButtonNode.manualText)
|
||||
node.color = accentColor
|
||||
if let validLayout = self.validLayout {
|
||||
let _ = node.updateLayout(constrainedSize: CGSize(width: validLayout.size.width, height: validLayout.defaultHeight), isLandscape: validLayout.isLandscape)
|
||||
let _ = node.updateLayout(constrainedSize: CGSize(width: validLayout.size.width, height: validLayout.defaultHeight), isLandscape: validLayout.isLandscape, isLeftAligned: true)
|
||||
node.frame = self.backButtonNode.frame
|
||||
}
|
||||
return node
|
||||
@ -1608,7 +1588,7 @@ open class NavigationBar: ASDisplayNode {
|
||||
node.updateManualText(self.backButtonNode.manualText)
|
||||
node.color = accentColor
|
||||
if let validLayout = self.validLayout {
|
||||
let _ = node.updateLayout(constrainedSize: CGSize(width: validLayout.size.width, height: validLayout.defaultHeight), isLandscape: validLayout.isLandscape)
|
||||
let _ = node.updateLayout(constrainedSize: CGSize(width: validLayout.size.width, height: validLayout.defaultHeight), isLandscape: validLayout.isLandscape, isLeftAligned: true)
|
||||
node.frame = self.backButtonNode.frame
|
||||
}
|
||||
return node.view
|
||||
@ -1628,10 +1608,10 @@ open class NavigationBar: ASDisplayNode {
|
||||
items = [rightBarButtonItem]
|
||||
}
|
||||
}
|
||||
node.updateItems(items)
|
||||
node.updateItems(items, animated: false)
|
||||
node.color = accentColor
|
||||
if let validLayout = self.validLayout {
|
||||
let _ = node.updateLayout(constrainedSize: CGSize(width: validLayout.size.width, height: validLayout.defaultHeight), isLandscape: validLayout.isLandscape)
|
||||
let _ = node.updateLayout(constrainedSize: CGSize(width: validLayout.size.width, height: validLayout.defaultHeight), isLandscape: validLayout.isLandscape, isLeftAligned: false)
|
||||
node.frame = self.backButtonNode.frame
|
||||
}
|
||||
return node
|
||||
|
@ -331,6 +331,8 @@ private final class NavigationButtonItemNode: ImmediateTextNode {
|
||||
public final class NavigationButtonNode: ContextControllerSourceNode {
|
||||
private var nodes: [NavigationButtonItemNode] = []
|
||||
|
||||
private var disappearingNodes: [(frame: CGRect, size: CGSize, node: NavigationButtonItemNode)] = []
|
||||
|
||||
public var singleCustomNode: ASDisplayNode? {
|
||||
for node in self.nodes {
|
||||
return node.node
|
||||
@ -452,7 +454,7 @@ public final class NavigationButtonNode: ContextControllerSourceNode {
|
||||
}
|
||||
}
|
||||
|
||||
func updateItems(_ items: [UIBarButtonItem]) {
|
||||
func updateItems(_ items: [UIBarButtonItem], animated: Bool) {
|
||||
for i in 0 ..< items.count {
|
||||
let node: NavigationButtonItemNode
|
||||
if self.nodes.count > i {
|
||||
@ -486,16 +488,41 @@ public final class NavigationButtonNode: ContextControllerSourceNode {
|
||||
node.bold = items[i].style == .done
|
||||
node.isEnabled = items[i].isEnabled
|
||||
node.node = items[i].customDisplayNode
|
||||
|
||||
if animated {
|
||||
node.layer.animateAlpha(from: 0.0, to: self.manualAlpha, duration: 0.16)
|
||||
node.layer.animateScale(from: 0.001, to: 1.0, duration: 0.4, timingFunction: kCAMediaTimingFunctionSpring)
|
||||
}
|
||||
}
|
||||
if items.count < self.nodes.count {
|
||||
for i in items.count ..< self.nodes.count {
|
||||
self.nodes[i].removeFromSupernode()
|
||||
let itemNode = self.nodes[i]
|
||||
if animated {
|
||||
disappearingNodes.append((itemNode.frame, self.bounds.size, itemNode))
|
||||
itemNode.layer.animateAlpha(from: self.manualAlpha, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak self, weak itemNode] _ in
|
||||
guard let itemNode else {
|
||||
return
|
||||
}
|
||||
|
||||
itemNode.removeFromSupernode()
|
||||
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
if let index = self.disappearingNodes.firstIndex(where: { $0.node === itemNode }) {
|
||||
self.disappearingNodes.remove(at: index)
|
||||
}
|
||||
})
|
||||
itemNode.layer.animateScale(from: 1.0, to: 0.001, duration: 0.4, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false)
|
||||
} else {
|
||||
itemNode.removeFromSupernode()
|
||||
}
|
||||
}
|
||||
self.nodes.removeSubrange(items.count...)
|
||||
}
|
||||
}
|
||||
|
||||
public func updateLayout(constrainedSize: CGSize, isLandscape: Bool) -> CGSize {
|
||||
public func updateLayout(constrainedSize: CGSize, isLandscape: Bool, isLeftAligned: Bool) -> CGSize {
|
||||
var nodeOrigin = CGPoint()
|
||||
var totalHeight: CGFloat = 0.0
|
||||
for i in 0 ..< self.nodes.count {
|
||||
@ -520,6 +547,13 @@ public final class NavigationButtonNode: ContextControllerSourceNode {
|
||||
nodeOrigin.x -= 5.0
|
||||
}
|
||||
}
|
||||
|
||||
if !isLeftAligned {
|
||||
for disappearingNode in self.disappearingNodes {
|
||||
disappearingNode.node.frame = disappearingNode.frame.offsetBy(dx: nodeOrigin.x - disappearingNode.size.width, dy: (totalHeight - disappearingNode.size.height) * 0.5)
|
||||
}
|
||||
}
|
||||
|
||||
return CGSize(width: nodeOrigin.x, height: totalHeight)
|
||||
}
|
||||
|
||||
|
@ -265,31 +265,47 @@ public final class ChatAvatarNavigationNode: ASDisplayNode {
|
||||
|
||||
public final class SnapshotState {
|
||||
fileprivate let snapshotView: UIView?
|
||||
fileprivate let snapshotStatusView: UIView?
|
||||
|
||||
fileprivate init(snapshotView: UIView?) {
|
||||
fileprivate init(snapshotView: UIView?, snapshotStatusView: UIView?) {
|
||||
self.snapshotView = snapshotView
|
||||
self.snapshotStatusView = snapshotStatusView
|
||||
}
|
||||
}
|
||||
|
||||
public func prepareSnapshotState() -> SnapshotState {
|
||||
let snapshotView = self.avatarNode.view.snapshotView(afterScreenUpdates: false)
|
||||
let snapshotStatusView = self.statusView.view?.snapshotView(afterScreenUpdates: false)
|
||||
return SnapshotState(
|
||||
snapshotView: snapshotView
|
||||
snapshotView: snapshotView,
|
||||
snapshotStatusView: snapshotStatusView
|
||||
)
|
||||
}
|
||||
|
||||
public func animateFromSnapshot(_ snapshotState: SnapshotState) {
|
||||
self.avatarNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
|
||||
self.avatarNode.layer.animateScale(from: 0.1, to: 1.0, duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: true)
|
||||
self.avatarNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.16)
|
||||
self.avatarNode.layer.animateScale(from: 0.1, to: 1.0, duration: 0.4, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: true)
|
||||
|
||||
self.statusView.view?.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.16)
|
||||
self.statusView.view?.layer.animateScale(from: 0.1, to: 1.0, duration: 0.4, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: true)
|
||||
|
||||
if let snapshotView = snapshotState.snapshotView {
|
||||
snapshotView.frame = self.frame
|
||||
self.containerNode.view.addSubview(snapshotView)
|
||||
self.containerNode.view.insertSubview(snapshotView, at: 0)
|
||||
|
||||
snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak snapshotView] _ in
|
||||
snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak snapshotView] _ in
|
||||
snapshotView?.removeFromSuperview()
|
||||
})
|
||||
snapshotView.layer.animateScale(from: 1.0, to: 0.1, duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false)
|
||||
snapshotView.layer.animateScale(from: 1.0, to: 0.1, duration: 0.4, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false)
|
||||
}
|
||||
if let snapshotStatusView = snapshotState.snapshotStatusView {
|
||||
snapshotStatusView.frame = CGRect(origin: CGPoint(x: floor((self.containerNode.bounds.width - snapshotStatusView.bounds.width) / 2.0), y: floor((self.containerNode.bounds.height - snapshotStatusView.bounds.height) / 2.0)), size: snapshotStatusView.bounds.size)
|
||||
self.containerNode.view.insertSubview(snapshotStatusView, at: 0)
|
||||
|
||||
snapshotStatusView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak snapshotStatusView] _ in
|
||||
snapshotStatusView?.removeFromSuperview()
|
||||
})
|
||||
snapshotStatusView.layer.animateScale(from: 1.0, to: 0.1, duration: 0.4, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1021,16 +1021,16 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
|
||||
if activitySize.width < size.width {
|
||||
activityFrame.origin.x = -clearBounds.minX + floor((size.width - activityFrame.width) / 2.0)
|
||||
}
|
||||
self.activityNode.frame = activityFrame
|
||||
titleTransition.updateFrameAdditiveToCenter(node: self.activityNode, frame: activityFrame)
|
||||
}
|
||||
|
||||
if let image = self.titleLeftIconNode.image {
|
||||
self.titleLeftIconNode.frame = CGRect(origin: CGPoint(x: -image.size.width - 3.0 - UIScreenPixel, y: 4.0), size: image.size)
|
||||
titleTransition.updateFrame(node: self.titleLeftIconNode, frame: CGRect(origin: CGPoint(x: -image.size.width - 3.0 - UIScreenPixel, y: 4.0), size: image.size))
|
||||
}
|
||||
|
||||
var nextIconX: CGFloat = titleFrame.width
|
||||
|
||||
self.titleVerifiedIconView.frame = CGRect(origin: CGPoint(x: 0.0, y: floor((titleFrame.height - titleVerifiedSize.height) / 2.0)), size: titleVerifiedSize)
|
||||
titleTransition.updateFrame(view: self.titleVerifiedIconView, frame: CGRect(origin: CGPoint(x: 0.0, y: floor((titleFrame.height - titleVerifiedSize.height) / 2.0)), size: titleVerifiedSize))
|
||||
|
||||
self.titleCredibilityIconView.frame = CGRect(origin: CGPoint(x: nextIconX - titleCredibilitySize.width, y: floor((titleFrame.height - titleCredibilitySize.height) / 2.0)), size: titleCredibilitySize)
|
||||
nextIconX -= titleCredibilitySize.width
|
||||
@ -1056,7 +1056,7 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
|
||||
titleTransition.updateFrameAdditiveToCenter(view: self.titleContainerView, frame: titleFrame)
|
||||
titleTransition.updateFrameAdditiveToCenter(node: self.titleTextNode, frame: CGRect(origin: CGPoint(), size: titleFrame.size))
|
||||
|
||||
self.activityNode.frame = CGRect(origin: CGPoint(x: floor((clearBounds.width - combinedWidth) / 2.0 + titleSize.width + leftIconWidth + credibilityIconWidth + verifiedIconWidth + statusIconWidth + rightIconWidth + titleInfoSpacing), y: floor((size.height - activitySize.height) / 2.0)), size: activitySize)
|
||||
titleTransition.updateFrameAdditiveToCenter(node: self.activityNode, frame: CGRect(origin: CGPoint(x: floor((clearBounds.width - combinedWidth) / 2.0 + titleSize.width + leftIconWidth + credibilityIconWidth + verifiedIconWidth + statusIconWidth + rightIconWidth + titleInfoSpacing), y: floor((size.height - activitySize.height) / 2.0)), size: activitySize))
|
||||
|
||||
if let image = self.titleLeftIconNode.image {
|
||||
self.titleLeftIconNode.frame = CGRect(origin: CGPoint(x: titleFrame.minX, y: titleFrame.minY + 4.0), size: image.size)
|
||||
@ -1069,11 +1069,11 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
|
||||
self.titleCredibilityIconView.frame = CGRect(origin: CGPoint(x: nextIconX - titleCredibilitySize.width, y: floor((titleFrame.height - titleCredibilitySize.height) / 2.0)), size: titleCredibilitySize)
|
||||
nextIconX -= titleCredibilitySize.width
|
||||
|
||||
self.titleStatusIconView.frame = CGRect(origin: CGPoint(x: nextIconX - titleStatusSize.width, y: floor((titleFrame.height - titleStatusSize.height) / 2.0)), size: titleStatusSize)
|
||||
titleTransition.updateFrame(view: self.titleStatusIconView, frame: CGRect(origin: CGPoint(x: nextIconX - titleStatusSize.width, y: floor((titleFrame.height - titleStatusSize.height) / 2.0)), size: titleStatusSize))
|
||||
nextIconX -= titleStatusSize.width
|
||||
|
||||
if let image = self.titleRightIconNode.image {
|
||||
self.titleRightIconNode.frame = CGRect(origin: CGPoint(x: titleFrame.maxX - image.size.width, y: titleFrame.minY + 6.0), size: image.size)
|
||||
titleTransition.updateFrame(node: self.titleRightIconNode, frame: CGRect(origin: CGPoint(x: titleFrame.maxX - image.size.width, y: titleFrame.minY + 6.0), size: image.size))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -153,7 +153,8 @@ extension ChatControllerImpl {
|
||||
currentChatListFilter: self.currentChatListFilter,
|
||||
customChatNavigationStack: self.customChatNavigationStack,
|
||||
presentationData: self.presentationData,
|
||||
historyNode: historyNode
|
||||
historyNode: historyNode,
|
||||
inviteRequestsContext: self.contentData?.inviteRequestsContext
|
||||
)
|
||||
self.pendingContentData = (contentData, historyNode)
|
||||
self.contentDataDisposable = (contentData.isReady.get()
|
||||
@ -248,7 +249,16 @@ extension ChatControllerImpl {
|
||||
|
||||
self.chatDisplayNode.overlayTitle = contentData.overlayTitle
|
||||
|
||||
self.chatDisplayNode.historyNode.nextChannelToRead = contentData.state.nextChannelToRead
|
||||
self.chatDisplayNode.historyNode.nextChannelToRead = contentData.state.nextChannelToRead.flatMap { nextChannelToRead -> (peer: EnginePeer, threadData: (id: Int64, data: MessageHistoryThreadData)?, unreadCount: Int, location: TelegramEngine.NextUnreadChannelLocation)? in
|
||||
return (
|
||||
nextChannelToRead.peer,
|
||||
nextChannelToRead.threadData.flatMap { threadData -> (id: Int64, data: MessageHistoryThreadData) in
|
||||
return (threadData.id, threadData.data)
|
||||
},
|
||||
nextChannelToRead.unreadCount,
|
||||
nextChannelToRead.location
|
||||
)
|
||||
}
|
||||
self.chatDisplayNode.historyNode.nextChannelToReadDisplayName = contentData.state.nextChannelToReadDisplayName
|
||||
self.updateNextChannelToReadVisibility()
|
||||
|
||||
@ -286,6 +296,18 @@ extension ChatControllerImpl {
|
||||
didDisplayActionsPanel = true
|
||||
}
|
||||
|
||||
var previousInvitationPeers: [EnginePeer] = []
|
||||
if let requestsState = previousState.requestsState {
|
||||
previousInvitationPeers = Array(requestsState.importers.compactMap({ $0.peer.peer.flatMap({ EnginePeer($0) }) }).prefix(3))
|
||||
}
|
||||
var previousInvitationRequestsPeersDismissed = false
|
||||
if let dismissedInvitationRequests = previousState.dismissedInvitationRequests, Set(previousInvitationPeers.map({ $0.id.toInt64() })) == Set(dismissedInvitationRequests) {
|
||||
previousInvitationRequestsPeersDismissed = true
|
||||
}
|
||||
if let requestsState = previousState.requestsState, requestsState.count > 0 && !previousInvitationRequestsPeersDismissed {
|
||||
didDisplayActionsPanel = true
|
||||
}
|
||||
|
||||
var displayActionsPanel = false
|
||||
if let contactStatus = contentData.state.contactStatus, !contactStatus.isEmpty, let peerStatusSettings = contactStatus.peerStatusSettings {
|
||||
if !peerStatusSettings.flags.isEmpty {
|
||||
@ -307,6 +329,18 @@ extension ChatControllerImpl {
|
||||
displayActionsPanel = true
|
||||
}
|
||||
|
||||
var invitationPeers: [EnginePeer] = []
|
||||
if let requestsState = contentData.state.requestsState {
|
||||
invitationPeers = Array(requestsState.importers.compactMap({ $0.peer.peer.flatMap({ EnginePeer($0) }) }).prefix(3))
|
||||
}
|
||||
var invitationRequestsPeersDismissed = false
|
||||
if let dismissedInvitationRequests = contentData.state.dismissedInvitationRequests, Set(invitationPeers.map({ $0.id.toInt64() })) == Set(dismissedInvitationRequests) {
|
||||
invitationRequestsPeersDismissed = true
|
||||
}
|
||||
if let requestsState = contentData.state.requestsState, requestsState.count > 0 && !invitationRequestsPeersDismissed {
|
||||
displayActionsPanel = true
|
||||
}
|
||||
|
||||
if displayActionsPanel != didDisplayActionsPanel {
|
||||
animated = true
|
||||
}
|
||||
@ -411,7 +445,6 @@ extension ChatControllerImpl {
|
||||
if let dismissedInvitationRequests = contentData.state.dismissedInvitationRequests, Set(peers.map({ $0.id.toInt64() })) == Set(dismissedInvitationRequests) {
|
||||
peersDismissed = true
|
||||
}
|
||||
|
||||
if let requestsState = contentData.state.requestsState, requestsState.count > 0 && !peersDismissed {
|
||||
if !context.contains(where: {
|
||||
switch $0 {
|
||||
|
@ -434,14 +434,6 @@ func updateChatPresentationInterfaceStateImpl(
|
||||
|
||||
selfController.presentationInterfaceState = updatedChatPresentationInterfaceState
|
||||
|
||||
/*if selfController.chatDisplayNode.chatLocation != selfController.presentationInterfaceState.chatLocation {
|
||||
let defaultDirection: ChatControllerAnimateInnerChatSwitchDirection? = selfController.chatDisplayNode.chatLocationTabSwitchDirection(from: selfController.chatLocation.threadId, to: selfController.presentationInterfaceState.chatLocation.threadId).flatMap { direction -> ChatControllerAnimateInnerChatSwitchDirection in
|
||||
return direction ? .right : .left
|
||||
}
|
||||
let tabSwitchDirection = selfController.currentChatSwitchDirection ?? defaultDirection
|
||||
selfController.chatDisplayNode.updateChatLocation(chatLocation: selfController.presentationInterfaceState.chatLocation, transition: transition, tabSwitchDirection: tabSwitchDirection)
|
||||
}*/
|
||||
|
||||
selfController.updateSlowmodeStatus()
|
||||
|
||||
switch updatedChatPresentationInterfaceState.inputMode {
|
||||
@ -498,20 +490,11 @@ func updateChatPresentationInterfaceStateImpl(
|
||||
}
|
||||
|
||||
var buttonsAnimated = transition.isAnimated
|
||||
if selfController.currentChatSwitchDirection != nil {
|
||||
buttonsAnimated = false
|
||||
}
|
||||
if let button = rightNavigationButtonForChatInterfaceState(context: selfController.context, presentationInterfaceState: updatedChatPresentationInterfaceState, strings: updatedChatPresentationInterfaceState.strings, currentButton: selfController.rightNavigationButton, target: selfController, selector: #selector(selfController.rightNavigationButtonAction), chatInfoNavigationButton: selfController.chatInfoNavigationButton, moreInfoNavigationButton: selfController.moreInfoNavigationButton) {
|
||||
if selfController.rightNavigationButton != button {
|
||||
if let currentButton = selfController.rightNavigationButton?.action, currentButton == button.action {
|
||||
buttonsAnimated = false
|
||||
}
|
||||
if case .replyThread = selfController.chatLocation {
|
||||
buttonsAnimated = false
|
||||
}
|
||||
if let channel = updatedChatPresentationInterfaceState.renderedPeer?.peer as? TelegramChannel, channel.isMonoForum {
|
||||
buttonsAnimated = false
|
||||
}
|
||||
selfController.rightNavigationButton = button
|
||||
}
|
||||
} else if let _ = selfController.rightNavigationButton {
|
||||
|
@ -9751,6 +9751,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
|
||||
let navigationSnapshot = self.chatTitleView?.prepareSnapshotState()
|
||||
let avatarSnapshot = self.chatInfoNavigationButton?.buttonItem.customDisplayNode?.view.window != nil ? (self.chatInfoNavigationButton?.buttonItem.customDisplayNode as? ChatAvatarNavigationNode)?.prepareSnapshotState() : nil
|
||||
|
||||
let chatLocationContextHolder = Atomic<ChatLocationContextHolder?>(value: nil)
|
||||
let historyNode = self.chatDisplayNode.createHistoryNodeForChatLocation(chatLocation: updatedChatLocation, chatLocationContextHolder: chatLocationContextHolder)
|
||||
@ -9780,108 +9781,15 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
|
||||
self.chatTitleView?.animateFromSnapshot(navigationSnapshot, direction: mappedAnimationDirection)
|
||||
/*if let rightBarButtonItems = self.navigationItem.rightBarButtonItems {
|
||||
for i in 0 ..< rightBarButtonItems.count {
|
||||
let item = rightBarButtonItems[i]
|
||||
if let customDisplayNode = item.customDisplayNode {
|
||||
customDisplayNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||
//customDisplayNode.layer.animateScale(from: 0.001, to: 1.0, duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring)
|
||||
}
|
||||
|
||||
let _ = rightBarButtonItemSnapshots
|
||||
/*if i < rightBarButtonItemSnapshots.count {
|
||||
let (snapshotItem, snapshotFrame) = rightBarButtonItemSnapshots[i]
|
||||
if let targetSuperview = customDisplayNode.view.superview {
|
||||
snapshotItem.frame = targetSuperview.convert(snapshotFrame, from: self.view)
|
||||
targetSuperview.addSubview(snapshotItem)
|
||||
|
||||
snapshotItem.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.18, completion: { [weak snapshotItem] _ in
|
||||
snapshotItem?.removeFromSuperview()
|
||||
})
|
||||
snapshotItem.layer.animateScale(from: 1.0, to: 0.1, duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring)
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}*/
|
||||
if let avatarSnapshot, self.chatInfoNavigationButton?.buttonItem.customDisplayNode?.view.window != nil {
|
||||
(self.chatInfoNavigationButton?.buttonItem.customDisplayNode as? ChatAvatarNavigationNode)?.animateFromSnapshot(avatarSnapshot)
|
||||
}
|
||||
|
||||
self.currentChatSwitchDirection = nil
|
||||
|
||||
self.isUpdatingChatLocationThread = false
|
||||
})
|
||||
|
||||
/*
|
||||
|
||||
//
|
||||
|
||||
let rightBarButtonItemSnapshots: [(UIView, CGRect)] = (self.navigationItem.rightBarButtonItems ?? []).compactMap { item -> (UIView, CGRect)? in
|
||||
guard let view = item.customDisplayNode?.view, let snapshotView = view.snapshotView(afterScreenUpdates: false) else {
|
||||
return nil
|
||||
}
|
||||
return (snapshotView, view.convert(view.bounds, to: self.view))
|
||||
}
|
||||
|
||||
let isReady = Promise<Bool>()
|
||||
let chatLocationContextHolder = Atomic<ChatLocationContextHolder?>(value: nil)
|
||||
self.reloadChatLocation(chatLocation: updatedChatLocation, chatLocationContextHolder: chatLocationContextHolder, historyNode: historyNode, isReady: isReady)
|
||||
|
||||
self.isUpdatingChatLocationThread = true
|
||||
self.updateChatLocationThreadDisposable?.dispose()
|
||||
self.updateChatLocationThreadDisposable = (isReady.get()
|
||||
|> filter { $0 }
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] _ in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.isUpdatingChatLocationThread = false
|
||||
|
||||
self.currentChatSwitchDirection = animationDirection
|
||||
self.updateChatPresentationInterfaceState(animated: animationDirection != nil, interactive: false, { presentationInterfaceState in
|
||||
return presentationInterfaceState.updatedChatLocation(updatedChatLocation)
|
||||
})
|
||||
|
||||
if let navigationSnapshot, let animationDirection {
|
||||
let mappedAnimationDirection: ChatTitleView.AnimateFromSnapshotDirection
|
||||
switch animationDirection {
|
||||
case .up:
|
||||
mappedAnimationDirection = .up
|
||||
case .down:
|
||||
mappedAnimationDirection = .down
|
||||
case .left:
|
||||
mappedAnimationDirection = .left
|
||||
case .right:
|
||||
mappedAnimationDirection = .right
|
||||
}
|
||||
|
||||
self.chatTitleView?.animateFromSnapshot(navigationSnapshot, direction: mappedAnimationDirection)
|
||||
if let rightBarButtonItems = self.navigationItem.rightBarButtonItems {
|
||||
for i in 0 ..< rightBarButtonItems.count {
|
||||
let item = rightBarButtonItems[i]
|
||||
if let customDisplayNode = item.customDisplayNode {
|
||||
customDisplayNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||
//customDisplayNode.layer.animateScale(from: 0.001, to: 1.0, duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring)
|
||||
|
||||
let _ = rightBarButtonItemSnapshots
|
||||
/*if i < rightBarButtonItemSnapshots.count {
|
||||
let (snapshotItem, snapshotFrame) = rightBarButtonItemSnapshots[i]
|
||||
if let targetSuperview = customDisplayNode.view.superview {
|
||||
snapshotItem.frame = targetSuperview.convert(snapshotFrame, from: self.view)
|
||||
targetSuperview.addSubview(snapshotItem)
|
||||
|
||||
snapshotItem.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.18, completion: { [weak snapshotItem] _ in
|
||||
snapshotItem?.removeFromSuperview()
|
||||
})
|
||||
snapshotItem.layer.animateScale(from: 1.0, to: 0.1, duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring)
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.currentChatSwitchDirection = nil
|
||||
})*/
|
||||
}
|
||||
|
||||
public var contentContainerNode: ASDisplayNode {
|
||||
|
@ -57,6 +57,30 @@ extension ChatControllerImpl {
|
||||
case dismiss
|
||||
}
|
||||
|
||||
struct NextChannelToRead: Equatable {
|
||||
struct ThreadData: Equatable {
|
||||
let id: Int64
|
||||
let data: MessageHistoryThreadData
|
||||
|
||||
init(id: Int64, data: MessageHistoryThreadData) {
|
||||
self.id = id
|
||||
self.data = data
|
||||
}
|
||||
}
|
||||
|
||||
let peer: EnginePeer
|
||||
let threadData: ThreadData?
|
||||
let unreadCount: Int
|
||||
let location: TelegramEngine.NextUnreadChannelLocation
|
||||
|
||||
init(peer: EnginePeer, threadData: ThreadData?, unreadCount: Int, location: TelegramEngine.NextUnreadChannelLocation) {
|
||||
self.peer = peer
|
||||
self.threadData = threadData
|
||||
self.unreadCount = unreadCount
|
||||
self.location = location
|
||||
}
|
||||
}
|
||||
|
||||
struct State {
|
||||
var peerView: PeerView?
|
||||
var threadInfo: EngineMessageHistoryThread.Info?
|
||||
@ -72,7 +96,7 @@ extension ChatControllerImpl {
|
||||
var contactStatus: ChatContactStatus?
|
||||
var adMessage: Message?
|
||||
var offerNextChannelToRead: Bool = false
|
||||
var nextChannelToRead: (peer: EnginePeer, threadData: (id: Int64, data: MessageHistoryThreadData)?, unreadCount: Int, location: TelegramEngine.NextUnreadChannelLocation)?
|
||||
var nextChannelToRead: NextChannelToRead?
|
||||
var nextChannelToReadDisplayName: Bool = false
|
||||
var isNotAccessible: Bool = false
|
||||
var hasBots: Bool = false
|
||||
@ -178,8 +202,8 @@ extension ChatControllerImpl {
|
||||
let chatThemeEmoticonPromise = Promise<String?>()
|
||||
let chatWallpaperPromise = Promise<TelegramWallpaper?>()
|
||||
|
||||
var inviteRequestsContext: PeerInvitationImportersContext?
|
||||
private var inviteRequestsDisposable = MetaDisposable()
|
||||
private(set) var inviteRequestsContext: PeerInvitationImportersContext?
|
||||
private var inviteRequestsDisposable: Disposable?
|
||||
|
||||
init(
|
||||
context: AccountContext,
|
||||
@ -192,10 +216,14 @@ extension ChatControllerImpl {
|
||||
currentChatListFilter: Int32?,
|
||||
customChatNavigationStack: [EnginePeer.Id]?,
|
||||
presentationData: PresentationData,
|
||||
historyNode: ChatHistoryListNodeImpl
|
||||
historyNode: ChatHistoryListNodeImpl,
|
||||
inviteRequestsContext: PeerInvitationImportersContext?
|
||||
) {
|
||||
self.chatLocation = chatLocation
|
||||
self.presentationData = presentationData
|
||||
|
||||
self.inviteRequestsContext = inviteRequestsContext
|
||||
|
||||
let strings = self.presentationData.strings
|
||||
|
||||
let chatLocationPeerId: PeerId? = chatLocation.peerId
|
||||
@ -972,11 +1000,23 @@ extension ChatControllerImpl {
|
||||
|
||||
let previousState = strongSelf.state
|
||||
|
||||
var isUpdated = false
|
||||
|
||||
if !strongSelf.state.offerNextChannelToRead {
|
||||
strongSelf.state.offerNextChannelToRead = true
|
||||
strongSelf.state.nextChannelToRead = nextPeer.flatMap { nextPeer -> (peer: EnginePeer, threadData: (id: Int64, data: MessageHistoryThreadData)?, unreadCount: Int, location: TelegramEngine.NextUnreadChannelLocation) in
|
||||
return (peer: nextPeer, threadData: nil, unreadCount: 0, location: .same)
|
||||
isUpdated = true
|
||||
}
|
||||
let nextChannelToRead = nextPeer.flatMap { nextPeer -> NextChannelToRead in
|
||||
return NextChannelToRead(peer: nextPeer, threadData: nil, unreadCount: 0, location: .same)
|
||||
}
|
||||
if strongSelf.state.nextChannelToRead != nextChannelToRead {
|
||||
strongSelf.state.nextChannelToRead = nextChannelToRead
|
||||
isUpdated = true
|
||||
}
|
||||
if strongSelf.state.nextChannelToReadDisplayName != (nextChatSuggestionTip >= 3) {
|
||||
strongSelf.state.nextChannelToReadDisplayName = nextChatSuggestionTip >= 3
|
||||
isUpdated = true
|
||||
}
|
||||
|
||||
let nextPeerId = nextPeer?.id
|
||||
|
||||
@ -992,7 +1032,9 @@ extension ChatControllerImpl {
|
||||
}
|
||||
}
|
||||
|
||||
if isUpdated {
|
||||
strongSelf.onUpdated?(previousState)
|
||||
}
|
||||
})
|
||||
}
|
||||
} else if isRegularChat, strongSelf.nextChannelToReadDisposable == nil {
|
||||
@ -1012,11 +1054,23 @@ extension ChatControllerImpl {
|
||||
|
||||
let previousState = strongSelf.state
|
||||
|
||||
var isUpdated = false
|
||||
|
||||
if !strongSelf.state.offerNextChannelToRead {
|
||||
strongSelf.state.offerNextChannelToRead = true
|
||||
strongSelf.state.nextChannelToRead = nextPeer.flatMap { nextPeer -> (peer: EnginePeer, threadData: (id: Int64, data: MessageHistoryThreadData)?, unreadCount: Int, location: TelegramEngine.NextUnreadChannelLocation) in
|
||||
return (peer: nextPeer.peer, threadData: nil, unreadCount: nextPeer.unreadCount, location: nextPeer.location)
|
||||
isUpdated = true
|
||||
}
|
||||
let nextChannelToRead = nextPeer.flatMap { nextPeer -> NextChannelToRead in
|
||||
return NextChannelToRead(peer: nextPeer.peer, threadData: nil, unreadCount: nextPeer.unreadCount, location: nextPeer.location)
|
||||
}
|
||||
if strongSelf.state.nextChannelToRead != nextChannelToRead {
|
||||
strongSelf.state.nextChannelToRead = nextChannelToRead
|
||||
isUpdated = true
|
||||
}
|
||||
if strongSelf.state.nextChannelToReadDisplayName != (nextChatSuggestionTip >= 3) {
|
||||
strongSelf.state.nextChannelToReadDisplayName = nextChatSuggestionTip >= 3
|
||||
isUpdated = true
|
||||
}
|
||||
|
||||
let nextPeerId = nextPeer?.peer.id
|
||||
|
||||
@ -1032,7 +1086,9 @@ extension ChatControllerImpl {
|
||||
}
|
||||
}
|
||||
|
||||
if isUpdated {
|
||||
strongSelf.onUpdated?(previousState)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -1570,13 +1626,27 @@ extension ChatControllerImpl {
|
||||
|
||||
let previousState = strongSelf.state
|
||||
|
||||
strongSelf.state.offerNextChannelToRead = true
|
||||
strongSelf.state.nextChannelToRead = nextThreadData.flatMap { nextThreadData -> (peer: EnginePeer, threadData: (id: Int64, data: MessageHistoryThreadData)?, unreadCount: Int, location: TelegramEngine.NextUnreadChannelLocation) in
|
||||
return (peer: EnginePeer(channel), threadData: nextThreadData, unreadCount: Int(nextThreadData.data.incomingUnreadCount), location: .same)
|
||||
}
|
||||
strongSelf.state.nextChannelToReadDisplayName = nextChatSuggestionTip >= 3
|
||||
var isUpdated = false
|
||||
|
||||
if !strongSelf.state.offerNextChannelToRead {
|
||||
strongSelf.state.offerNextChannelToRead = true
|
||||
isUpdated = true
|
||||
}
|
||||
let nextChannelToRead = nextThreadData.flatMap { nextThreadData -> NextChannelToRead in
|
||||
return NextChannelToRead(peer: EnginePeer(channel), threadData: NextChannelToRead.ThreadData(id: nextThreadData.id, data: nextThreadData.data), unreadCount: Int(nextThreadData.data.incomingUnreadCount), location: .same)
|
||||
}
|
||||
if strongSelf.state.nextChannelToRead != nextChannelToRead {
|
||||
strongSelf.state.nextChannelToRead = nextChannelToRead
|
||||
isUpdated = true
|
||||
}
|
||||
if strongSelf.state.nextChannelToReadDisplayName != (nextChatSuggestionTip >= 3) {
|
||||
strongSelf.state.nextChannelToReadDisplayName = nextChatSuggestionTip >= 3
|
||||
isUpdated = true
|
||||
}
|
||||
|
||||
if isUpdated {
|
||||
strongSelf.onUpdated?(previousState)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -2129,8 +2199,19 @@ extension ChatControllerImpl {
|
||||
if strongSelf.inviteRequestsContext == nil {
|
||||
let inviteRequestsContext = context.engine.peers.peerInvitationImporters(peerId: peerId, subject: .requests(query: nil))
|
||||
strongSelf.inviteRequestsContext = inviteRequestsContext
|
||||
} else if let inviteRequestsContext = strongSelf.inviteRequestsContext {
|
||||
let _ = (inviteRequestsContext.state
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).startStandalone(next: { [weak inviteRequestsContext] state in
|
||||
if state.count != inviteRequestsPending {
|
||||
inviteRequestsContext?.loadMore()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
strongSelf.inviteRequestsDisposable.set((combineLatest(queue: Queue.mainQueue(), inviteRequestsContext.state, ApplicationSpecificNotice.dismissedInvitationRequests(accountManager: context.sharedContext.accountManager, peerId: peerId))).startStrict(next: { [weak strongSelf] requestsState, dismissedInvitationRequests in
|
||||
if chatLocation.threadId == nil {
|
||||
if strongSelf.inviteRequestsDisposable == nil, let inviteRequestsContext = strongSelf.inviteRequestsContext {
|
||||
strongSelf.inviteRequestsDisposable = combineLatest(queue: Queue.mainQueue(), inviteRequestsContext.state, ApplicationSpecificNotice.dismissedInvitationRequests(accountManager: context.sharedContext.accountManager, peerId: peerId)).startStrict(next: { [weak strongSelf] requestsState, dismissedInvitationRequests in
|
||||
guard let strongSelf else {
|
||||
return
|
||||
}
|
||||
@ -2141,16 +2222,16 @@ extension ChatControllerImpl {
|
||||
strongSelf.state.dismissedInvitationRequests = dismissedInvitationRequests
|
||||
|
||||
strongSelf.onUpdated?(previousState)
|
||||
}))
|
||||
} else if let inviteRequestsContext = strongSelf.inviteRequestsContext {
|
||||
let _ = (inviteRequestsContext.state
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).startStandalone(next: { [weak inviteRequestsContext] state in
|
||||
if state.count != inviteRequestsPending {
|
||||
inviteRequestsContext?.loadMore()
|
||||
}
|
||||
})
|
||||
}
|
||||
} else {
|
||||
strongSelf.state.requestsState = nil
|
||||
strongSelf.state.dismissedInvitationRequests = []
|
||||
}
|
||||
} else {
|
||||
strongSelf.inviteRequestsContext = nil
|
||||
strongSelf.state.requestsState = nil
|
||||
strongSelf.state.dismissedInvitationRequests = []
|
||||
}
|
||||
|
||||
var isUpdated = false
|
||||
@ -2196,7 +2277,7 @@ extension ChatControllerImpl {
|
||||
self.cachedDataDisposable?.dispose()
|
||||
self.premiumGiftSuggestionDisposable?.dispose()
|
||||
self.translationStateDisposable?.dispose()
|
||||
self.inviteRequestsDisposable.dispose()
|
||||
self.inviteRequestsDisposable?.dispose()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -108,12 +108,27 @@ private final class ChatInfoTitlePanelPeerNearbyInfoNode: ASDisplayNode {
|
||||
}
|
||||
|
||||
final class ChatInviteRequestsTitlePanelNode: ChatTitleAccessoryPanelNode {
|
||||
private final class Params {
|
||||
let width: CGFloat
|
||||
let leftInset: CGFloat
|
||||
let rightInset: CGFloat
|
||||
let interfaceState: ChatPresentationInterfaceState
|
||||
|
||||
init(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, interfaceState: ChatPresentationInterfaceState) {
|
||||
self.width = width
|
||||
self.leftInset = leftInset
|
||||
self.rightInset = rightInset
|
||||
self.interfaceState = interfaceState
|
||||
}
|
||||
}
|
||||
|
||||
private let context: AccountContext
|
||||
|
||||
private let separatorNode: ASDisplayNode
|
||||
|
||||
private let closeButton: HighlightableButtonNode
|
||||
private var button: UIButton?
|
||||
private let button: HighlightableButtonNode
|
||||
private let buttonTitle: ImmediateTextNode
|
||||
|
||||
private let avatarsContext: AnimatedAvatarSetContext
|
||||
private var avatarsContent: AnimatedAvatarSetContext.Content?
|
||||
@ -127,6 +142,8 @@ final class ChatInviteRequestsTitlePanelNode: ChatTitleAccessoryPanelNode {
|
||||
private var peers: [EnginePeer] = []
|
||||
private var count: Int32 = 0
|
||||
|
||||
private var params: Params?
|
||||
|
||||
init(context: AccountContext) {
|
||||
self.context = context
|
||||
|
||||
@ -137,6 +154,10 @@ final class ChatInviteRequestsTitlePanelNode: ChatTitleAccessoryPanelNode {
|
||||
self.closeButton.hitTestSlop = UIEdgeInsets(top: -8.0, left: -8.0, bottom: -8.0, right: -8.0)
|
||||
self.closeButton.displaysAsynchronously = false
|
||||
|
||||
self.button = HighlightableButtonNode()
|
||||
self.buttonTitle = ImmediateTextNode()
|
||||
self.buttonTitle.anchorPoint = CGPoint()
|
||||
|
||||
self.avatarsContext = AnimatedAvatarSetContext()
|
||||
self.avatarsNode = AnimatedAvatarSetNode()
|
||||
|
||||
@ -150,6 +171,12 @@ final class ChatInviteRequestsTitlePanelNode: ChatTitleAccessoryPanelNode {
|
||||
self.closeButton.addTarget(self, action: #selector(self.closePressed), forControlEvents: [.touchUpInside])
|
||||
self.addSubnode(self.closeButton)
|
||||
|
||||
self.button.addTarget(self, action: #selector(self.buttonPressed), forControlEvents: .touchUpInside)
|
||||
self.addSubnode(self.button)
|
||||
|
||||
self.buttonTitle.isUserInteractionEnabled = false
|
||||
self.button.addSubnode(self.buttonTitle)
|
||||
|
||||
self.addSubnode(self.avatarsNode)
|
||||
|
||||
self.addSubnode(self.activateAreaNode)
|
||||
@ -161,12 +188,16 @@ final class ChatInviteRequestsTitlePanelNode: ChatTitleAccessoryPanelNode {
|
||||
self.peers = peers
|
||||
self.count = count
|
||||
|
||||
let presentationData = self.context.sharedContext.currentPresentationData.with { $0 }
|
||||
self.avatarsContent = self.avatarsContext.update(peers: peers, animated: false)
|
||||
self.button?.setTitle(presentationData.strings.Conversation_RequestsToJoin(count), for: [])
|
||||
|
||||
if let params = self.params {
|
||||
let _ = self.updateLayout(width: params.width, leftInset: params.leftInset, rightInset: params.rightInset, transition: .immediate, interfaceState: params.interfaceState)
|
||||
}
|
||||
}
|
||||
|
||||
override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState) -> LayoutResult {
|
||||
self.params = Params(width: width, leftInset: leftInset, rightInset: rightInset, interfaceState: interfaceState)
|
||||
|
||||
if interfaceState.theme !== self.theme {
|
||||
self.theme = interfaceState.theme
|
||||
|
||||
@ -181,21 +212,15 @@ final class ChatInviteRequestsTitlePanelNode: ChatTitleAccessoryPanelNode {
|
||||
let closeButtonSize = self.closeButton.measure(CGSize(width: 100.0, height: 100.0))
|
||||
transition.updateFrame(node: self.closeButton, frame: CGRect(origin: CGPoint(x: width - contentRightInset - closeButtonSize.width, y: floorToScreenPixels((panelHeight - closeButtonSize.height) / 2.0)), size: closeButtonSize))
|
||||
|
||||
if self.button == nil {
|
||||
let view = UIButton()
|
||||
view.titleLabel?.font = Font.regular(16.0)
|
||||
view.setTitleColor(interfaceState.theme.rootController.navigationBar.accentTextColor, for: [])
|
||||
view.setTitleColor(interfaceState.theme.rootController.navigationBar.accentTextColor.withAlphaComponent(0.7), for: [.highlighted])
|
||||
view.addTarget(self, action: #selector(self.buttonPressed), for: [.touchUpInside])
|
||||
self.view.addSubview(view)
|
||||
self.button = view
|
||||
}
|
||||
self.buttonTitle.attributedText = NSAttributedString(string: interfaceState.strings.Conversation_RequestsToJoin(self.count), font: Font.regular(16.0), textColor: interfaceState.theme.rootController.navigationBar.accentTextColor)
|
||||
|
||||
self.button?.setTitle(interfaceState.strings.Conversation_RequestsToJoin(self.count), for: [])
|
||||
transition.updateFrame(node: self.button, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: width, height: panelHeight)))
|
||||
|
||||
let maxInset = max(contentRightInset, leftInset)
|
||||
let buttonWidth = floor(width - maxInset * 2.0)
|
||||
self.button?.frame = CGRect(origin: CGPoint(x: maxInset, y: 0.0), size: CGSize(width: buttonWidth, height: panelHeight))
|
||||
let titleSize = self.buttonTitle.updateLayout(CGSize(width: width - leftInset - 90.0 - contentRightInset, height: 100.0))
|
||||
var buttonTitleFrame = CGRect(origin: CGPoint(x: leftInset + floor((width - leftInset - titleSize.width) * 0.5), y: floor((panelHeight - titleSize.height) * 0.5)), size: titleSize)
|
||||
buttonTitleFrame.origin.x = max(buttonTitleFrame.minX, leftInset + 90.0)
|
||||
transition.updatePosition(node: self.buttonTitle, position: buttonTitleFrame.origin)
|
||||
self.buttonTitle.bounds = CGRect(origin: CGPoint(), size: buttonTitleFrame.size)
|
||||
|
||||
let initialPanelHeight = panelHeight
|
||||
transition.updateFrame(node: self.separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: width, height: UIScreenPixel)))
|
||||
|
Loading…
x
Reference in New Issue
Block a user