Skip to content

Commit

Permalink
FEAT: Preset login values from network printer if it was selected
Browse files Browse the repository at this point in the history
  • Loading branch information
josefdolezal committed May 10, 2017
1 parent af61e8d commit 426966e
Show file tree
Hide file tree
Showing 8 changed files with 90 additions and 34 deletions.
18 changes: 10 additions & 8 deletions OctoPhone/Coordinators/PrinterListCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,16 @@ extension PrinterListCoordinator: PrinterListViewControllerDelegate {
}

func addPrinterButtonTapped() {
let coordinator = PrinterLoginCoordinator(
navigationController: navigationController,
contextManager: contextManager
)
presentPrinterLoginScreen()
}

func selectedNetworkPrinter(withService service: BonjourService) {
presentPrinterLoginScreen(withService: service)
}

private func presentPrinterLoginScreen(withService service: BonjourService? = nil) {
let coordinator = PrinterLoginCoordinator(navigationController: navigationController,
contextManager: contextManager, service: service)

coordinator.completed = { [weak self] in
self?.childCoordinators.removeLast()
Expand All @@ -49,8 +55,4 @@ extension PrinterListCoordinator: PrinterListViewControllerDelegate {
childCoordinators.append(coordinator)
coordinator.start()
}

func selectedNetworkPrinter(withService service: BonjourService) {

}
}
14 changes: 13 additions & 1 deletion OctoPhone/Coordinators/PrinterLoginCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,20 @@ import UIKit
/// Controlls printer login controller flow
final class PrinterLoginCoordinator: ContextCoordinator {

/// Network printer service
private let service: BonjourService?

init(navigationController: UINavigationController?, contextManager: ContextManagerType,
service: BonjourService?) {

self.service = service

super.init(navigationController: navigationController, contextManager: contextManager)
}

override func start() {
let viewModel = PrinterLoginViewModel(delegate: self, contextManager: contextManager)
let viewModel = PrinterLoginViewModel(delegate: self, contextManager: contextManager,
service: service)
let controller = PrinterLoginViewController(viewModel: viewModel)

navigationController?.present(UINavigationController(rootViewController: controller),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ extension PrinterListViewController {
if indexPath.section == 0 {
viewModel.inputs.selectedStoredPrinter(at: indexPath)
}

viewModel.inputs.selectedNetworkPrinter(at: indexPath.row)
}
}

Expand Down
11 changes: 11 additions & 0 deletions OctoPhone/View Related/Printer List/PrinterListViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ protocol PrinterListViewModelInputs {
/// - Parameter indexPath: Index path of selected printer
func selectedStoredPrinter(at indexPath: IndexPath)

/// Call when user selected network printer
///
/// - Parameter index: Index of printer
func selectedNetworkPrinter(at index: Int)

/// Call when user tapped button for printer addition
func addPrinterButtonTapped()
}
Expand Down Expand Up @@ -157,6 +162,12 @@ PrinterListViewModelOutputs {
delegate?.selectedPrinterProvider(provider: provider, printerID: printer.ID)
}

func selectedNetworkPrinter(at index: Int) {
let service = networkPrintersProperty.value[index]

delegate?.selectedNetworkPrinter(withService: service)
}

func addPrinterButtonTapped() {
delegate?.addPrinterButtonTapped()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,9 @@ final class PrinterLoginViewController: BaseViewController {

edgesForExtendedLayout = []

printerNameField.reactive.text <~ viewModel.outputs.namePreset
urlField.reactive.text <~ viewModel.outputs.addressPreset

printerNameField.reactive.continuousTextValues.observeValues { [weak self] name in
self?.viewModel.inputs.printerNameChanged(name)
}
Expand Down
62 changes: 42 additions & 20 deletions OctoPhone/View Related/Printer Login/PrinterLoginViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import ReactiveSwift
import ReactiveMoya
import RealmSwift

/// Inputs for login logic
protocol PrinterLoginViewModelInputs {
/// Call when view did load
func viewDidLoad()
Expand Down Expand Up @@ -47,14 +48,22 @@ protocol PrinterLoginViewModelInputs {
func cancelLoginPressed()
}

/// Outputs of login logic
protocol PrinterLoginViewModelOutputs {
/// Initial name of printer
var namePreset: ReactiveSwift.Property<String?> { get }

/// Initial address of printer
var addressPreset: ReactiveSwift.Property<String?> { get }

/// Bool value for form validation
var isFormValid: Signal<Bool, NoError> { get }
var isFormValid: SignalProducer<Bool, NoError> { get }

/// Errors which should be displayed
var displayError: Signal<DisplayableError, NoError> { get }
}

/// Common interface for login ViewModels
protocol PrinterLoginViewModelType {
/// View model inputs
var inputs: PrinterLoginViewModelInputs { get }
Expand All @@ -63,6 +72,7 @@ protocol PrinterLoginViewModelType {
var outputs: PrinterLoginViewModelOutputs { get }
}

/// Login screen logic
final class PrinterLoginViewModel: PrinterLoginViewModelType, PrinterLoginViewModelInputs,
PrinterLoginViewModelOutputs {

Expand All @@ -72,17 +82,21 @@ PrinterLoginViewModelOutputs {

// MARK: Outputs

let isFormValid: Signal<Bool, NoError>
let namePreset: ReactiveSwift.Property<String?>

let addressPreset: ReactiveSwift.Property<String?>

let isFormValid: SignalProducer<Bool, NoError>

let displayError: Signal<DisplayableError, NoError>

// MARK: Properties

/// Model property for printer name
private let printerNameProperty = MutableProperty<String?>(nil)
private let printerNameProperty: MutableProperty<String?>

/// Model property for printer URL
private let printerUrlProperty = MutableProperty<String?>(nil)
private let printerUrlProperty: MutableProperty<String?>

/// Model property for printer login token
private let tokenProperty = MutableProperty<String?>(nil)
Expand Down Expand Up @@ -112,24 +126,32 @@ PrinterLoginViewModelOutputs {
private weak var delegate: PrinterLoginViewControllerDelegate?

// swiftlint:disable function_body_length
init(delegate: PrinterLoginViewControllerDelegate, contextManager: ContextManagerType) {
init(delegate: PrinterLoginViewControllerDelegate, contextManager: ContextManagerType,
service: BonjourService? = nil) {

self.delegate = delegate
self.contextManager = contextManager

let formValues = Signal.combineLatest(
printerNameProperty.signal.skipNil(),
printerUrlProperty.signal.skipNil(),
tokenProperty.signal.skipNil(),
streamUrlProperty.signal
self.namePreset = Property(value: service?.name)
self.addressPreset = Property(value: service?.fullAddress)

// Set the initial values also to ViewModel
printerUrlProperty = MutableProperty(service?.fullAddress)
printerNameProperty = MutableProperty(service?.name)

let formValues = SignalProducer.combineLatest(
printerNameProperty.producer.skipNil(),
printerUrlProperty.producer.skipNil(),
tokenProperty.producer.skipNil(),
streamUrlProperty.producer
)

// Dirty hack to make stream URL optional
streamUrlProperty.value = nil

displayError = displayErrorProperty.signal.skipNil()

isFormValid = Signal.merge([
viewWillAppearProperty.signal.map({ _ in false }).take(first: 1),
isFormValid = SignalProducer.merge([
viewWillAppearProperty.producer.map({ _ in false }).take(first: 1),
formValues.map(PrinterLoginViewModel.isValid)
])

Expand All @@ -148,13 +170,13 @@ PrinterLoginViewModelOutputs {
.filterSuccessfulStatusCodes()
.map({_ in return printer })
.materialize()
}
}

// Observe for successful login
loginEvent.signal
loginEvent
.map({ $0.event.value })
.skipNil()
.observeValues { [weak self] printer in
.startWithValues { [weak self] printer in
guard let weakSelf = self else { return }

do {
Expand All @@ -166,19 +188,19 @@ PrinterLoginViewModelOutputs {
} catch { }

weakSelf.delegate?.successfullyLoggedIn()
}
}

// Observe for errors while logging in
loginEvent.signal
loginEvent
.map({ $0.event.error })
.skipNil()
.observeValues { [weak self] error in
.startWithValues { [weak self] error in
if case let .statusCode(response) = error, response.statusCode == 401 {
self?.displayErrorProperty.value = (tr(.loginError), tr(.incorrectCredentials))
} else {
self?.displayErrorProperty.value = (tr(.loginError), tr(.couldNotConnectToPrinter))
}
}
}
}
// swiftlint:enable function_body_length

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class PrinterListViewModelTests: QuickSpec {

contextManager = InMemoryContextManager()
subject = PrinterListViewModel(delegate: self, contextManager: contextManager)
subject.outputs.storedPrintersChanged.startWithValues { printersCountChanged += 1 }
subject.outputs.printersChanged.startWithValues { printersCountChanged += 1 }
}

afterEach {
Expand All @@ -52,22 +52,22 @@ class PrinterListViewModelTests: QuickSpec {
}

it("update printers count dataset changed") {
expect(printersCountChanged) == 1
expect(printersCountChanged) == 0
expect(subject.storedPrintersCount) == 0

let realm = try! contextManager.createContext()
try! realm.write {
realm.add(self.createPrinter(index: 0))
}

expect(printersCountChanged) == 2
expect(printersCountChanged) == 1
expect(subject.outputs.storedPrintersCount) == 1

try! realm.write {
realm.add(self.createPrinter(index: 1))
}

expect(printersCountChanged) == 3
expect(printersCountChanged) == 2
expect(subject.outputs.storedPrintersCount) == 2
}

Expand Down Expand Up @@ -118,4 +118,8 @@ extension PrinterListViewModelTests: PrinterListViewControllerDelegate {
func addPrinterButtonTapped() {
onAddPrinterButtonTapped?()
}

func selectedNetworkPrinter(withService service: BonjourService) {

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class PrinterLoginViewModelSpec: QuickSpec {
subject = PrinterLoginViewModel(delegate: self, contextManager: InMemoryContextManager())

subject.inputs.viewDidLoad()
subject.outputs.isFormValid.observeValues({ buttonEnabled = $0 })
subject.outputs.isFormValid.startWithValues({ buttonEnabled = $0 })
subject.inputs.viewWillAppear()
}

Expand Down

0 comments on commit 426966e

Please sign in to comment.