mirror of
https://github.com/SideStore/SideStore.git
synced 2026-02-09 06:43:25 +01:00
Adds altstore://source?url=[link] deep link to add sources
This commit is contained in:
@@ -54,11 +54,13 @@ extension AppDelegate
|
||||
{
|
||||
static let openPatreonSettingsDeepLinkNotification = Notification.Name("com.rileytestut.AltStore.OpenPatreonSettingsDeepLinkNotification")
|
||||
static let importAppDeepLinkNotification = Notification.Name("com.rileytestut.AltStore.ImportAppDeepLinkNotification")
|
||||
static let addSourceDeepLinkNotification = Notification.Name("com.rileytestut.AltStore.AddSourceDeepLinkNotification")
|
||||
|
||||
static let appBackupDidFinish = Notification.Name("com.rileytestut.AltStore.AppBackupDidFinish")
|
||||
|
||||
static let importAppDeepLinkURLKey = "fileURL"
|
||||
static let appBackupResultKey = "result"
|
||||
static let addSourceDeepLinkURLKey = "sourceURL"
|
||||
}
|
||||
|
||||
@UIApplicationMain
|
||||
@@ -184,6 +186,16 @@ private extension AppDelegate
|
||||
|
||||
return true
|
||||
|
||||
case "source":
|
||||
let queryItems = components.queryItems?.reduce(into: [String: String]()) { $0[$1.name.lowercased()] = $1.value } ?? [:]
|
||||
guard let sourceURLString = queryItems["url"], let sourceURL = URL(string: sourceURLString) else { return false }
|
||||
|
||||
DispatchQueue.main.async {
|
||||
NotificationCenter.default.post(name: AppDelegate.addSourceDeepLinkNotification, object: nil, userInfo: [AppDelegate.addSourceDeepLinkURLKey: sourceURL])
|
||||
}
|
||||
|
||||
return true
|
||||
|
||||
default: return false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,13 @@ import Roxas
|
||||
|
||||
class SourcesViewController: UICollectionViewController
|
||||
{
|
||||
var deepLinkSourceURL: URL? {
|
||||
didSet {
|
||||
guard let sourceURL = self.deepLinkSourceURL else { return }
|
||||
self.addSource(url: sourceURL)
|
||||
}
|
||||
}
|
||||
|
||||
private lazy var dataSource = self.makeDataSource()
|
||||
|
||||
override func viewDidLoad()
|
||||
@@ -21,6 +28,27 @@ class SourcesViewController: UICollectionViewController
|
||||
|
||||
self.collectionView.dataSource = self.dataSource
|
||||
}
|
||||
|
||||
override func viewWillAppear(_ animated: Bool)
|
||||
{
|
||||
super.viewWillAppear(animated)
|
||||
|
||||
if self.deepLinkSourceURL != nil
|
||||
{
|
||||
self.navigationItem.leftBarButtonItem?.isIndicatingActivity = true
|
||||
}
|
||||
}
|
||||
|
||||
override func viewDidAppear(_ animated: Bool)
|
||||
{
|
||||
super.viewDidAppear(animated)
|
||||
|
||||
if let sourceURL = self.deepLinkSourceURL
|
||||
{
|
||||
self.addSource(url: sourceURL)
|
||||
self.deepLinkSourceURL = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension SourcesViewController
|
||||
@@ -67,26 +95,6 @@ private extension SourcesViewController
|
||||
{
|
||||
@IBAction func addSource()
|
||||
{
|
||||
func addSource(url: URL)
|
||||
{
|
||||
AppManager.shared.fetchSource(sourceURL: url) { (result) in
|
||||
do
|
||||
{
|
||||
let source = try result.get()
|
||||
try source.managedObjectContext?.save()
|
||||
}
|
||||
catch let error as NSError
|
||||
{
|
||||
let error = error.withLocalizedFailure(NSLocalizedString("Could not add source.", comment: ""))
|
||||
|
||||
DispatchQueue.main.async {
|
||||
let toastView = ToastView(error: error)
|
||||
toastView.show(in: self)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let alertController = UIAlertController(title: NSLocalizedString("Add Source", comment: ""), message: nil, preferredStyle: .alert)
|
||||
alertController.addTextField { (textField) in
|
||||
textField.placeholder = "https://apps.altstore.io"
|
||||
@@ -95,14 +103,77 @@ private extension SourcesViewController
|
||||
alertController.addAction(.cancel)
|
||||
alertController.addAction(UIAlertAction(title: NSLocalizedString("Add", comment: ""), style: .default) { (action) in
|
||||
guard let text = alertController.textFields![0].text, let sourceURL = URL(string: text) else { return }
|
||||
addSource(url: sourceURL)
|
||||
self.addSource(url: sourceURL)
|
||||
})
|
||||
|
||||
self.present(alertController, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
func addSource(url: URL)
|
||||
{
|
||||
guard self.view.window != nil else { return }
|
||||
|
||||
self.navigationItem.leftBarButtonItem?.isIndicatingActivity = true
|
||||
|
||||
func finish(error: Error?)
|
||||
{
|
||||
DispatchQueue.main.async {
|
||||
if let error = error
|
||||
{
|
||||
self.present(error)
|
||||
}
|
||||
|
||||
self.navigationItem.leftBarButtonItem?.isIndicatingActivity = false
|
||||
}
|
||||
}
|
||||
|
||||
AppManager.shared.fetchSource(sourceURL: url) { (result) in
|
||||
do
|
||||
{
|
||||
let source = try result.get()
|
||||
let sourceName = source.name
|
||||
let managedObjectContext = source.managedObjectContext
|
||||
|
||||
DispatchQueue.main.async {
|
||||
let alertController = UIAlertController(title: String(format: NSLocalizedString("Would you like to add the source “%@”?", comment: ""), sourceName),
|
||||
message: NSLocalizedString("Sources control what apps appear in AltStore. Make sure to only add sources that you trust.", comment: ""), preferredStyle: .alert)
|
||||
alertController.addAction(UIAlertAction(title: UIAlertAction.cancel.title, style: UIAlertAction.cancel.style) { _ in
|
||||
finish(error: nil)
|
||||
})
|
||||
alertController.addAction(UIAlertAction(title: UIAlertAction.ok.title, style: UIAlertAction.ok.style) { _ in
|
||||
managedObjectContext?.perform {
|
||||
do
|
||||
{
|
||||
try managedObjectContext?.save()
|
||||
finish(error: nil)
|
||||
}
|
||||
catch
|
||||
{
|
||||
finish(error: error)
|
||||
}
|
||||
}
|
||||
})
|
||||
self.present(alertController, animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
finish(error: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func present(_ error: Error)
|
||||
{
|
||||
if let transitionCoordinator = self.transitionCoordinator
|
||||
{
|
||||
transitionCoordinator.animate(alongsideTransition: nil) { _ in
|
||||
self.present(error)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
let nsError = error as NSError
|
||||
let message = nsError.userInfo[NSDebugDescriptionErrorKey] as? String ?? nsError.localizedRecoverySuggestion
|
||||
|
||||
|
||||
@@ -21,12 +21,52 @@ extension TabBarController
|
||||
|
||||
class TabBarController: UITabBarController
|
||||
{
|
||||
private var initialSegue: (identifier: String, sender: Any?)?
|
||||
|
||||
private var _viewDidAppear = false
|
||||
|
||||
required init?(coder aDecoder: NSCoder)
|
||||
{
|
||||
super.init(coder: aDecoder)
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(TabBarController.openPatreonSettings(_:)), name: AppDelegate.openPatreonSettingsDeepLinkNotification, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(TabBarController.importApp(_:)), name: AppDelegate.importAppDeepLinkNotification, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(TabBarController.presentSources(_:)), name: AppDelegate.addSourceDeepLinkNotification, object: nil)
|
||||
}
|
||||
|
||||
override func viewDidAppear(_ animated: Bool)
|
||||
{
|
||||
super.viewDidAppear(animated)
|
||||
|
||||
_viewDidAppear = true
|
||||
|
||||
if let (identifier, sender) = self.initialSegue
|
||||
{
|
||||
self.initialSegue = nil
|
||||
self.performSegue(withIdentifier: identifier, sender: sender)
|
||||
}
|
||||
}
|
||||
|
||||
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
|
||||
{
|
||||
guard segue.identifier == "presentSources",
|
||||
let notification = sender as? Notification,
|
||||
let sourceURL = notification.userInfo?[AppDelegate.addSourceDeepLinkURLKey] as? URL
|
||||
else { return }
|
||||
|
||||
let navigationController = segue.destination as! UINavigationController
|
||||
let sourcesViewController = navigationController.viewControllers.first as! SourcesViewController
|
||||
sourcesViewController.deepLinkSourceURL = sourceURL
|
||||
}
|
||||
|
||||
override func performSegue(withIdentifier identifier: String, sender: Any?)
|
||||
{
|
||||
guard _viewDidAppear else {
|
||||
self.initialSegue = (identifier, sender)
|
||||
return
|
||||
}
|
||||
|
||||
super.performSegue(withIdentifier: identifier, sender: sender)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +74,31 @@ extension TabBarController
|
||||
{
|
||||
@objc func presentSources(_ sender: Any)
|
||||
{
|
||||
if let presentedViewController = self.presentedViewController
|
||||
{
|
||||
if let navigationController = presentedViewController as? UINavigationController,
|
||||
let sourcesViewController = navigationController.viewControllers.first as? SourcesViewController
|
||||
{
|
||||
if let notification = (sender as? Notification),
|
||||
let sourceURL = notification.userInfo?[AppDelegate.addSourceDeepLinkURLKey] as? URL
|
||||
{
|
||||
sourcesViewController.deepLinkSourceURL = sourceURL
|
||||
}
|
||||
else
|
||||
{
|
||||
// Don't dismiss SourcesViewController if it's already presented.
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
presentedViewController.dismiss(animated: true) {
|
||||
self.presentSources(sender)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
self.performSegue(withIdentifier: "presentSources", sender: sender)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user