import Foundation import UIKit import LegacyComponents import Postbox import TelegramCore import SyncCore import SwiftSignalKit import Display private let gradientColors: [NSArray] = [ [UIColor(rgb: 0xff516a).cgColor, UIColor(rgb: 0xff885e).cgColor], [UIColor(rgb: 0xffa85c).cgColor, UIColor(rgb: 0xffcd6a).cgColor], [UIColor(rgb: 0x54cb68).cgColor, UIColor(rgb: 0xa0de7e).cgColor], [UIColor(rgb: 0x2a9ef1).cgColor, UIColor(rgb: 0x72d5fd).cgColor], [UIColor(rgb: 0x665fff).cgColor, UIColor(rgb: 0x82b1ff).cgColor], [UIColor(rgb: 0xd669ed).cgColor, UIColor(rgb: 0xe0a2f3).cgColor] ] private let grayscaleColors: NSArray = [ UIColor(rgb: 0xefefef).cgColor, UIColor(rgb: 0xeeeeee).cgColor ] private let sharedImageCache = TGMemoryImageCache(softMemoryLimit: 2 * 1024 * 1024, hardMemoryLimit: 3 * 1024 * 1024)! final class LegacyPeerAvatarPlaceholderDataSource: 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("placeholder://") { return true } } return false } override func loadDataSync(withUri uri: String!, canWait: Bool, acceptPartialData: Bool, asyncTaskId: AutoreleasingUnsafeMutablePointer!, 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 signal: Signal = Signal { subscriber in let args: [AnyHashable : Any] let argumentsString = String(uri[uri.index(uri.startIndex, offsetBy: "placeholder://?".count)...]) args = TGStringUtils.argumentDictionary(inUrlString: argumentsString)! guard let width = Int((args["w"] as! String)), width > 1 else { return EmptyDisposable } guard let height = Int((args["h"] as! String)), height > 1 else { return EmptyDisposable } var peerId = PeerId(0) if let uid = args["uid"] as? String, let nUid = Int64(uid) { peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(nUid)) } else if let cid = args["cid"] as? String, let nCid = Int64(cid) { peerId = PeerId(namespace: Namespaces.Peer.CloudGroup, id: PeerId.Id._internalFromInt64Value(nCid)) } let image = generateImage(CGSize(width: CGFloat(width), height: CGFloat(height)), rotatedContext: { size, context in context.clear(CGRect(origin: CGPoint(), size: size)) context.beginPath() context.addEllipse(in: CGRect(x: 0.0, y: 0.0, width: size.width, height: size.height)) context.clip() let colorIndex: Int if peerId.id._internalGetInt64Value() == 0 { colorIndex = -1 } else { colorIndex = abs(Int(clamping: account.peerId.id._internalGetInt64Value() &+ peerId.id._internalGetInt64Value())) } let colorsArray: NSArray if colorIndex == -1 { colorsArray = grayscaleColors } else { colorsArray = gradientColors[colorIndex % gradientColors.count] } var locations: [CGFloat] = [1.0, 0.2]; let colorSpace = CGColorSpaceCreateDeviceRGB() let gradient = CGGradient(colorsSpace: colorSpace, colors: colorsArray, locations: &locations)! context.drawLinearGradient(gradient, start: CGPoint(), end: CGPoint(x: 0.0, y: size.height), options: CGGradientDrawingOptions()) context.setBlendMode(.normal) }) sharedImageCache.setImage(image, forKey: uri, attributes: nil) completion?(TGDataResource(image: image, decoded: true)) subscriber.putCompletion() return EmptyDisposable } return (signal |> runOn(Queue.concurrentDefaultQueue())).start() } else { return nil } } override func cancelTask(byId taskId: Any!) { if let disposable = taskId as? Disposable { disposable.dispose() } } }