Skip to content

Instantly share code, notes, and snippets.

@YannisDC
Last active November 10, 2018 15:27
Show Gist options
  • Save YannisDC/b46e2a567fa0792e7884580dd51e68b6 to your computer and use it in GitHub Desktop.
Save YannisDC/b46e2a567fa0792e7884580dd51e68b6 to your computer and use it in GitHub Desktop.
A short piece of code showing how you can use RxSwift and MVVM to make a view that can reactively save an image encrypted on Blockstack.
import Foundation
import Core
import RxSwift
import Blockstack
final class UseCaseProvider: Core.UseCaseProvider {
private let awesome: Core.AwesomeProvider
init() {
awesome = AwesomeProvider()
}
func awesomeProvider() -> Core.AwesomeProvider {
return awesome
}
}
final class AwesomeProvider: Core.AwesomeProvider {
private var blockstack = Blockstack.shared
func saveImageEncrypted(path: String, image: UIImage) -> Observable<String?> {
if let imageData = image.jpegData(compressionQuality: 0.5)?.bytes {
return self.blockstack.rx.saveEncrypted(path: path, bytes: imageData)
}
return Observable.just(nil)
}
}
extension Reactive where Base: Blockstack {
func saveEncrypted(path: String, bytes: Bytes) -> Observable<String?> {
return Observable.deferred {
return Observable.create { observer in
self.base.putFile(to: path, bytes: bytes, encrypt: true) { (publicURL, error) in
if let error = error {
observer.onError(error)
} else {
observer.onNext((publicURL))
observer.onCompleted()
}
}
return Disposables.create()
}
}.subscribeOn(OperationQueueScheduler(operationQueue: OperationQueue()))
}
}
// ViewModel
import Foundation
import RxSwift
import RxCocoa
final class SaveViewModel: ViewModel {
private var usecase = UseCaseProvider().awesomeProvider()
fileprivate let imagesTrigger: PublishSubject<UIImage?>
init(imagesTrigger: PublishSubject<UIImage?>) {
self.imagesTrigger = imagesTrigger
}
func transform(input: SaveViewModel.Input) -> SaveViewModel.Output {
let imageToSave = imagesTrigger.asDriver(onErrorJustReturn: nil)
let saveResult = input.saveTap
// TODO: UploadConfirmation output Driver<Bool> that shows some animation or coordinates to new viewcontroller
let uploadConfirmation = saveResult
.withLatestFrom(imageToSave)
.flatMapLatest { (image) -> Driver<String?> in
guard let image = image else { return Driver.just(nil) }
return self.usecase
.saveImageEncrypted(path: "testFile", image: image)
.do(onNext: { (path) in
print(path)
}).asDriver(onErrorJustReturn: nil)
}
return Output(saveResult: saveResult,
imageToSave: imageToSave,
uploadConfirmation: uploadConfirmation)
}
}
// MARK: - ViewModel
extension HomeViewModel {
struct Input {
let saveTap: Driver<Void>
}
struct Output {
let saveResult: Driver<Void>
let imageToSave: Driver<UIImage?>
let uploadConfirmation: Driver<String?>
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment