Merge branch 'bad-host-wizard-flow'

This commit is contained in:
Davide De Rosa 2018-10-27 22:19:07 +02:00
commit e3d2d54226
6 changed files with 62 additions and 48 deletions

View File

@ -90,52 +90,49 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UISplitViewControllerDele
fatalError("No window.rootViewController?") fatalError("No window.rootViewController?")
} }
let topmost = root.presentedViewController ?? root
let fm = FileManager.default let fm = FileManager.default
guard let parsedFile = ParsedFile.from(url, withErrorAlertIn: root) else { guard let parsedFile = ParsedFile.from(url, withErrorAlertIn: topmost) else {
try? fm.removeItem(at: url) try? fm.removeItem(at: url)
return true return true
} }
if let warning = parsedFile.warning { if let warning = parsedFile.warning {
ParsedFile.alertImportWarning(url: url, in: root, withWarning: warning) { ParsedFile.alertImportWarning(url: url, in: topmost, withWarning: warning) {
if $0 { if $0 {
self.handleParsedFile(parsedFile, in: root) self.handleParsedFile(parsedFile, in: topmost)
} else { } else {
try? fm.removeItem(at: url) try? fm.removeItem(at: url)
} }
} }
return true return true
} }
handleParsedFile(parsedFile, in: root) handleParsedFile(parsedFile, in: topmost)
return true return true
} }
private func handleParsedFile(_ parsedFile: ParsedFile, in root: UIViewController) { private func handleParsedFile(_ parsedFile: ParsedFile, in target: UIViewController) {
// already presented: update parsed configuration // already presented: update parsed configuration
if let nav = root.presentedViewController as? UINavigationController, let wizard = nav.topViewController as? WizardHostViewController { if let nav = target as? UINavigationController, let wizard = nav.topViewController as? WizardHostViewController {
if let oldURL = wizard.parsedFile?.url {
try? FileManager.default.removeItem(at: oldURL)
}
wizard.parsedFile = parsedFile wizard.parsedFile = parsedFile
wizard.removesConfigurationOnCancel = true wizard.removesConfigurationOnCancel = true
return return
} }
// present now // present now
let nav = StoryboardScene.Organizer.wizardHostIdentifier.instantiate() let wizardNav = StoryboardScene.Organizer.wizardHostIdentifier.instantiate()
guard let wizard = nav.topViewController as? WizardHostViewController else { guard let wizard = wizardNav.topViewController as? WizardHostViewController else {
fatalError("Expected WizardHostViewController from storyboard") fatalError("Expected WizardHostViewController from storyboard")
} }
wizard.parsedFile = parsedFile wizard.parsedFile = parsedFile
wizard.removesConfigurationOnCancel = true wizard.removesConfigurationOnCancel = true
// best effort to delegate to main vc wizardNav.modalPresentationStyle = .formSheet
let split = root as? UISplitViewController target.present(wizardNav, animated: true, completion: nil)
let master = split?.viewControllers.first as? UINavigationController
master?.viewControllers.forEach {
if let organizerVC = $0 as? OrganizerViewController {
wizard.delegate = organizerVC
}
}
nav.modalPresentationStyle = .formSheet
root.present(nav, animated: true, completion: nil)
} }
} }

View File

@ -34,8 +34,6 @@ class ImportedHostsViewController: UITableViewController {
private var parsedFile: ParsedFile? private var parsedFile: ParsedFile?
weak var wizardDelegate: WizardDelegate?
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
@ -104,7 +102,6 @@ class ImportedHostsViewController: UITableViewController {
return return
} }
wizard.parsedFile = parsedFile wizard.parsedFile = parsedFile
wizard.delegate = wizardDelegate
// retain back button // retain back button
wizard.navigationItem.leftBarButtonItem = nil wizard.navigationItem.leftBarButtonItem = nil

View File

@ -70,6 +70,10 @@ class OrganizerViewController: UITableViewController, TableModelHost {
// MARK: UIViewController // MARK: UIViewController
deinit {
NotificationCenter.default.removeObserver(self)
}
override func awakeFromNib() { override func awakeFromNib() {
super.awakeFromNib() super.awakeFromNib()
@ -90,6 +94,8 @@ class OrganizerViewController: UITableViewController, TableModelHost {
} }
service.delegate = self service.delegate = self
NotificationCenter.default.addObserver(self, selector: #selector(wizardDidCreate(notification:)), name: .WizardDidCreate, object: nil)
} }
override func viewDidAppear(_ animated: Bool) { override func viewDidAppear(_ animated: Bool) {
@ -134,13 +140,8 @@ class OrganizerViewController: UITableViewController, TableModelHost {
assert(selectedProfile != nil, "No selected profile") assert(selectedProfile != nil, "No selected profile")
vc.profile = selectedProfile vc.profile = selectedProfile
} else if let vc = destination as? Wizard { } else if let providerVC = destination as? WizardProviderViewController {
if let providerVC = vc as? WizardProviderViewController { providerVC.availableNames = availableProviderNames ?? []
providerVC.availableNames = availableProviderNames ?? []
}
vc.delegate = self
} else if let vc = destination as? ImportedHostsViewController {
vc.wizardDelegate = self
} }
} }
@ -436,14 +437,34 @@ extension OrganizerViewController: ConnectionServiceDelegate {
} }
} }
extension OrganizerViewController: WizardDelegate { extension OrganizerViewController {
func wizard(didCreate profile: ConnectionProfile, withCredentials credentials: Credentials) { @objc private func wizardDidCreate(notification: Notification) {
guard let profile = notification.userInfo?[WizardCreationKey.profile] as? ConnectionProfile,
let credentials = notification.userInfo?[WizardCreationKey.credentials] as? Credentials else {
fatalError("WizardDidCreate notification must post profile and credentials")
}
service.addOrReplaceProfile(profile, credentials: credentials) service.addOrReplaceProfile(profile, credentials: credentials)
TransientStore.shared.serialize() // add TransientStore.shared.serialize() // add
reloadModel() reloadModel()
tableView.reloadData() tableView.reloadData()
// XXX: hack around bad replace when detail presented in compact view
if let detailNav = navigationController?.viewControllers.last as? UINavigationController {
var existingServiceVC: ServiceViewController?
for vc in detailNav.viewControllers {
if let found = vc as? ServiceViewController {
existingServiceVC = found
break
}
}
let serviceVC = existingServiceVC ?? (StoryboardScene.Main.serviceIdentifier.instantiate().topViewController as! ServiceViewController)
serviceVC.profile = profile
detailNav.setViewControllers([serviceVC], animated: true)
return
}
perform(segue: StoryboardSegue.Organizer.selectProfileSegueIdentifier, sender: profile) perform(segue: StoryboardSegue.Organizer.selectProfileSegueIdentifier, sender: profile)
} }
} }

View File

@ -29,7 +29,7 @@ import SwiftyBeaver
private let log = SwiftyBeaver.self private let log = SwiftyBeaver.self
class WizardHostViewController: UITableViewController, TableModelHost, Wizard { class WizardHostViewController: UITableViewController, TableModelHost {
@IBOutlet private weak var itemNext: UIBarButtonItem! @IBOutlet private weak var itemNext: UIBarButtonItem!
private let existingHosts: [String] = { private let existingHosts: [String] = {
@ -46,8 +46,6 @@ class WizardHostViewController: UITableViewController, TableModelHost, Wizard {
private var createdProfile: HostConnectionProfile? private var createdProfile: HostConnectionProfile?
weak var delegate: WizardDelegate?
// MARK: TableModelHost // MARK: TableModelHost
lazy var model: TableModel<SectionType, RowType> = { lazy var model: TableModel<SectionType, RowType> = {
@ -89,12 +87,7 @@ class WizardHostViewController: UITableViewController, TableModelHost, Wizard {
// MARK: Actions // MARK: Actions
private func useSuggestedTitle() { private func useSuggestedTitle() {
guard let field = cellTitle?.field else { cellTitle?.field.text = parsedFile?.url.normalizedFilename
return
}
if field.text?.isEmpty ?? true {
field.text = parsedFile?.url.normalizedFilename
}
} }
@IBAction private func next() { @IBAction private func next() {
@ -150,7 +143,10 @@ class WizardHostViewController: UITableViewController, TableModelHost, Wizard {
} }
dismiss(animated: true) { dismiss(animated: true) {
self.delegate?.wizard(didCreate: profile, withCredentials: credentials) NotificationCenter.default.post(name: .WizardDidCreate, object: nil, userInfo: [
WizardCreationKey.profile: profile,
WizardCreationKey.credentials: credentials
])
} }
} }

View File

@ -25,13 +25,11 @@
import UIKit import UIKit
class WizardProviderViewController: UITableViewController, Wizard { class WizardProviderViewController: UITableViewController {
var availableNames: [Infrastructure.Name] = [] var availableNames: [Infrastructure.Name] = []
private var createdProfile: ProviderConnectionProfile? private var createdProfile: ProviderConnectionProfile?
weak var delegate: WizardDelegate?
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
@ -55,7 +53,10 @@ class WizardProviderViewController: UITableViewController, Wizard {
fatalError("No profile created?") fatalError("No profile created?")
} }
dismiss(animated: true) { dismiss(animated: true) {
self.delegate?.wizard(didCreate: profile, withCredentials: credentials) NotificationCenter.default.post(name: .WizardDidCreate, object: nil, userInfo: [
WizardCreationKey.profile: profile,
WizardCreationKey.credentials: credentials
])
} }
} }

View File

@ -25,10 +25,12 @@
import Foundation import Foundation
protocol Wizard: class { extension Notification.Name {
var delegate: WizardDelegate? { get set } static let WizardDidCreate = Notification.Name("WizardDidCreate")
} }
protocol WizardDelegate: class { enum WizardCreationKey: String {
func wizard(didCreate profile: ConnectionProfile, withCredentials credentials: Credentials) case profile
case credentials
} }