Advertisement
Guest User

Untitled

a guest
Dec 6th, 2016
122
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 26.76 KB | None | 0 0
  1. //
  2. // ShareViewController.swift
  3. // Kuoter
  4. //
  5. // Created by Leone Parise Vieira da Silva on 23/09/16.
  6. // Copyright © 2016 Kuoter. All rights reserved.
  7. //
  8.  
  9. import UIKit
  10. import RxSwift
  11. import RxCocoa
  12. import TTTAttributedLabel
  13. import WebImage
  14. import SVProgressHUD
  15. import Photos
  16. import DAKeyboardControl
  17. import Appz
  18. import FBSDKShareKit
  19. import Async
  20. import Photos
  21. import Permission
  22. import RxOptional
  23.  
  24. class ShareViewController: RxViewController<ShareViewModel>, CloseableViewControllerType {
  25. @IBOutlet weak var contentView:UIView!
  26. @IBOutlet weak var quoteImageView:UIImageView!
  27. @IBOutlet weak var authorLabel:UILabel!
  28. @IBOutlet weak var overlayView:UIView!
  29.  
  30. @IBOutlet weak var changeFontButton:UIButton!
  31. @IBOutlet weak var changePicButton:UIButton!
  32. @IBOutlet weak var toggleOverlayButton:UIButton!
  33. @IBOutlet weak var decLineButton:UIButton!
  34. @IBOutlet weak var decWidthButton:UIButton!
  35. @IBOutlet weak var textAlignCenterButton:UIButton!
  36. @IBOutlet weak var toggleAuthorButton:UIButton!
  37.  
  38. @IBOutlet weak var facebookShareButton:UIButton!
  39. @IBOutlet weak var instagramShareButton:UIButton!
  40. @IBOutlet weak var whatsappShareButton:UIButton!
  41. @IBOutlet weak var messengerShareButton:UIButton!
  42. @IBOutlet weak var saveButton:UIButton!
  43. @IBOutlet weak var copyButton:UIButton!
  44. @IBOutlet weak var shareButton:UIButton!
  45. @IBOutlet weak var shareScrollView:UIScrollView!
  46. @IBOutlet weak var sharePageControl:UIPageControl!
  47. @IBOutlet weak var editView:EditTextAccessoryView!
  48. @IBOutlet weak var toolsScrollView:UIScrollView!
  49.  
  50. @IBOutlet weak var bottomConstraint: NSLayoutConstraint!
  51.  
  52. private var quoteLabel:TTTAttributedLabel!
  53. private var doc:UIDocumentInteractionController!
  54. private var pasteboard:UIPasteboard!
  55.  
  56. private var didAppear = false
  57. private var fontPickerView:FontPickerView!
  58. private var lineSpacePickerView:ArrayPickerView<CGFloat>!
  59. private var widthPickerView:ArrayPickerView<Int>!
  60. private var textAlignPickerView:ArrayPickerView<NSTextAlignment>!
  61.  
  62. override func viewDidLoad() {
  63. title = "Share"
  64.  
  65. let fontToolbar = toolbar(title: "Font & Size", icon: R.image.changeFontButton())
  66. fontPickerView = FontPickerView()
  67. fontPickerView.accessoryView = fontToolbar
  68. fontPickerView.add(toViewController: self)
  69.  
  70. let lineSpaceToolbar = toolbar(title: "Line Spacing", icon: R.image.lineSpaceDecButton())
  71. lineSpacePickerView = ArrayPickerView<CGFloat>()
  72. lineSpacePickerView.values = (-14).stride(through: 14, by: 2).map{ CGFloat($0) }
  73. lineSpacePickerView.startValue = 0
  74. lineSpacePickerView.titleForValue = { "\($0) pt" }
  75. lineSpacePickerView.accessoryView = lineSpaceToolbar
  76. lineSpacePickerView.add(toViewController: self)
  77.  
  78. let widthToolbar = toolbar(title: "Width", icon: R.image.widthDecButton())
  79. widthPickerView = ArrayPickerView<Int>()
  80. widthPickerView.values = 20.stride(through: 100, by: 5).map{ $0 }
  81. widthPickerView.startValue = 100
  82. widthPickerView.titleForValue = { "\($0) %" }
  83. widthPickerView.accessoryView = widthToolbar
  84. widthPickerView.add(toViewController: self)
  85.  
  86. let textAlignToolbar = toolbar(title: "Text Alignment", icon: R.image.centerAlignButton())
  87. textAlignPickerView = ArrayPickerView<NSTextAlignment>()
  88. textAlignPickerView.values = [.Left, .Center, .Right]
  89. textAlignPickerView.startValue = .Center
  90. textAlignPickerView.titleForValue = {
  91. switch $0 {
  92. case .Left: return "Left"
  93. case .Center: return "Center"
  94. case .Right: return "Right"
  95. default: return ""
  96. }
  97. }
  98. textAlignPickerView.accessoryView = textAlignToolbar
  99. textAlignPickerView.add(toViewController: self)
  100.  
  101. // Connect editor tools
  102. fontToolbar.nextField = lineSpacePickerView.hiddenTextField
  103. lineSpaceToolbar.backField = fontPickerView.hiddenTextField
  104. lineSpaceToolbar.nextField = widthPickerView.hiddenTextField
  105. widthToolbar.backField = lineSpacePickerView.hiddenTextField
  106. widthToolbar.nextField = textAlignPickerView.hiddenTextField
  107. textAlignToolbar.backField = widthPickerView.hiddenTextField
  108.  
  109. pasteboard = UIPasteboard.generalPasteboard()
  110.  
  111. quoteLabel = TTTAttributedLabel(frame: CGRectZero)
  112. quoteLabel.textColor = .whiteColor()
  113. quoteLabel.numberOfLines = 0
  114. quoteLabel.textAlignment = .Center
  115. quoteLabel.lineBreakMode = .ByWordWrapping
  116. quoteLabel.layer.cornerRadius = 5
  117. quoteLabel.clipsToBounds = true
  118. quoteLabel.hidden = true
  119. self.contentView.addSubview(quoteLabel)
  120.  
  121. let pan = UIPanGestureRecognizer(target: self, action: #selector(handlePan))
  122. self.quoteLabel.addGestureRecognizer(pan)
  123.  
  124. let doubleTap = UITapGestureRecognizer(target: self, action: #selector(self.editQuote))
  125. doubleTap.numberOfTapsRequired = 2
  126. self.quoteLabel.addGestureRecognizer(doubleTap)
  127.  
  128. shareScrollView.rx_contentOffset.map{ $0.x }.subscribeNext {[unowned self] x in
  129. let w = self.shareScrollView.frame.width
  130. self.sharePageControl.currentPage = Int(round(x / w))
  131. }.addDisposableTo(rx_disposeBag)
  132.  
  133. let didCropImage = { [weak self] (image:UIImage) -> Void in
  134. self?.quoteImageView.image = image
  135. UIApplication.topMostVC?.dismiss()
  136. }
  137.  
  138. let didSelectImage = { (image:UIImage) -> Void in
  139. if let parent = UIApplication.topMostVC as? UINavigationController {
  140. Navigator.push(MainRoute.Crop(image: image, action: didCropImage), parent: parent)
  141. }
  142. }
  143.  
  144. changePicButton.rx_tap
  145. .track(AppEvents.shareGalleryOpen)
  146. .subscribeNext { [unowned self] in
  147. if let parent = self.navigationController {
  148. Navigator.present(MainRoute.Gallery(action: didSelectImage), parent: parent)
  149. }
  150. }.addDisposableTo(rx_disposeBag)
  151.  
  152. setupCloseButton()
  153. super.viewDidLoad()
  154. }
  155.  
  156. override func viewWillAppear(animated: Bool) {
  157. self.view.addKeyboardPanningWithFrameBasedActionHandler(nil) {[unowned self] (keyboardRect, opening, closing) in
  158. let bottomSpace = max(0, self.view.bounds.h - keyboardRect.y)
  159. self.bottomConstraint.constant = bottomSpace
  160.  
  161. self.view.setNeedsLayout()
  162. self.view.layoutIfNeeded()
  163.  
  164. if closing {
  165. self.editView.hidden = true
  166. }
  167. }
  168.  
  169. super.viewWillAppear(animated)
  170. }
  171.  
  172. override func viewDidAppear(animated: Bool) {
  173. super.viewDidAppear(animated)
  174.  
  175. if didAppear { return }
  176.  
  177. //showOverlay() TODO: Enable when I develop better overlays
  178.  
  179. viewModel.initWidth(contentView.frame.w - 20)
  180. updateLabelSize(width: contentView.frame.w - 20)
  181. quoteLabel.center = contentView.center
  182. quoteLabel.hidden = false
  183.  
  184. didAppear = true
  185. }
  186.  
  187. override func viewWillDisappear(animated: Bool) {
  188. super.viewWillDisappear(animated)
  189. self.view.removeKeyboardControl()
  190. }
  191.  
  192. func handlePan(sender: UIPanGestureRecognizer) {
  193. if sender.state == .Began {
  194. self.showLabel()
  195. } else if sender.state == .Ended {
  196. self.hideLabel()
  197. }
  198.  
  199. let translation = sender.translationInView(self.view)
  200. sender.view!.center = CGPoint(x: sender.view!.center.x + translation.x,
  201. y: sender.view!.center.y + translation.y)
  202. sender.setTranslation(CGPointZero, inView: self.view)
  203. }
  204.  
  205. func updateLabelSize(width width:CGFloat? = nil) {
  206. // Center quote label
  207. let frame = quoteLabel.frame
  208. let size = quoteLabel.sizeThatFits(CGSize(width: width ?? frame.width, height: CGFloat.max))
  209. let w = min(contentView.frame.w, width ?? frame.width)
  210. quoteLabel.preferredMaxLayoutWidth = w
  211. quoteLabel.frame = CGRect(x: frame.x + (frame.w - w) / 2,
  212. y: frame.y,
  213. width: w,
  214. height: size.height)
  215. }
  216.  
  217. override func bindToViewModel() {
  218. changeFontButton.rx_tap
  219. .track(AppEvents.shareFontChange)
  220. .subscribeNext { [unowned self] in
  221. self.fontPickerView.show()
  222. }.addDisposableTo(rx_disposeBag)
  223.  
  224. decLineButton.rx_tap
  225. .track(AppEvents.shareLineSpacingChange)
  226. .subscribeNext {[unowned self] in
  227. self.lineSpacePickerView.show()
  228. }.addDisposableTo(rx_disposeBag)
  229.  
  230. decWidthButton.rx_tap
  231. .track(AppEvents.shareWidthChange)
  232. .subscribeNext{[unowned self] in
  233. self.widthPickerView.show()
  234. }.addDisposableTo(rx_disposeBag)
  235.  
  236. textAlignCenterButton.rx_tap
  237. .track(AppEvents.shareTextAlignmentChange)
  238. .subscribeNext{[unowned self] in
  239. self.textAlignPickerView.show()
  240. }.addDisposableTo(rx_disposeBag)
  241.  
  242. // INPUTS
  243. viewModel.quote.bindTo(editView.rx_text)
  244. .addDisposableTo(rx_disposeBag)
  245.  
  246. editView.rx_text.bindTo(viewModel.inputs.quote)
  247. .addDisposableTo(rx_disposeBag)
  248.  
  249. lineSpacePickerView.rx_valueSelected
  250. .bindTo(viewModel.inputs.lineSpace)
  251. .addDisposableTo(rx_disposeBag)
  252.  
  253. widthPickerView.rx_valueSelected
  254. .bindTo(viewModel.inputs.width)
  255. .addDisposableTo(rx_disposeBag)
  256.  
  257. textAlignPickerView.rx_valueSelected
  258. .bindTo(viewModel.inputs.textAlignment)
  259. .addDisposableTo(rx_disposeBag)
  260.  
  261. toggleAuthorButton.rx_tap
  262. .track(AppEvents.shareAuthorToggle)
  263. .bindTo(viewModel.inputs.toggleAuthor)
  264. .addDisposableTo(rx_disposeBag)
  265.  
  266. toggleOverlayButton.rx_tap
  267. .track(AppEvents.shareOverlayToggle)
  268. .bindTo(viewModel.inputs.toggleOverlay)
  269. .addDisposableTo(rx_disposeBag)
  270.  
  271. facebookShareButton.rx_tap
  272. .track(AppEvents.shareWithFacebook)
  273. .bindTo(viewModel.inputs.facebookShare)
  274. .addDisposableTo(rx_disposeBag)
  275.  
  276. messengerShareButton.rx_tap
  277. .track(AppEvents.shareWithMessenger)
  278. .bindTo(viewModel.inputs.messengerShare)
  279. .addDisposableTo(rx_disposeBag)
  280.  
  281. whatsappShareButton.rx_tap
  282. .track(AppEvents.shareWithWhatsapp)
  283. .bindTo(viewModel.inputs.whastappShare)
  284. .addDisposableTo(rx_disposeBag)
  285.  
  286. instagramShareButton.rx_tap
  287. .track(AppEvents.shareWithInstagram)
  288. .bindTo(viewModel.inputs.instagramShare)
  289. .addDisposableTo(rx_disposeBag)
  290.  
  291. copyButton.rx_tap
  292. .track(AppEvents.shareQuoteCopy)
  293. .bindTo(viewModel.inputs.copyShare)
  294. .addDisposableTo(rx_disposeBag)
  295.  
  296. shareButton.rx_tap
  297. .track(AppEvents.shareMoreActions)
  298. .bindTo(viewModel.inputs.moreShare)
  299. .addDisposableTo(rx_disposeBag)
  300.  
  301. saveButton.rx_tap
  302. .track(AppEvents.shareImageSave)
  303. .bindTo(viewModel.inputs.saveShare)
  304. .addDisposableTo(rx_disposeBag)
  305.  
  306. // OUTPUTS
  307. viewModel.quote.bindTo(rx_quote)
  308. .addDisposableTo(rx_disposeBag)
  309.  
  310. viewModel.author.bindTo(authorLabel.rx_text)
  311. .addDisposableTo(rx_disposeBag)
  312.  
  313. viewModel.font.bindTo(rx_quoteFont)
  314. .addDisposableTo(rx_disposeBag)
  315.  
  316. // The font output must be binded first to change the font picker view state
  317. viewModel.font.bindTo(fontPickerView.rx_fontSelected)
  318. .addDisposableTo(rx_disposeBag)
  319. // Bind font picker view to view model input
  320. fontPickerView.rx_fontSelected.mapToOptional()
  321. .bindTo(viewModel.inputs.font)
  322. .addDisposableTo(rx_disposeBag)
  323.  
  324. viewModel.lineSpace.bindTo(rx_lineSpace)
  325. .addDisposableTo(rx_disposeBag)
  326.  
  327. viewModel.image.bindTo(quoteImageView.rx_image)
  328. .addDisposableTo(rx_disposeBag)
  329.  
  330. viewModel.width.bindTo(rx_width)
  331. .addDisposableTo(rx_disposeBag)
  332.  
  333. viewModel.overlayLevel.bindTo(rx_overlayLevel)
  334. .addDisposableTo(rx_disposeBag)
  335.  
  336. viewModel.authorVisible.bindTo(rx_authorVisible)
  337. .addDisposableTo(rx_disposeBag)
  338.  
  339. viewModel.textAlignment.bindTo(rx_textAlignment)
  340. .addDisposableTo(rx_disposeBag)
  341.  
  342. viewModel.facebookShare.subscribeNext {[weak self] (quote, author) in
  343. self?.copyQuote(quote:quote, author: author)
  344. Async.main(after: 1){
  345. self?.showFacebookShare(self?.contentView.takeSnapshot())
  346. }
  347. }.addDisposableTo(rx_disposeBag)
  348.  
  349. viewModel.messengerShare.subscribeNext {[weak self] (quote, author) in
  350. self?.copyQuote(quote:quote, author: author)
  351. Async.main(after: 1){
  352. self?.showMessengerShare(self?.contentView.takeSnapshot())
  353. }
  354. }.addDisposableTo(rx_disposeBag)
  355.  
  356. viewModel.whatsappShare.subscribeNext {[weak self] (quote, author) in
  357. self?.copyQuote(quote:quote, author: author)
  358. Async.main(after: 1){
  359. self?.showWhatsappShare(self?.contentView.takeSnapshot())
  360. }
  361. }.addDisposableTo(rx_disposeBag)
  362.  
  363. viewModel.instagramShare.subscribeNext {[weak self] (quote, author) in
  364. self?.copyQuote(quote:quote, author: author)
  365. Async.main(after: 1){
  366. self?.showInstagramShare(self?.contentView.takeSnapshot())
  367. }
  368. }.addDisposableTo(rx_disposeBag)
  369.  
  370. viewModel?.copyShare.subscribeNext{[weak self] (quote, author) in
  371. self?.copyQuote(quote:quote, author: author)
  372. }.addDisposableTo(rx_disposeBag)
  373.  
  374. viewModel?.moreShare.subscribeNext{[weak self] (quote, author) in
  375. self?.copyQuote(quote:quote, author: author)
  376. Async.main(after: 1){
  377. self?.showMoreShare(self?.contentView.takeSnapshot())
  378. }
  379. }.addDisposableTo(rx_disposeBag)
  380.  
  381. viewModel?.saveShare.subscribeNext{[weak self] (quote, author) in
  382. self?.requestAndSaveImage(self?.contentView.takeSnapshot())
  383. }.addDisposableTo(rx_disposeBag)
  384.  
  385. super.bindToViewModel()
  386. }
  387.  
  388. private func animateTools() {
  389. UIView.animateWithDuration(0.3, delay: 0.3, options: [], animations: { [unowned self] in
  390. self.toolsScrollView.contentOffset = CGPoint(x: 60, y: 0)
  391. }, completion: { [unowned self] _ in
  392. self.toolsScrollView.setContentOffset(CGPointZero, animated: true)
  393. })
  394. }
  395.  
  396. private func flashLabel() {
  397. UIView.animateWithDuration(0.1, animations: { [unowned self] in
  398. self.quoteLabel.layer.backgroundColor = UIColor(white: 1, alpha: 0.3).CGColor
  399. }, completion: { _ in
  400. UIView.animateWithDuration(0.5) { [unowned self] in
  401. self.quoteLabel.layer.backgroundColor = UIColor(white: 1, alpha: 0.0).CGColor
  402. }
  403. })
  404. }
  405.  
  406. private func showLabel() {
  407. UIView.animateWithDuration(0.4) { [unowned self] in
  408. self.quoteLabel.layer.backgroundColor = UIColor(white: 1, alpha: 0.3).CGColor
  409. }
  410. }
  411.  
  412. private func hideLabel() {
  413. UIView.animateWithDuration(0.4) { [unowned self] in
  414. self.quoteLabel.layer.backgroundColor = UIColor(white: 1, alpha: 0.0).CGColor
  415. }
  416. }
  417.  
  418. @objc private func editQuote() {
  419. track(AppEvents.shareQuoteEdit)
  420. self.editView.hidden = false
  421. self.editView.startEditing()
  422. }
  423.  
  424. private func showOverlay() {
  425. if AppSession().didShowShareOverlay { return }
  426.  
  427. if let parent = UIApplication.topMostVC {
  428. Async.main(after:1) {
  429. Navigator.present(MainRoute.ShareOverlay, parent: parent, wrap: false, transitionStyle: .CrossDissolve)
  430. }
  431. }
  432. }
  433.  
  434. private func toolbar(title title:String, icon:UIImage?) -> EditorToolbar {
  435. let toolbar = EditorToolbar(frame: CGRect(x: 0, y: 0, width: self.view.w, height: 44))
  436. toolbar.title = title
  437. toolbar.icon = icon
  438. return toolbar
  439. }
  440. }
  441.  
  442. // MARK: Share Extensions
  443.  
  444. extension ShareViewController {
  445. private func copyQuote(quote quote:String, author:String) {
  446. pasteboard.string = "\(quote) - \(author)"
  447. SVProgressHUD.showSuccessWithStatus("Quote copied!")
  448. }
  449.  
  450. private func showFacebookShare(image:UIImage?) {
  451. let photo = FBSDKSharePhoto(image: image!, userGenerated: true)
  452.  
  453. let content = FBSDKSharePhotoContent()
  454. content.photos = [photo]
  455.  
  456. let dialog = FBSDKShareDialog()
  457. dialog.fromViewController = self
  458. dialog.shareContent = content
  459. dialog.mode = .Native
  460. dialog.show()
  461. }
  462.  
  463. private func showMessengerShare(image:UIImage?) {
  464. let photo = FBSDKSharePhoto(image: image!, userGenerated: true)
  465.  
  466. let content = FBSDKSharePhotoContent()
  467. content.photos = [photo]
  468.  
  469. FBSDKMessageDialog.showWithContent(content, delegate: nil)
  470. }
  471.  
  472. private func showMoreShare(image:UIImage?) {
  473. if
  474. let imageURL = image?.saveAsJPEG(withName: "share.jpg") {
  475. doc = UIDocumentInteractionController(URL: imageURL)
  476. doc.presentOpenInMenuFromRect(self.view.bounds, inView: self.view, animated: true)
  477. }
  478. }
  479.  
  480. private func showWhatsappShare(image:UIImage?) {
  481. if
  482. let imageURL = image?.saveAsJPEG(withName: "share.wai"),
  483. let appURL = NSURL(string:"whatsapp://app")
  484. where UIApplication.sharedApplication().canOpenURL(appURL) {
  485. doc = UIDocumentInteractionController(URL: imageURL)
  486. doc.UTI = "net.whatsapp.image"
  487. doc.presentOpenInMenuFromRect(self.view.bounds, inView: self.view, animated: true)
  488. }
  489. }
  490.  
  491. private func showInstagramShare(image:UIImage?) {
  492. if
  493. let imageURL = image?.saveAsJPEG(withName: "igo"),
  494. let appURL = NSURL(string:"instagram://app")
  495. where UIApplication.sharedApplication().canOpenURL(appURL) {
  496. doc = UIDocumentInteractionController(URL: imageURL)
  497. doc.UTI = "com.instagram.exclusivegram"
  498. doc.presentOpenInMenuFromRect(self.view.bounds, inView: self.view, animated: true)
  499. }
  500.  
  501. }
  502.  
  503. private func requestAndSaveImage(imageOrNil:UIImage?) {
  504. if Permission.Photos.status == .Authorized {
  505. if let image = imageOrNil {
  506. self.saveImage(image)
  507. }
  508. } else {
  509. Permission.Photos.request{[weak self] (status) in
  510. if let image = imageOrNil where status == .Authorized {
  511. self?.saveImage(image)
  512. }
  513. }
  514. }
  515. }
  516.  
  517. private func saveImage(image:UIImage) {
  518. PHPhotoLibrary.sharedPhotoLibrary().performChanges({
  519. PHAssetChangeRequest.creationRequestForAssetFromImage(image)
  520. }, completionHandler: { (success, error) in
  521. if success {
  522. SVProgressHUD.showSuccessWithStatus("Image saved!")
  523. } else {
  524. let alert = UIAlertController(title: "Could not save image to gallery",
  525. message:"An error happened when we tried to save the image into your gallery. Try again later.",
  526. preferredStyle: .Alert)
  527.  
  528. alert.addAction(UIAlertAction(title: "Ok", style: .Cancel, handler: nil))
  529. self.navigationController?.presentViewController(alert, animated: true, completion: nil)
  530. }
  531. })
  532. }
  533. }
  534.  
  535. // MARK: Rx Extensions
  536.  
  537. extension ShareViewController {
  538. var rx_quote:AnyObserver<String> {
  539. return UIBindingObserver(UIElement: self) { (vc, text) in
  540. vc.quoteLabel.text = text
  541. vc.updateLabelSize()
  542. }.asObserver()
  543. }
  544.  
  545. var rx_quoteFont:AnyObserver<UIFont> {
  546. return UIBindingObserver(UIElement: self){ (vc, font) in
  547. vc.quoteLabel.font = font
  548. vc.quoteLabel.text = vc.quoteLabel.text
  549. vc.updateLabelSize(width: vc.quoteLabel.frame.w)
  550. vc.flashLabel()
  551. }.asObserver()
  552. }
  553.  
  554. var rx_lineSpace:AnyObserver<CGFloat> {
  555. return UIBindingObserver(UIElement: self){ (vc, space) in
  556. vc.quoteLabel.lineSpacing = space
  557. vc.quoteLabel.text = vc.quoteLabel.text
  558. vc.updateLabelSize(width: vc.quoteLabel.frame.w)
  559. vc.flashLabel()
  560. }.asObserver()
  561. }
  562.  
  563. var rx_width:AnyObserver<CGFloat> {
  564. return UIBindingObserver(UIElement: self){ (vc, width) in
  565. vc.updateLabelSize(width: width)
  566. vc.flashLabel()
  567. }.asObserver()
  568. }
  569.  
  570. var rx_overlayLevel:AnyObserver<Int> {
  571. return UIBindingObserver(UIElement: self) { (vc, level) in
  572. let overlayIcon = { () -> UIImage? in
  573. switch level {
  574. case 1: return R.image.toggleOverlay25Button()
  575. case 2: return R.image.toggleOverlay50Button()
  576. case 3: return R.image.toggleOverlay75Button()
  577. default: return R.image.toggleOverlay0Button()
  578. }
  579. }()
  580.  
  581. vc.toggleOverlayButton.setImage(overlayIcon, forState: .Normal)
  582.  
  583. UIView.animateWithDuration(0.3){
  584. vc.overlayView.backgroundColor = UIColor.blackColor()
  585. .colorWithAlphaComponent(0.25 * CGFloat(level))
  586. }
  587. }.asObserver()
  588. }
  589.  
  590. var rx_authorVisible:AnyObserver<Bool> {
  591. return UIBindingObserver(UIElement: self) { (cell, visible) in
  592. cell.authorLabel.hidden = !visible
  593. cell.toggleAuthorButton.tintColor = visible ? UIColor.flatSkyBlueColorDark() : UIColor.lightGrayColor()
  594. }.asObserver()
  595. }
  596.  
  597. var rx_textAlignment:AnyObserver<NSTextAlignment> {
  598. return UIBindingObserver(UIElement: self) { (vc, alignment) in
  599. vc.quoteLabel.textAlignment = alignment
  600.  
  601. let image = { Void -> UIImage? in
  602. switch alignment {
  603. case .Left: return R.image.leftAlignButton()
  604. case .Center: return R.image.centerAlignButton()
  605. case .Right: return R.image.rightAlignButton()
  606. default: return nil
  607. }
  608. }()
  609.  
  610. vc.textAlignCenterButton.setImage(image, forState: .Normal)
  611. }.asObserver()
  612. }
  613. }
  614.  
  615. class ShareViewModel:RxViewModel {
  616. let inputs = (
  617. quote:Variable(""),
  618. font:Variable<UIFont?>(nil),
  619. lineSpace:Variable<CGFloat>(0.0),
  620. width:Variable<Int>(100),
  621. textAlignment:Variable<NSTextAlignment>(.Center),
  622. toggleAuthor:PublishSubject<Void>(),
  623. toggleOverlay:PublishSubject<Void>(),
  624. facebookShare:PublishSubject<Void>(),
  625. instagramShare:PublishSubject<Void>(),
  626. whastappShare:PublishSubject<Void>(),
  627. messengerShare:PublishSubject<Void>(),
  628. copyShare:PublishSubject<Void>(),
  629. saveShare:PublishSubject<Void>(),
  630. moreShare:PublishSubject<Void>()
  631. )
  632.  
  633. var quote:Observable<String>!
  634. var author:Observable<String>!
  635. var authorVisible:Observable<Bool>!
  636. var font:Observable<UIFont>!
  637. var lineSpace:Observable<CGFloat>!
  638. var width:Observable<CGFloat>!
  639. var overlayLevel:Observable<Int>!
  640. var image:Observable<UIImage?>!
  641. var textAlignment:Observable<NSTextAlignment>!
  642.  
  643. var facebookShare:Observable<(quote:String, author:String)>!
  644. var instagramShare:Observable<(quote:String, author:String)>!
  645. var whatsappShare:Observable<(quote:String, author:String)>!
  646. var messengerShare:Observable<(quote:String, author:String)>!
  647. var copyShare:Observable<(quote:String, author:String)>!
  648. var saveShare:Observable<(quote:String, author:String)>!
  649. var moreShare:Observable<(quote:String, author:String)>!
  650.  
  651. private let authorVar = Variable("")
  652. private let overlayLevelVar = Variable(1)
  653. private let authorVisibleVar = Variable(true)
  654. private let imageVar = Variable<UIImage?>(nil)
  655. private var maxWidth:CGFloat = 0.0
  656. private let fontIndex = Variable(0)
  657.  
  658. init(quote:String, author:String, font:UIFont, image:UIImage) {
  659. super.init()
  660.  
  661. inputs.quote.value = quote
  662.  
  663. authorVar.value = author
  664.  
  665. inputs.font.value = font
  666.  
  667. imageVar.value = image
  668.  
  669. self.quote = inputs.quote.asObservable().distinctUntilChanged()
  670.  
  671. self.author = authorVar.asObservable()
  672.  
  673. self.font = inputs.font.asObservable().filterNil()
  674.  
  675. self.lineSpace = inputs.lineSpace.asObservable()
  676.  
  677. self.width = inputs.width.asObservable()
  678. .map{[unowned self] w in self.maxWidth * CGFloat(w) / 100.0 }
  679.  
  680. self.overlayLevel = overlayLevelVar.asObservable()
  681.  
  682. self.authorVisible = authorVisibleVar.asObservable()
  683.  
  684. self.image = imageVar.asObservable()
  685.  
  686. self.textAlignment = inputs.textAlignment.asObservable()
  687.  
  688. let quoteAndAuthor$ = Observable.combineLatest(self.quote, self.author) { (quote:$0, author:$1) }
  689.  
  690. inputs.toggleAuthor.withLatestFrom(self.authorVisible)
  691. .subscribeNext{ [unowned self] visible in
  692. self.authorVisibleVar.value = !visible
  693. }.addDisposableTo(rx_disposeBag)
  694.  
  695. inputs.toggleOverlay.withLatestFrom(self.overlayLevel)
  696. .subscribeNext{ [unowned self] level in
  697. self.overlayLevelVar.value = level == 3 ? 0 : level + 1
  698. }.addDisposableTo(rx_disposeBag)
  699.  
  700. facebookShare = inputs.facebookShare.withLatestFrom(quoteAndAuthor$)
  701.  
  702. instagramShare = inputs.instagramShare.withLatestFrom(quoteAndAuthor$)
  703.  
  704. messengerShare = inputs.messengerShare.withLatestFrom(quoteAndAuthor$)
  705.  
  706. whatsappShare = inputs.whastappShare.withLatestFrom(quoteAndAuthor$)
  707.  
  708. copyShare = inputs.copyShare.withLatestFrom(quoteAndAuthor$)
  709.  
  710. saveShare = inputs.saveShare.withLatestFrom(quoteAndAuthor$)
  711.  
  712. moreShare = inputs.moreShare.withLatestFrom(quoteAndAuthor$)
  713. }
  714.  
  715. func initWidth(width:CGFloat) {
  716. self.maxWidth = width
  717. }
  718. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement