Display progress when adding sticker packs

This commit is contained in:
Ali 2019-12-27 20:57:06 +04:00
parent e653760a74
commit 0b5be7edad
3 changed files with 139 additions and 25 deletions

View File

@ -145,6 +145,8 @@ final class ChatMediaInputTrendingPane: ChatMediaInputPane {
var scrollingInitiated: (() -> Void)? var scrollingInitiated: (() -> Void)?
private let installDisposable = MetaDisposable()
init(context: AccountContext, controllerInteraction: ChatControllerInteraction, getItemIsPreviewed: @escaping (StickerPackItem) -> Bool) { init(context: AccountContext, controllerInteraction: ChatControllerInteraction, getItemIsPreviewed: @escaping (StickerPackItem) -> Bool) {
self.context = context self.context = context
self.controllerInteraction = controllerInteraction self.controllerInteraction = controllerInteraction
@ -163,6 +165,7 @@ final class ChatMediaInputTrendingPane: ChatMediaInputPane {
deinit { deinit {
self.disposable?.dispose() self.disposable?.dispose()
self.installDisposable.dispose()
} }
func activate() { func activate() {
@ -174,7 +177,7 @@ final class ChatMediaInputTrendingPane: ChatMediaInputPane {
let interaction = TrendingPaneInteraction(installPack: { [weak self] info in let interaction = TrendingPaneInteraction(installPack: { [weak self] info in
if let strongSelf = self, let info = info as? StickerPackCollectionInfo { if let strongSelf = self, let info = info as? StickerPackCollectionInfo {
let account = strongSelf.context.account let account = strongSelf.context.account
let _ = (loadedStickerPack(postbox: strongSelf.context.account.postbox, network: strongSelf.context.account.network, reference: .id(id: info.id.id, accessHash: info.accessHash), forceActualized: false) var installSignal = loadedStickerPack(postbox: strongSelf.context.account.postbox, network: strongSelf.context.account.network, reference: .id(id: info.id.id, accessHash: info.accessHash), forceActualized: false)
|> mapToSignal { result -> Signal<(StickerPackCollectionInfo, [ItemCollectionItem]), NoError> in |> mapToSignal { result -> Signal<(StickerPackCollectionInfo, [ItemCollectionItem]), NoError> in
switch result { switch result {
case let .result(info, items, installed): case let .result(info, items, installed):
@ -200,7 +203,37 @@ final class ChatMediaInputTrendingPane: ChatMediaInputPane {
} }
return .complete() return .complete()
} }
|> deliverOnMainQueue).start(next: { info, items in |> deliverOnMainQueue
let context = strongSelf.context
var cancelImpl: (() -> Void)?
let progressSignal = Signal<Never, NoError> { subscriber in
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let controller = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: {
cancelImpl?()
}))
self?.controllerInteraction.presentController(controller, nil)
return ActionDisposable { [weak controller] in
Queue.mainQueue().async() {
controller?.dismiss()
}
}
}
|> runOn(Queue.mainQueue())
|> delay(0.12, queue: Queue.mainQueue())
let progressDisposable = progressSignal.start()
installSignal = installSignal
|> afterDisposed {
Queue.mainQueue().async {
progressDisposable.dispose()
}
}
cancelImpl = {
self?.installDisposable.set(nil)
}
strongSelf.installDisposable.set(installSignal.start(next: { info, items in
guard let strongSelf = self else { guard let strongSelf = self else {
return return
} }
@ -219,7 +252,7 @@ final class ChatMediaInputTrendingPane: ChatMediaInputPane {
strongSelf.controllerInteraction.navigationController()?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_AddedTitle, text: presentationData.strings.StickerPackActionInfo_AddedText(info.title).0, undo: false, info: info, topItem: items.first, account: strongSelf.context.account), elevatedLayout: false, animateInAsReplacement: animateInAsReplacement, action: { _ in strongSelf.controllerInteraction.navigationController()?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_AddedTitle, text: presentationData.strings.StickerPackActionInfo_AddedText(info.title).0, undo: false, info: info, topItem: items.first, account: strongSelf.context.account), elevatedLayout: false, animateInAsReplacement: animateInAsReplacement, action: { _ in
return true return true
})) }))
}) }))
} }
}, openPack: { [weak self] info in }, openPack: { [weak self] info in
if let strongSelf = self, let info = info as? StickerPackCollectionInfo { if let strongSelf = self, let info = info as? StickerPackCollectionInfo {

View File

@ -7,20 +7,23 @@ import Postbox
import TelegramCore import TelegramCore
import SyncCore import SyncCore
import TelegramPresentationData import TelegramPresentationData
import PresentationDataUtils
import LegacyComponents import LegacyComponents
import MergeLists import MergeLists
import AccountContext import AccountContext
import StickerPackPreviewUI import StickerPackPreviewUI
import Emoji import Emoji
import AppBundle import AppBundle
import OverlayStatusController
import UndoUI
final class StickerPaneSearchInteraction { final class StickerPaneSearchInteraction {
let open: (StickerPackCollectionInfo) -> Void let open: (StickerPackCollectionInfo) -> Void
let install: (StickerPackCollectionInfo) -> Void let install: (StickerPackCollectionInfo, [ItemCollectionItem]) -> Void
let sendSticker: (FileMediaReference, ASDisplayNode, CGRect) -> Void let sendSticker: (FileMediaReference, ASDisplayNode, CGRect) -> Void
let getItemIsPreviewed: (StickerPackItem) -> Bool let getItemIsPreviewed: (StickerPackItem) -> Bool
init(open: @escaping (StickerPackCollectionInfo) -> Void, install: @escaping (StickerPackCollectionInfo) -> Void, sendSticker: @escaping (FileMediaReference, ASDisplayNode, CGRect) -> Void, getItemIsPreviewed: @escaping (StickerPackItem) -> Bool) { init(open: @escaping (StickerPackCollectionInfo) -> Void, install: @escaping (StickerPackCollectionInfo, [ItemCollectionItem]) -> Void, sendSticker: @escaping (FileMediaReference, ASDisplayNode, CGRect) -> Void, getItemIsPreviewed: @escaping (StickerPackItem) -> Bool) {
self.open = open self.open = open
self.install = install self.install = install
self.sendSticker = sendSticker self.sendSticker = sendSticker
@ -104,7 +107,7 @@ private enum StickerSearchEntry: Identifiable, Comparable {
return StickerPaneSearchGlobalItem(account: account, theme: theme, strings: strings, info: info, topItems: topItems, grid: false, topSeparator: topSeparator, installed: installed, unread: false, open: { return StickerPaneSearchGlobalItem(account: account, theme: theme, strings: strings, info: info, topItems: topItems, grid: false, topSeparator: topSeparator, installed: installed, unread: false, open: {
interaction.open(info) interaction.open(info)
}, install: { }, install: {
interaction.install(info) interaction.install(info, topItems)
}, getItemIsPreviewed: { item in }, getItemIsPreviewed: { item in
return interaction.getItemIsPreviewed(item) return interaction.getItemIsPreviewed(item)
}) })
@ -171,6 +174,8 @@ final class StickerPaneSearchContentNode: ASDisplayNode, PaneSearchContentNode {
var deactivateSearchBar: (() -> Void)? var deactivateSearchBar: (() -> Void)?
var updateActivity: ((Bool) -> Void)? var updateActivity: ((Bool) -> Void)?
private let installDisposable = MetaDisposable()
init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, controllerInteraction: ChatControllerInteraction, inputNodeInteraction: ChatMediaInputNodeInteraction) { init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, controllerInteraction: ChatControllerInteraction, inputNodeInteraction: ChatMediaInputNodeInteraction) {
self.context = context self.context = context
self.controllerInteraction = controllerInteraction self.controllerInteraction = controllerInteraction
@ -227,25 +232,87 @@ final class StickerPaneSearchContentNode: ASDisplayNode, PaneSearchContentNode {
}) })
strongSelf.controllerInteraction.presentController(controller, nil) strongSelf.controllerInteraction.presentController(controller, nil)
} }
}, install: { [weak self] info in }, install: { [weak self] info, items in
if let strongSelf = self { guard let strongSelf = self else {
let _ = (loadedStickerPack(postbox: strongSelf.context.account.postbox, network: strongSelf.context.account.network, reference: .id(id: info.id.id, accessHash: info.accessHash), forceActualized: false) return
|> mapToSignal { result -> Signal<Void, NoError> in
switch result {
case let .result(info, items, installed):
if installed {
return .complete()
} else {
return addStickerPackInteractively(postbox: strongSelf.context.account.postbox, info: info, items: items)
}
case .fetching:
break
case .none:
break
}
return .complete()
}).start()
} }
let account = strongSelf.context.account
var installSignal = loadedStickerPack(postbox: strongSelf.context.account.postbox, network: strongSelf.context.account.network, reference: .id(id: info.id.id, accessHash: info.accessHash), forceActualized: false)
|> mapToSignal { result -> Signal<(StickerPackCollectionInfo, [ItemCollectionItem]), NoError> in
switch result {
case let .result(info, items, installed):
if installed {
return .complete()
} else {
return preloadedStickerPackThumbnail(account: account, info: info, items: items)
|> filter { $0 }
|> ignoreValues
|> then(
addStickerPackInteractively(postbox: strongSelf.context.account.postbox, info: info, items: items)
|> ignoreValues
)
|> mapToSignal { _ -> Signal<(StickerPackCollectionInfo, [ItemCollectionItem]), NoError> in
return .complete()
}
|> then(.single((info, items)))
}
case .fetching:
break
case .none:
break
}
return .complete()
}
|> deliverOnMainQueue
let context = strongSelf.context
var cancelImpl: (() -> Void)?
let progressSignal = Signal<Never, NoError> { subscriber in
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let controller = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: {
cancelImpl?()
}))
self?.controllerInteraction.presentController(controller, nil)
return ActionDisposable { [weak controller] in
Queue.mainQueue().async() {
controller?.dismiss()
}
}
}
|> runOn(Queue.mainQueue())
|> delay(0.12, queue: Queue.mainQueue())
let progressDisposable = progressSignal.start()
installSignal = installSignal
|> afterDisposed {
Queue.mainQueue().async {
progressDisposable.dispose()
}
}
cancelImpl = {
self?.installDisposable.set(nil)
}
strongSelf.installDisposable.set(installSignal.start(next: { info, items in
guard let strongSelf = self else {
return
}
var animateInAsReplacement = false
if let navigationController = strongSelf.controllerInteraction.navigationController() {
for controller in navigationController.overlayControllers {
if let controller = controller as? UndoOverlayController {
controller.dismissWithCommitActionAndReplacementAnimation()
animateInAsReplacement = true
}
}
}
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
strongSelf.controllerInteraction.navigationController()?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_AddedTitle, text: presentationData.strings.StickerPackActionInfo_AddedText(info.title).0, undo: false, info: info, topItem: items.first, account: strongSelf.context.account), elevatedLayout: false, animateInAsReplacement: animateInAsReplacement, action: { _ in
return true
}))
}))
}, sendSticker: { [weak self] file, sourceNode, sourceRect in }, sendSticker: { [weak self] file, sourceNode, sourceRect in
if let strongSelf = self { if let strongSelf = self {
let _ = strongSelf.controllerInteraction.sendSticker(file, false, sourceNode, sourceRect) let _ = strongSelf.controllerInteraction.sendSticker(file, false, sourceNode, sourceRect)
@ -262,6 +329,7 @@ final class StickerPaneSearchContentNode: ASDisplayNode, PaneSearchContentNode {
deinit { deinit {
self.searchDisposable.dispose() self.searchDisposable.dispose()
self.installDisposable.dispose()
} }
func updateText(_ text: String, languageCode: String?) { func updateText(_ text: String, languageCode: String?) {

View File

@ -7,6 +7,7 @@ import SyncCore
import SwiftSignalKit import SwiftSignalKit
import Postbox import Postbox
import TelegramPresentationData import TelegramPresentationData
import StickerPackPreviewUI
final class StickerPaneSearchGlobalSection: GridSection { final class StickerPaneSearchGlobalSection: GridSection {
let height: CGFloat = 0.0 let height: CGFloat = 0.0
@ -41,6 +42,7 @@ final class StickerPaneSearchGlobalItem: GridItem {
let grid: Bool let grid: Bool
let topSeparator: Bool let topSeparator: Bool
let installed: Bool let installed: Bool
let installing: Bool
let unread: Bool let unread: Bool
let open: () -> Void let open: () -> Void
let install: () -> Void let install: () -> Void
@ -51,7 +53,7 @@ final class StickerPaneSearchGlobalItem: GridItem {
return self.grid ? nil : (128.0 + (self.topSeparator ? 12.0 : 0.0)) return self.grid ? nil : (128.0 + (self.topSeparator ? 12.0 : 0.0))
} }
init(account: Account, theme: PresentationTheme, strings: PresentationStrings, info: StickerPackCollectionInfo, topItems: [StickerPackItem], grid: Bool, topSeparator: Bool, installed: Bool, unread: Bool, open: @escaping () -> Void, install: @escaping () -> Void, getItemIsPreviewed: @escaping (StickerPackItem) -> Bool) { init(account: Account, theme: PresentationTheme, strings: PresentationStrings, info: StickerPackCollectionInfo, topItems: [StickerPackItem], grid: Bool, topSeparator: Bool, installed: Bool, installing: Bool = false, unread: Bool, open: @escaping () -> Void, install: @escaping () -> Void, getItemIsPreviewed: @escaping (StickerPackItem) -> Bool) {
self.account = account self.account = account
self.theme = theme self.theme = theme
self.strings = strings self.strings = strings
@ -60,6 +62,7 @@ final class StickerPaneSearchGlobalItem: GridItem {
self.grid = grid self.grid = grid
self.topSeparator = topSeparator self.topSeparator = topSeparator
self.installed = installed self.installed = installed
self.installing = installing
self.unread = unread self.unread = unread
self.open = open self.open = open
self.install = install self.install = install
@ -98,6 +101,9 @@ class StickerPaneSearchGlobalItemNode: GridItemNode {
private var item: StickerPaneSearchGlobalItem? private var item: StickerPaneSearchGlobalItem?
private var appliedItem: StickerPaneSearchGlobalItem? private var appliedItem: StickerPaneSearchGlobalItem?
private let preloadDisposable = MetaDisposable() private let preloadDisposable = MetaDisposable()
private let preloadedStickerPackThumbnailDisposable = MetaDisposable()
private var preloadedThumbnail = false
override var isVisibleInGrid: Bool { override var isVisibleInGrid: Bool {
didSet { didSet {
@ -105,6 +111,12 @@ class StickerPaneSearchGlobalItemNode: GridItemNode {
for node in self.itemNodes { for node in self.itemNodes {
node.visibility = self.isVisibleInGrid node.visibility = self.isVisibleInGrid
} }
if let item = self.item, self.isVisibleInGrid, !self.preloadedThumbnail {
self.preloadedThumbnail = true
self.preloadedStickerPackThumbnailDisposable.set(preloadedStickerPackThumbnail(account: item.account, info: item.info, items: item.topItems).start())
}
} }
} }
} }
@ -173,6 +185,7 @@ class StickerPaneSearchGlobalItemNode: GridItemNode {
deinit { deinit {
self.preloadDisposable.dispose() self.preloadDisposable.dispose()
self.preloadedStickerPackThumbnailDisposable.dispose()
} }
override func didLoad() { override func didLoad() {