diff --git a/submodules/TelegramCore/TelegramCore/ChannelOwnershipTransfer.swift b/submodules/TelegramCore/TelegramCore/ChannelOwnershipTransfer.swift index a72975a992..f942cf3d56 100644 --- a/submodules/TelegramCore/TelegramCore/ChannelOwnershipTransfer.swift +++ b/submodules/TelegramCore/TelegramCore/ChannelOwnershipTransfer.swift @@ -29,7 +29,7 @@ public enum ChannelOwnershipTransferError { public func checkOwnershipTranfserAvailability(postbox: Postbox, network: Network, accountStateManager: AccountStateManager, memberId: PeerId) -> Signal { return postbox.transaction { transaction -> Peer? in return transaction.getPeer(memberId) - } + } |> introduceError(ChannelOwnershipTransferError.self) |> mapToSignal { user -> Signal in guard let user = user else { diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageAnimatedStickerItemNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageAnimatedStickerItemNode.swift index eee88d5376..1addbf9378 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageAnimatedStickerItemNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageAnimatedStickerItemNode.swift @@ -20,7 +20,6 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { private var shareButtonNode: HighlightableButtonNode? var telegramFile: TelegramMediaFile? - private let disposable = MetaDisposable() private let dateAndStatusNode: ChatMessageDateAndStatusNode private var replyInfoNode: ChatMessageReplyInfoNode? @@ -46,11 +45,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { self.addSubnode(self.animationNode) self.addSubnode(self.dateAndStatusNode) } - - deinit { - self.disposable.dispose() - } - + required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } diff --git a/submodules/TelegramUI/TelegramUI/ContactsController.swift b/submodules/TelegramUI/TelegramUI/ContactsController.swift index ac2a1167cb..062c973a78 100644 --- a/submodules/TelegramUI/TelegramUI/ContactsController.swift +++ b/submodules/TelegramUI/TelegramUI/ContactsController.swift @@ -309,13 +309,30 @@ public class ContactsController: ViewController { } self.contactsNode.openInvite = { [weak self] in - if let strongSelf = self { - (strongSelf.navigationController as? NavigationController)?.pushViewController(InviteContactsController(context: strongSelf.context), completion: { - if let strongSelf = self { + let _ = (DeviceAccess.authorizationStatus(subject: .contacts) + |> take(1) + |> deliverOnMainQueue).start(next: { value in + guard let strongSelf = self else { + return + } + switch value { + case .allowed: + (strongSelf.navigationController as? NavigationController)?.pushViewController(InviteContactsController(context: strongSelf.context), completion: { + if let strongSelf = self { + strongSelf.contactsNode.contactListNode.listNode.clearHighlightAnimated(true) + } + }) + case .notDetermined: + DeviceAccess.authorizeAccess(to: .contacts) strongSelf.contactsNode.contactListNode.listNode.clearHighlightAnimated(true) - } - }) - } + default: + let presentationData = strongSelf.presentationData + strongSelf.present(textAlertController(context: strongSelf.context, title: presentationData.strings.AccessDenied_Title, text: presentationData.strings.Contacts_AccessDeniedError, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_NotNow, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.AccessDenied_Settings, action: { + self?.context.sharedContext.applicationBindings.openSettings() + })]), in: .window(.root)) + strongSelf.contactsNode.contactListNode.listNode.clearHighlightAnimated(true) + } + }) } self.contactsNode.contactListNode.openSortMenu = { [weak self] in diff --git a/submodules/TelegramUI/TelegramUI/ContactsControllerNode.swift b/submodules/TelegramUI/TelegramUI/ContactsControllerNode.swift index d203fd4c09..2e992c6065 100644 --- a/submodules/TelegramUI/TelegramUI/ContactsControllerNode.swift +++ b/submodules/TelegramUI/TelegramUI/ContactsControllerNode.swift @@ -83,25 +83,9 @@ final class ContactsControllerNode: ASDisplayNode { } inviteImpl = { [weak self] in - let _ = (DeviceAccess.authorizationStatus(subject: .contacts) - |> take(1) - |> deliverOnMainQueue).start(next: { value in - guard let strongSelf = self else { - return - } - - switch value { - case .allowed: - strongSelf.openInvite?() - case .notDetermined: - DeviceAccess.authorizeAccess(to: .contacts) - default: - let presentationData = strongSelf.presentationData - present(textAlertController(context: strongSelf.context, title: presentationData.strings.AccessDenied_Title, text: presentationData.strings.Contacts_AccessDeniedError, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_NotNow, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.AccessDenied_Settings, action: { - self?.context.sharedContext.applicationBindings.openSettings() - })]), nil) - } - }) + if let strongSelf = self { + strongSelf.openInvite?() + } } } diff --git a/submodules/TelegramUI/TelegramUI/ContactsPeerItem.swift b/submodules/TelegramUI/TelegramUI/ContactsPeerItem.swift index 81c532b0a2..26b8d3f5ac 100644 --- a/submodules/TelegramUI/TelegramUI/ContactsPeerItem.swift +++ b/submodules/TelegramUI/TelegramUI/ContactsPeerItem.swift @@ -155,7 +155,7 @@ class ContactsPeerItem: ListViewItem { self.deletePeer = deletePeer self.header = header self.itemHighlighting = itemHighlighting - self.selectable = self.enabled + self.selectable = enabled if let index = index { var letter: String = "#" @@ -369,33 +369,14 @@ class ContactsPeerItemNode: ItemListRevealOptionsItemNode { } override func setHighlighted(_ highlighted: Bool, at point: CGPoint, animated: Bool) { + if let item = self.item, case .selectable = item.selection { + return + } + super.setHighlighted(highlighted, at: point, animated: animated) self.isHighlighted = highlighted - self.updateIsHighlighted(transition: (animated && !highlighted) ? .animated(duration: 0.3, curve: .easeInOut) : .immediate) - -// if highlighted && self.selectionNode == nil { -// self.highlightedBackgroundNode.alpha = 1.0 -// if self.highlightedBackgroundNode.supernode == nil { -// self.insertSubnode(self.highlightedBackgroundNode, aboveSubnode: self.separatorNode) -// } -// } else { -// if self.highlightedBackgroundNode.supernode != nil { -// if animated { -// self.highlightedBackgroundNode.layer.animateAlpha(from: self.highlightedBackgroundNode.alpha, to: 0.0, duration: 0.4, completion: { [weak self] completed in -// if let strongSelf = self { -// if completed { -// strongSelf.highlightedBackgroundNode.removeFromSupernode() -// } -// } -// }) -// self.highlightedBackgroundNode.alpha = 0.0 -// } else { -// self.highlightedBackgroundNode.removeFromSupernode() -// } -// } -// } } diff --git a/submodules/TelegramUI/TelegramUI/HorizontalStickerGridItem.swift b/submodules/TelegramUI/TelegramUI/HorizontalStickerGridItem.swift index e173272bca..4d7a290535 100755 --- a/submodules/TelegramUI/TelegramUI/HorizontalStickerGridItem.swift +++ b/submodules/TelegramUI/TelegramUI/HorizontalStickerGridItem.swift @@ -41,6 +41,7 @@ final class HorizontalStickerGridItem: GridItem { final class HorizontalStickerGridItemNode: GridItemNode { private var currentState: (Account, HorizontalStickerGridItem, CGSize)? private let imageNode: TransformImageNode + private var animationNode: AnimatedStickerNode? private let stickerFetchedDisposable = MetaDisposable() @@ -48,6 +49,18 @@ final class HorizontalStickerGridItemNode: GridItemNode { private var currentIsPreviewing: Bool = false + override var isVisibleInGrid: Bool { + didSet { + if oldValue != self.isVisibleInGrid { + if self.isVisibleInGrid { + self.animationNode?.visibility = true + } else { + self.animationNode?.visibility = false + } + } + } + } + var stickerItem: StickerPackItem? { if let (_, item, _) = self.currentState { return StickerPackItem(index: ItemCollectionItemIndex(index: 0, id: 0), file: item.file, indexKeys: []) @@ -66,7 +79,7 @@ final class HorizontalStickerGridItemNode: GridItemNode { } deinit { - stickerFetchedDisposable.dispose() + self.stickerFetchedDisposable.dispose() } override func didLoad() { @@ -78,8 +91,33 @@ final class HorizontalStickerGridItemNode: GridItemNode { func setup(account: Account, item: HorizontalStickerGridItem) { if self.currentState == nil || self.currentState!.0 !== account || self.currentState!.1.file.id != item.file.id { if let dimensions = item.file.dimensions { - self.imageNode.setSignal(chatMessageSticker(account: account, file: item.file, small: true)) - self.stickerFetchedDisposable.set(freeMediaFileResourceInteractiveFetched(account: account, fileReference: stickerPackFileReference(item.file), resource: chatMessageStickerResource(file: item.file, small: true)).start()) + if item.file.isAnimatedSticker { + self.stickerFetchedDisposable.set(nil) + + let animationNode: AnimatedStickerNode + if let currentAnimationNode = self.animationNode { + animationNode = currentAnimationNode + } else { + animationNode = AnimatedStickerNode() + animationNode.transform = self.imageNode.transform + animationNode.visibility = self.isVisibleInGrid + self.addSubnode(animationNode) + self.animationNode = animationNode + } + animationNode.started = { [weak self] in + self?.imageNode.alpha = 0.0 + } + animationNode.setup(account: account, fileReference: stickerPackFileReference(item.file), width: 140, height: 140) + } else { + self.imageNode.alpha = 1.0 + self.imageNode.setSignal(chatMessageSticker(account: account, file: item.file, small: true)) + self.stickerFetchedDisposable.set(freeMediaFileResourceInteractiveFetched(account: account, fileReference: stickerPackFileReference(item.file), resource: chatMessageStickerResource(file: item.file, small: true)).start()) + + if let currentAnimationNode = self.animationNode { + self.animationNode = nil + currentAnimationNode.removeFromSupernode() + } + } self.currentState = (account, item, dimensions) self.setNeedsLayout() @@ -101,6 +139,12 @@ final class HorizontalStickerGridItemNode: GridItemNode { let imageFrame = CGRect(origin: CGPoint(x: floor((bounds.size.width - imageSize.width) / 2.0), y: (bounds.size.height - imageSize.height) / 2.0), size: CGSize(width: imageSize.width, height: imageSize.height)) self.imageNode.bounds = CGRect(origin: CGPoint(), size: CGSize(width: imageSize.width, height: imageSize.height)) self.imageNode.position = CGPoint(x: imageFrame.midX, y: imageFrame.midY) + + if let animationNode = self.animationNode { + animationNode.bounds = self.imageNode.bounds + animationNode.position = self.imageNode.position + animationNode.updateLayout(size: self.imageNode.bounds.size) + } } } diff --git a/submodules/TelegramUI/TelegramUI/InviteContactsControllerNode.swift b/submodules/TelegramUI/TelegramUI/InviteContactsControllerNode.swift index fd9df9f1e4..37a86a97cd 100644 --- a/submodules/TelegramUI/TelegramUI/InviteContactsControllerNode.swift +++ b/submodules/TelegramUI/TelegramUI/InviteContactsControllerNode.swift @@ -204,7 +204,7 @@ struct InviteContactsGroupSelectionState: Equatable { } } -private func inviteContactsEntries(accountPeer: Peer?, sortedContacts: [(DeviceContactStableId, DeviceContactBasicData, Int32)], selectionState: InviteContactsGroupSelectionState, theme: PresentationTheme, strings: PresentationStrings, nameSortOrder: PresentationPersonNameOrder, nameDisplayOrder: PresentationPersonNameOrder, interaction: InviteContactsInteraction) -> [InviteContactsEntry] { +private func inviteContactsEntries(accountPeer: Peer?, sortedContacts: [(DeviceContactStableId, DeviceContactBasicData, Int32)]?, selectionState: InviteContactsGroupSelectionState, theme: PresentationTheme, strings: PresentationStrings, nameSortOrder: PresentationPersonNameOrder, nameDisplayOrder: PresentationPersonNameOrder, interaction: InviteContactsInteraction) -> [InviteContactsEntry] { var entries: [InviteContactsEntry] = [] entries.append(.option(0, ContactListAdditionalOption(title: strings.Contacts_ShareTelegram, icon: .generic(UIImage(bundleImageName: "Contact List/InviteActionIcon")!), action: { @@ -212,35 +212,39 @@ private func inviteContactsEntries(accountPeer: Peer?, sortedContacts: [(DeviceC }), theme, strings)) var index = 0 - for (id, contact, count) in sortedContacts { - entries.append(.peer(index, id, contact, count, .selectable(selected: selectionState.selectedContactIndices[id] != nil), theme, strings, nameSortOrder, nameDisplayOrder)) - index += 1 + if let sortedContacts = sortedContacts { + for (id, contact, count) in sortedContacts { + entries.append(.peer(index, id, contact, count, .selectable(selected: selectionState.selectedContactIndices[id] != nil), theme, strings, nameSortOrder, nameDisplayOrder)) + index += 1 + } } return entries } -private func preparedInviteContactsTransition(account: Account, from fromEntries: [InviteContactsEntry], to toEntries: [InviteContactsEntry], sortedContats: [(DeviceContactStableId, DeviceContactBasicData, Int32)], interaction: InviteContactsInteraction, firstTime: Bool, animated: Bool) -> InviteContactsTransition { +private func preparedInviteContactsTransition(account: Account, from fromEntries: [InviteContactsEntry], to toEntries: [InviteContactsEntry], sortedContacts: [(DeviceContactStableId, DeviceContactBasicData, Int32)]?, interaction: InviteContactsInteraction, firstTime: Bool, isLoading: Bool, animated: Bool) -> InviteContactsTransition { let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries) let deletions = deleteIndices.map { ListViewDeleteItem(index: $0, directionHint: nil) } let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, interaction: interaction), directionHint: nil) } let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, interaction: interaction), directionHint: nil) } - return InviteContactsTransition(deletions: deletions, insertions: insertions, updates: updates, sortedContats: sortedContats, firstTime: firstTime, animated: animated) + return InviteContactsTransition(deletions: deletions, insertions: insertions, updates: updates, sortedContacts: sortedContacts, firstTime: firstTime, isLoading: isLoading, animated: animated) } private struct InviteContactsTransition { let deletions: [ListViewDeleteItem] let insertions: [ListViewInsertItem] let updates: [ListViewUpdateItem] - let sortedContats: [(DeviceContactStableId, DeviceContactBasicData, Int32)] + let sortedContacts: [(DeviceContactStableId, DeviceContactBasicData, Int32)]? let firstTime: Bool + let isLoading: Bool let animated: Bool } final class InviteContactsControllerNode: ASDisplayNode { let listNode: ListView + private var activityIndicator: ActivityIndicator? private let context: AccountContext private var searchDisplayController: SearchDisplayController? @@ -365,8 +369,8 @@ final class InviteContactsControllerNode: ASDisplayNode { } let currentSortedContacts = self.currentSortedContacts - let sortedContacts: Signal<[(DeviceContactStableId, DeviceContactBasicData, Int32)], NoError> = combineLatest(existingNumbers, (context.sharedContext.contactDataManager?.basicData() ?? .single([:])) |> take(1)) - |> mapToSignal { existingNumbersAndPeerIds, contacts -> Signal<[(DeviceContactStableId, DeviceContactBasicData, Int32)], NoError> in + let sortedContacts: Signal<[(DeviceContactStableId, DeviceContactBasicData, Int32)]?, NoError> = combineLatest(existingNumbers, (context.sharedContext.contactDataManager?.basicData() ?? .single([:])) |> take(1)) + |> mapToSignal { existingNumbersAndPeerIds, contacts -> Signal<[(DeviceContactStableId, DeviceContactBasicData, Int32)]?, NoError> in var mappedContacts: [(String, [DeviceContactNormalizedPhoneNumber])] = [] for (id, basicData) in contacts { mappedContacts.append((id: id, basicData.phoneNumbers.map({ phoneNumber in @@ -374,7 +378,7 @@ final class InviteContactsControllerNode: ASDisplayNode { }))) } return deviceContactsImportedByCount(postbox: context.account.postbox, contacts: mappedContacts) - |> map { counts -> [(DeviceContactStableId, DeviceContactBasicData, Int32)] in + |> map { counts -> [(DeviceContactStableId, DeviceContactBasicData, Int32)]? in var result: [(DeviceContactStableId, DeviceContactBasicData, Int32)] = [] var contactValues: [DeviceContactStableId: DeviceContactBasicData] = [:] for (id, basicData) in contacts { @@ -410,10 +414,13 @@ final class InviteContactsControllerNode: ASDisplayNode { } } |> beforeNext { sortedContacts in - let _ = currentSortedContacts.swap(sortedContacts) + if let sortedContacts = sortedContacts { + let _ = currentSortedContacts.swap(sortedContacts) + } } + let processingQueue = Queue() - transition = (combineLatest(sortedContacts, selectionStateSignal, themeAndStringsPromise.get()) + transition = (combineLatest(.single(nil) |> then(sortedContacts), selectionStateSignal, themeAndStringsPromise.get()) |> mapToQueue { sortedContacts, selectionState, themeAndStrings -> Signal in let signal = deferred { () -> Signal in let entries = inviteContactsEntries(accountPeer: nil, sortedContacts: sortedContacts, selectionState: selectionState, theme: themeAndStrings.0, strings: themeAndStrings.1, nameSortOrder: themeAndStrings.2, nameDisplayOrder: themeAndStrings.3, interaction: interaction) @@ -424,16 +431,18 @@ final class InviteContactsControllerNode: ASDisplayNode { } else { animated = false } - return .single(preparedInviteContactsTransition(account: context.account, from: previous ?? [], to: entries, sortedContats: sortedContacts, interaction: interaction, firstTime: previous == nil, animated: animated)) + return .single(preparedInviteContactsTransition(account: context.account, from: previous ?? [], to: entries, sortedContacts: sortedContacts, interaction: interaction, firstTime: previous == nil, isLoading: false, animated: animated)) } + return signal + |> runOn(processingQueue) - if OSAtomicCompareAndSwap32(1, 0, &firstTime) { - return signal - |> runOn(Queue.mainQueue()) - } else { - return signal - |> runOn(processingQueue) - } +// if OSAtomicCompareAndSwap32(1, 0, &firstTime) { +// return signal +// |> runOn(Queue.mainQueue()) +// } else { +// return signal +// |> runOn(processingQueue) +// } }) |> deliverOnMainQueue @@ -441,6 +450,8 @@ final class InviteContactsControllerNode: ASDisplayNode { self?.enqueueTransition(transition) }) + self.enqueueTransition(InviteContactsTransition(deletions: [], insertions: [], updates: [], sortedContacts: [], firstTime: true, isLoading: true, animated: false)) + shareImpl = { [weak self] in if let strongSelf = self { var result: [(DeviceContactBasicData, Int32)] = [] @@ -524,6 +535,11 @@ final class InviteContactsControllerNode: ASDisplayNode { self.listNode.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous, .LowLatency], scrollToItem: nil, updateSizeAndInsets: updateSizeAndInsets, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in }) + if let activityIndicator = self.activityIndicator { + let indicatorSize = activityIndicator.measure(CGSize(width: 100.0, height: 100.0)) + transition.updateFrame(node: activityIndicator, frame: CGRect(origin: CGPoint(x: floor((layout.size.width - indicatorSize.width) / 2.0), y: updateSizeAndInsets.insets.top + 50.0 + floor((layout.size.height - updateSizeAndInsets.insets.top - updateSizeAndInsets.insets.bottom - indicatorSize.height - 50.0) / 2.0)), size: indicatorSize)) + } + if !hadValidLayout { self.dequeueTransitions() } @@ -587,6 +603,15 @@ final class InviteContactsControllerNode: ASDisplayNode { self.listNode.transaction(deleteIndices: transition.deletions, insertIndicesAndItems: transition.insertions, updateIndicesAndItems: transition.updates, options: options, updateOpaqueState: nil, completion: { [weak self] _ in if let strongSelf = self { strongSelf.readyValue = true + + if transition.isLoading, strongSelf.activityIndicator == nil { + let activityIndicator = ActivityIndicator(type: .custom(strongSelf.presentationData.theme.list.itemAccentColor, 22.0, 1.0, false)) + strongSelf.activityIndicator = activityIndicator + strongSelf.insertSubnode(activityIndicator, aboveSubnode: strongSelf.listNode) + } else if !transition.isLoading, let activityIndicator = strongSelf.activityIndicator { + strongSelf.activityIndicator = nil + activityIndicator.removeFromSupernode() + } } }) } @@ -605,4 +630,3 @@ final class InviteContactsControllerNode: ASDisplayNode { self.selectionState = self.selectionState.withReplacedSelectedContactIds(allSelected ? [] : ids) } } - diff --git a/submodules/TelegramUI/TelegramUI/MediaInputPaneTrendingItem.swift b/submodules/TelegramUI/TelegramUI/MediaInputPaneTrendingItem.swift index 6f6a552ae6..f483b97882 100644 --- a/submodules/TelegramUI/TelegramUI/MediaInputPaneTrendingItem.swift +++ b/submodules/TelegramUI/TelegramUI/MediaInputPaneTrendingItem.swift @@ -66,12 +66,63 @@ private let titleFont = Font.bold(16.0) private let statusFont = Font.regular(15.0) private let buttonFont = Font.medium(13.0) -private final class TrendingTopItemNode: TransformImageNode { - var file: TelegramMediaFile? = nil - let loadDisposable = MetaDisposable() +private final class TrendingTopItemNode: ASDisplayNode { + private let imageNode: TransformImageNode + private var animationNode: AnimatedStickerNode? + public private(set) var file: TelegramMediaFile? = nil + private var itemSize: CGSize? + private let loadDisposable = MetaDisposable() var currentIsPreviewing = false + var visibility: Bool = false { + didSet { + if oldValue != self.visibility { + self.animationNode?.visibility = self.visibility + } + } + } + + override init() { + self.imageNode = TransformImageNode() + self.imageNode.contentAnimations = [.subsequentUpdates] + super.init() + + self.addSubnode(self.imageNode) + } + + func setup(account: Account, item: StickerPackItem, itemSize: CGSize, synchronousLoads: Bool) { + self.file = item.file + self.itemSize = itemSize + + if item.file.isAnimatedSticker { + self.loadDisposable.set(nil) + + let animationNode: AnimatedStickerNode + if let currentAnimationNode = self.animationNode { + animationNode = currentAnimationNode + } else { + animationNode = AnimatedStickerNode() + animationNode.transform = self.imageNode.transform + animationNode.visibility = self.visibility + self.addSubnode(animationNode) + self.animationNode = animationNode + } + animationNode.started = { [weak self] in + self?.imageNode.alpha = 0.0 + } + animationNode.setup(account: account, fileReference: stickerPackFileReference(item.file), width: 140, height: 140) + } else { + self.imageNode.setSignal(chatMessageSticker(account: account, file: item.file, small: true, synchronousLoad: synchronousLoads), attemptSynchronously: synchronousLoads) + self.loadDisposable.set(freeMediaFileResourceInteractiveFetched(account: account, fileReference: stickerPackFileReference(item.file), resource: chatMessageStickerResource(file: item.file, small: true)).start()) + + if let currentAnimationNode = self.animationNode { + self.animationNode = nil + currentAnimationNode.removeFromSupernode() + } + } + } + func updatePreviewing(animated: Bool, isPreviewing: Bool) { if self.currentIsPreviewing != isPreviewing { self.currentIsPreviewing = isPreviewing @@ -88,6 +139,18 @@ private final class TrendingTopItemNode: TransformImageNode { } } } + + override func layout() { + super.layout() + + if let dimensions = self.file?.dimensions, let itemSize = self.itemSize { + let imageSize = dimensions.aspectFitted(itemSize) + self.imageNode.asyncLayout()(TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: imageSize, intrinsicInsets: UIEdgeInsets()))() + } + + self.imageNode.frame = self.bounds + self.animationNode?.updateLayout(size: self.bounds.size) + } } class MediaInputPaneTrendingItemNode: ListViewItemNode { @@ -109,6 +172,10 @@ class MediaInputPaneTrendingItemNode: ListViewItemNode { let isVisible = self.visibility != .none if isVisible != wasVisible { + for node in self.itemNodes { + node.visibility = isVisible + } + if isVisible { if let item = self.item, item.unread { self.readDisposable.set(( @@ -278,6 +345,8 @@ class MediaInputPaneTrendingItemNode: ListViewItemNode { var offset = sideInset let itemSpacing = (max(0, availableWidth - 5.0 * itemSide - sideInset * 2.0)) / 4.0 + let isVisible = strongSelf.visibility != .none + for i in 0 ..< topItems.count { let file = topItems[i].file let node: TrendingTopItemNode @@ -285,18 +354,15 @@ class MediaInputPaneTrendingItemNode: ListViewItemNode { node = strongSelf.itemNodes[i] } else { node = TrendingTopItemNode() - node.contentAnimations = [.subsequentUpdates] + node.visibility = isVisible strongSelf.itemNodes.append(node) strongSelf.addSubnode(node) } if file.fileId != node.file?.fileId { - node.file = file - node.setSignal(chatMessageSticker(account: item.account, file: file, small: true, synchronousLoad: synchronousLoads), attemptSynchronously: synchronousLoads) - node.loadDisposable.set(freeMediaFileResourceInteractiveFetched(account: item.account, fileReference: stickerPackFileReference(file), resource: chatMessageStickerResource(file: file, small: true)).start()) + node.setup(account: item.account, item: topItems[i], itemSize: itemSize, synchronousLoads: synchronousLoads) } if let dimensions = file.dimensions { let imageSize = dimensions.aspectFitted(itemSize) - node.asyncLayout()(TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: imageSize, intrinsicInsets: UIEdgeInsets()))() node.frame = CGRect(origin: CGPoint(x: offset, y: 48.0), size: imageSize) offset += itemSize.width + itemSpacing }