mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-09-04 11:50:38 +00:00
Display progress when adding sticker packs
This commit is contained in:
parent
e653760a74
commit
0b5be7edad
@ -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 {
|
||||||
|
@ -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?) {
|
||||||
|
@ -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() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user