-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
Copy pathProjectNavigatorPagesDataSource.swift
129 lines (99 loc) · 4.18 KB
/
ProjectNavigatorPagesDataSource.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 KsApi
import Library
internal final class ProjectNavigatorPagesDataSource: NSObject, UIPageViewControllerDataSource {
fileprivate let initialProject: Project
fileprivate var playlist: [Project] = []
fileprivate let refTag: RefTag
fileprivate var viewControllers: [UIViewController?] = []
init(refTag: RefTag, initialPlaylist: [Project]?, initialProject: Project) {
self.initialProject = initialProject
self.playlist = initialPlaylist ?? [initialProject]
self.refTag = refTag
super.init()
self.padControllers(toLength: self.playlist.count)
}
internal func updatePlaylist(_ playlist: [Project]) {
self.playlist = playlist
}
internal func initialController() -> UIViewController? {
return self.playlist.index(of: self.initialProject).flatMap(self.controllerFor(index:))
}
internal func initialPamphletController() -> ProjectPamphletViewController? {
return self.playlist.index(of: self.initialProject).flatMap(self.projectPamphletControllerFor(index:))
}
internal func controllerFor(index: Int) -> UIViewController? {
guard index >= 0 && index < self.playlist.count else { return nil }
let project = self.playlist[index]
self.padControllers(toLength: index)
self.viewControllers[index] = self.viewControllers[index]
?? self.createViewController(forProject: project)
return self.viewControllers[index]
}
internal func projectPamphletControllerFor(index: Int) -> ProjectPamphletViewController? {
return self.controllerFor(index: index)
.flatMap { $0 as? UINavigationController }
.flatMap { $0.viewControllers.first as? ProjectPamphletViewController }
}
internal func indexFor(controller: UIViewController) -> Int? {
return self.viewControllers.index { $0 == controller }
}
internal func projectFor(controller: UIViewController) -> Project? {
return self.indexFor(controller: controller).map { self.playlist[$0] }
}
internal func pageViewController(
_ pageViewController: UIPageViewController,
viewControllerAfter viewController: UIViewController) -> UIViewController? {
guard let pageIdx = self.viewControllers.index(where: { $0 == viewController }) else {
fatalError("Couldn't find \(viewController) in \(self.viewControllers)")
}
let nextPageIdx = pageIdx + 1
guard nextPageIdx < self.playlist.count else {
return nil
}
let project = self.playlist[nextPageIdx]
self.padControllers(toLength: nextPageIdx)
self.viewControllers[nextPageIdx] = self.viewControllers[nextPageIdx]
?? self.createViewController(forProject: project)
self.clearViewControllersFarAway(fromIndex: nextPageIdx)
return self.viewControllers[nextPageIdx]
}
internal func pageViewController(
_ pageViewController: UIPageViewController,
viewControllerBefore
viewController: UIViewController) -> UIViewController? {
guard let pageIdx = self.viewControllers.index(where: { $0 == viewController }) else {
fatalError("Couldn't find \(viewController) in \(self.viewControllers)")
}
let previousPageIdx = pageIdx - 1
guard previousPageIdx >= 0 else {
return nil
}
let project = self.playlist[previousPageIdx]
self.padControllers(toLength: previousPageIdx)
self.viewControllers[previousPageIdx] = self.viewControllers[previousPageIdx]
?? self.createViewController(forProject: project)
self.clearViewControllersFarAway(fromIndex: previousPageIdx)
return self.viewControllers[previousPageIdx]
}
fileprivate func createViewController(forProject project: Project) -> UIViewController {
return UINavigationController(
rootViewController: ProjectPamphletViewController.configuredWith(
projectOrParam: .left(project),
refTag: self.refTag
)
)
}
fileprivate func clearViewControllersFarAway(fromIndex index: Int) {
self.viewControllers.indices
.filter { abs($0 - index) >= 3 }
.forEach { idx in
self.viewControllers[idx] = nil
}
}
fileprivate func padControllers(toLength length: Int) {
guard self.viewControllers.count <= length else { return }
(self.viewControllers.count...length).forEach { _ in
self.viewControllers.append(nil)
}
}
}