Support widget data

This commit is contained in:
Peter
2019-10-11 16:22:41 +04:00
parent 29e6e29816
commit 841ecaba39
2 changed files with 35 additions and 160 deletions

View File

@@ -1,7 +1,6 @@
import Foundation
import Postbox
import TelegramCore
import UIKit
import WidgetItems
private extension UIColor {
convenience init(rgb: UInt32) {
@@ -53,7 +52,7 @@ private let deviceColorSpace: CGColorSpace = {
}
}()
private func avatarViewLettersImage(size: CGSize, peerId: PeerId, accountPeerId: PeerId, letters: [String]) -> UIImage? {
private func avatarViewLettersImage(size: CGSize, peerId: Int64, accountPeerId: Int64, letters: [String]) -> UIImage? {
UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
let context = UIGraphicsGetCurrentContext()
@@ -61,7 +60,7 @@ private func avatarViewLettersImage(size: CGSize, peerId: PeerId, accountPeerId:
context?.addEllipse(in: CGRect(x: 0.0, y: 0.0, width: size.width, height: size.height))
context?.clip()
let colorIndex = abs(Int(accountPeerId.id + peerId.id))
let colorIndex = abs(Int(accountPeerId + peerId))
let colorsArray = gradientColors[colorIndex % gradientColors.count]
var locations: [CGFloat] = [1.0, 0.0]
@@ -98,13 +97,13 @@ private func avatarViewLettersImage(size: CGSize, peerId: PeerId, accountPeerId:
private let avatarSize = CGSize(width: 50.0, height: 50.0)
private final class AvatarView: UIImageView {
init(account: Account, peer: Peer, size: CGSize) {
init(accountPeerId: Int64, peer: WidgetDataPeer, size: CGSize) {
super.init(frame: CGRect())
if let resource = peer.smallProfileImage?.resource, let path = account.postbox.mediaBox.completedResourcePath(resource), let image = UIImage(contentsOfFile: path), let roundImage = avatarRoundImage(size: size, source: image) {
if let path = peer.avatarPath, let image = UIImage(contentsOfFile: path), let roundImage = avatarRoundImage(size: size, source: image) {
self.image = roundImage
} else {
self.image = avatarViewLettersImage(size: size, peerId: peer.id, accountPeerId: account.peerId, letters: peer.displayLetters)
self.image = avatarViewLettersImage(size: size, peerId: peer.id, accountPeerId: accountPeerId, letters: peer.letters)
}
}
@@ -114,19 +113,20 @@ private final class AvatarView: UIImageView {
}
final class PeerView: UIView {
let peer: Peer
let peer: WidgetDataPeer
private let avatarView: AvatarView
private let titleLabel: UILabel
private let tapped: () -> Void
init(account: Account, peer: Peer, tapped: @escaping () -> Void) {
init(accountPeerId: Int64, peer: WidgetDataPeer, tapped: @escaping () -> Void) {
self.peer = peer
self.tapped = tapped
self.avatarView = AvatarView(account: account, peer: peer, size: avatarSize)
self.avatarView = AvatarView(accountPeerId: accountPeerId, peer: peer, size: avatarSize)
self.titleLabel = UILabel()
self.titleLabel.text = peer.compactDisplayTitle
let title = peer.name
self.titleLabel.text = title
self.titleLabel.textColor = .black
self.titleLabel.font = UIFont.systemFont(ofSize: 11.0)
self.titleLabel.lineBreakMode = .byTruncatingTail

View File

@@ -1,57 +1,26 @@
import UIKit
import TelegramCore
import SwiftSignalKit
import Postbox
import NotificationCenter
import BuildConfig
import WidgetItems
private var installedSharedLogger = false
private func setupSharedLogger(_ path: String) {
if !installedSharedLogger {
installedSharedLogger = true
Logger.setSharedLogger(Logger(basePath: path))
}
private func rootPathForBasePath(_ appGroupPath: String) -> String {
return appGroupPath + "/telegram-data"
}
private let auxiliaryMethods = AccountAuxiliaryMethods(updatePeerChatInputState: { _, _ in
return nil
}, fetchResource: { _, _, _, _ in
return nil
}, fetchResourceMediaReferenceHash: { _ in
return .single(nil)
}, prepareSecretThumbnailData: { _ in
return nil
})
@objc(TodayViewController)
class TodayViewController: UIViewController, NCWidgetProviding {
private var initializedInterface = false
private let disposable = MetaDisposable()
private var buildConfig: BuildConfig?
deinit {
self.disposable.dispose()
}
private var snapshotView: UIImageView?
override func viewDidLoad() {
super.viewDidLoad()
self.snapshotView?.removeFromSuperview()
let snapshotView = UIImageView()
if let path = self.getSnapshotPath(), let image = UIImage(contentsOfFile: path) {
snapshotView.image = image
}
self.snapshotView = snapshotView
self.view.addSubview(snapshotView)
if self.initializedInterface {
return
}
self.initializedInterface = true
let appBundleIdentifier = Bundle.main.bundleIdentifier!
guard let lastDotRange = appBundleIdentifier.range(of: ".", options: [.backwards]) else {
return
@@ -61,9 +30,6 @@ class TodayViewController: UIViewController, NCWidgetProviding {
let buildConfig = BuildConfig(baseAppBundleId: baseAppBundleId)
self.buildConfig = buildConfig
let apiId: Int32 = buildConfig.apiId
let languagesCategory = "ios"
let appGroupName = "group.\(baseAppBundleId)"
let maybeAppGroupUrl = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroupName)
@@ -72,56 +38,11 @@ class TodayViewController: UIViewController, NCWidgetProviding {
}
let rootPath = rootPathForBasePath(appGroupUrl.path)
performAppGroupUpgrades(appGroupPath: appGroupUrl.path, rootPath: rootPath)
let dataPath = rootPath + "/widget-data"
TempBox.initializeShared(basePath: rootPath, processType: "widget", launchSpecificId: arc4random64())
let logsPath = rootPath + "/today-logs"
let _ = try? FileManager.default.createDirectory(atPath: logsPath, withIntermediateDirectories: true, attributes: nil)
setupSharedLogger(logsPath)
let account: Signal<Account, NoError>
let appVersion = (Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String) ?? "unknown"
initializeAccountManagement()
let accountManager = AccountManager(basePath: rootPath + "/accounts-metadata")
let deviceSpecificEncryptionParameters = BuildConfig.deviceSpecificEncryptionParameters(rootPath, baseAppBundleId: baseAppBundleId)
let encryptionParameters = ValueBoxEncryptionParameters(forceEncryptionIfNoSet: false, key: ValueBoxEncryptionParameters.Key(data: deviceSpecificEncryptionParameters.key)!, salt: ValueBoxEncryptionParameters.Salt(data: deviceSpecificEncryptionParameters.salt)!)
account = currentAccount(allocateIfNotExists: false, networkArguments: NetworkInitializationArguments(apiId: apiId, languagesCategory: languagesCategory, appVersion: appVersion, voipMaxLayer: 0, appData: .single(buildConfig.bundleData(withAppToken: nil))), supplementary: true, manager: accountManager, rootPath: rootPath, auxiliaryMethods: auxiliaryMethods, encryptionParameters: encryptionParameters)
|> mapToSignal { account -> Signal<Account, NoError> in
if let account = account {
switch account {
case .upgrading:
return .complete()
case let .authorized(account):
return .single(account)
case .unauthorized:
return .complete()
}
} else {
return .complete()
}
if let data = try? Data(contentsOf: URL(fileURLWithPath: dataPath)), let widgetData = try? JSONDecoder().decode(WidgetData.self, from: data) {
self.setWidgetData(widgetData: widgetData)
}
let applicationInterface = account
|> deliverOnMainQueue
|> afterNext { [weak self] account in
let _ = (recentPeers(account: account)
|> deliverOnMainQueue).start(next: { peers in
if let strongSelf = self {
switch peers {
case let .peers(peers):
strongSelf.setPeers(account: account, peers: peers.filter { !$0.isDeleted })
case .disabled:
strongSelf.setPeers(account: account, peers: [])
}
}
})
}
self.disposable.set(applicationInterface.start())
}
func widgetPerformUpdate(completionHandler: (@escaping (NCUpdateResult) -> Void)) {
@@ -133,34 +54,37 @@ class TodayViewController: UIViewController, NCWidgetProviding {
}
private var peers: [Peer]?
private var widgetData: WidgetData?
private func setPeers(account: Account, peers: [Peer]) {
self.peers = peers
private func setWidgetData(widgetData: WidgetData) {
self.widgetData = widgetData
self.peerViews.forEach {
$0.removeFromSuperview()
}
self.peerViews = []
for peer in peers {
let peerView = PeerView(account: account, peer: peer, tapped: { [weak self] in
if let strongSelf = self, let buildConfig = strongSelf.buildConfig {
if let url = URL(string: "\(buildConfig.appSpecificUrlScheme)://localpeer?id=\(peer.id.toInt64())") {
strongSelf.extensionContext?.open(url, completionHandler: nil)
switch widgetData {
case .notAuthorized, .disabled:
break
case let .peers(peers):
for peer in peers.peers {
let peerView = PeerView(accountPeerId: peers.accountPeerId, peer: peer, tapped: { [weak self] in
if let strongSelf = self, let buildConfig = strongSelf.buildConfig {
if let url = URL(string: "\(buildConfig.appSpecificUrlScheme)://localpeer?id=\(peer.id)") {
strongSelf.extensionContext?.open(url, completionHandler: nil)
}
}
}
})
self.view.addSubview(peerView)
self.peerViews.append(peerView)
})
self.view.addSubview(peerView)
self.peerViews.append(peerView)
}
}
self.validSnapshotSize = nil
if let size = self.validLayout {
self.updateLayout(size: size)
}
}
private var validLayout: CGSize?
private var validSnapshotSize: CGSize?
private var peerViews: [PeerView] = []
@@ -173,11 +97,6 @@ class TodayViewController: UIViewController, NCWidgetProviding {
private func updateLayout(size: CGSize) {
self.validLayout = size
if let image = self.snapshotView?.image {
let scale = UIScreen.main.scale
self.snapshotView?.frame = CGRect(origin: CGPoint(), size: CGSize(width: image.size.width / scale, height: image.size.height / scale))
}
let peerSize = CGSize(width: 70.0, height: 100.0)
var peerFrames: [CGRect] = []
@@ -205,49 +124,5 @@ class TodayViewController: UIViewController, NCWidgetProviding {
peerView.updateLayout(size: peerFrames[i].size)
offset += peerFrames[i].width + spacing
}
if self.peers != nil {
self.snapshotView?.removeFromSuperview()
if self.validSnapshotSize != size {
self.validSnapshotSize = size
self.updateSnapshot()
}
}
}
private func updateSnapshot() {
if let path = self.getSnapshotPath() {
DispatchQueue.main.async {
UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, false, 0.0)
self.view.drawHierarchy(in: self.view.bounds, afterScreenUpdates: false)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
if let image = image, let data = image.pngData() {
let _ = try? FileManager.default.removeItem(atPath: path)
do {
try data.write(to: URL(fileURLWithPath: path))
} catch let e {
print("\(e)")
}
}
}
}
}
private func getSnapshotPath() -> String? {
let appBundleIdentifier = Bundle.main.bundleIdentifier!
guard let lastDotRange = appBundleIdentifier.range(of: ".", options: [.backwards]) else {
return nil
}
let appGroupName = "group.\(appBundleIdentifier[..<lastDotRange.lowerBound])"
let maybeAppGroupUrl = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroupName)
guard let appGroupUrl = maybeAppGroupUrl else {
return nil
}
let rootPath = rootPathForBasePath(appGroupUrl.path)
return rootPath + "/widget-snapshot.png"
}
}