Swiftgram/submodules/LegacyUI/Sources/LegacyPeerAvatarPlaceholderDataSource.swift
2021-06-28 20:02:50 +04:00

123 lines
5.2 KiB
Swift

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<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 signal: Signal<Never, NoError> = 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()
}
}
}