説明なし

MessageListViewController.swift 5.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. //
  2. // MessageListViewController.swift
  3. // Paiai_iOS
  4. //
  5. // Created by FFIB on 16/5/13.
  6. // Copyright © 2016年 FFIB. All rights reserved.
  7. //
  8. import UIKit
  9. import RxSwift
  10. import RxCocoa
  11. import RxDataSources
  12. import PaiaiDataKit
  13. import PaiaiUIKit
  14. import PullToRefresh
  15. protocol MessageViewControllerDelegate: class {
  16. func didSelect(item: MessageItem)
  17. }
  18. final class MessageListViewController: UIViewController {
  19. @IBOutlet weak var tableView: UITableView!
  20. var emptyView: UILabel = {
  21. let empty = UILabel(frame: CGRect(x: kScreenWidth / 2 - 50, y: 5, width: 50, height: 50))
  22. empty.isHidden = true
  23. empty.text = "当前没有任何消息"
  24. empty.textColor = UIColor.gray
  25. empty.font = UIFont.systemFont(ofSize: 14)
  26. empty.sizeToFit()
  27. return empty
  28. }()
  29. var viewModel: MessageListViewModel!
  30. var type: MessageType!
  31. fileprivate let disposeBag = DisposeBag()
  32. // MARK: view function
  33. override func viewDidLoad() {
  34. super.viewDidLoad()
  35. view.addSubview(emptyView)
  36. setup()
  37. binding()
  38. setupNavigationBar()
  39. self.viewModel.reload()
  40. }
  41. private func setupNavigationBar() {
  42. navigationItem.title = type.model.title
  43. let rightItem = UIBarButtonItem(image: UIImage.Navigation.right, target: self, action: #selector(clearMessage))
  44. navigationItem.setRightItem(rightItem)
  45. }
  46. private func setup() {
  47. setupReloadControl()
  48. setupLoadingControl()
  49. }
  50. private func setupReloadControl() {
  51. tableView.addPullToRefresh(PullToRefresh()) {
  52. [weak self] in
  53. guard let `self` = self else { return }
  54. self.viewModel.reload()
  55. }
  56. tableView.startRefreshing(at: .top)
  57. }
  58. private func setupLoadingControl() {
  59. tableView.addPullToRefresh(PullToRefresh(position: .bottom)) {
  60. [weak self] in
  61. guard let `self` = self else { return }
  62. self.viewModel.preload()
  63. }
  64. }
  65. // MARK: button function
  66. @objc func clearMessage() {
  67. let alert = ActionSheetController()
  68. alert.addAlertAction(AlertAction(title: "取消", style: .cancel))
  69. alert.addAlertAction(AlertAction(title: "清空消息", handler: { _ in
  70. self.viewModel.removeAll()
  71. }))
  72. presentController(alert)
  73. }
  74. deinit {
  75. tableView.endAllRefreshing()
  76. }
  77. }
  78. fileprivate extension MessageListViewController {
  79. func observeMessage() {
  80. viewModel.showMessage
  81. .asDriver { _ in fatalError("Unexpected error from error messages observable.") }
  82. .drive(onNext: { message in
  83. Toast.show(message: message)
  84. })
  85. .disposed(by: disposeBag)
  86. }
  87. }
  88. fileprivate extension MessageListViewController {
  89. var dataSource: RxTableViewSectionedAnimatedDataSource<AnimatableSectionModel<Int, MessageListItem>> {
  90. return RxTableViewSectionedAnimatedDataSource<AnimatableSectionModel<Int, MessageListItem>>(
  91. configureCell: { (_, tableView, indexPath, item) in
  92. switch self.type! {
  93. case .system:
  94. let cell = tableView.dequeueReusableCell(withIdentifier: "messageSystemCell",
  95. for: indexPath) as! MessageSystemCell
  96. cell.setInfo(item)
  97. return cell
  98. case .comment, .thumbup:
  99. let cell = tableView.dequeueReusableCell(withIdentifier: "messageCommentAndThumbupCell",
  100. for: indexPath) as! MessageCommentAndThumbupCell
  101. cell.setInfo(item)
  102. return cell
  103. }
  104. }, canEditRowAtIndexPath: { _, _ in true })
  105. }
  106. func binding() {
  107. observeMessage()
  108. bindViewModelToTableView()
  109. bindTableViewToViewModel()
  110. bindViewModelToRefreshing()
  111. }
  112. func bindViewModelToTableView() {
  113. viewModel.isEmpty
  114. .bind(to: emptyView.rx.isHidden)
  115. .disposed(by: disposeBag)
  116. viewModel.contents
  117. .bind(to: tableView.rx.items(dataSource: dataSource))
  118. .disposed(by: disposeBag)
  119. }
  120. func bindTableViewToViewModel() {
  121. tableView.rx.itemDeleted
  122. .asDriver()
  123. .drive(onNext: { [unowned self] in self.viewModel.remove(of: $0.row) })
  124. .disposed(by: disposeBag)
  125. tableView.rx.modelSelected(MessageListItem.self)
  126. .asDriver()
  127. .drive(onNext: { [unowned self] in self.viewModel.didSelect(item: $0) })
  128. .disposed(by: disposeBag)
  129. tableView.rx.willDisplayCell
  130. .asDriver()
  131. .drive(onNext: { [unowned self] in self.preload(indexPath: $0.indexPath) })
  132. .disposed(by: disposeBag)
  133. }
  134. func preload(indexPath: IndexPath) {
  135. guard indexPath.row == tableView.numberOfRows(inSection: 0) - 5 else { return }
  136. tableView.startRefreshing(at: .bottom)
  137. }
  138. func bindViewModelToRefreshing() {
  139. viewModel.isLoading
  140. .asDriver(onErrorJustReturn: true)
  141. .drive(onNext: {[weak self] flag in
  142. guard let `self` = self else { return }
  143. if flag {
  144. self.tableView.endRefreshing(at: .top)
  145. } else {
  146. self.tableView.endRefreshing(at: .bottom)
  147. }
  148. }).disposed(by: disposeBag)
  149. }
  150. }
  151. extension MessageListViewController: NavigationBackViewController {}
  152. extension MessageListViewController: Storyboarded {
  153. static func instantiate() -> MessageListViewController {
  154. return UIStoryboard.message.instantiateViewController(type: MessageListViewController.self)
  155. }
  156. }