Update Trending stickers panel

This commit is contained in:
Ali 2020-01-03 16:10:57 +04:00
parent 610ed62517
commit 722ce97e9a
9 changed files with 125 additions and 48 deletions

View File

@ -2,17 +2,7 @@
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "StickerKeyboardTrendingIcon@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "StickerKeyboardTrendingIcon@3x.png",
"scale" : "3x"
"filename" : "ic_addstickers.pdf"
}
],
"info" : {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -88,7 +88,7 @@ enum ChatMediaInputGridEntry: Equatable, Comparable, Identifiable {
case search(theme: PresentationTheme, strings: PresentationStrings)
case peerSpecificSetup(theme: PresentationTheme, strings: PresentationStrings, dismissed: Bool)
case sticker(index: ItemCollectionViewEntryIndex, stickerItem: StickerPackItem, stickerPackInfo: StickerPackCollectionInfo?, canManagePeerSpecificPack: Bool?, theme: PresentationTheme)
case trending(TrendingPaneEntry)
case trending(TrendingPanePackEntry)
var index: ChatMediaInputGridEntryIndex {
switch self {

View File

@ -496,7 +496,7 @@ final class ChatMediaInputNode: ChatInputNode {
var getItemIsPreviewedImpl: ((StickerPackItem) -> Bool)?
self.trendingPane = ChatMediaInputTrendingPane(context: context, controllerInteraction: controllerInteraction, getItemIsPreviewed: { item in
return getItemIsPreviewedImpl?(item) ?? false
})
}, isPane: true)
self.paneArrangement = ChatMediaInputPaneArrangement(panes: [.gifs, .stickers, .trending], currentIndex: 1, indexTransition: 0.0)
@ -754,6 +754,7 @@ final class ChatMediaInputNode: ChatInputNode {
strongSelf.controllerInteraction.presentController(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
}, getItemIsPreviewed: { item in
return getItemIsPreviewedImpl?(item) ?? false
}, openSearch: {
})
let previousView = Atomic<ItemCollectionsView?>(value: nil)
@ -803,7 +804,7 @@ final class ChatMediaInputNode: ChatInputNode {
var index = 0
for item in trendingPacks {
if !installedPacks.contains(item.info.id) {
gridEntries.append(.trending(TrendingPaneEntry(index: index, info: item.info, theme: theme, strings: strings, topItems: item.topItems, installed: installedPacks.contains(item.info.id), unread: item.unread, topSeparator: true)))
gridEntries.append(.trending(TrendingPanePackEntry(index: index, info: item.info, theme: theme, strings: strings, topItems: item.topItems, installed: installedPacks.contains(item.info.id), unread: item.unread, topSeparator: true)))
index += 1
}
}
@ -877,6 +878,7 @@ final class ChatMediaInputNode: ChatInputNode {
self.stickerPane.inputNodeInteraction = self.inputNodeInteraction
self.gifPane.inputNodeInteraction = self.inputNodeInteraction
self.trendingPane.inputNodeInteraction = self.inputNodeInteraction
paneDidScrollImpl = { [weak self] pane, state, transition in
self?.updatePaneDidScroll(pane: pane, state: state, transition: transition)
@ -1387,14 +1389,20 @@ final class ChatMediaInputNode: ChatInputNode {
var placeholderNode: PaneSearchBarPlaceholderNode?
if let searchMode = searchMode {
switch searchMode {
case .gif:
placeholderNode = self.gifPane.searchPlaceholderNode
case .sticker:
self.stickerPane.gridNode.forEachItemNode { itemNode in
if let itemNode = itemNode as? PaneSearchBarPlaceholderNode {
placeholderNode = itemNode
}
case .gif:
placeholderNode = self.gifPane.searchPlaceholderNode
case .sticker:
self.stickerPane.gridNode.forEachItemNode { itemNode in
if let itemNode = itemNode as? PaneSearchBarPlaceholderNode {
placeholderNode = itemNode
}
}
case .trending:
self.trendingPane.gridNode.forEachItemNode { itemNode in
if let itemNode = itemNode as? PaneSearchBarPlaceholderNode {
placeholderNode = itemNode
}
}
}
}
@ -1558,15 +1566,22 @@ final class ChatMediaInputNode: ChatInputNode {
var placeholderNode: PaneSearchBarPlaceholderNode?
if let searchMode = searchMode {
switch searchMode {
case .gif:
placeholderNode = self.gifPane.searchPlaceholderNode
paneIsEmpty = self.gifPane.isEmpty
case .sticker:
self.stickerPane.gridNode.forEachItemNode { itemNode in
if let itemNode = itemNode as? PaneSearchBarPlaceholderNode {
placeholderNode = itemNode
}
case .gif:
placeholderNode = self.gifPane.searchPlaceholderNode
paneIsEmpty = self.gifPane.isEmpty
case .sticker:
self.stickerPane.gridNode.forEachItemNode { itemNode in
if let itemNode = itemNode as? PaneSearchBarPlaceholderNode {
placeholderNode = itemNode
}
}
case .trending:
self.trendingPane.gridNode.forEachItemNode { itemNode in
if let itemNode = itemNode as? PaneSearchBarPlaceholderNode {
placeholderNode = itemNode
}
}
paneIsEmpty = true
}
}
if let placeholderNode = placeholderNode {

View File

@ -18,15 +18,17 @@ final class TrendingPaneInteraction {
let installPack: (ItemCollectionInfo) -> Void
let openPack: (ItemCollectionInfo) -> Void
let getItemIsPreviewed: (StickerPackItem) -> Bool
let openSearch: () -> Void
init(installPack: @escaping (ItemCollectionInfo) -> Void, openPack: @escaping (ItemCollectionInfo) -> Void, getItemIsPreviewed: @escaping (StickerPackItem) -> Bool) {
init(installPack: @escaping (ItemCollectionInfo) -> Void, openPack: @escaping (ItemCollectionInfo) -> Void, getItemIsPreviewed: @escaping (StickerPackItem) -> Bool, openSearch: @escaping () -> Void) {
self.installPack = installPack
self.openPack = openPack
self.getItemIsPreviewed = getItemIsPreviewed
self.openSearch = openSearch
}
}
final class TrendingPaneEntry: Identifiable, Comparable {
final class TrendingPanePackEntry: Identifiable, Comparable {
let index: Int
let info: StickerPackCollectionInfo
let theme: PresentationTheme
@ -51,7 +53,7 @@ final class TrendingPaneEntry: Identifiable, Comparable {
return self.info.id
}
static func ==(lhs: TrendingPaneEntry, rhs: TrendingPaneEntry) -> Bool {
static func ==(lhs: TrendingPanePackEntry, rhs: TrendingPanePackEntry) -> Bool {
if lhs.index != rhs.index {
return false
}
@ -79,7 +81,7 @@ final class TrendingPaneEntry: Identifiable, Comparable {
return true
}
static func <(lhs: TrendingPaneEntry, rhs: TrendingPaneEntry) -> Bool {
static func <(lhs: TrendingPanePackEntry, rhs: TrendingPanePackEntry) -> Bool {
return lhs.index < rhs.index
}
@ -95,6 +97,67 @@ final class TrendingPaneEntry: Identifiable, Comparable {
}
}
private enum TrendingPaneEntryId: Hashable {
case search
case pack(ItemCollectionId)
}
private enum TrendingPaneEntry: Identifiable, Comparable {
case search(theme: PresentationTheme, strings: PresentationStrings)
case pack(TrendingPanePackEntry)
var stableId: TrendingPaneEntryId {
switch self {
case .search:
return .search
case let .pack(pack):
return .pack(pack.stableId)
}
}
static func ==(lhs: TrendingPaneEntry, rhs: TrendingPaneEntry) -> Bool {
switch lhs {
case let .search(lhsTheme, lhsStrings):
if case let .search(rhsTheme, rhsStrings) = rhs, lhsTheme === rhsTheme, lhsStrings === rhsStrings {
return true
} else {
return false
}
case let .pack(pack):
if case .pack(pack) = rhs {
return true
} else {
return false
}
}
}
static func <(lhs: TrendingPaneEntry, rhs: TrendingPaneEntry) -> Bool {
switch lhs {
case .search:
return false
case let .pack(lhsPack):
switch rhs {
case .search:
return false
case let .pack(rhsPack):
return lhsPack < rhsPack
}
}
}
func item(account: Account, interaction: TrendingPaneInteraction, grid: Bool) -> GridItem {
switch self {
case let .search(theme, strings):
return PaneSearchBarPlaceholderItem(theme: theme, strings: strings, type: .stickers, activate: {
interaction.openSearch()
})
case let .pack(pack):
return pack.item(account: account, interaction: interaction, grid: grid)
}
}
}
private struct TrendingPaneTransition {
let deletions: [Int]
let insertions: [GridNodeInsertItem]
@ -112,12 +175,15 @@ private func preparedTransition(from fromEntries: [TrendingPaneEntry], to toEntr
return TrendingPaneTransition(deletions: deletions, insertions: insertions, updates: updates, initial: initial)
}
func trendingPaneEntries(trendingEntries: [FeaturedStickerPackItem], installedPacks: Set<ItemCollectionId>, theme: PresentationTheme, strings: PresentationStrings) -> [TrendingPaneEntry] {
private func trendingPaneEntries(trendingEntries: [FeaturedStickerPackItem], installedPacks: Set<ItemCollectionId>, theme: PresentationTheme, strings: PresentationStrings, isPane: Bool) -> [TrendingPaneEntry] {
var result: [TrendingPaneEntry] = []
var index = 0
if isPane {
result.append(.search(theme: theme, strings: strings))
}
for item in trendingEntries {
if !installedPacks.contains(item.info.id) {
result.append(TrendingPaneEntry(index: index, info: item.info, theme: theme, strings: strings, topItems: item.topItems, installed: installedPacks.contains(item.info.id), unread: item.unread, topSeparator: index != 0))
result.append(.pack(TrendingPanePackEntry(index: index, info: item.info, theme: theme, strings: strings, topItems: item.topItems, installed: installedPacks.contains(item.info.id), unread: item.unread, topSeparator: index != 0)))
index += 1
}
}
@ -128,6 +194,7 @@ final class ChatMediaInputTrendingPane: ChatMediaInputPane {
private let context: AccountContext
private let controllerInteraction: ChatControllerInteraction
private let getItemIsPreviewed: (StickerPackItem) -> Bool
private let isPane: Bool
let gridNode: GridNode
@ -147,10 +214,11 @@ final class ChatMediaInputTrendingPane: ChatMediaInputPane {
private let installDisposable = MetaDisposable()
init(context: AccountContext, controllerInteraction: ChatControllerInteraction, getItemIsPreviewed: @escaping (StickerPackItem) -> Bool) {
init(context: AccountContext, controllerInteraction: ChatControllerInteraction, getItemIsPreviewed: @escaping (StickerPackItem) -> Bool, isPane: Bool) {
self.context = context
self.controllerInteraction = controllerInteraction
self.getItemIsPreviewed = getItemIsPreviewed
self.isPane = isPane
self.gridNode = GridNode()
@ -220,7 +288,7 @@ final class ChatMediaInputTrendingPane: ChatMediaInputPane {
}
}
|> runOn(Queue.mainQueue())
|> delay(0.12, queue: Queue.mainQueue())
|> delay(1.0, queue: Queue.mainQueue())
let progressDisposable = progressSignal.start()
installSignal = installSignal
@ -267,8 +335,12 @@ final class ChatMediaInputTrendingPane: ChatMediaInputPane {
})
strongSelf.controllerInteraction.presentController(controller, nil)
}
}, getItemIsPreviewed: self.getItemIsPreviewed)
}, getItemIsPreviewed: self.getItemIsPreviewed,
openSearch: { [weak self] in
self?.inputNodeInteraction?.toggleSearch(true, .trending)
})
let isPane = self.isPane
let previousEntries = Atomic<[TrendingPaneEntry]?>(value: nil)
let context = self.context
self.disposable = (combineLatest(context.account.viewTracker.featuredStickerPacks(), context.account.postbox.combinedView(keys: [.itemCollectionInfos(namespaces: [Namespaces.ItemCollection.CloudStickerPacks])]), context.sharedContext.presentationData)
@ -281,7 +353,7 @@ final class ChatMediaInputTrendingPane: ChatMediaInputPane {
}
}
}
let entries = trendingPaneEntries(trendingEntries: trendingEntries, installedPacks: installedPacks, theme: presentationData.theme, strings: presentationData.strings)
let entries = trendingPaneEntries(trendingEntries: trendingEntries, installedPacks: installedPacks, theme: presentationData.theme, strings: presentationData.strings, isPane: isPane)
let previous = previousEntries.swap(entries)
return preparedTransition(from: previous ?? [], to: entries, account: context.account, interaction: interaction, initial: previous == nil)

View File

@ -49,10 +49,10 @@ final class PaneSearchContainerNode: ASDisplayNode {
self.controllerInteraction = controllerInteraction
self.inputNodeInteraction = inputNodeInteraction
switch mode {
case .gif:
self.contentNode = GifPaneSearchContentNode(context: context, theme: theme, strings: strings, controllerInteraction: controllerInteraction, inputNodeInteraction: inputNodeInteraction, trendingPromise: trendingGifsPromise)
case .sticker:
self.contentNode = StickerPaneSearchContentNode(context: context, theme: theme, strings: strings, controllerInteraction: controllerInteraction, inputNodeInteraction: inputNodeInteraction)
case .gif:
self.contentNode = GifPaneSearchContentNode(context: context, theme: theme, strings: strings, controllerInteraction: controllerInteraction, inputNodeInteraction: inputNodeInteraction, trendingPromise: trendingGifsPromise)
case .sticker, .trending:
self.contentNode = StickerPaneSearchContentNode(context: context, theme: theme, strings: strings, controllerInteraction: controllerInteraction, inputNodeInteraction: inputNodeInteraction)
}
self.backgroundNode = ASDisplayNode()
@ -92,10 +92,10 @@ final class PaneSearchContainerNode: ASDisplayNode {
let placeholder: String
switch mode {
case .gif:
placeholder = strings.Gif_Search
case .sticker:
placeholder = strings.Stickers_Search
case .gif:
placeholder = strings.Gif_Search
case .sticker, .trending:
placeholder = strings.Stickers_Search
}
self.searchBar.placeholderString = NSAttributedString(string: placeholder, font: Font.regular(17.0), textColor: theme.chat.inputMediaPanel.stickersSearchPlaceholderColor)
}

View File

@ -186,7 +186,7 @@ final class StickerPaneSearchContentNode: ASDisplayNode, PaneSearchContentNode {
self.trendingPane = ChatMediaInputTrendingPane(context: context, controllerInteraction: controllerInteraction, getItemIsPreviewed: { [weak inputNodeInteraction] item in
return inputNodeInteraction?.previewedStickerPackItem == .pack(item)
})
}, isPane: false)
self.gridNode = GridNode()