// // LaunchViewController.swift // AltStore // // Created by Riley Testut on 7/30/19. // Copyright © 2019 Riley Testut. All rights reserved. // import UIKit import Roxas import EmotionalDamage import minimuxer import AltStoreCore class LaunchViewController: RSTLaunchViewController { private var didFinishLaunching = false private var destinationViewController: UIViewController! override var launchConditions: [RSTLaunchCondition] { let isDatabaseStarted = RSTLaunchCondition(condition: { DatabaseManager.shared.isStarted }) { (completionHandler) in DatabaseManager.shared.start(completionHandler: completionHandler) } return [isDatabaseStarted] } override var childForStatusBarStyle: UIViewController? { return self.children.first } override var childForStatusBarHidden: UIViewController? { return self.children.first } override func viewDidLoad() { defer { // Create destinationViewController now so view controllers can register for receiving Notifications. self.destinationViewController = self.storyboard!.instantiateViewController(withIdentifier: "tabBarController") as! TabBarController } super.viewDidLoad() start_em_proxy(bind_addr: Consts.Proxy.serverURL) guard let pf = fetchPairingFile() else { displayError("ALTPairingFile not found.") return } set_usbmuxd_socket() start_minimuxer(pairing_file: pf) auto_mount_dev_image() } func fetchPairingFile() -> String? { let filename = "ALTPairingFile.mobiledevicepairing" let fm = FileManager.default let documentsPath = fm.documentsDirectory.appendingPathComponent("/\(filename)") if fm.fileExists(atPath: documentsPath.path), let contents = try? String(contentsOf: documentsPath), !contents.isEmpty { print("Loaded ALTPairingFile from \(documentsPath.path)") return contents } else if let appResourcePath = Bundle.main.url(forResource: "ALTPairingFile", withExtension: "mobiledevicepairing"), fm.fileExists(atPath: appResourcePath.path), let data = fm.contents(atPath: appResourcePath.path), let contents = String(data: data, encoding: .utf8), !contents.isEmpty { print("Loaded ALTPairingFile from \(appResourcePath.path)") return contents } else if let plistString = Bundle.main.object(forInfoDictionaryKey: "ALTPairingFile") as? String, !plistString.isEmpty, !plistString.contains("insert pairing file here"){ print("Loaded ALTPairingFile from Info.plist") return plistString } else { return nil } } func displayError(_ msg: String) { let label = UILabel() label.text = msg label.textColor = .refreshRed label.sizeToFit() self.view.addSubview(label) NSLayoutConstraint.activate([ label.centerXAnchor.constraint(equalTo: view.centerXAnchor), label.centerYAnchor.constraint(equalTo: view.centerYAnchor) ]) } } extension LaunchViewController { override func handleLaunchError(_ error: Error) { do { throw error } catch let error as NSError { let title = error.userInfo[NSLocalizedFailureErrorKey] as? String ?? NSLocalizedString("Unable to Launch SideStore", comment: "") let alertController = UIAlertController(title: title, message: error.localizedDescription, preferredStyle: .alert) alertController.addAction(UIAlertAction(title: NSLocalizedString("Retry", comment: ""), style: .default, handler: { (action) in self.handleLaunchConditions() })) self.present(alertController, animated: true, completion: nil) } } override func finishLaunching() { super.finishLaunching() guard !self.didFinishLaunching else { return } AppManager.shared.update() AppManager.shared.updatePatronsIfNeeded() PatreonAPI.shared.refreshPatreonAccount() // Add view controller as child (rather than presenting modally) // so tint adjustment + card presentations works correctly. self.destinationViewController.view.frame = CGRect(x: 0, y: 0, width: self.view.bounds.width, height: self.view.bounds.height) self.destinationViewController.view.alpha = 0.0 self.addChild(self.destinationViewController) self.view.addSubview(self.destinationViewController.view, pinningEdgesWith: .zero) self.destinationViewController.didMove(toParent: self) UIView.animate(withDuration: 0.2) { self.destinationViewController.view.alpha = 1.0 } self.didFinishLaunching = true } }