Files
GLEGram-iOS/submodules/ImportStickerPackUI/Sources/ImportStickerPackController.swift
T
Leeksov 4647310322 GLEGram 12.5 — Initial public release
Based on Swiftgram 12.5 (Telegram iOS 12.5).
All GLEGram features ported and organized in GLEGram/ folder.

Features: Ghost Mode, Saved Deleted Messages, Content Protection Bypass,
Font Replacement, Fake Profile, Chat Export, Plugin System, and more.

See CHANGELOG_12.5.md for full details.
2026-04-06 09:48:12 +03:00

169 lines
7.5 KiB
Swift

import Foundation
import UIKit
import Display
import AsyncDisplayKit
import TelegramCore
import SwiftSignalKit
import TelegramUIPreferences
import AccountContext
import ShareController
import StickerResources
import AlertUI
import PresentationDataUtils
import UndoUI
public final class ImportStickerPackController: ViewController, StandalonePresentableController {
private var controllerNode: ImportStickerPackControllerNode {
return self.displayNode as! ImportStickerPackControllerNode
}
private var animatedIn = false
private var isDismissed = false
public var dismissed: (() -> Void)?
private let context: AccountContext
private weak var parentNavigationController: NavigationController?
private let stickerPack: ImportStickerPack
private var presentationDataDisposable: Disposable?
private var verificationDisposable: Disposable?
public init(context: AccountContext, stickerPack: ImportStickerPack, parentNavigationController: NavigationController?) {
self.context = context
self.parentNavigationController = parentNavigationController
self.stickerPack = stickerPack
super.init(navigationBarPresentationData: nil)
self.blocksBackgroundWhenInOverlay = true
self.acceptsFocusWhenInOverlay = true
self.statusBar.statusBarStyle = .Ignore
self.presentationDataDisposable = (context.sharedContext.presentationData
|> deliverOnMainQueue).start(next: { [weak self] presentationData in
if let strongSelf = self, strongSelf.isNodeLoaded {
strongSelf.controllerNode.updatePresentationData(presentationData)
}
})
}
required public init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
deinit {
self.presentationDataDisposable?.dispose()
self.verificationDisposable?.dispose()
}
override public func loadDisplayNode() {
self.displayNode = ImportStickerPackControllerNode(context: self.context)
self.controllerNode.dismiss = { [weak self] in
self?.dismissed?()
self?.presentingViewController?.dismiss(animated: false, completion: nil)
}
self.controllerNode.cancel = { [weak self] in
self?.dismiss()
}
self.controllerNode.present = { [weak self] controller, arguments in
self?.present(controller, in: .window(.root), with: arguments)
}
self.controllerNode.presentInGlobalOverlay = { [weak self] controller, arguments in
self?.presentInGlobalOverlay(controller, with: arguments)
}
self.controllerNode.navigationController = self.parentNavigationController
Queue.mainQueue().after(0.1) {
self.controllerNode.updateStickerPack(self.stickerPack, verifiedStickers: Set(), declinedStickers: Set(), uploadedStickerResources: [:])
if case .image = self.stickerPack.type.contentType {
} else {
let _ = (self.context.account.postbox.loadedPeerWithId(self.context.account.peerId)
|> deliverOnMainQueue).start(next: { [weak self] peer in
guard let strongSelf = self else {
return
}
var signals: [Signal<(UUID, StickerVerificationStatus, EngineMediaResource?), NoError>] = []
for sticker in strongSelf.stickerPack.stickers {
if let resource = strongSelf.controllerNode.stickerResources[sticker.uuid] {
signals.append(strongSelf.context.engine.stickers.uploadSticker(peer: peer, resource: resource._asResource(), thumbnail: nil, alt: sticker.emojis.first ?? "", dimensions: PixelDimensions(width: 512, height: 512), duration: nil, mimeType: sticker.mimeType)
|> map { result -> (UUID, StickerVerificationStatus, EngineMediaResource?) in
switch result {
case .progress:
return (sticker.uuid, .loading, nil)
case let .complete(resource, mimeType):
if ["application/x-tgsticker", "video/webm"].contains(mimeType) {
return (sticker.uuid, .verified, EngineMediaResource(resource))
} else {
return (sticker.uuid, .declined, nil)
}
}
}
|> `catch` { _ -> Signal<(UUID, StickerVerificationStatus, EngineMediaResource?), NoError> in
return .single((sticker.uuid, .declined, nil))
})
}
}
strongSelf.verificationDisposable = (combineLatest(signals)
|> deliverOnMainQueue).start(next: { [weak self] results in
guard let strongSelf = self else {
return
}
var verifiedStickers = Set<UUID>()
var declinedStickers = Set<UUID>()
var uploadedStickerResources: [UUID: EngineMediaResource] = [:]
for (uuid, result, resource) in results {
switch result {
case .verified:
if let resource = resource {
verifiedStickers.insert(uuid)
uploadedStickerResources[uuid] = resource
} else {
declinedStickers.insert(uuid)
}
case .declined:
declinedStickers.insert(uuid)
case .loading:
break
}
}
strongSelf.controllerNode.updateStickerPack(strongSelf.stickerPack, verifiedStickers: verifiedStickers, declinedStickers: declinedStickers, uploadedStickerResources: uploadedStickerResources)
})
})
}
}
self.ready.set(self.controllerNode.ready.get())
}
override public func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if !self.animatedIn {
self.animatedIn = true
self.controllerNode.animateIn()
}
}
override public func dismiss(completion: (() -> Void)? = nil) {
if !self.isDismissed {
self.isDismissed = true
} else {
return
}
self.acceptsFocusWhenInOverlay = false
self.requestUpdateParameters()
self.controllerNode.animateOut(completion: completion)
}
override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
super.containerLayoutUpdated(layout, transition: transition)
self.controllerNode.containerLayoutUpdated(layout, navigationBarHeight: self.navigationLayout(layout: layout).navigationFrame.maxY, transition: transition)
}
}