import UIKit import TelegramCore import SwiftSignalKit import Postbox import NotificationCenter private var accountCache: Account? private var installedSharedLogger = false private func setupSharedLogger(_ path: String) { if !installedSharedLogger { installedSharedLogger = true Logger.setSharedLogger(Logger(basePath: path)) } } private let auxiliaryMethods = AccountAuxiliaryMethods(updatePeerChatInputState: { _, _ in return nil }, fetchResource: { _, _, _, _ in return nil }, fetchResourceMediaReferenceHash: { _ in return .single(nil) }) class TodayViewController: UIViewController, NCWidgetProviding { private var initializedInterface = false private let disposable = MetaDisposable() 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 } let apiId: Int32 = BuildConfig.shared().apiId let languagesCategory = "ios" let appGroupName = "group.\(appBundleIdentifier[.. if let accountCache = accountCache { account = .single(accountCache) } else { let appVersion = (Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String) ?? "unknown" initializeAccountManagement() account = accountManager(basePath: rootPath + "/accounts-metadata") |> take(1) |> mapToSignal { accountManager -> Signal in return currentAccount(allocateIfNotExists: false, networkArguments: NetworkInitializationArguments(apiId: apiId, languagesCategory: languagesCategory, appVersion: appVersion, voipMaxLayer: 0), supplementary: true, manager: accountManager, rootPath: rootPath, beginWithTestingEnvironment: false, auxiliaryMethods: auxiliaryMethods) |> mapToSignal { account -> Signal in if let account = account { switch account { case .upgrading: return .complete() case let .authorized(account): accountCache = account return .single(account) case .unauthorized: return .complete() } } else { return .complete() } } } |> take(1) } let applicationInterface = account |> afterNext { account in setupAccount(account) } |> deliverOnMainQueue |> afterNext { [weak self] account in account.resetStateManagement() 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: break } } }) //account.network.shouldKeepConnection.set(shouldBeMaster.get() |> map({ $0 })) } self.disposable.set(applicationInterface.start()) } func widgetPerformUpdate(completionHandler: (@escaping (NCUpdateResult) -> Void)) { completionHandler(.newData) } @available(iOSApplicationExtension 10.0, *) func widgetActiveDisplayModeDidChange(_ activeDisplayMode: NCWidgetDisplayMode, withMaximumSize maxSize: CGSize) { } private var peers: [Peer]? private func setPeers(account: Account, peers: [Peer]) { self.peers = peers 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 { if let url = URL(string: "\(BuildConfig.shared().appSpecificUrlScheme)://localpeer?id=\(peer.id.toInt64())") { strongSelf.extensionContext?.open(url, completionHandler: nil) } } }) 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] = [] override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() self.updateLayout(size: self.view.bounds.size) } 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] = [] var offset: CGFloat = 0.0 for _ in self.peerViews { let peerFrame = CGRect(origin: CGPoint(x: offset, y: 10.0), size: peerSize) offset += peerFrame.size.width if peerFrame.maxX > size.width { break } peerFrames.append(peerFrame) } var totalSize: CGFloat = 0.0 for i in 0 ..< peerFrames.count { totalSize += peerFrames[i].width } let spacing: CGFloat = floor((size.width - totalSize) / CGFloat(peerFrames.count)) offset = floor(spacing / 2.0) for i in 0 ..< peerFrames.count { let peerView = self.peerViews[i] peerView.frame = CGRect(origin: CGPoint(x: offset, y: 20.0), size: peerFrames[i].size) 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) /*let context = UIGraphicsGetCurrentContext() context?.setFillColor(UIColor.blue.cgColor) context?.fill(CGRect(origin: CGPoint(), size: self.view.bounds.size))*/ self.view.drawHierarchy(in: self.view.bounds, afterScreenUpdates: false) let image = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() if let image = image, let data = UIImagePNGRepresentation(image) { 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[..