ServerListViewController.swift 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. //
  2. // ServerListViewController.swift
  3. // Bark
  4. //
  5. // Created by huangfeng on 2022/3/25.
  6. // Copyright © 2022 Fin. All rights reserved.
  7. //
  8. import Material
  9. import RxCocoa
  10. import RxDataSources
  11. import RxSwift
  12. import UIKit
  13. enum ServerActionType {
  14. case copy
  15. case reset(key: String?)
  16. case delete
  17. }
  18. func == (lhs: ServerActionType, rhs: ServerActionType) -> Bool {
  19. switch (lhs, rhs) {
  20. case (.copy, .copy),
  21. (.delete, .delete):
  22. return true
  23. case let (.reset(a), .reset(b)):
  24. return a == b
  25. default:
  26. return false
  27. }
  28. }
  29. class ServerListViewController: BaseViewController<ServerListViewModel> {
  30. let closeButton: BKButton = {
  31. let closeButton = BKButton()
  32. closeButton.setImage(UIImage(named: "baseline_keyboard_arrow_down_black_24pt")?.withRenderingMode(.alwaysTemplate), for: .normal)
  33. closeButton.frame = CGRect(x: 0, y: 0, width: 40, height: 40)
  34. closeButton.hitTestSlop = UIEdgeInsets(top: -10, left: -10, bottom: -10, right: -10)
  35. closeButton.tintColor = BKColor.grey.darken4
  36. return closeButton
  37. }()
  38. let tableView: UITableView = {
  39. let tableView = UITableView()
  40. tableView.separatorStyle = .none
  41. tableView.backgroundColor = BKColor.background.primary
  42. tableView.register(ServerListTableViewCell.self, forCellReuseIdentifier: "\(ServerListTableViewCell.self)")
  43. tableView.contentInset = UIEdgeInsets(top: 20, left: 0, bottom: 0, right: 0)
  44. return tableView
  45. }()
  46. override func makeUI() {
  47. self.title = NSLocalizedString("serverList")
  48. navigationItem.setRightBarButtonItem(item: UIBarButtonItem(customView: closeButton))
  49. self.view.addSubview(tableView)
  50. tableView.snp.makeConstraints { make in
  51. make.edges.equalToSuperview()
  52. }
  53. closeButton.rx.tap.subscribe {[weak self] in
  54. self?.dismiss(animated: true, completion: nil)
  55. } onError: { _ in
  56. }.disposed(by: rx.disposeBag)
  57. }
  58. override func bindViewModel() {
  59. let action = getServerAction()
  60. // 复制 server
  61. let copyServer = action.filter { $0.1 == ServerActionType.copy }
  62. .map { $0.0 }.asDriver(onErrorDriveWith: .empty())
  63. // 删除 server
  64. let deleteServer = action.filter { $0.1 == ServerActionType.delete }
  65. .map { $0.0 }.asDriver(onErrorDriveWith: .empty())
  66. // 重置 server key
  67. let resetServer = action.compactMap { r -> (Server, String?)? in
  68. if case let ServerActionType.reset(key) = r.1 {
  69. return (r.0, key)
  70. }
  71. return nil
  72. }.asDriver(onErrorDriveWith: .empty())
  73. let output = viewModel.transform(input: ServerListViewModel.Input(
  74. copyServer: copyServer,
  75. deleteServer: deleteServer,
  76. resetServer: resetServer
  77. ))
  78. let dataSource = RxTableViewSectionedReloadDataSource<SectionModel<String, ServerListTableViewCellViewModel>> { _, tableView, _, item -> UITableViewCell in
  79. if let cell = tableView.dequeueReusableCell(withIdentifier: "\(ServerListTableViewCell.self)") as? ServerListTableViewCell {
  80. cell.bindViewModel(model: item)
  81. return cell
  82. }
  83. return UITableViewCell()
  84. }
  85. // TableView数据源
  86. output.servers
  87. .drive(self.tableView.rx.items(dataSource: dataSource))
  88. .disposed(by: rx.disposeBag)
  89. // 复制文本
  90. output.copy
  91. .drive(onNext: { [weak self] text in
  92. UIPasteboard.general.string = text
  93. self?.showSnackbar(text: NSLocalizedString("Copy"))
  94. })
  95. .disposed(by: rx.disposeBag)
  96. // 弹出提示
  97. output.showSnackbar
  98. .drive(onNext: { [weak self] text in
  99. self?.showSnackbar(text: text)
  100. })
  101. .disposed(by: rx.disposeBag)
  102. }
  103. func getServerAction() -> Driver<(Server, ServerActionType)> {
  104. return tableView.rx
  105. .itemSelected
  106. .flatMapLatest { indexPath in
  107. let relay = PublishRelay<(Server, ServerActionType)>()
  108. guard let viewModel: ServerListTableViewCellViewModel = try? self.tableView.rx.model(at: indexPath) else {
  109. return relay;
  110. }
  111. let alertController = UIAlertController(title: nil, message: "\(viewModel.address.value)", preferredStyle: .actionSheet)
  112. alertController.addAction(UIAlertAction(title: NSLocalizedString("copyAddressAndKey"), style: .default, handler: { _ in
  113. relay.accept((viewModel.server, .copy))
  114. }))
  115. alertController.addAction(UIAlertAction(title: NSLocalizedString("resetKey"), style: .default, handler: { _ in
  116. let alertController = UIAlertController(title: NSLocalizedString("resetKey"), message: NSLocalizedString("resetKeyDesc"), preferredStyle: .alert)
  117. alertController.addTextField { textField in
  118. textField.placeholder = NSLocalizedString("resetKeyPlaceholder")
  119. }
  120. alertController.addAction(UIAlertAction(title: NSLocalizedString("confirm"), style: .default, handler: { _ in
  121. relay.accept((viewModel.server, .reset(key: alertController.textFields?.first?.text)))
  122. }))
  123. alertController.addAction(UIAlertAction(title: NSLocalizedString("Cancel"), style: .cancel, handler: nil))
  124. self.navigationController?.present(alertController, animated: true, completion: nil)
  125. }))
  126. alertController.addAction(UIAlertAction(title: NSLocalizedString("deleteServer"), style: .destructive, handler: { _ in
  127. let alertController = UIAlertController(title: nil, message: NSLocalizedString("confirmDeleteServer"), preferredStyle: .alert)
  128. alertController.addAction(UIAlertAction(title: NSLocalizedString("confirm"), style: .destructive, handler: { _ in
  129. relay.accept((viewModel.server, .delete))
  130. }))
  131. alertController.addAction(UIAlertAction(title: NSLocalizedString("Cancel"), style: .cancel, handler: nil))
  132. self.navigationController?.present(alertController, animated: true, completion: nil)
  133. }))
  134. alertController.addAction(UIAlertAction(title: NSLocalizedString("Cancel"), style: .cancel, handler: nil))
  135. if UIDevice.current.userInterfaceIdiom == .pad {
  136. alertController.modalPresentationStyle = .popover
  137. if let cell = self.tableView.cellForRow(at: indexPath) {
  138. alertController.popoverPresentationController?.sourceView = self.tableView
  139. alertController.popoverPresentationController?.sourceRect = cell.frame
  140. }
  141. }
  142. self.navigationController?.present(alertController, animated: true, completion: nil)
  143. return relay
  144. }.asDriver(onErrorDriveWith: .empty())
  145. }
  146. }