72c6167121a48e30786b6b0893da0762d9806eR66">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) |