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)?
private let installDisposable = MetaDisposable()
init(context: AccountContext, controllerInteraction: ChatControllerInteraction, getItemIsPreviewed: @escaping (StickerPackItem) -> Bool) {
self.context = context
self.controllerInteraction = controllerInteraction
@ -163,6 +165,7 @@ final class ChatMediaInputTrendingPane: ChatMediaInputPane {
deinit {
self.disposable?.dispose()
self.installDisposable.dispose()
}
func activate() {
@ -174,7 +177,7 @@ final class ChatMediaInputTrendingPane: ChatMediaInputPane {
let interaction = TrendingPaneInteraction(installPack: { [weak self] info in
if let strongSelf = self, let info = info as? StickerPackCollectionInfo {
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
switch result {
case let .result(info, items, installed):
@ -200,7 +203,37 @@ final class ChatMediaInputTrendingPane: ChatMediaInputPane {
}
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 {
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
return true
}))
})
}))
}
}, openPack: { [weak self] info in
if let strongSelf = self, let info = info as? StickerPackCollectionInfo {

View File

@ -7,20 +7,23 @@ import Postbox
import TelegramCore
import SyncCore
import TelegramPresentationData
import PresentationDataUtils
import LegacyComponents
import MergeLists
import AccountContext
import StickerPackPreviewUI
import Emoji
import AppBundle
import OverlayStatusController
import UndoUI
final class StickerPaneSearchInteraction {
let open: (StickerPackCollectionInfo) -> Void
let install: (StickerPackCollectionInfo) -> Void
let install: (StickerPackCollectionInfo, [ItemCollectionItem]) -> Void
let sendSticker: (FileMediaReference, ASDisplayNode, CGRect) -> Void
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.install = install
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: {
interaction.open(info)
}, install: {
interaction.install(info)
interaction.install(info, topItems)
}, getItemIsPreviewed: { item in
return interaction.getItemIsPreviewed(item)
})
@ -171,6 +174,8 @@ final class StickerPaneSearchContentNode: ASDisplayNode, PaneSearchContentNode {
var deactivateSearchBar: (() -> Void)?
var updateActivity: ((Bool) -> Void)?
private let installDisposable = MetaDisposable()
init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, controllerInteraction: ChatControllerInteraction, inputNodeInteraction: ChatMediaInputNodeInteraction) {
self.context = context
self.controllerInteraction = controllerInteraction
@ -227,25 +232,87 @@ final class StickerPaneSearchContentNode: ASDisplayNode, PaneSearchContentNode {
})
strongSelf.controllerInteraction.presentController(controller, nil)
}
}, install: { [weak self] info in
if let strongSelf = self {
let _ = (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<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()
}, install: { [weak self] info, items in
guard let strongSelf = self else {
return
}
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
if let strongSelf = self {
let _ = strongSelf.controllerInteraction.sendSticker(file, false, sourceNode, sourceRect)
@ -262,6 +329,7 @@ final class StickerPaneSearchContentNode: ASDisplayNode, PaneSearchContentNode {
deinit {
self.searchDisposable.dispose()
self.installDisposable.dispose()
}
func updateText(_ text: String, languageCode: String?) {

View File

@ -7,6 +7,7 @@ import SyncCore
import SwiftSignalKit
import Postbox
import TelegramPresentationData
import StickerPackPreviewUI
final class StickerPaneSearchGlobalSection: GridSection {
let height: CGFloat = 0.0
@ -41,6 +42,7 @@ final class StickerPaneSearchGlobalItem: GridItem {
let grid: Bool
let topSeparator: Bool
let installed: Bool
let installing: Bool
let unread: Bool
let open: () -> Void
let install: () -> Void
@ -51,7 +53,7 @@ final class StickerPaneSearchGlobalItem: GridItem {
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.theme = theme
self.strings = strings
@ -60,6 +62,7 @@ final class StickerPaneSearchGlobalItem: GridItem {
self.grid = grid
self.topSeparator = topSeparator
self.installed = installed
self.installing = installing
self.unread = unread
self.open = open
self.install = install
@ -98,6 +101,9 @@ class StickerPaneSearchGlobalItemNode: GridItemNode {
private var item: StickerPaneSearchGlobalItem?
private var appliedItem: StickerPaneSearchGlobalItem?
private let preloadDisposable = MetaDisposable()
private let preloadedStickerPackThumbnailDisposable = MetaDisposable()
private var preloadedThumbnail = false
override var isVisibleInGrid: Bool {
didSet {
@ -105,6 +111,12 @@ class StickerPaneSearchGlobalItemNode: GridItemNode {
for node in self.itemNodes {
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 {
self.preloadDisposable.dispose()
self.preloadedStickerPackThumbnailDisposable.dispose()
}
override func didLoad() {