Last active
November 10, 2018 15:27
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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