mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-29 03:21:29 +00:00
Elevate trending stickers panel item when it contains unread items
This commit is contained in:
parent
a9e5a1c451
commit
2c2ecfe1fc
@ -665,7 +665,7 @@ public class ChatListController: TelegramController, KeyShortcutResponder, UIVie
|
||||
override public func viewDidAppear(_ animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
|
||||
#if DEBUG
|
||||
#if false && DEBUG
|
||||
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1.0, execute: { [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
|
||||
@ -150,9 +150,12 @@ private func preparedChatMediaInputGridEntryTransition(account: Account, view: I
|
||||
return ChatMediaInputGridTransition(deletions: deletions, insertions: insertions, updates: updates, updateFirstIndexInSectionOffset: firstIndexInSectionOffset, stationaryItems: stationaryItems, scrollToItem: scrollToItem, updateOpaqueState: opaqueState, animated: animated)
|
||||
}
|
||||
|
||||
private func chatMediaInputPanelEntries(view: ItemCollectionsView, savedStickers: OrderedItemListView?, recentStickers: OrderedItemListView?, peerSpecificPack: PeerSpecificPackData?, canInstallPeerSpecificPack: CanInstallPeerSpecificPack, theme: PresentationTheme) -> [ChatMediaInputPanelEntry] {
|
||||
private func chatMediaInputPanelEntries(view: ItemCollectionsView, savedStickers: OrderedItemListView?, recentStickers: OrderedItemListView?, peerSpecificPack: PeerSpecificPackData?, canInstallPeerSpecificPack: CanInstallPeerSpecificPack, hasUnreadTrending: Bool, theme: PresentationTheme) -> [ChatMediaInputPanelEntry] {
|
||||
var entries: [ChatMediaInputPanelEntry] = []
|
||||
entries.append(.recentGifs(theme))
|
||||
if hasUnreadTrending {
|
||||
entries.append(.trending(true, theme))
|
||||
}
|
||||
if let savedStickers = savedStickers, !savedStickers.items.isEmpty {
|
||||
entries.append(.savedStickers(theme))
|
||||
}
|
||||
@ -195,7 +198,9 @@ private func chatMediaInputPanelEntries(view: ItemCollectionsView, savedStickers
|
||||
entries.append(.peerSpecific(theme: theme, peer: peer))
|
||||
}
|
||||
|
||||
entries.append(.trending(false, theme))
|
||||
if !hasUnreadTrending {
|
||||
entries.append(.trending(false, theme))
|
||||
}
|
||||
entries.append(.settings(theme))
|
||||
return entries
|
||||
}
|
||||
@ -658,9 +663,20 @@ final class ChatMediaInputNode: ChatInputNode {
|
||||
peerSpecificPack = .single((nil, .none))
|
||||
}
|
||||
|
||||
let hasUnreadTrending = context.account.viewTracker.featuredStickerPacks()
|
||||
|> map { packs -> Bool in
|
||||
for pack in packs {
|
||||
if pack.unread {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|> distinctUntilChanged
|
||||
|
||||
let previousView = Atomic<ItemCollectionsView?>(value: nil)
|
||||
let transitions = combineLatest(itemCollectionsView, peerSpecificPack, self.themeAndStringsPromise.get())
|
||||
|> map { viewAndUpdate, peerSpecificPack, themeAndStrings -> (ItemCollectionsView, ChatMediaInputPanelTransition, Bool, ChatMediaInputGridTransition, Bool) in
|
||||
let transitions = combineLatest(itemCollectionsView, peerSpecificPack, hasUnreadTrending, self.themeAndStringsPromise.get())
|
||||
|> map { viewAndUpdate, peerSpecificPack, hasUnreadTrending, themeAndStrings -> (ItemCollectionsView, ChatMediaInputPanelTransition, Bool, ChatMediaInputGridTransition, Bool) in
|
||||
let (view, viewUpdate) = viewAndUpdate
|
||||
let previous = previousView.swap(view)
|
||||
var update = viewUpdate
|
||||
@ -678,7 +694,7 @@ final class ChatMediaInputNode: ChatInputNode {
|
||||
savedStickers = orderedView
|
||||
}
|
||||
}
|
||||
let panelEntries = chatMediaInputPanelEntries(view: view, savedStickers: savedStickers, recentStickers: recentStickers, peerSpecificPack: peerSpecificPack.0, canInstallPeerSpecificPack: peerSpecificPack.1, theme: theme)
|
||||
let panelEntries = chatMediaInputPanelEntries(view: view, savedStickers: savedStickers, recentStickers: recentStickers, peerSpecificPack: peerSpecificPack.0, canInstallPeerSpecificPack: peerSpecificPack.1, hasUnreadTrending: hasUnreadTrending, theme: theme)
|
||||
let gridEntries = chatMediaInputGridEntries(view: view, savedStickers: savedStickers, recentStickers: recentStickers, peerSpecificPack: peerSpecificPack.0, canInstallPeerSpecificPack: peerSpecificPack.1, strings: strings, theme: theme)
|
||||
let (previousPanelEntries, previousGridEntries) = previousEntries.swap((panelEntries, gridEntries))
|
||||
return (view, preparedChatMediaInputPanelEntryTransition(account: context.account, from: previousPanelEntries, to: panelEntries, inputNodeInteraction: inputNodeInteraction), previousPanelEntries.isEmpty, preparedChatMediaInputGridEntryTransition(account: context.account, view: view, from: previousGridEntries, to: gridEntries, update: update, interfaceInteraction: controllerInteraction, inputNodeInteraction: inputNodeInteraction), previousGridEntries.isEmpty)
|
||||
|
||||
@ -255,8 +255,8 @@ enum ChatMediaInputPanelEntry: Comparable, Identifiable {
|
||||
let collectionId = ItemCollectionId(namespace: ChatMediaInputPanelAuxiliaryNamespace.recentStickers.rawValue, id: 0)
|
||||
inputNodeInteraction.navigateToCollectionId(collectionId)
|
||||
})
|
||||
case let .trending(_, theme):
|
||||
return ChatMediaInputTrendingItem(inputNodeInteraction: inputNodeInteraction, theme: theme, selected: {
|
||||
case let .trending(elevated, theme):
|
||||
return ChatMediaInputTrendingItem(inputNodeInteraction: inputNodeInteraction, elevated: elevated, theme: theme, selected: {
|
||||
let collectionId = ItemCollectionId(namespace: ChatMediaInputPanelAuxiliaryNamespace.trending.rawValue, id: 0)
|
||||
inputNodeInteraction.navigateToCollectionId(collectionId)
|
||||
})
|
||||
|
||||
@ -8,14 +8,16 @@ import Postbox
|
||||
final class ChatMediaInputTrendingItem: ListViewItem {
|
||||
let inputNodeInteraction: ChatMediaInputNodeInteraction
|
||||
let selectedItem: () -> Void
|
||||
let elevated: Bool
|
||||
let theme: PresentationTheme
|
||||
|
||||
var selectable: Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
init(inputNodeInteraction: ChatMediaInputNodeInteraction, theme: PresentationTheme, selected: @escaping () -> Void) {
|
||||
init(inputNodeInteraction: ChatMediaInputNodeInteraction, elevated: Bool, theme: PresentationTheme, selected: @escaping () -> Void) {
|
||||
self.inputNodeInteraction = inputNodeInteraction
|
||||
self.elevated = elevated
|
||||
self.selectedItem = selected
|
||||
self.theme = theme
|
||||
}
|
||||
@ -26,7 +28,7 @@ final class ChatMediaInputTrendingItem: ListViewItem {
|
||||
node.contentSize = CGSize(width: 41.0, height: 41.0)
|
||||
node.insets = ChatMediaInputNode.setupPanelIconInsets(item: self, previousItem: previousItem, nextItem: nextItem)
|
||||
node.inputNodeInteraction = self.inputNodeInteraction
|
||||
node.updateTheme(theme: self.theme)
|
||||
node.updateTheme(elevated: self.elevated, theme: self.theme)
|
||||
node.updateIsHighlighted()
|
||||
node.updateAppearanceTransition(transition: .immediate)
|
||||
Queue.mainQueue().async {
|
||||
@ -40,7 +42,7 @@ final class ChatMediaInputTrendingItem: ListViewItem {
|
||||
public func updateNode(async: @escaping (@escaping () -> Void) -> Void, node: @escaping () -> ListViewItemNode, params: ListViewItemLayoutParams, previousItem: ListViewItem?, nextItem: ListViewItem?, animation: ListViewItemUpdateAnimation, completion: @escaping (ListViewItemNodeLayout, @escaping (ListViewItemApply) -> Void) -> Void) {
|
||||
Queue.mainQueue().async {
|
||||
completion(ListViewItemNodeLayout(contentSize: node().contentSize, insets: ChatMediaInputNode.setupPanelIconInsets(item: self, previousItem: previousItem, nextItem: nextItem)), { _ in
|
||||
(node() as? ChatMediaInputTrendingItemNode)?.updateTheme(theme: self.theme)
|
||||
(node() as? ChatMediaInputTrendingItemNode)?.updateTheme(elevated: self.elevated, theme: self.theme)
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -62,8 +64,11 @@ final class ChatMediaInputTrendingItemNode: ListViewItemNode {
|
||||
var currentCollectionId: ItemCollectionId?
|
||||
var inputNodeInteraction: ChatMediaInputNodeInteraction?
|
||||
|
||||
var elevated: Bool = false
|
||||
var theme: PresentationTheme?
|
||||
|
||||
let badgeBackground: ASImageNode
|
||||
|
||||
init() {
|
||||
self.highlightNode = ASImageNode()
|
||||
self.highlightNode.isLayerBacked = true
|
||||
@ -74,6 +79,11 @@ final class ChatMediaInputTrendingItemNode: ListViewItemNode {
|
||||
self.imageNode.contentMode = .center
|
||||
self.imageNode.contentsScale = UIScreenScale
|
||||
|
||||
self.badgeBackground = ASImageNode()
|
||||
self.badgeBackground.displaysAsynchronously = false
|
||||
self.badgeBackground.displayWithoutProcessing = true
|
||||
self.badgeBackground.isHidden = true
|
||||
|
||||
self.highlightNode.frame = CGRect(origin: CGPoint(x: floor((boundingSize.width - highlightSize.width) / 2.0) + verticalOffset, y: floor((boundingSize.height - highlightSize.height) / 2.0)), size: highlightSize)
|
||||
|
||||
self.imageNode.transform = CATransform3DMakeRotation(CGFloat.pi / 2.0, 0.0, 0.0, 1.0)
|
||||
@ -82,22 +92,34 @@ final class ChatMediaInputTrendingItemNode: ListViewItemNode {
|
||||
|
||||
self.addSubnode(self.highlightNode)
|
||||
self.addSubnode(self.imageNode)
|
||||
self.addSubnode(self.badgeBackground)
|
||||
|
||||
self.currentCollectionId = ItemCollectionId(namespace: ChatMediaInputPanelAuxiliaryNamespace.trending.rawValue, id: 0)
|
||||
|
||||
let imageSize = CGSize(width: 26.0, height: 26.0)
|
||||
self.imageNode.frame = CGRect(origin: CGPoint(x: floor((boundingSize.width - imageSize.width) / 2.0) + verticalOffset, y: floor((boundingSize.height - imageSize.height) / 2.0) + UIScreenPixel), size: imageSize)
|
||||
}
|
||||
|
||||
deinit {
|
||||
}
|
||||
|
||||
func updateTheme(theme: PresentationTheme) {
|
||||
func updateTheme(elevated: Bool, theme: PresentationTheme) {
|
||||
if self.theme !== theme {
|
||||
self.theme = theme
|
||||
|
||||
self.highlightNode.image = PresentationResourcesChat.chatMediaInputPanelHighlightedIconImage(theme)
|
||||
self.imageNode.image = PresentationResourcesChat.chatInputMediaPanelTrendingIconImage(theme)
|
||||
self.badgeBackground.image = generateFilledCircleImage(diameter: 16.0, color: theme.chat.inputPanel.mediaRecordingDotColor)
|
||||
|
||||
let imageSize = CGSize(width: 26.0, height: 26.0)
|
||||
let imageFrame = CGRect(origin: CGPoint(x: floor((boundingSize.width - imageSize.width) / 2.0) + verticalOffset, y: floor((boundingSize.height - imageSize.height) / 2.0) + UIScreenPixel), size: imageSize)
|
||||
self.imageNode.frame = imageFrame
|
||||
|
||||
if let image = self.badgeBackground.image {
|
||||
self.badgeBackground.frame = CGRect(origin: CGPoint(x: imageFrame.maxX - image.size.width + 2.0, y: imageFrame.maxY - image.size.width + 3.0), size: image.size)
|
||||
}
|
||||
}
|
||||
|
||||
if self.elevated != elevated {
|
||||
self.elevated = elevated
|
||||
self.badgeBackground.isHidden = !self.elevated
|
||||
}
|
||||
}
|
||||
|
||||
@ -112,5 +134,13 @@ final class ChatMediaInputTrendingItemNode: ListViewItemNode {
|
||||
transition.updateSublayerTransformScale(node: self, scale: inputNodeInteraction.appearanceTransition)
|
||||
}
|
||||
}
|
||||
|
||||
override func animateAdded(_ currentTimestamp: Double, duration: Double) {
|
||||
self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||
}
|
||||
|
||||
override func animateRemoved(_ currentTimestamp: Double, duration: Double) {
|
||||
self.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -59,6 +59,9 @@ private final class TrendingPaneEntry: Identifiable, Comparable {
|
||||
if lhs.installed != rhs.installed {
|
||||
return false
|
||||
}
|
||||
if lhs.unread != rhs.unread {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
@ -99,6 +99,24 @@ class MediaInputPaneTrendingItemNode: ListViewItemNode {
|
||||
|
||||
private var item: MediaInputPaneTrendingItem?
|
||||
private let preloadDisposable = MetaDisposable()
|
||||
private let readDisposable = MetaDisposable()
|
||||
|
||||
override var visibility: ListViewItemNodeVisibility {
|
||||
didSet {
|
||||
if self.visibility != oldValue {
|
||||
if self.visibility == .visible {
|
||||
if let item = self.item, item.unread {
|
||||
self.readDisposable.set((
|
||||
markFeaturedStickerPacksAsSeenInteractively(postbox: item.account.postbox, ids: [item.info.id])
|
||||
|> delay(1.0, queue: .mainQueue())
|
||||
).start())
|
||||
}
|
||||
} else {
|
||||
self.readDisposable.set(nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init() {
|
||||
self.titleNode = TextNode()
|
||||
@ -160,6 +178,7 @@ class MediaInputPaneTrendingItemNode: ListViewItemNode {
|
||||
|
||||
deinit {
|
||||
self.preloadDisposable.dispose()
|
||||
self.readDisposable.dispose()
|
||||
}
|
||||
|
||||
override func didLoad() {
|
||||
@ -236,7 +255,7 @@ class MediaInputPaneTrendingItemNode: ListViewItemNode {
|
||||
strongSelf.titleNode.frame = titleFrame
|
||||
strongSelf.descriptionNode.frame = CGRect(origin: CGPoint(x: params.leftInset + leftInset, y: 23.0), size: descriptionLayout.size)
|
||||
|
||||
if false && item.unread {
|
||||
if item.unread {
|
||||
strongSelf.unreadNode.isHidden = false
|
||||
} else {
|
||||
strongSelf.unreadNode.isHidden = true
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user