From c18bd3456dba3d4a2560ec539071457b5eece012 Mon Sep 17 00:00:00 2001 From: Theo Spears Date: Thu, 5 Dec 2024 15:24:40 -0800 Subject: [PATCH 1/9] Switch to using uistack view --- BeeSwift/Gallery/GalleryViewController.swift | 128 +++++++------------ 1 file changed, 44 insertions(+), 84 deletions(-) diff --git a/BeeSwift/Gallery/GalleryViewController.swift b/BeeSwift/Gallery/GalleryViewController.swift index b4364548..2f90fa64 100644 --- a/BeeSwift/Gallery/GalleryViewController.swift +++ b/BeeSwift/Gallery/GalleryViewController.swift @@ -20,6 +20,7 @@ import BeeKit class GalleryViewController: UIViewController, UICollectionViewDelegateFlowLayout, UICollectionViewDelegate, UICollectionViewDataSource, UISearchBarDelegate, SFSafariViewControllerDelegate { let logger = Logger(subsystem: "com.beeminder.beeminder", category: "GalleryViewController") + var stackView = UIStackView() var collectionView :UICollectionView? var collectionViewLayout :UICollectionViewFlowLayout? private let freshnessIndicator = FreshnessIndicatorView() @@ -42,9 +43,21 @@ class GalleryViewController: UIViewController, UICollectionViewDelegateFlowLayou NotificationCenter.default.addObserver(self, selector: #selector(self.handleSignOut), name: NSNotification.Name(rawValue: CurrentUserManager.signedOutNotificationName), object: nil) NotificationCenter.default.addObserver(self, selector: #selector(self.openGoalFromNotification(_:)), name: NSNotification.Name(rawValue: "openGoal"), object: nil) NotificationCenter.default.addObserver(self, selector: #selector(self.handleGoalsFetchedNotification), name: NSNotification.Name(rawValue: GoalManager.goalsUpdatedNotificationName), object: nil) - + + self.view.addSubview(stackView) + stackView.axis = .vertical + stackView.alignment = .fill + stackView.distribution = .fill + stackView.spacing = 0 + stackView.snp.makeConstraints { (make) -> Void in + make.top.left.right.equalTo(self.view.safeAreaLayoutGuide) + // We are happy for the bottom of the scrollview to be partially obscured by the + // home indicator. This looks better than a bit white area at the bottom. + make.bottom.equalTo(self.view) + } + self.collectionViewLayout = UICollectionViewFlowLayout() - self.collectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: self.collectionViewLayout!) + self.collectionView = UICollectionView(frame: stackView.frame, collectionViewLayout: self.collectionViewLayout!) self.collectionView?.backgroundColor = .systemBackground self.collectionView?.alwaysBounceVertical = true self.collectionView?.register(UICollectionReusableView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: "footer") @@ -55,93 +68,69 @@ class GalleryViewController: UIViewController, UICollectionViewDelegateFlowLayou let item = UIBarButtonItem(image: UIImage(systemName: "gearshape.fill"), style: UIBarButtonItem.Style.plain, target: self, action: #selector(self.settingsButtonPressed)) self.navigationItem.rightBarButtonItem = item - self.view.addSubview(self.freshnessIndicator) - self.freshnessIndicator.snp.makeConstraints { (make) -> Void in - make.top.equalTo(self.view.safeAreaLayoutGuide.snp.topMargin) - make.left.equalTo(0) - make.right.equalTo(0) - } - + stackView.addArrangedSubview(self.freshnessIndicator) self.updateLastUpdatedLabel() Timer.scheduledTimer(timeInterval: 60, target: self, selector: #selector(GalleryViewController.updateLastUpdatedLabel), userInfo: nil, repeats: true) - self.view.addSubview(self.deadbeatView) + stackView.addArrangedSubview(self.deadbeatView) + self.deadbeatView.accessibilityIdentifier = "deadbeatView" self.deadbeatView.backgroundColor = UIColor.Beeminder.gray - self.deadbeatView.snp.makeConstraints { (make) -> Void in - make.left.equalTo(0) - make.right.equalTo(0) - make.top.equalTo(self.freshnessIndicator.snp.bottom) - if !ServiceLocator.currentUserManager.isDeadbeat(context: ServiceLocator.persistentContainer.viewContext) { - make.height.equalTo(0) - } + if !ServiceLocator.currentUserManager.isDeadbeat(context: ServiceLocator.persistentContainer.viewContext) { + self.deadbeatView.isHidden = true } - + let deadbeatLabel = BSLabel() self.deadbeatView.addSubview(deadbeatLabel) + deadbeatLabel.accessibilityIdentifier = "deadbeatLabel" deadbeatLabel.textColor = UIColor.Beeminder.red deadbeatLabel.numberOfLines = 0 deadbeatLabel.font = UIFont.beeminder.defaultFontHeavy.withSize(13) deadbeatLabel.text = "Hey! Beeminder couldn't charge your credit card, so you can't see your graphs. Please update your card on beeminder.com or email support@beeminder.com if this is a mistake." deadbeatLabel.snp.makeConstraints { (make) -> Void in - make.top.equalTo(3) - make.bottom.equalTo(-3) + make.top.equalTo(4) + make.bottom.equalTo(-4) make.left.equalTo(10) make.right.equalTo(-10) } - self.view.addSubview(self.outofdateView) + stackView.addArrangedSubview(self.outofdateView) + self.outofdateView.accessibilityIdentifier = "outofdateView" self.outofdateView.backgroundColor = UIColor.Beeminder.gray - self.outofdateView.snp.makeConstraints { (make) in - make.right.left.equalTo(0) - make.top.equalTo(self.deadbeatView.snp.bottom) - make.height.equalTo(0) - } - + self.outofdateView.isHidden = true + self.outofdateView.addSubview(self.outofdateLabel) + self.outofdateLabel.accessibilityIdentifier = "outofdateLabel" self.outofdateLabel.textColor = UIColor.Beeminder.red self.outofdateLabel.numberOfLines = 0 self.outofdateLabel.font = UIFont.beeminder.defaultFontHeavy.withSize(12) self.outofdateLabel.textAlignment = .center self.outofdateLabel.snp.makeConstraints { (make) in - make.top.equalTo(3) - make.bottom.equalTo(-3) + make.top.equalTo(6) + make.bottom.equalTo(-6) make.left.equalTo(10) make.right.equalTo(-10) } - self.view.addSubview(self.searchBar) + stackView.addArrangedSubview(self.searchBar) + self.searchBar.accessibilityIdentifier = "searchBar" self.searchBar.delegate = self self.searchBar.placeholder = "Filter goals by slug" self.searchBar.isHidden = true self.searchBar.showsCancelButton = true - self.searchBar.snp.makeConstraints { (make) in - make.left.right.equalTo(0) - make.top.equalTo(self.outofdateView.snp.bottom) - make.height.equalTo(0) - } - + self.collectionView!.delegate = self self.collectionView!.dataSource = self self.collectionView!.register(GoalCollectionViewCell.self, forCellWithReuseIdentifier: self.cellReuseIdentifier) - self.view.addSubview(self.collectionView!) - + stackView.addArrangedSubview(self.collectionView!) + self.collectionView?.refreshControl = { let refreshControl = UIRefreshControl() refreshControl.addTarget(self, action: #selector(self.fetchGoals), for: UIControl.Event.valueChanged) return refreshControl }() - - self.collectionView!.snp.makeConstraints { (make) -> Void in - make.top.equalTo(self.searchBar.snp.bottom) - make.left.equalTo(self.view.safeAreaLayoutGuide.snp.leftMargin) - make.right.equalTo(self.view.safeAreaLayoutGuide.snp.rightMargin) - make.bottom.equalTo(self.collectionView!.keyboardLayoutGuide.snp.top) - } - - self.view.addSubview(self.noGoalsLabel) - self.noGoalsLabel.snp.makeConstraints { (make) in - make.top.left.right.equalTo(self.collectionView!) - } + + stackView.addArrangedSubview(self.noGoalsLabel) + self.noGoalsLabel.accessibilityIdentifier = "noGoalsLabel" self.noGoalsLabel.text = "You have no Beeminder goals!\n\nYou'll need to create one before this app will be any use." self.noGoalsLabel.textAlignment = .center self.noGoalsLabel.numberOfLines = 0 @@ -167,26 +156,17 @@ class GalleryViewController: UIViewController, UICollectionViewDelegateFlowLayou switch updateState { case .UpdateRequired: - self.outofdateView.snp.remakeConstraints { (make) -> Void in - make.left.equalTo(0) - make.right.equalTo(0) - make.top.equalTo(self.deadbeatView.snp.bottom) - make.height.equalTo(42) - } + self.outofdateView.isHidden = false self.outofdateLabel.isHidden = false self.outofdateLabel.text = "This version of the Beeminder app is no longer supported.\n Please update to the newest version in the App Store." self.collectionView?.isHidden = true case .UpdateSuggested: - self.outofdateView.snp.remakeConstraints { (make) -> Void in - make.left.equalTo(0) - make.right.equalTo(0) - make.top.equalTo(self.deadbeatView.snp.bottom) - make.height.equalTo(42) - } + self.outofdateView.isHidden = false self.outofdateLabel.isHidden = false self.outofdateLabel.text = "There is a new version of the Beeminder app in the App Store.\nPlease update when you have a moment." self.collectionView?.isHidden = false case .UpToDate: + self.outofdateView.isHidden = true self.collectionView?.isHidden = false } } catch let error as VersionError { @@ -242,20 +222,6 @@ class GalleryViewController: UIViewController, UICollectionViewDelegateFlowLayou } else { self.searchBar.becomeFirstResponder() } - - self.updateSearchBarConstraints() - } - - private func updateSearchBarConstraints() { - self.searchBar.snp.remakeConstraints { (make) in - make.left.right.equalTo(0) - make.top.equalTo(self.outofdateView.snp.bottom) - if self.searchBar.isHidden { - make.height.equalTo(0) - } else { - make.height.equalTo(self.maxSearchBarHeight) - } - } } @objc func handleSignIn() { @@ -294,14 +260,8 @@ class GalleryViewController: UIViewController, UICollectionViewDelegateFlowLayou func updateDeadbeatHeight() { - self.deadbeatView.snp.remakeConstraints { (make) -> Void in - make.left.equalTo(0) - make.right.equalTo(0) - make.top.equalTo(self.freshnessIndicator.snp.bottom) - if !ServiceLocator.currentUserManager.isDeadbeat(context: ServiceLocator.persistentContainer.viewContext) { - make.height.equalTo(0) - } - } + let isDeadbeat = ServiceLocator.currentUserManager.isDeadbeat(context: ServiceLocator.persistentContainer.viewContext) + self.deadbeatView.isHidden = !isDeadbeat } private let lastUpdatedDateFormatter: RelativeDateTimeFormatter = { From 1c1e51fbe262f735786b3ecf5111fec658bf959a Mon Sep 17 00:00:00 2001 From: Theo Spears Date: Thu, 5 Dec 2024 15:27:56 -0800 Subject: [PATCH 2/9] undo padding changes --- BeeSwift/Gallery/GalleryViewController.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/BeeSwift/Gallery/GalleryViewController.swift b/BeeSwift/Gallery/GalleryViewController.swift index 2f90fa64..e03ac808 100644 --- a/BeeSwift/Gallery/GalleryViewController.swift +++ b/BeeSwift/Gallery/GalleryViewController.swift @@ -87,8 +87,8 @@ class GalleryViewController: UIViewController, UICollectionViewDelegateFlowLayou deadbeatLabel.font = UIFont.beeminder.defaultFontHeavy.withSize(13) deadbeatLabel.text = "Hey! Beeminder couldn't charge your credit card, so you can't see your graphs. Please update your card on beeminder.com or email support@beeminder.com if this is a mistake." deadbeatLabel.snp.makeConstraints { (make) -> Void in - make.top.equalTo(4) - make.bottom.equalTo(-4) + make.top.equalTo(3) + make.bottom.equalTo(-3) make.left.equalTo(10) make.right.equalTo(-10) } @@ -105,8 +105,8 @@ class GalleryViewController: UIViewController, UICollectionViewDelegateFlowLayou self.outofdateLabel.font = UIFont.beeminder.defaultFontHeavy.withSize(12) self.outofdateLabel.textAlignment = .center self.outofdateLabel.snp.makeConstraints { (make) in - make.top.equalTo(6) - make.bottom.equalTo(-6) + make.top.equalTo(3) + make.bottom.equalTo(-3) make.left.equalTo(10) make.right.equalTo(-10) } From 8f18cd142e45093aaf2a1e56a66c346c47cdbd08 Mon Sep 17 00:00:00 2001 From: Theo Spears Date: Thu, 5 Dec 2024 15:30:45 -0800 Subject: [PATCH 3/9] update deadbeat visibility a little --- BeeSwift/Gallery/GalleryViewController.swift | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/BeeSwift/Gallery/GalleryViewController.swift b/BeeSwift/Gallery/GalleryViewController.swift index e03ac808..40bf2593 100644 --- a/BeeSwift/Gallery/GalleryViewController.swift +++ b/BeeSwift/Gallery/GalleryViewController.swift @@ -75,9 +75,7 @@ class GalleryViewController: UIViewController, UICollectionViewDelegateFlowLayou stackView.addArrangedSubview(self.deadbeatView) self.deadbeatView.accessibilityIdentifier = "deadbeatView" self.deadbeatView.backgroundColor = UIColor.Beeminder.gray - if !ServiceLocator.currentUserManager.isDeadbeat(context: ServiceLocator.persistentContainer.viewContext) { - self.deadbeatView.isHidden = true - } + updateDeadbeatVisibility() let deadbeatLabel = BSLabel() self.deadbeatView.addSubview(deadbeatLabel) @@ -259,7 +257,7 @@ class GalleryViewController: UIViewController, UICollectionViewDelegateFlowLayou } - func updateDeadbeatHeight() { + func updateDeadbeatVisibility() { let isDeadbeat = ServiceLocator.currentUserManager.isDeadbeat(context: ServiceLocator.persistentContainer.viewContext) self.deadbeatView.isHidden = !isDeadbeat } @@ -352,7 +350,7 @@ class GalleryViewController: UIViewController, UICollectionViewDelegateFlowLayou self.collectionView?.refreshControl?.endRefreshing() MBProgressHUD.hide(for: self.view, animated: true) self.collectionView!.reloadData() - self.updateDeadbeatHeight() + self.updateDeadbeatVisibility() self.lastUpdated = Date() self.updateLastUpdatedLabel() if self.goals.count == 0 { From e275c2e8078a671318c08b2eba1240d78454111f Mon Sep 17 00:00:00 2001 From: Theo Spears Date: Thu, 5 Dec 2024 15:48:52 -0800 Subject: [PATCH 4/9] respect the safe layout area --- BeeSwift/Gallery/GalleryViewController.swift | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/BeeSwift/Gallery/GalleryViewController.swift b/BeeSwift/Gallery/GalleryViewController.swift index 40bf2593..6250c9a8 100644 --- a/BeeSwift/Gallery/GalleryViewController.swift +++ b/BeeSwift/Gallery/GalleryViewController.swift @@ -21,6 +21,7 @@ class GalleryViewController: UIViewController, UICollectionViewDelegateFlowLayou let logger = Logger(subsystem: "com.beeminder.beeminder", category: "GalleryViewController") var stackView = UIStackView() + var collectionContainer = UIView() var collectionView :UICollectionView? var collectionViewLayout :UICollectionViewFlowLayout? private let freshnessIndicator = FreshnessIndicatorView() @@ -49,11 +50,10 @@ class GalleryViewController: UIViewController, UICollectionViewDelegateFlowLayou stackView.alignment = .fill stackView.distribution = .fill stackView.spacing = 0 + stackView.insetsLayoutMarginsFromSafeArea = true stackView.snp.makeConstraints { (make) -> Void in - make.top.left.right.equalTo(self.view.safeAreaLayoutGuide) - // We are happy for the bottom of the scrollview to be partially obscured by the - // home indicator. This looks better than a bit white area at the bottom. - make.bottom.equalTo(self.view) + make.top.left.right.equalToSuperview() + make.bottom.equalTo(stackView.keyboardLayoutGuide.snp.top) } self.collectionViewLayout = UICollectionViewFlowLayout() @@ -116,10 +116,16 @@ class GalleryViewController: UIViewController, UICollectionViewDelegateFlowLayou self.searchBar.isHidden = true self.searchBar.showsCancelButton = true + stackView.addArrangedSubview(self.collectionContainer) + + self.collectionContainer.addSubview(self.collectionView!) self.collectionView!.delegate = self self.collectionView!.dataSource = self self.collectionView!.register(GoalCollectionViewCell.self, forCellWithReuseIdentifier: self.cellReuseIdentifier) - stackView.addArrangedSubview(self.collectionView!) + self.collectionView?.snp.makeConstraints { (make) in + make.top.bottom.equalTo(collectionContainer) + make.left.right.equalTo(collectionContainer.safeAreaLayoutGuide) + } self.collectionView?.refreshControl = { let refreshControl = UIRefreshControl() From 2c399477ac2e389296e8861107acaeb9d7a769e5 Mon Sep 17 00:00:00 2001 From: Theo Spears Date: Wed, 25 Dec 2024 20:05:35 -0800 Subject: [PATCH 5/9] No goals label should scale to fix --- BeeSwift/Gallery/GalleryViewController.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/BeeSwift/Gallery/GalleryViewController.swift b/BeeSwift/Gallery/GalleryViewController.swift index 6250c9a8..03e6e94c 100644 --- a/BeeSwift/Gallery/GalleryViewController.swift +++ b/BeeSwift/Gallery/GalleryViewController.swift @@ -139,7 +139,8 @@ class GalleryViewController: UIViewController, UICollectionViewDelegateFlowLayou self.noGoalsLabel.textAlignment = .center self.noGoalsLabel.numberOfLines = 0 self.noGoalsLabel.isHidden = true - + self.noGoalsLabel.setContentHuggingPriority(.defaultLow, for: .vertical) + self.updateGoals() self.fetchGoals() From 4aad02236a8b6ed40c48eb02bdf7d15e6dfe207e Mon Sep 17 00:00:00 2001 From: Theo Spears Date: Sun, 29 Dec 2024 14:43:49 -0800 Subject: [PATCH 6/9] review feedback var -> let --- BeeSwift/Gallery/GalleryViewController.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/BeeSwift/Gallery/GalleryViewController.swift b/BeeSwift/Gallery/GalleryViewController.swift index 03e6e94c..7f5c075d 100644 --- a/BeeSwift/Gallery/GalleryViewController.swift +++ b/BeeSwift/Gallery/GalleryViewController.swift @@ -20,8 +20,8 @@ import BeeKit class GalleryViewController: UIViewController, UICollectionViewDelegateFlowLayout, UICollectionViewDelegate, UICollectionViewDataSource, UISearchBarDelegate, SFSafariViewControllerDelegate { let logger = Logger(subsystem: "com.beeminder.beeminder", category: "GalleryViewController") - var stackView = UIStackView() - var collectionContainer = UIView() + let stackView = UIStackView() + let collectionContainer = UIView() var collectionView :UICollectionView? var collectionViewLayout :UICollectionViewFlowLayout? private let freshnessIndicator = FreshnessIndicatorView() From cbe58f7c23af9dcb960079220227a676069be470 Mon Sep 17 00:00:00 2001 From: Theo Spears Date: Sun, 29 Dec 2024 15:08:44 -0800 Subject: [PATCH 7/9] Fix position of no goal text --- BeeSwift/Gallery/GalleryViewController.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/BeeSwift/Gallery/GalleryViewController.swift b/BeeSwift/Gallery/GalleryViewController.swift index 7f5c075d..bd9a3c87 100644 --- a/BeeSwift/Gallery/GalleryViewController.swift +++ b/BeeSwift/Gallery/GalleryViewController.swift @@ -139,7 +139,7 @@ class GalleryViewController: UIViewController, UICollectionViewDelegateFlowLayou self.noGoalsLabel.textAlignment = .center self.noGoalsLabel.numberOfLines = 0 self.noGoalsLabel.isHidden = true - self.noGoalsLabel.setContentHuggingPriority(.defaultLow, for: .vertical) + self.noGoalsLabel.setContentHuggingPriority(UILayoutPriority(UILayoutPriority.defaultLow.rawValue - 10), for: .vertical) self.updateGoals() self.fetchGoals() @@ -362,10 +362,10 @@ class GalleryViewController: UIViewController, UICollectionViewDelegateFlowLayou self.updateLastUpdatedLabel() if self.goals.count == 0 { self.noGoalsLabel.isHidden = false - self.collectionView?.isHidden = true + self.collectionContainer.isHidden = true } else { self.noGoalsLabel.isHidden = true - self.collectionView?.isHidden = false + self.collectionContainer.isHidden = false } let searchItem = UIBarButtonItem(barButtonSystemItem: .search, target: self, action: #selector(self.searchButtonPressed)) self.navigationItem.leftBarButtonItem = searchItem From 20ecc86e72e33ca8ee7218fee477acc946b0c712 Mon Sep 17 00:00:00 2001 From: Theo Spears Date: Sun, 29 Dec 2024 15:09:22 -0800 Subject: [PATCH 8/9] Add comment --- BeeSwift/Gallery/GalleryViewController.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/BeeSwift/Gallery/GalleryViewController.swift b/BeeSwift/Gallery/GalleryViewController.swift index bd9a3c87..79eb4d3c 100644 --- a/BeeSwift/Gallery/GalleryViewController.swift +++ b/BeeSwift/Gallery/GalleryViewController.swift @@ -139,6 +139,7 @@ class GalleryViewController: UIViewController, UICollectionViewDelegateFlowLayou self.noGoalsLabel.textAlignment = .center self.noGoalsLabel.numberOfLines = 0 self.noGoalsLabel.isHidden = true + // When shown this label should fill all remaining space so it is centered on the screen. self.noGoalsLabel.setContentHuggingPriority(UILayoutPriority(UILayoutPriority.defaultLow.rawValue - 10), for: .vertical) self.updateGoals() From 1f57cf96251d10621e02276a9b46794002ea0479 Mon Sep 17 00:00:00 2001 From: Theo Spears Date: Sun, 29 Dec 2024 15:29:27 -0800 Subject: [PATCH 9/9] Don't hide out of date label --- BeeSwift/Gallery/GalleryViewController.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/BeeSwift/Gallery/GalleryViewController.swift b/BeeSwift/Gallery/GalleryViewController.swift index 79eb4d3c..b87e4709 100644 --- a/BeeSwift/Gallery/GalleryViewController.swift +++ b/BeeSwift/Gallery/GalleryViewController.swift @@ -163,12 +163,10 @@ class GalleryViewController: UIViewController, UICollectionViewDelegateFlowLayou switch updateState { case .UpdateRequired: self.outofdateView.isHidden = false - self.outofdateLabel.isHidden = false self.outofdateLabel.text = "This version of the Beeminder app is no longer supported.\n Please update to the newest version in the App Store." self.collectionView?.isHidden = true case .UpdateSuggested: self.outofdateView.isHidden = false - self.outofdateLabel.isHidden = false self.outofdateLabel.text = "There is a new version of the Beeminder app in the App Store.\nPlease update when you have a moment." self.collectionView?.isHidden = false case .UpToDate: