Advertisement
Guest User

Untitled

a guest
Dec 6th, 2016
76
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.46 KB | None | 0 0
  1. //
  2. // SavedImagesViewController.swift
  3. // Kuoter
  4. //
  5. // Created by Leone Parise Vieira da Silva on 01/10/16.
  6. // Copyright © 2016 Kuoter. All rights reserved.
  7. //
  8.  
  9. import UIKit
  10. import RxDataSources
  11. import RxCocoa
  12. import RxSwift
  13. import RealmSwift
  14. import MisterFusion
  15. import Alamofire
  16. import RxAlamofire
  17. import Photos
  18. import SVProgressHUD
  19. import Async
  20.  
  21. private let cellId = "ImageCellId"
  22.  
  23. class SavedImagesViewController:RxViewController<SavedImagesViewModel>, NavigationAwareViewController, AlertViewControllerType {
  24. @IBOutlet weak var collectionView:GridCollectionView!
  25. @IBOutlet weak var deleteButton:UIBarButtonItem!
  26. @IBOutlet weak var saveButton:UIBarButtonItem!
  27. @IBOutlet weak var toolBar:UIToolbar!
  28. @IBOutlet weak var toolBarBottom: NSLayoutConstraint!
  29.  
  30. private var dataSource:RxCollectionViewSectionedAnimatedDataSource<ImageSection>!
  31.  
  32. private var emptyView:UIView!
  33.  
  34. override func viewDidLoad() {
  35. emptyView = R.nib.savedImagesEmptyView.firstView(owner: self)!
  36. self.view.addLayoutSubview(emptyView, andConstraints:
  37. self.emptyView.Top |-| self.top, self.emptyView.Left, self.emptyView.Right, self.emptyView.Bottom
  38. )
  39.  
  40. title = "Images I saved"
  41.  
  42. track(AppEvents.savedImagesOpen)
  43.  
  44. collectionView.columns = 3
  45. collectionView.registerClass(ImageCollectionViewCell.self, forCellWithReuseIdentifier: cellId)
  46. collectionView.allowsMultipleSelection = true
  47.  
  48. dataSource = RxCollectionViewSectionedAnimatedDataSource<ImageSection>()
  49. dataSource.animationConfiguration = AnimationConfiguration(insertAnimation: .Fade,
  50. reloadAnimation: .Fade,
  51. deleteAnimation: .Fade)
  52.  
  53. dataSource.configureCell = { ds, collectionView, indexPath, item in
  54. let cell = collectionView.dequeueReusableCellWithReuseIdentifier(cellId, forIndexPath: indexPath) as! ImageCollectionViewCell
  55. cell.imageURL = item.url
  56. cell.selected = item.selected
  57.  
  58. if item.selected {
  59. collectionView.selectItemAtIndexPath(indexPath, animated: false, scrollPosition: .None)
  60. } else {
  61. collectionView.deselectItemAtIndexPath(indexPath, animated: false)
  62. }
  63.  
  64. return cell
  65. }
  66.  
  67. setupSideMenu()
  68.  
  69. super.viewDidLoad()
  70. }
  71.  
  72. override func bindToViewModel() {
  73. viewModel.images.bindTo(collectionView.rx_itemsWithDataSource(dataSource))
  74. .addDisposableTo(rx_disposeBag)
  75.  
  76. collectionView.rx_modelSelected(ImageItem.self).bindTo(viewModel.inputs.addItem)
  77. .addDisposableTo(rx_disposeBag)
  78.  
  79. collectionView.rx_modelDeselected(ImageItem.self).bindTo(viewModel.inputs.deleteItem)
  80. .addDisposableTo(rx_disposeBag)
  81.  
  82. viewModel.empty.bindTo(emptyView.rx_visible)
  83. .addDisposableTo(rx_disposeBag)
  84.  
  85. deleteButton.rx_tap
  86. .track(AppEvents.imageDelete)
  87. .bindTo(viewModel.inputs.delete)
  88. .addDisposableTo(rx_disposeBag)
  89.  
  90. saveButton.rx_tap
  91. .track(AppEvents.imageGallerySave)
  92. .bindTo(viewModel.inputs.save)
  93. .addDisposableTo(rx_disposeBag)
  94.  
  95. viewModel.toolbarVisible.subscribeNext { [unowned self] (visible) in
  96. self.toggleToolbar(visible, animated: true)
  97. }.addDisposableTo(rx_disposeBag)
  98.  
  99. viewModel.saveResult.subscribeNext {[weak self] (result) in
  100. switch result {
  101. case .Success:
  102. Async.main(after: 0.4){
  103. SVProgressHUD.showSuccessWithStatus("Images saved!")
  104. }
  105. case .Failure:
  106. self?.showAlert(title: "Oh oh!", message: "An error happened when we tried to save images to your gallery. Check your settings and try again")
  107. }
  108. }.addDisposableTo(rx_disposeBag)
  109.  
  110. viewModel.executing
  111. .drive(SVProgressHUD.rx_visible)
  112. .addDisposableTo(rx_disposeBag)
  113.  
  114. super.bindToViewModel()
  115. }
  116.  
  117. private func toggleToolbar(visible:Bool, animated:Bool = true) {
  118. toolBarBottom.constant = visible ? 0 : -50
  119. if animated {
  120. UIView.animateWithDuration(0.3) { [unowned self] in
  121. self.view.layoutIfNeeded()
  122. }
  123. } else {
  124. self.view.layoutIfNeeded()
  125. }
  126. }
  127. }
  128.  
  129. class SavedImagesViewModel:RxViewModel {
  130. let inputs = (
  131. addItem:PublishSubject<ImageItem>(),
  132. deleteItem:PublishSubject<ImageItem>(),
  133. delete:PublishSubject<Void>(),
  134. save:PublishSubject<Void>()
  135. )
  136.  
  137. var images:Observable<[ImageSection]>!
  138. var toolbarVisible:Observable<Bool>!
  139. var empty:Observable<Bool>!
  140. var saveResult:Observable<RxResult<Void>>!
  141.  
  142. private var selected = Variable<Set<ImageItem>>(Set<ImageItem>())
  143.  
  144. init(imageManager:ImageManager) {
  145. super.init()
  146.  
  147. images = imageManager.rx_savedImages
  148. .map{ images in images.map{ $0.asImageItem } }
  149. .map{ [ImageSection(items:$0)] }
  150.  
  151. toolbarVisible = selected.asObservable().map{ $0.count > 0 }
  152.  
  153. inputs.addItem.subscribeNext {[unowned self] (item) in
  154. self.selected.value.insert(item)
  155. item.selected = true
  156. }.addDisposableTo(rx_disposeBag)
  157.  
  158. inputs.deleteItem.subscribeNext { [unowned self] (item) in
  159. self.selected.value.remove(item)
  160. item.selected = false
  161. }.addDisposableTo(rx_disposeBag)
  162.  
  163. inputs.delete.withLatestFrom(selected.asObservable())
  164. .doOnNext{ (selected) in
  165. for item in selected {
  166. try imageManager.deleteImage(item.url)
  167. }
  168. }
  169. .subscribeNext {[unowned self] (selected) in
  170. self.selected.value = Set()
  171. }
  172. .addDisposableTo(rx_disposeBag)
  173.  
  174. empty = images.map{ $0[0].items.count == 0 }
  175.  
  176. // MARK: Save images to gallery
  177. func downloadImages(images:Set<ImageItem>) -> Observable<[UIImage]> {
  178. return images.map{ item -> Observable<UIImage?> in
  179. Alamofire.request(.GET, item.url)
  180. .rx_data()
  181. .map{ UIImage(data:$0) }
  182. }.zip { (images) -> [UIImage] in
  183. images.flatMap{ $0 }
  184. .filter{ $0 != nil }
  185. .map{ $0! }
  186. }
  187. .trackActivity(self.activityIndicator)
  188. .observeOn(MainScheduler.instance)
  189. }
  190.  
  191. func saveImages(images:[UIImage]) -> Observable<Void> {
  192. let library = PHPhotoLibrary.sharedPhotoLibrary()
  193.  
  194. return images.map { image -> Observable<Bool> in
  195. library.rx_saveImage(image)
  196. }.zip { _ in
  197. return true
  198. }
  199. .mapToVoid()
  200. .trackActivity(self.activityIndicator)
  201. .observeOn(MainScheduler.instance)
  202. }
  203.  
  204. saveResult = inputs.save.withLatestFrom(selected.asObservable())
  205. .flatMapLatest(downloadImages)
  206. .flatMapLatest(saveImages)
  207. .shareReplayLatestWhileConnected()
  208. .mapToResult()
  209. }
  210. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement