mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
221 lines
12 KiB
Swift
221 lines
12 KiB
Swift
import Foundation
|
|
import UIKit
|
|
import LegacyComponents
|
|
import Postbox
|
|
import TelegramCore
|
|
import SwiftSignalKit
|
|
import Display
|
|
import StickerResources
|
|
|
|
func stickerFromLegacyDocument(_ documentAttachment: TGDocumentMediaAttachment) -> TelegramMediaFile? {
|
|
if documentAttachment.isSticker() {
|
|
for case let sticker as TGDocumentAttributeSticker in documentAttachment.attributes {
|
|
var attributes: [TelegramMediaFileAttribute] = []
|
|
var packReference: StickerPackReference?
|
|
if let legacyPackReference = sticker.packReference as? TGStickerPackIdReference {
|
|
packReference = .id(id: legacyPackReference.packId, accessHash: legacyPackReference.packAccessHash)
|
|
} else if let legacyPackReference = sticker.packReference as? TGStickerPackShortnameReference {
|
|
packReference = .name(legacyPackReference.shortName)
|
|
}
|
|
attributes.append(.Sticker(displayText: sticker.alt, packReference: packReference, maskData: nil))
|
|
|
|
var fileReference: Data?
|
|
if let originInfo = documentAttachment.originInfo, let data = originInfo.fileReference {
|
|
fileReference = data
|
|
}
|
|
|
|
return TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.CloudFile, id: documentAttachment.documentId), partialReference: nil, resource: CloudDocumentMediaResource(datacenterId: Int(documentAttachment.datacenterId), fileId: documentAttachment.documentId, accessHash: documentAttachment.accessHash, size: Int(documentAttachment.size), fileReference: fileReference, fileName: documentAttachment.fileName()), previewRepresentations: [], immediateThumbnailData: nil, mimeType: documentAttachment.mimeType, size: Int(documentAttachment.size), attributes: attributes)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func legacyComponentsStickers(postbox: Postbox, namespace: Int32) -> SSignal {
|
|
return SSignal { subscriber in
|
|
let disposable = (postbox.itemCollectionsView(orderedItemListCollectionIds: [], namespaces: [namespace], aroundIndex: nil, count: 200 * 200)).start(next: { view in
|
|
var stickerPackDocuments: [ItemCollectionId: [Any]] = [:]
|
|
|
|
for entry in view.entries {
|
|
if let item = entry.item as? StickerPackItem {
|
|
if item.file.isAnimatedSticker {
|
|
continue
|
|
}
|
|
let document = TGDocumentMediaAttachment()
|
|
document.documentId = item.file.fileId.id
|
|
if let resource = item.file.resource as? CloudDocumentMediaResource {
|
|
document.accessHash = resource.accessHash
|
|
document.datacenterId = Int32(resource.datacenterId)
|
|
var stickerPackId: Int64 = 0
|
|
var accessHash: Int64 = 0
|
|
for case let .Sticker(sticker) in item.file.attributes {
|
|
if let packReference = sticker.packReference, case let .id(id, h) = packReference {
|
|
stickerPackId = id
|
|
accessHash = h
|
|
}
|
|
break
|
|
}
|
|
document.originInfo = TGMediaOriginInfo(fileReference: resource.fileReference ?? Data(), fileReferences: [:], stickerPackId: stickerPackId, accessHash: accessHash)
|
|
}
|
|
document.mimeType = item.file.mimeType
|
|
if let size = item.file.size {
|
|
document.size = Int32(size)
|
|
}
|
|
if let thumbnail = item.file.previewRepresentations.first {
|
|
let imageInfo = TGImageInfo()
|
|
let encoder = PostboxEncoder()
|
|
encoder.encodeRootObject(thumbnail.resource)
|
|
let dataString = encoder.makeData().base64EncodedString(options: [])
|
|
imageInfo.addImage(with: thumbnail.dimensions, url: dataString)
|
|
document.thumbnailInfo = imageInfo
|
|
}
|
|
var attributes: [Any] = []
|
|
for attribute in item.file.attributes {
|
|
switch attribute {
|
|
case let .Sticker(displayText, _, maskData):
|
|
attributes.append(TGDocumentAttributeSticker(alt: displayText, packReference: nil, mask: maskData.flatMap {
|
|
return TGStickerMaskDescription(n: $0.n, point: CGPoint(x: CGFloat($0.x), y: CGFloat($0.y)), zoom: CGFloat($0.zoom))
|
|
}))
|
|
case let .ImageSize(size):
|
|
attributes.append(TGDocumentAttributeImageSize(size: size))
|
|
default:
|
|
break
|
|
}
|
|
}
|
|
document.attributes = attributes
|
|
if stickerPackDocuments[entry.index.collectionId] == nil {
|
|
stickerPackDocuments[entry.index.collectionId] = []
|
|
}
|
|
stickerPackDocuments[entry.index.collectionId]!.append(document)
|
|
}
|
|
}
|
|
|
|
let stickerPacks = NSMutableArray()
|
|
for (id, info, _) in view.collectionInfos {
|
|
if let info = info as? StickerPackCollectionInfo, !info.flags.contains(.isAnimated) {
|
|
let pack = TGStickerPack(packReference: TGStickerPackIdReference(), title: info.title, stickerAssociations: [], documents: stickerPackDocuments[id] ?? [], packHash: info.hash, hidden: false, isMask: true, isFeatured: false, installedDate: 0)!
|
|
stickerPacks.add(pack)
|
|
}
|
|
}
|
|
|
|
var dict: [AnyHashable: Any] = [:]
|
|
dict["packs"] = stickerPacks
|
|
subscriber?.putNext(dict)
|
|
})
|
|
|
|
return SBlockDisposable {
|
|
disposable.dispose()
|
|
}
|
|
}
|
|
}
|
|
|
|
private final class LegacyStickerImageDataTask: NSObject {
|
|
private let disposable = DisposableSet()
|
|
|
|
init(account: Account, file: TelegramMediaFile, small: Bool, fitSize: CGSize, completion: @escaping (UIImage?) -> Void) {
|
|
super.init()
|
|
|
|
self.disposable.add(chatMessageLegacySticker(account: account, file: file, small: small, fitSize: fitSize, fetched: true, onlyFullSize: true).start(next: { generator in
|
|
if let image = generator(TransformImageArguments(corners: ImageCorners(), imageSize: fitSize, boundingSize: fitSize, intrinsicInsets: UIEdgeInsets()))?.generateImage() {
|
|
completion(image)
|
|
}
|
|
}))
|
|
}
|
|
|
|
deinit {
|
|
self.disposable.dispose()
|
|
}
|
|
|
|
func cancel() {
|
|
self.disposable.dispose()
|
|
}
|
|
}
|
|
|
|
private let sharedImageCache = TGMemoryImageCache(softMemoryLimit: 2 * 1024 * 1024, hardMemoryLimit: 3 * 1024 * 1024)!
|
|
|
|
final class LegacyStickerImageDataSource: TGImageDataSource {
|
|
private let account: () -> Account?
|
|
|
|
init(account: @escaping () -> Account?) {
|
|
self.account = account
|
|
|
|
super.init()
|
|
}
|
|
|
|
override func canHandleUri(_ uri: String!) -> Bool {
|
|
if let uri = uri {
|
|
if uri.hasPrefix("sticker-preview://") {
|
|
return true
|
|
} else if uri.hasPrefix("sticker://") {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
override func loadDataSync(withUri uri: String!, canWait: Bool, acceptPartialData: Bool, asyncTaskId: AutoreleasingUnsafeMutablePointer<AnyObject?>!, progress: ((Float) -> Void)!, partialCompletion: ((TGDataResource?) -> Void)!, completion: ((TGDataResource?) -> Void)!) -> TGDataResource! {
|
|
if let image = sharedImageCache.image(forKey: uri, attributes: nil) {
|
|
return TGDataResource(image: image, decoded: true)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
override func loadDataAsync(withUri uri: String!, progress: ((Float) -> Void)!, partialCompletion: ((TGDataResource?) -> Void)!, completion: ((TGDataResource?) -> Void)!) -> Any! {
|
|
if let account = self.account() {
|
|
let args: [AnyHashable : Any]
|
|
var highQuality: Bool
|
|
if uri.hasPrefix("sticker-preview://") {
|
|
let argumentsString = String(uri[uri.index(uri.startIndex, offsetBy: "sticker-preview://?".count)...])
|
|
args = TGStringUtils.argumentDictionary(inUrlString: argumentsString)!
|
|
highQuality = Int((args["highQuality"] as! String))! != 0
|
|
} else if uri.hasPrefix("sticker://") {
|
|
let argumentsString = String(uri[uri.index(uri.startIndex, offsetBy: "sticker://?".count)...])
|
|
args = TGStringUtils.argumentDictionary(inUrlString: argumentsString)!
|
|
highQuality = true
|
|
} else {
|
|
return nil
|
|
}
|
|
|
|
let documentId = Int64((args["documentId"] as! String))!
|
|
let datacenterId = Int((args["datacenterId"] as! String))!
|
|
let accessHash = Int64((args["accessHash"] as! String))!
|
|
let size: Int? = nil
|
|
|
|
let width = Int((args["width"] as! String))!
|
|
let height = Int((args["height"] as! String))!
|
|
|
|
if width < 128 {
|
|
highQuality = false
|
|
}
|
|
|
|
let fitSize = CGSize(width: CGFloat(width), height: CGFloat(height))
|
|
|
|
var attributes: [TelegramMediaFileAttribute] = []
|
|
if let originInfoString = args["origin_info"] as? String, let originInfo = TGMediaOriginInfo(stringRepresentation: originInfoString), let stickerPackId = originInfo.stickerPackId?.int64Value, let stickerPackAccessHash = originInfo.stickerPackAccessHash?.int64Value {
|
|
attributes.append(.Sticker(displayText: "", packReference: .id(id: stickerPackId, accessHash: stickerPackAccessHash), maskData: nil))
|
|
}
|
|
|
|
var previewRepresentations: [TelegramMediaImageRepresentation] = []
|
|
if let legacyThumbnailUri = args["legacyThumbnailUri"] as? String, let data = Data(base64Encoded: legacyThumbnailUri, options: []) {
|
|
if let resource = PostboxDecoder(buffer: MemoryBuffer(data: data)).decodeRootObject() as? TelegramMediaResource {
|
|
previewRepresentations.append(TelegramMediaImageRepresentation(dimensions: CGSize(width: 140.0, height: 140.0), resource: resource))
|
|
}
|
|
}
|
|
|
|
return LegacyStickerImageDataTask(account: account, file: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.CloudFile, id: documentId), partialReference: nil, resource: CloudDocumentMediaResource(datacenterId: datacenterId, fileId: documentId, accessHash: accessHash, size: size, fileReference: nil, fileName: fileNameFromFileAttributes(attributes)), previewRepresentations: previewRepresentations, immediateThumbnailData: nil, mimeType: "image/webp", size: size, attributes: attributes), small: !highQuality, fitSize: fitSize, completion: { image in
|
|
if let image = image {
|
|
sharedImageCache.setImage(image, forKey: uri, attributes: nil)
|
|
completion?(TGDataResource(image: image, decoded: true))
|
|
}
|
|
})
|
|
} else {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
override func cancelTask(byId taskId: Any!) {
|
|
if let task = taskId as? LegacyStickerImageDataTask {
|
|
task.cancel()
|
|
}
|
|
}
|
|
}
|