Load additional featured packs while scrolling

This commit is contained in:
Ali 2020-04-14 18:32:04 +04:00
parent b3266c8273
commit 4e8fb6561d
5 changed files with 140 additions and 39 deletions

View File

@ -623,8 +623,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[1251549527] = { return Api.InputStickeredMedia.parse_inputStickeredMediaPhoto($0) }
dict[70813275] = { return Api.InputStickeredMedia.parse_inputStickeredMediaDocument($0) }
dict[1421174295] = { return Api.WebPageAttribute.parse_webPageAttributeTheme($0) }
dict[82699215] = { return Api.messages.FeaturedStickers.parse_featuredStickersNotModified($0) }
dict[-123893531] = { return Api.messages.FeaturedStickers.parse_featuredStickers($0) }
dict[-958657434] = { return Api.messages.FeaturedStickers.parse_featuredStickersNotModified($0) }
dict[-1230257343] = { return Api.messages.FeaturedStickers.parse_featuredStickers($0) }
dict[-2048646399] = { return Api.PhoneCallDiscardReason.parse_phoneCallDiscardReasonMissed($0) }
dict[-527056480] = { return Api.PhoneCallDiscardReason.parse_phoneCallDiscardReasonDisconnect($0) }
dict[1471006352] = { return Api.PhoneCallDiscardReason.parse_phoneCallDiscardReasonHangup($0) }

View File

@ -1363,22 +1363,23 @@ public struct messages {
}
public enum FeaturedStickers: TypeConstructorDescription {
case featuredStickersNotModified
case featuredStickers(hash: Int32, sets: [Api.StickerSetCovered], unread: [Int64])
case featuredStickersNotModified(count: Int32)
case featuredStickers(hash: Int32, count: Int32, sets: [Api.StickerSetCovered], unread: [Int64])
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .featuredStickersNotModified:
case .featuredStickersNotModified(let count):
if boxed {
buffer.appendInt32(82699215)
buffer.appendInt32(-958657434)
}
serializeInt32(count, buffer: buffer, boxed: false)
break
case .featuredStickers(let hash, let sets, let unread):
case .featuredStickers(let hash, let count, let sets, let unread):
if boxed {
buffer.appendInt32(-123893531)
buffer.appendInt32(-1230257343)
}
serializeInt32(hash, buffer: buffer, boxed: false)
serializeInt32(count, buffer: buffer, boxed: false)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(sets.count))
for item in sets {
@ -1395,32 +1396,43 @@ public struct messages {
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .featuredStickersNotModified:
return ("featuredStickersNotModified", [])
case .featuredStickers(let hash, let sets, let unread):
return ("featuredStickers", [("hash", hash), ("sets", sets), ("unread", unread)])
case .featuredStickersNotModified(let count):
return ("featuredStickersNotModified", [("count", count)])
case .featuredStickers(let hash, let count, let sets, let unread):
return ("featuredStickers", [("hash", hash), ("count", count), ("sets", sets), ("unread", unread)])
}
}
public static func parse_featuredStickersNotModified(_ reader: BufferReader) -> FeaturedStickers? {
return Api.messages.FeaturedStickers.featuredStickersNotModified
var _1: Int32?
_1 = reader.readInt32()
let _c1 = _1 != nil
if _c1 {
return Api.messages.FeaturedStickers.featuredStickersNotModified(count: _1!)
}
else {
return nil
}
}
public static func parse_featuredStickers(_ reader: BufferReader) -> FeaturedStickers? {
var _1: Int32?
_1 = reader.readInt32()
var _2: [Api.StickerSetCovered]?
var _2: Int32?
_2 = reader.readInt32()
var _3: [Api.StickerSetCovered]?
if let _ = reader.readInt32() {
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StickerSetCovered.self)
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StickerSetCovered.self)
}
var _3: [Int64]?
var _4: [Int64]?
if let _ = reader.readInt32() {
_3 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self)
_4 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
if _c1 && _c2 && _c3 {
return Api.messages.FeaturedStickers.featuredStickers(hash: _1!, sets: _2!, unread: _3!)
let _c4 = _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.messages.FeaturedStickers.featuredStickers(hash: _1!, count: _2!, sets: _3!, unread: _4!)
}
else {
return nil

View File

@ -3276,6 +3276,22 @@ public extension Api {
return result
})
}
public static func getOldFeaturedStickers(offset: Int32, limit: Int32, hash: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.FeaturedStickers>) {
let buffer = Buffer()
buffer.appendInt32(1608974939)
serializeInt32(offset, buffer: buffer, boxed: false)
serializeInt32(limit, buffer: buffer, boxed: false)
serializeInt32(hash, buffer: buffer, boxed: false)
return (FunctionDescription(name: "messages.getOldFeaturedStickers", parameters: [("offset", offset), ("limit", limit), ("hash", hash)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.FeaturedStickers? in
let reader = BufferReader(buffer)
var result: Api.messages.FeaturedStickers?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.messages.FeaturedStickers
}
return result
})
}
}
public struct channels {
public static func readHistory(channel: Api.InputChannel, maxId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {

View File

@ -48,7 +48,7 @@ func updatedFeaturedStickerPacks(network: Network, postbox: Postbox) -> Signal<V
switch result {
case .featuredStickersNotModified:
break
case let .featuredStickers(_, sets, unread):
case let .featuredStickers(_, _, sets, unread):
let unreadIds = Set(unread)
var updatedPacks: [FeaturedStickerPackItem] = []
for set in sets {
@ -67,6 +67,25 @@ func updatedFeaturedStickerPacks(network: Network, postbox: Postbox) -> Signal<V
} |> switchToLatest
}
public func requestOldFeaturedStickerPacks(network: Network, postbox: Postbox, offset: Int, limit: Int) -> Signal<[FeaturedStickerPackItem], NoError> {
return network.request(Api.functions.messages.getOldFeaturedStickers(offset: Int32(offset), limit: Int32(limit), hash: 0))
|> retryRequest
|> map { result -> [FeaturedStickerPackItem] in
switch result {
case .featuredStickersNotModified:
return []
case let .featuredStickers(_, _, sets, unread):
let unreadIds = Set(unread)
var updatedPacks: [FeaturedStickerPackItem] = []
for set in sets {
let (info, items) = parsePreviewStickerSet(set)
updatedPacks.append(FeaturedStickerPackItem(info: info, topItems: items, unread: unreadIds.contains(info.id.id)))
}
return updatedPacks
}
}
}
public func preloadedFeaturedStickerSet(network: Network, postbox: Postbox, id: ItemCollectionId) -> Signal<Void, NoError> {
return postbox.transaction { transaction -> Signal<Void, NoError> in
if let pack = transaction.getOrderedItemListItem(collectionId: Namespaces.OrderedItemList.CloudFeaturedStickerPacks, itemId: FeaturedStickerPackItemId(id.id).rawValue)?.contents as? FeaturedStickerPackItem {

View File

@ -177,13 +177,24 @@ private func preparedTransition(from fromEntries: [FeaturedEntry], to toEntries:
return FeaturedTransition(deletions: deletions, insertions: insertions, updates: updates, initial: initial)
}
private func featuredScreenEntries(featuredEntries: [FeaturedStickerPackItem], installedPacks: Set<ItemCollectionId>, theme: PresentationTheme, strings: PresentationStrings, fixedUnread: Set<ItemCollectionId>) -> [FeaturedEntry] {
private func featuredScreenEntries(featuredEntries: [FeaturedStickerPackItem], installedPacks: Set<ItemCollectionId>, theme: PresentationTheme, strings: PresentationStrings, fixedUnread: Set<ItemCollectionId>, additionalPacks: [FeaturedStickerPackItem]) -> [FeaturedEntry] {
var result: [FeaturedEntry] = []
var index = 0
var existingIds = Set<ItemCollectionId>()
for item in featuredEntries {
if !existingIds.contains(item.info.id) {
existingIds.insert(item.info.id)
result.append(.pack(FeaturedPackEntry(index: index, info: item.info, theme: theme, strings: strings, topItems: item.topItems, installed: installedPacks.contains(item.info.id), unread: item.unread || fixedUnread.contains(item.info.id), topSeparator: index != 0)))
index += 1
}
}
for item in additionalPacks {
if !existingIds.contains(item.info.id) {
existingIds.insert(item.info.id)
result.append(.pack(FeaturedPackEntry(index: index, info: item.info, theme: theme, strings: strings, topItems: item.topItems, installed: installedPacks.contains(item.info.id), unread: item.unread || fixedUnread.contains(item.info.id), topSeparator: index != 0)))
index += 1
}
}
return result
}
@ -195,12 +206,18 @@ private final class FeaturedStickersScreenNode: ViewControllerTracingNode {
let gridNode: GridNode
private let additionalPacks = Promise<[FeaturedStickerPackItem]>([])
private var additionalPacksValue: [FeaturedStickerPackItem] = []
private var canLoadMore: Bool = true
private var isLoadingMore: Bool = false
private var enqueuedTransitions: [FeaturedTransition] = []
private var validLayout: ContainerViewLayout?
private var disposable: Disposable?
private let installDisposable = MetaDisposable()
private let loadMoreDisposable = MetaDisposable()
private var searchNode: FeaturedPaneSearchContentNode?
@ -251,6 +268,12 @@ private final class FeaturedStickersScreenNode: ViewControllerTracingNode {
if !addedRead.isEmpty {
let _ = markFeaturedStickerPacksAsSeenInteractively(postbox: strongSelf.context.account.postbox, ids: addedRead).start()
}
if bottomIndex >= strongSelf.gridNode.items.count - 15 {
if strongSelf.canLoadMore {
strongSelf.loadMore()
}
}
}
}
@ -405,8 +428,13 @@ private final class FeaturedStickersScreenNode: ViewControllerTracingNode {
return (items, fixedUnread)
}
self.disposable = (combineLatest(queue: .mainQueue(), mappedFeatured, context.account.postbox.combinedView(keys: [.itemCollectionInfos(namespaces: [Namespaces.ItemCollection.CloudStickerPacks])]), context.sharedContext.presentationData)
|> map { featuredEntries, view, presentationData -> FeaturedTransition in
self.disposable = (combineLatest(queue: .mainQueue(),
mappedFeatured,
self.additionalPacks.get(),
context.account.postbox.combinedView(keys: [.itemCollectionInfos(namespaces: [Namespaces.ItemCollection.CloudStickerPacks])]),
context.sharedContext.presentationData
)
|> map { featuredEntries, additionalPacks, view, presentationData -> FeaturedTransition in
var installedPacks = Set<ItemCollectionId>()
if let stickerPacksView = view.views[.itemCollectionInfos(namespaces: [Namespaces.ItemCollection.CloudStickerPacks])] as? ItemCollectionInfosView {
if let packsEntries = stickerPacksView.entriesByNamespace[Namespaces.ItemCollection.CloudStickerPacks] {
@ -415,7 +443,7 @@ private final class FeaturedStickersScreenNode: ViewControllerTracingNode {
}
}
}
let entries = featuredScreenEntries(featuredEntries: featuredEntries.0, installedPacks: installedPacks, theme: presentationData.theme, strings: presentationData.strings, fixedUnread: featuredEntries.1)
let entries = featuredScreenEntries(featuredEntries: featuredEntries.0, installedPacks: installedPacks, theme: presentationData.theme, strings: presentationData.strings, fixedUnread: featuredEntries.1, additionalPacks: additionalPacks)
let previous = previousEntries.swap(entries)
return preparedTransition(from: previous ?? [], to: entries, account: context.account, interaction: interaction, initial: previous == nil)
@ -446,6 +474,32 @@ private final class FeaturedStickersScreenNode: ViewControllerTracingNode {
deinit {
self.disposable?.dispose()
self.installDisposable.dispose()
self.loadMoreDisposable.dispose()
}
private func loadMore() {
if self.isLoadingMore || !self.canLoadMore {
return
}
self.isLoadingMore = true
self.loadMoreDisposable.set((requestOldFeaturedStickerPacks(network: self.context.account.network, postbox: self.context.account.postbox, offset: self.additionalPacksValue.count, limit: 50)
|> deliverOnMainQueue).start(next: { [weak self] result in
guard let strongSelf = self else {
return
}
var existingIds = Set(strongSelf.additionalPacksValue.map { $0.info.id })
var updatedItems = strongSelf.additionalPacksValue
for item in result {
if !existingIds.contains(item.info.id) {
existingIds.insert(item.info.id)
updatedItems.append(item)
}
}
strongSelf.additionalPacksValue = updatedItems
strongSelf.additionalPacks.set(.single(strongSelf.additionalPacksValue))
strongSelf.canLoadMore = result.count >= 50
strongSelf.isLoadingMore = false
}))
}
override func didLoad() {