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
18 changes: 9 additions & 9 deletions DashWallet.xcworkspace/xcshareddata/swiftpm/Package.resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 21 additions & 4 deletions DashWallet/Sources/Models/Usernames/CurrentUserProfileModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,20 @@ class CurrentUserProfileModel: NSObject, ObservableObject {
@objc private(set) var state: CurrentUserProfileModelState = .none
@objc let updateModel: DWDPUpdateProfileModel
@Published private(set) var showJoinDashpay: Bool = false

/// Chain still catching up. The Join DashPay row stays visible throughout
/// (it is a standing menu entry) but presents itself as unavailable:
/// registration cannot be started until the chain is synced.
@Published private(set) var isSyncing: Bool = false

override init() {
updateModel = DWDPUpdateProfileModel()
super.init()

model.$state
.removeDuplicates()
.receive(on: DispatchQueue.main)
.sink { [weak self] _ in
.sink { [weak self] state in
self?.isSyncing = state != .syncDone
self?.updateShowJoinDashpay()
}
.store(in: &cancellableBag)
Expand Down Expand Up @@ -106,8 +111,20 @@ class CurrentUserProfileModel: NSObject, ObservableObject {
}
showJoinDashpay = JoinDashPayBannerPolicy.shouldShow(
contextReady: identityState.contextReady,
syncDone: model.state == .syncDone,
dismissed: UsernamePrefs.shared.joinDashPayDismissed,
// Not gated on sync. The More entry is a standing menu row, and
// gating it made it come and go depending on how far the chain
// had caught up — the row was simply absent for the whole of a
// long sync. Registration itself still needs a synced chain; the
// row reflects that in its own copy rather than by vanishing.
syncDone: true,
// Deliberately not `UsernamePrefs.shared.joinDashPayDismissed`.
// That flag is set by the close control, which exists only on
// Home — the More entry has no dismiss affordance at all. Reading
// it here meant one tap on Home's close permanently removed the
// menu entry too, with no way for the user to bring it back.
// On More the banner is a standing menu row: it disappears when
// the user actually has a username, not when they dismiss it.
dismissed: false,
hasRegisteredUsername: hasUsername,
hasRegistrationInProgress: hasPendingRecoveredName)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,14 @@ class CreateUsernameViewController: UIViewController {
#if DASHPAY
let mainTabController = self.tabBarController as? MainTabbarController
#endif
navigationController?.popViewController(animated: true)
// Pop the whole registration stack, not one level. The invitation
// entry pushes this screen ON TOP of the redeem screen, so popping
// once lands the freshly-registered user back on "Claim your
// invitation" — a flow they just completed and cannot repeat.
// Every push site roots this flow at a tab's own screen, so
// unwinding to that root is the correct destination for all of
// them (Home for the home/deep-link entries, More for the menu).
navigationController?.popToRootViewController(animated: true)
self.completionHandler?(true)
#if DASHPAY
if let transitionCoordinator = navigationController?.transitionCoordinator {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,22 @@ class CreateUsernameViewModel: ObservableObject {
username: submittedUsername,
invitationURI: invitationURI,
temporaryUsername: temporaryUsername)
// This path never touches `DWIdentityRegistrationBridge.shared`,
// so on an invitation-first launch that singleton is never
// constructed, never observes the coordinator's phases, and
// never posts the canonical registration notification —
// `.shared` and `.stateChangedNotification` are independently
// lazy statics, so referencing the notification name does not
// build the bridge. Every consumer of app-wide "registered now"
// state (the DashPay tab set, the More screen's Join DashPay
// banner, `DWCurrentUserIdentityInfo`'s cached snapshot) then
// kept its pre-registration value until the next launch rebuilt
// it from disk. Announce it explicitly here, the same way
// `DWCurrentUserIdentityInfo.reconcileRecoveredIdentity()` does
// for identities that arrive outside the bridge's flow.
DWCurrentUserIdentityInfo.shared.refreshFromSDK()
NotificationCenter.default.post(
name: .DWDashPayRegistrationStatusUpdated, object: nil)
return registrationOutcome(for: submittedUsername)
} catch DWIdentityRegistrationCoordinator.CoordinatorError.authCancelled {
return .cancelled
Expand Down
Loading
Loading