ZcashLightClientKit/Example/ZcashLightClientSample/ZcashLightClientSample/Sync Blocks/SyncBlocksViewController.swift

147 lines
4.4 KiB
Swift
Raw Normal View History

//
// SyncBlocksViewController.swift
// ZcashLightClientSample
//
// Created by Francisco Gindre on 11/1/19.
// Copyright © 2019 Electric Coin Company. All rights reserved.
//
import UIKit
import ZcashLightClientKit
/**
Sync blocks view controller leverages Compact Block Processor directly. This provides more detail on block processing if needed.
2020-03-26 07:27:55 -07:00
We advise to use the SDKSynchronizer first since it provides a lot of functionality out of the box.
*/
class SyncBlocksViewController: UIViewController {
@IBOutlet weak var statusLabel: UILabel!
@IBOutlet weak var progressBar: UIProgressView!
@IBOutlet weak var progressLabel: UILabel!
@IBOutlet weak var startPause: UIButton!
private var processor: CompactBlockProcessor?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let wallet = Initializer.shared
processor = CompactBlockProcessor(initializer: wallet)
statusLabel.text = textFor(state: processor?.state ?? .stopped)
progressBar.progress = 0
NotificationCenter.default.addObserver(self, selector: #selector(processorNotification(_:)), name: nil, object: processor)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
NotificationCenter.default.removeObserver(self)
guard let processor = self.processor else { return }
processor.stop()
}
@objc func processorNotification(_ notification: Notification) {
DispatchQueue.main.async {
guard self.processor != nil else { return }
self.updateUI()
switch notification.name {
case let not where not == Notification.Name.blockProcessorUpdated:
guard let progress = notification.userInfo?[CompactBlockProcessorNotificationKey.progress] as? Float else { return }
self.progressBar.progress = progress
self.progressLabel.text = "\(progress)%"
default:
return
}
}
}
@IBAction func startStop() {
guard let processor = processor else { return }
switch processor.state {
case .stopped:
startProcessor()
default:
stopProcessor()
}
}
func startProcessor() {
guard let processor = processor else { return }
do {
try processor.start()
updateUI()
} catch {
fail(error: error)
}
}
func stopProcessor() {
guard let processor = processor else { return }
processor.stop(cancelTasks: true)
updateUI()
}
func fail(error: Error) {
let alert = UIAlertController(title: "Error", message: "\(error)", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Ok", style: .cancel, handler: { (_) in
self.navigationController?.popViewController(animated: true)
}))
self.present(alert, animated: true, completion: nil)
updateUI()
}
func updateUI() {
guard let state = processor?.state else { return }
statusLabel.text = textFor(state: state)
startPause.setTitle(buttonText(for: state), for: .normal)
if case CompactBlockProcessor.State.synced = state {
startPause.isEnabled = false
} else {
startPause.isEnabled = true
}
}
func buttonText(for state: CompactBlockProcessor.State) -> String {
switch state {
case .downloading, .scanning, .validating:
return "Pause"
case .stopped:
return "Start"
case .error(_):
return "Retry"
case .synced:
return "Chill!"
}
}
func textFor(state: CompactBlockProcessor.State) -> String {
switch state {
case .downloading:
return "Downloading ⛓"
case .error(_):
return "error 💔"
case .scanning:
return "Scanning Blocks 🤖"
case .stopped:
return "Stopped 🚫"
case .validating:
return "Validating chain 🕵️‍♀️"
case .synced:
return "Synced 😎"
}
}
}