86b6b0893da0762d9806eR66">66
+ if attributesArr.count != itemCount || itemCount == 0 || itemWidth == -1 || isNeedLayout {
minColumn = 0
originIndex = 0
minColumnHeight = 0
@@ -73,6 +73,12 @@ public final class WaterfallFlowLayout: UICollectionViewLayout {
} else {
originIndex = attributesArr.count
}
+
+ if itemCount == 0 {
+ columnHeights = []
+ return
+ }
+
for i in originIndex..<itemCount {
guard let attributes = layoutAttributesForItem(at: IndexPath(row: i, section: 0))
else { continue }
@@ -81,9 +87,9 @@ public final class WaterfallFlowLayout: UICollectionViewLayout {
}
fileprivate func calculateViewSize() -> CGSize {
- guard let collectionView = collectionView,
+ guard let v = collectionView,
let maxH = columnHeights.max() else { return CGSize.zero }
- return CGSize(width: collectionView.bounds.width, height: maxH + configuration.rowSpace)
+ return CGSize(width: v.bounds.width, height: maxH + configuration.rowSpace)
}
fileprivate func calculateItemX() -> CGFloat {
@@ -117,4 +123,9 @@ public final class WaterfallFlowLayout: UICollectionViewLayout {
columnHeights[minColumn] = minColumnHeight
(minColumn, minColumnHeight) = columnHeights.enumerated().min(by: { $0.1 < $1.1 }) ?? (0, 0)
}
+
+ /// called at collectionView reload
+ func setNeedsLayout() {
+ isNeedLayout = true
+ }
}
@@ -41,9 +41,8 @@ public final class AppCoordinator: BaseCoordinator<Void> { |
||
41 | 41 |
extension AppCoordinator: ContainerViewControllerDelegate { |
42 | 42 |
func presentLogin() { |
43 | 43 |
let vc = makeLoginViewController() |
44 |
- coordinate(to: LoginCoordinator(vc, |
|
45 |
- rootViewController: containerViewController)) |
|
46 |
- .subscribe(onNext: { (_) in |
|
44 |
+ coordinate(to: LoginCoordinator(vc)) |
|
45 |
+ .subscribe(onNext: { _ in |
|
47 | 46 |
vc.removeFromParentAndView() |
48 | 47 |
}).disposed(by: disposeBag) |
49 | 48 |
navigationController.addFullScreen(childViewController: vc) |
@@ -58,7 +57,7 @@ extension AppCoordinator: ContainerViewControllerDelegate { |
||
58 | 57 |
} |
59 | 58 |
} |
60 | 59 |
|
61 |
-fileprivate extension AppCoordinator { |
|
60 |
+extension AppCoordinator { |
|
62 | 61 |
func makeContainerViewController() { |
63 | 62 |
containerViewController.userInfo = shareUserInfoViewModel |
64 | 63 |
containerViewController.delegate = self |
@@ -100,7 +99,7 @@ fileprivate extension AppCoordinator { |
||
100 | 99 |
} |
101 | 100 |
} |
102 | 101 |
|
103 |
-fileprivate extension AppCoordinator { |
|
102 |
+extension AppCoordinator { |
|
104 | 103 |
func makeMineViewController() -> MineViewController { |
105 | 104 |
let vc = MineViewController.instantiate() |
106 | 105 |
vc.userInfoViewModel = shareUserInfoViewModel |
@@ -63,6 +63,7 @@ final class GroupViewController: UIViewController { |
||
63 | 63 |
collectionView.register(UINib(nibName: "PhotoCell", |
64 | 64 |
bundle: Bundle(identifier: "com.Paiai-iOS")), |
65 | 65 |
forCellWithReuseIdentifier: "photoCell") |
66 |
+ collectionView.alwaysBounceVertical = true |
|
66 | 67 |
setup() |
67 | 68 |
binding() |
68 | 69 |
setupNavigationBar() |
@@ -36,7 +36,7 @@ final class HomeViewController: UIViewController { |
||
36 | 36 |
collectionView.register(UINib(nibName: "PhotoCell", |
37 | 37 |
bundle: Bundle(identifier: "com.Paiai-iOS")), |
38 | 38 |
forCellWithReuseIdentifier: "photoCell") |
39 |
- |
|
39 |
+ collectionView.alwaysBounceVertical = true |
|
40 | 40 |
setup() |
41 | 41 |
binding() |
42 | 42 |
} |
@@ -69,12 +69,12 @@ final class HomeViewController: UIViewController { |
||
69 | 69 |
/// UI bindings |
70 | 70 |
fileprivate extension HomeViewController { |
71 | 71 |
|
72 |
- var dataSource: RxCollectionViewSectionedAnimatedDataSource<AnimatableSectionModel<Int, PhotoItem>> { |
|
73 |
- return RxCollectionViewSectionedAnimatedDataSource<AnimatableSectionModel<Int, PhotoItem>>( |
|
72 |
+ var dataSource: RxCollectionViewSectionedAnimatedDataSource<AnimatableSectionModel<String, PhotoItem>> { |
|
73 |
+ return RxCollectionViewSectionedAnimatedDataSource<AnimatableSectionModel<String, PhotoItem>>( |
|
74 | 74 |
configureCell: {(_, collectionView, indexPath, item) -> UICollectionViewCell in |
75 |
- let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "photoCell", |
|
76 |
- for: indexPath) as! PhotoCell |
|
77 |
- cell.setInfo(item, source: .home) |
|
75 |
+ let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "photoCell", |
|
76 |
+ for: indexPath) as! PhotoCell |
|
77 |
+ cell.setInfo(item, source: .home) |
|
78 | 78 |
return cell |
79 | 79 |
}) |
80 | 80 |
} |
@@ -111,14 +111,16 @@ fileprivate extension HomeViewController { |
||
111 | 111 |
func bindUserInfoViewModelToView() { |
112 | 112 |
userInfoViewModel.isLoggedIn |
113 | 113 |
.asDriver(onErrorJustReturn: ()) |
114 |
- .drive(onNext: { (_) in |
|
114 |
+ .drive(onNext: {[unowned self] _ in |
|
115 |
+ self.viewModel.clear() |
|
115 | 116 |
self.collectionView.startRefreshing(at: .top) |
116 | 117 |
}).disposed(by: disposeBag) |
117 | 118 |
} |
118 | 119 |
|
119 | 120 |
func bindViewModelToCollectionView() { |
120 | 121 |
viewModel.contents |
121 |
- .bind(to: collectionView.rx.items(dataSource: dataSource)) |
|
122 |
+ .asDriver(onErrorDriveWith: .empty()) |
|
123 |
+ .drive(collectionView.rx.items(dataSource: dataSource)) |
|
122 | 124 |
.disposed(by: disposeBag) |
123 | 125 |
} |
124 | 126 |
|
@@ -10,21 +10,17 @@ import UIKit |
||
10 | 10 |
import RxSwift |
11 | 11 |
import PaiaiDataKit |
12 | 12 |
|
13 |
-class LoginCoordinator: BaseCoordinator<UserInfo> { |
|
14 |
- private let rootViewController: UIViewController |
|
13 |
+class LoginCoordinator: BaseCoordinator<Void> { |
|
15 | 14 |
private let loginViewController: LoginViewController |
16 | 15 |
|
17 |
- init(_ loginViewController: LoginViewController, |
|
18 |
- rootViewController: UIViewController) { |
|
19 |
- self.rootViewController = rootViewController |
|
16 |
+ init(_ loginViewController: LoginViewController) { |
|
20 | 17 |
self.loginViewController = loginViewController |
21 | 18 |
|
22 | 19 |
super.init(navigationController: UINavigationController(), viewController: loginViewController) |
23 | 20 |
} |
24 | 21 |
|
25 |
- override func start() -> Observable<UserInfo> { |
|
26 |
- let viewModel = UserInfoViewModel() |
|
27 |
- loginViewController.userInfoViewModel = viewModel |
|
28 |
- return viewModel.shareUserInfo.asObservable() |
|
22 |
+ override func start() -> Observable<Void> { |
|
23 |
+ |
|
24 |
+ return loginViewController.userInfoViewModel.loginCompleted |
|
29 | 25 |
} |
30 | 26 |
} |
@@ -39,7 +39,6 @@ extension LoginViewController { |
||
39 | 39 |
func binding() { |
40 | 40 |
bindInteraction() |
41 | 41 |
bindScrollViewDelegate() |
42 |
- bindUserInfoViewModelToView() |
|
43 | 42 |
} |
44 | 43 |
|
45 | 44 |
func bindInteraction() { |
@@ -52,12 +51,6 @@ extension LoginViewController { |
||
52 | 51 |
.disposed(by: disposeBag) |
53 | 52 |
} |
54 | 53 |
|
55 |
- func bindUserInfoViewModelToView() { |
|
56 |
- userInfoViewModel.loginCompleted.subscribe {[unowned self] _ in |
|
57 |
- self.removeFromParentAndView() |
|
58 |
- }.disposed(by: disposeBag) |
|
59 |
- } |
|
60 |
- |
|
61 | 54 |
func bindScrollViewDelegate() { |
62 | 55 |
scrollView.rx.didEndDecelerating |
63 | 56 |
.asDriver() |
@@ -59,6 +59,7 @@ extension MessageViewController { |
||
59 | 59 |
userInfoViewModel.isLoggedIn |
60 | 60 |
.asDriver(onErrorJustReturn: ()) |
61 | 61 |
.drive(onNext: {[unowned self] (_) in |
62 |
+ self.viewModel.clear() |
|
62 | 63 |
self.viewModel.reload() |
63 | 64 |
}).disposed(by: disposeBag) |
64 | 65 |
} |
@@ -33,10 +33,15 @@ extension MineCoordinator: MineViewControllerDelegate { |
||
33 | 33 |
func logout() { |
34 | 34 |
mineViewController.dismissController() |
35 | 35 |
didCancel.onNext(()) |
36 |
- |
|
37 |
- let vc = makeLoginViewController() |
|
38 |
- vc.userInfoViewModel = mineViewController.userInfoViewModel |
|
39 |
- navigationController.addFullScreen(childViewController: vc) |
|
36 |
+ |
|
37 |
+ guard let coordinator = parentCoordinator as? AppCoordinator else { return } |
|
38 |
+ |
|
39 |
+ let vc = coordinator.makeLoginViewController() |
|
40 |
+ let loginCoordinator = LoginCoordinator(vc) |
|
41 |
+ coordinator.coordinate(to: loginCoordinator).subscribe { _ in |
|
42 |
+ vc.dismissController() |
|
43 |
+ }.disposed(by: disposeBag) |
|
44 |
+ navigationController.presentController(vc) |
|
40 | 45 |
} |
41 | 46 |
|
42 | 47 |
func didSelect(_ item: MineItem) { |
@@ -58,9 +63,6 @@ extension MineCoordinator: MineViewControllerDelegate { |
||
58 | 63 |
self.didCancel.onNext(()) |
59 | 64 |
}).disposed(by: disposeBag) |
60 | 65 |
} |
61 |
- |
|
62 |
- func loginout() { |
|
63 |
- } |
|
64 | 66 |
} |
65 | 67 |
|
66 | 68 |
extension MineCoordinator: MineGroupViewModelDelegate { |
@@ -74,12 +76,6 @@ extension MineCoordinator: MineGroupViewModelDelegate { |
||
74 | 76 |
} |
75 | 77 |
|
76 | 78 |
fileprivate extension MineCoordinator { |
77 |
- func makeLoginViewController() -> LoginViewController { |
|
78 |
- let vc = LoginViewController.instantiate() |
|
79 |
-// vc.userInfoViewModel = shareUserInfoViewModel |
|
80 |
- return vc |
|
81 |
- } |
|
82 |
- |
|
83 | 79 |
func makeMineGroupViewController() -> MineGroupViewController { |
84 | 80 |
let vc = MineGroupViewController.instantiate() |
85 | 81 |
vc.viewModel = MineGroupViewModel() |
@@ -20,6 +20,7 @@ public class BaseCoordinator<ResultType> { |
||
20 | 20 |
|
21 | 21 |
private let identifier = UUID() |
22 | 22 |
private var childCoordinators = [UUID: Any]() |
23 |
+ var parentCoordinator: (Any)? = nil |
|
23 | 24 |
|
24 | 25 |
init(navigationController: UINavigationController, viewController: UIViewController) { |
25 | 26 |
self.viewController = viewController |
@@ -37,6 +38,7 @@ public class BaseCoordinator<ResultType> { |
||
37 | 38 |
|
38 | 39 |
func coordinate<T>(to coordinator: BaseCoordinator<T>) -> Observable<T> { |
39 | 40 |
store(coordinator: coordinator) |
41 |
+ coordinator.parentCoordinator = self |
|
40 | 42 |
return coordinator.start() |
41 | 43 |
.do(onNext: { [weak self] _ in |
42 | 44 |
self?.free(coordinator: coordinator) |