diff --git a/Flipcash/Core/Screens/Main/Username/UsernameGate.swift b/Flipcash/Core/Screens/Main/Username/UsernameGate.swift index 8fb04d579..67acf52a9 100644 --- a/Flipcash/Core/Screens/Main/Username/UsernameGate.swift +++ b/Flipcash/Core/Screens/Main/Username/UsernameGate.swift @@ -80,3 +80,10 @@ func usernameGate(session: some UsernameBalanceReading, minimum: TokenAmount?) - } return .proceed } + +/// Whether to offer the custom-username card: true unless the user holds a +/// handle they chose themselves. A server-assigned handle still counts as +/// unclaimed. +func usernameNeedsClaim(username: Username?, isAutoAssigned: Bool) -> Bool { + username == nil || isAutoAssigned +} diff --git a/Flipcash/Core/Screens/Main/You/YouScreen.swift b/Flipcash/Core/Screens/Main/You/YouScreen.swift index 71a5f8908..662154fa6 100644 --- a/Flipcash/Core/Screens/Main/You/YouScreen.swift +++ b/Flipcash/Core/Screens/Main/You/YouScreen.swift @@ -506,10 +506,16 @@ struct YouScreen: View { private var username: Username? { profile?.username } - /// Whether to offer the handle. Derived from the handle being absent rather - /// than from a separate claimed flag, so a handle that disappears across a - /// profile refresh puts the offer back on its own. - private var shouldPromptForUsername: Bool { username == nil } + /// Whether to offer the handle: the user has none, or the one they have was + /// auto-assigned by the server and they haven't picked their own. Re-derived + /// from the profile on every render, so a handle that disappears across a + /// refresh puts the offer back on its own. + private var shouldPromptForUsername: Bool { + usernameNeedsClaim( + username: username, + isAutoAssigned: profile?.isUsernameAutoAssigned == true + ) + } private var codeData: Data { TipCode.Payload(userID: sessionContainer.session.userID).codeData() diff --git a/FlipcashTests/UsernameGateTests.swift b/FlipcashTests/UsernameGateTests.swift index 37f612081..5ae149352 100644 --- a/FlipcashTests/UsernameGateTests.swift +++ b/FlipcashTests/UsernameGateTests.swift @@ -96,4 +96,21 @@ struct UsernameGateTests { #expect(usernameGate(session: session, minimum: minimum(usd: 100)) == .proceed) } + + @Test("A user with no handle is offered the username card") + func prompt_noHandle_prompts() { + #expect(usernameNeedsClaim(username: nil, isAutoAssigned: false)) + } + + @Test("A server-assigned handle still gets the username card") + func prompt_autoAssignedHandle_prompts() { + let assigned = Username("brandon4821")! + #expect(usernameNeedsClaim(username: assigned, isAutoAssigned: true)) + } + + @Test("A handle the user chose does not get the username card") + func prompt_customHandle_doesNotPrompt() { + let custom = Username("brandon")! + #expect(!usernameNeedsClaim(username: custom, isAutoAssigned: false)) + } }