Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 32 additions & 1 deletion DashWallet/Sources/UI/Home/HomeViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,24 @@ class HomeViewController: DWBasePayViewController, NavigationBarDisplayable {
private var homeView: HomeView!
weak var delegate: (HomeViewControllerDelegate & DWWipeDelegate)?

/// True while the home feed is scrolled to the top — the navigation
/// bar stays hidden there so the balance header owns the space; it
/// slides in once the balances scroll away. Read by
/// `BaseNavigationController` through `isNavigationBarHidden` on
/// every navigation transition, so pushed screens keep their bar and
/// popping back restores the current scroll-derived state.
private var hidesNavigationBarAtTop = true

#if DASHPAY
var isBackButtonHidden: Bool = false
private var invitationSetup: DWInvitationSetupState?
private var avatarView: DWDPAvatarView!
#else
var isBackButtonHidden: Bool = true
#endif


var isNavigationBarHidden: Bool { hidesNavigationBarAtTop }

override var payModel: any DWPayModelProtocol {
get { return model.payModel }
set { }
Expand Down Expand Up @@ -93,6 +103,12 @@ class HomeViewController: DWBasePayViewController, NavigationBarDisplayable {
super.viewWillAppear(animated)

navigationController?.navigationBar.applyOpaqueAppearance(with: UIColor.dw_dashNavigationBlue(), shadowColor: .clear)
// Apply the scroll-derived bar state directly too —
// `BaseNavigationController.willShow` reads `isNavigationBarHidden`
// on transitions, but the home tab must also start hidden on
// first display and stay correct if hosted outside that
// navigation controller subclass.
navigationController?.setNavigationBarHidden(hidesNavigationBarAtTop, animated: animated)
}

override func viewDidAppear(_ animated: Bool) {
Expand Down Expand Up @@ -649,6 +665,21 @@ extension HomeViewController: HomeViewDelegate {
present(controller, animated: true, completion: nil)
}

func homeViewDidChangeTopBarVisibility(shouldShow: Bool) {
// At the top of the feed the navigation bar stays hidden so the
// balance header gets the full height; once the user scrolls the
// balances away, the bar (Dash logo + avatar) slides in.
// `isNavigationBarHidden` keeps `BaseNavigationController`'s
// willShow pass consistent with the live state, so pushes show
// the bar for their own screens and pops restore ours.
let shouldHide = !shouldShow
guard hidesNavigationBarAtTop != shouldHide else { return }
hidesNavigationBarAtTop = shouldHide
if navigationController?.topViewController === self {
navigationController?.setNavigationBarHidden(shouldHide, animated: true)
}
}

func homeViewShowInternalTransfer(direction: InternalTransferDirection, source: InternalTransferSource) {
// Sheet, not push: a push drags the blue navigation header along;
// the sheet keeps the transfer form on its own background with
Expand Down
51 changes: 49 additions & 2 deletions DashWallet/Sources/UI/Home/Views/HomeView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ import DashUIKit
protocol HomeViewDelegate: AnyObject {
func homeViewShowSyncingStatus()
func homeViewShowInternalTransfer(direction: InternalTransferDirection, source: InternalTransferSource)
/// Scroll-derived chrome: false at the top of the feed (bar hidden,
/// balance header owns the space), true once the user scrolls down.
func homeViewDidChangeTopBarVisibility(shouldShow: Bool)

#if DASHPAY
func homeView(_ homeView: HomeView, didUpdateProfile identity: DSBlockchainIdentity?, unreadNotifications: UInt)
Expand Down Expand Up @@ -159,6 +162,22 @@ extension HomeView: HomeHeaderViewDelegate {
}
}

/// Scroll thresholds (pt scrolled down) for showing/hiding the
/// navigation bar. Two values (hysteresis) so the bar doesn't flicker
/// when the user rests exactly on the boundary. File-scoped because
/// `HomeViewContent` is generic (no static stored properties).
private let kTopBarShowThreshold: CGFloat = 100
private let kTopBarHideThreshold: CGFloat = 60

/// Scroll offset of the home feed's top sentinel in the scroll view's
/// coordinate space — feeds the collapsing top bar.
private struct HomeScrollOffsetKey: PreferenceKey {
static var defaultValue: CGFloat = 0
static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
value = nextValue()
}
}

struct HomeViewContent<Content: View>: View {
@State private var selectedTxDataItem: TransactionListDataItem? = nil
@State private var showFilterDialog: Bool = false
Expand All @@ -179,15 +198,16 @@ struct HomeViewContent<Content: View>: View {
@ViewBuilder var headerView: () -> Content

private let topOverscrollSize: CGFloat = 1000 // Fixed value for top overscroll area


@State private var isTopBarShown = false

var body: some View {
ZStack {
ScrollView {
ZStack { Color.navigationBarColor } // Top overscroll area
.frame(height: topOverscrollSize)
.padding(EdgeInsets(top: -topOverscrollSize, leading: 0, bottom: 0, trailing: 0))

LazyVStack(pinnedViews: [.sectionHeaders]) {
HomeBalanceView(
viewModel: balanceModel,
Expand Down Expand Up @@ -279,6 +299,33 @@ struct HomeViewContent<Content: View>: View {
}
}
.padding(EdgeInsets(top: -20, leading: 0, bottom: 0, trailing: 0))
// Scroll sentinel as a background so it adds no layout
// (a zero-height sibling would still get the scroll
// content's implicit spacing and open a light gap in the
// blue header). minY is ~0 at rest and goes negative as
// the user scrolls down; drives the collapsing top bar.
.background(
GeometryReader { proxy in
Color.clear.preference(
key: HomeScrollOffsetKey.self,
value: proxy.frame(in: .named("homeScroll")).minY)
}
)
}
.coordinateSpace(name: "homeScroll")
.onPreferenceChange(HomeScrollOffsetKey.self) { minY in
// minY == 0 at rest; more negative the further down the
// user has scrolled.
let scrolled = -minY
if isTopBarShown {
if scrolled < kTopBarHideThreshold {
isTopBarShown = false
delegate?.homeViewDidChangeTopBarVisibility(shouldShow: false)
}
} else if scrolled > kTopBarShowThreshold {
isTopBarShown = true
delegate?.homeViewDidChangeTopBarVisibility(shouldShow: true)
}
}
}
.sheet(item: $selectedTxDataItem) { item in
Expand Down
Loading