-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
ImmuTableViewController.swift
129 lines (104 loc) · 4.27 KB
/
ImmuTableViewController.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import UIKit
import WordPressShared
typealias ImmuTableRowControllerGenerator = (ImmuTableRow) -> UIViewController
protocol ImmuTablePresenter: class {
func push(_ controllerGenerator: @escaping ImmuTableRowControllerGenerator) -> ImmuTableAction
func present(_ controllerGenerator: @escaping ImmuTableRowControllerGenerator) -> ImmuTableAction
}
extension ImmuTablePresenter where Self: UIViewController {
internal func push(_ controllerGenerator: @escaping ImmuTableRowControllerGenerator) -> ImmuTableAction {
return {
[unowned self] in
let controller = controllerGenerator($0)
self.navigationController?.pushViewController(controller, animated: true)
}
}
internal func present(_ controllerGenerator: @escaping ImmuTableRowControllerGenerator) -> ImmuTableAction {
return {
[unowned self] in
let controller = controllerGenerator($0)
self.present(controller, animated: true)
}
}
}
extension ImmuTablePresenter {
func prompt<T: UIViewController>(_ controllerGenerator: @escaping (ImmuTableRow) -> T) -> ImmuTableAction where T: Confirmable {
return present({
let controller = controllerGenerator($0)
return PromptViewController(controller)
})
}
}
protocol ImmuTableController {
var title: String { get }
var immuTableRows: [ImmuTableRow.Type] { get }
var noticeMessage: String? { get }
func tableViewModelWithPresenter(_ presenter: ImmuTablePresenter) -> ImmuTable
func refreshModel()
}
/// Generic view controller to present ImmuTable-based tables
///
/// Instead of subclassing the view controller, this is designed to be used from
/// a "controller" class that handles all the logic, and updates the view
/// controller, like you would update a view.
final class ImmuTableViewController: UITableViewController, ImmuTablePresenter {
fileprivate lazy var handler: ImmuTableViewHandler = {
return ImmuTableViewHandler(takeOver: self)
}()
fileprivate var noticeAnimator: NoticeAnimator!
let controller: ImmuTableController
// MARK: - Table View Controller
init(controller: ImmuTableController) {
self.controller = controller
super.init(style: .grouped)
title = controller.title
registerRows(controller.immuTableRows)
controller.refreshModel()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
noticeAnimator = NoticeAnimator(target: view)
WPStyleGuide.configureColors(for: view, andTableView: tableView)
WPStyleGuide.configureAutomaticHeightRows(for: tableView)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
noticeAnimator.layout()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
loadModel()
NotificationCenter.default.addObserver(
self,
selector: #selector(ImmuTableViewController.loadModel),
name: NSNotification.Name(rawValue: ImmuTableViewController.modelChangedNotification),
object: nil)
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
NotificationCenter.default.removeObserver(self,
name: NSNotification.Name(rawValue: ImmuTableViewController.modelChangedNotification),
object: nil)
}
// MARK: - Inputs
/// Registers custom rows
/// - seealso: ImmuTable.registerRows(_:tableView)
func registerRows(_ rows: [ImmuTableRow.Type]) {
ImmuTable.registerRows(rows, tableView: tableView)
}
@objc func loadModel() {
handler.viewModel = controller.tableViewModelWithPresenter(self)
noticeMessage = controller.noticeMessage
}
@objc var noticeMessage: String? = nil {
didSet {
guard noticeMessage != oldValue else { return }
noticeAnimator.animateMessage(noticeMessage)
}
}
// MARK: - Constants
@objc static let modelChangedNotification = "ImmuTableControllerChanged"
}