Skip to content

Commit 15795b1

Browse files
committed
Consolidate header animation code and allow updates without animation
1 parent 3b18330 commit 15795b1

File tree

1 file changed

+58
-38
lines changed

1 file changed

+58
-38
lines changed

WooCommerce/Classes/ViewRelated/Dashboard/DashboardViewController.swift

Lines changed: 58 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ final class DashboardViewController: UIViewController {
146146

147147
override func viewDidAppear(_ animated: Bool) {
148148
super.viewDidAppear(animated)
149+
updateHeaderVisibility(animated: false)
149150
observeNavigationBarHeightForHeaderVisibility()
150151
}
151152

@@ -162,48 +163,78 @@ final class DashboardViewController: UIViewController {
162163
override var shouldShowOfflineBanner: Bool {
163164
return true
164165
}
166+
}
165167

166-
func showHeader() {
168+
// MARK: - Header animation
169+
private extension DashboardViewController {
170+
func showHeaderWithoutAnimation() {
167171
contentTopToHeaderConstraint?.isActive = true
168172
headerStackView.alpha = 1
169173
view.layoutIfNeeded()
170174
}
171175

172-
func hideHeader() {
176+
func hideHeaderWithoutAnimation() {
173177
contentTopToHeaderConstraint?.isActive = false
174178
headerStackView.alpha = 0
175179
view.layoutIfNeeded()
176180
}
177181

178-
func showHeaderWithAnimation() {
179-
if headerAnimator?.isRunning == true {
180-
headerAnimator?.stopAnimation(true)
182+
func updateHeaderVisibility(animated: Bool) {
183+
if navigationBarIsCollapsed() {
184+
hideHeader(animated: animated)
185+
} else {
186+
showHeader(animated: animated)
181187
}
182-
headerAnimator = UIViewPropertyAnimator.runningPropertyAnimator(
183-
withDuration: Constants.animationDurationSeconds,
184-
delay: 0,
185-
animations: { [weak self] in
186-
self?.showHeader()
187-
},
188-
completion: { [weak self] position in
189-
self?.headerAnimator = nil
190-
})
191188
}
192189

193-
func hideHeaderWithAnimation() {
190+
func showHeader(animated: Bool) {
191+
if animated {
192+
animateHeaderVisibility {
193+
self.showHeaderWithoutAnimation()
194+
}
195+
} else {
196+
showHeaderWithoutAnimation()
197+
}
198+
}
199+
200+
func hideHeader(animated: Bool) {
201+
if animated {
202+
animateHeaderVisibility {
203+
self.hideHeaderWithoutAnimation()
204+
}
205+
} else {
206+
hideHeaderWithoutAnimation()
207+
}
208+
}
209+
210+
func animateHeaderVisibility(animations: @escaping () -> Void) {
194211
if headerAnimator?.isRunning == true {
195212
headerAnimator?.stopAnimation(true)
196213
}
197214
headerAnimator = UIViewPropertyAnimator.runningPropertyAnimator(
198215
withDuration: Constants.animationDurationSeconds,
199216
delay: 0,
200-
animations: { [weak self] in
201-
self?.hideHeader()
202-
},
217+
animations: animations,
203218
completion: { [weak self] position in
204219
self?.headerAnimator = nil
205220
})
206221
}
222+
223+
func navigationBarIsCollapsed() -> Bool {
224+
guard let frame = navigationController?.navigationBar.frame else {
225+
return false
226+
}
227+
228+
return frame.height <= collapsedNavigationBarHeight
229+
}
230+
231+
var collapsedNavigationBarHeight: CGFloat {
232+
if self.traitCollection.userInterfaceIdiom == .pad {
233+
return Constants.iPadCollapsedNavigationBarHeight
234+
} else {
235+
return Constants.iPhoneCollapsedNavigationBarHeight
236+
}
237+
}
207238
}
208239

209240
// MARK: - Configuration
@@ -644,34 +675,23 @@ private extension DashboardViewController {
644675
}
645676

646677
func observeNavigationBarHeightForHeaderVisibility() {
647-
navbarObserverSubscription = navigationController?.navigationBar.publisher(for: \.frame, options: [.initial, .new])
648-
.map({ [collapsedNavigationBarHeight] rect in
649-
rect.height <= collapsedNavigationBarHeight
650-
}) // true if navigation bar is collapsed
678+
navbarObserverSubscription = navigationController?.navigationBar.publisher(for: \.frame, options: [.new])
679+
.map({ [weak self] rect in
680+
// This seems useless given that we're discarding the value later
681+
// and recalculating within updateHeaderVisibility, but this is an easy
682+
// way to avoid constant updates with the `removeDuplicates` that follows
683+
self?.navigationBarIsCollapsed() ?? false
684+
})
651685
.removeDuplicates()
652-
.sink(receiveValue: { [weak self] navigationBarIsShort in
653-
guard let self else { return }
654-
655-
if navigationBarIsShort {
656-
self.hideHeaderWithAnimation()
657-
} else {
658-
self.showHeaderWithAnimation()
659-
}
686+
.sink(receiveValue: { [weak self] _ in
687+
self?.updateHeaderVisibility(animated: true)
660688
})
661689
}
662690

663691
func stopObservingNavigationBarHeightForHeaderVisibility() {
664692
navbarObserverSubscription?.cancel()
665693
navbarObserverSubscription = nil
666694
}
667-
668-
var collapsedNavigationBarHeight: CGFloat {
669-
if self.traitCollection.userInterfaceIdiom == .pad {
670-
return Constants.iPadCollapsedNavigationBarHeight
671-
} else {
672-
return Constants.iPhoneCollapsedNavigationBarHeight
673-
}
674-
}
675695
}
676696

677697
// MARK: Constants

0 commit comments

Comments
 (0)