Skip to content

Commit b58040b

Browse files
authored
Merge pull request #704 from Syn-McJ/chore/usernames-contested-disable
chore: disable contested usernames
2 parents 8fcad99 + 7e2a661 commit b58040b

45 files changed

Lines changed: 1440 additions & 2715 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

DashWallet/Sources/UI/DashPay/Setup/CreateUsername/CreateUsernameViewController.swift

Lines changed: 40 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ struct CreateUsernameView: View {
9292
.padding(.top, 20)
9393
.focused($isTextInputFocused)
9494

95-
if viewModel.uiState.hasInvite && !viewModel.uiState.isInvitationForContested {
95+
if !viewModel.uiState.contestedAllowed {
9696
HStack(spacing: 0) {
9797
Text(NSLocalizedString("The username must meet ", comment: "Usernames"))
9898
Text(NSLocalizedString("one", comment: "Usernames"))
@@ -112,7 +112,7 @@ struct CreateUsernameView: View {
112112
if viewModel.uiState.lengthRule != .hidden {
113113
ValidationCheck(
114114
validationResult: viewModel.uiState.lengthRule,
115-
text: viewModel.uiState.hasInvite && !viewModel.uiState.isInvitationForContested ?
115+
text: !viewModel.uiState.contestedAllowed ?
116116
NSLocalizedString("Between 20 and 23 characters", comment: "Usernames") :
117117
NSLocalizedString("Between 3 and 23 characters", comment: "Usernames")
118118
).padding(.top, 20)
@@ -121,7 +121,7 @@ struct CreateUsernameView: View {
121121
if viewModel.uiState.allowedCharactersRule != .hidden {
122122
ValidationCheck(
123123
validationResult: viewModel.uiState.allowedCharactersRule,
124-
text: viewModel.uiState.hasInvite && !viewModel.uiState.isInvitationForContested ?
124+
text: !viewModel.uiState.contestedAllowed ?
125125
NSLocalizedString("Contains numbers 2-9", comment: "Usernames") :
126126
NSLocalizedString("Letter, numbers and hyphens only", comment: "Usernames")
127127
).padding(.top, 20)
@@ -158,48 +158,48 @@ struct CreateUsernameView: View {
158158

159159
Spacer()
160160

161-
if viewModel.uiState.hasInvite {
162-
if !viewModel.uiState.isInvitationMixed {
163-
HStack(alignment: .top) {
164-
Image("invite.unmixed")
165-
.resizable()
166-
.scaledToFit()
167-
.frame(width: 18, height: 18)
161+
162+
if viewModel.uiState.hasInvite && !viewModel.uiState.isInvitationMixed {
163+
HStack(alignment: .top) {
164+
Image("invite.unmixed")
165+
.resizable()
166+
.scaledToFit()
167+
.frame(width: 18, height: 18)
168168

169-
Text(NSLocalizedString("The invitation was created with un-mixed funds", comment: "Invites"))
170-
.foregroundColor(.primaryText)
171-
.font(.body2)
172-
}
173-
.padding(.bottom, 16)
169+
Text(NSLocalizedString("The invitation was created with un-mixed funds", comment: "Invites"))
170+
.foregroundColor(.primaryText)
171+
.font(.body2)
174172
}
175-
176-
if !viewModel.uiState.isInvitationForContested {
177-
HStack(alignment: .top) {
178-
Image("invite.noncontested")
173+
.padding(.bottom, 16)
174+
}
175+
176+
if !viewModel.uiState.contestedAllowed {
177+
HStack(alignment: .top) {
178+
Image("invite.noncontested")
179+
.resizable()
180+
.scaledToFit()
181+
.frame(width: 18, height: 18)
182+
183+
Text(viewModel.uiState.hasInvite ? NSLocalizedString("You can only create a non-contested username using this invitation", comment: "Invites") :
184+
NSLocalizedString("You can only create a non-contested username at this time", comment: "Invites"))
185+
.foregroundColor(.primaryText)
186+
.font(.body2)
187+
188+
Spacer()
189+
190+
Button {
191+
showContestedInfo = true
192+
} label: {
193+
Image(systemName: "info.circle.fill")
179194
.resizable()
180195
.scaledToFit()
181-
.frame(width: 18, height: 18)
182-
183-
Text(NSLocalizedString("You can only create a non-contested username using this invitaiton", comment: "Invites"))
184-
.foregroundColor(.primaryText)
185-
.font(.body2)
186-
187-
Spacer()
188-
189-
Button {
190-
showContestedInfo = true
191-
} label: {
192-
Image(systemName: "info.circle.fill")
193-
.resizable()
194-
.scaledToFit()
195-
.padding(8)
196-
.foregroundColor(.gray300)
197-
}
198-
.frame(width: 30, height: 30)
196+
.padding(8)
197+
.foregroundColor(.gray300)
199198
}
200-
.frame(minHeight: 36)
201-
.padding(.bottom, 20)
199+
.frame(width: 30, height: 30)
202200
}
201+
.frame(minHeight: 36)
202+
.padding(.bottom, 20)
203203
}
204204

205205
DashButton(
@@ -303,10 +303,6 @@ struct CreateUsernameView: View {
303303
.sheet(isPresented: $showContestedInfo) {
304304
let dialog = BottomSheet(showBackButton: Binding<Bool>.constant(false)) {
305305
TextIntro(
306-
buttonLabel: NSLocalizedString("OK", comment: ""),
307-
action: {
308-
showContestedInfo = false
309-
},
310306
inProgress: .constant(false)
311307
) {
312308
FeatureTopText(
@@ -318,7 +314,7 @@ struct CreateUsernameView: View {
318314
}
319315

320316
if #available(iOS 16.0, *) {
321-
dialog.presentationDetents([.height(500)])
317+
dialog.presentationDetents([.height(400)])
322318
} else {
323319
dialog
324320
}

DashWallet/Sources/UI/DashPay/Setup/CreateUsername/CreateUsernameViewModel.swift

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,26 @@
1717

1818
import Combine
1919

20+
private let ALLOW_CONTESTED_USERNAMES_WITHOUT_INVITE = false
21+
2022
struct CreateUsernameUIState {
2123
var lengthRule: UsernameValidationRuleResult
2224
var allowedCharactersRule: UsernameValidationRuleResult
2325
var costRule: UsernameValidationRuleResult
2426
var usernameBlockedRule: UsernameValidationRuleResult
27+
var contestedAllowed: Bool
2528
var hasInvite: Bool
2629
var isInvitationMixed: Bool
2730
var isInvitationForContested: Bool
2831
var requiredDash: UInt64
2932
var canContinue: Bool
3033

31-
init(lengthRule: UsernameValidationRuleResult, allowedCharactersRule: UsernameValidationRuleResult, costRule: UsernameValidationRuleResult, usernameBlockedRule: UsernameValidationRuleResult, hasInvite: Bool, isInvitationMixed: Bool, isInvitationForContested: Bool, requiredDash: UInt64, canContinue: Bool) {
34+
init(lengthRule: UsernameValidationRuleResult, allowedCharactersRule: UsernameValidationRuleResult, costRule: UsernameValidationRuleResult, usernameBlockedRule: UsernameValidationRuleResult, contestedAllowed: Bool, hasInvite: Bool, isInvitationMixed: Bool, isInvitationForContested: Bool, requiredDash: UInt64, canContinue: Bool) {
3235
self.lengthRule = lengthRule
3336
self.allowedCharactersRule = allowedCharactersRule
3437
self.costRule = costRule
3538
self.usernameBlockedRule = usernameBlockedRule
39+
self.contestedAllowed = contestedAllowed
3640
self.hasInvite = hasInvite
3741
self.isInvitationMixed = isInvitationMixed
3842
self.isInvitationForContested = isInvitationForContested
@@ -45,6 +49,7 @@ struct CreateUsernameUIState {
4549
self.allowedCharactersRule = .empty
4650
self.costRule = .hidden
4751
self.usernameBlockedRule = .hidden
52+
self.contestedAllowed = ALLOW_CONTESTED_USERNAMES_WITHOUT_INVITE
4853
self.hasInvite = false
4954
self.isInvitationMixed = false
5055
self.isInvitationForContested = false
@@ -173,6 +178,7 @@ class CreateUsernameViewModel: ObservableObject {
173178
uiState.isInvitationMixed = await isInvitationMixed(assetLockTx: tx)
174179
uiState.isInvitationForContested = await invitationAmount(assetLockTx: tx) >= DWDP_MIN_BALANCE_FOR_CONTESTED_USERNAME
175180
uiState.hasInvite = true
181+
uiState.contestedAllowed = uiState.isInvitationForContested
176182
uiState.costRule = .hidden
177183
}
178184
}
@@ -219,23 +225,33 @@ class CreateUsernameViewModel: ObservableObject {
219225
let hasInvite = uiState.hasInvite
220226
let isMixed = uiState.isInvitationMixed
221227
let isContested = uiState.isInvitationForContested
228+
let contestedAllowed = uiState.contestedAllowed
222229

223230
uiState = CreateUsernameUIState()
224231
uiState.hasInvite = hasInvite
225232
uiState.isInvitationMixed = isMixed
226233
uiState.isInvitationForContested = isContested
234+
uiState.contestedAllowed = contestedAllowed
227235
return
228236
}
229237

230238
let isContestable = isUsernameContestable(username: username)
231-
let isContested = isContestable // TODO: MOCK_DASHPAY
239+
// Disable contested usernames if no invite and the constant is false
240+
let isContested = if ALLOW_CONTESTED_USERNAMES_WITHOUT_INVITE {
241+
isContestable // TODO: MOCK_DASHPAY
242+
} else {
243+
uiState.hasInvite ? isContestable : false
244+
}
232245
let lengthValid = isLengthValid(username: username)
233246
let allowedCharactersRuleValid = allowedCharactersRuleValid(username: username)
234247
let requiredCost = isContested ? DWDP_MIN_BALANCE_FOR_CONTESTED_USERNAME : DWDP_MIN_BALANCE_TO_CREATE_USERNAME
235248
let balance = DWEnvironment.sharedInstance().currentWallet.balance
236249
let hasEnoughBalance = balance >= requiredCost
237250
let isAffordable = uiState.isInvitationForContested || (uiState.hasInvite && !isContested) || hasEnoughBalance
238-
let criteriaValid = if uiState.hasInvite && !uiState.isInvitationForContested {
251+
252+
// Treat no-invite scenario like non-contested invite for validation rules
253+
let shouldUseRelaxedValidation = (uiState.hasInvite && !uiState.isInvitationForContested) || (!uiState.hasInvite && !ALLOW_CONTESTED_USERNAMES_WITHOUT_INVITE)
254+
let criteriaValid = if shouldUseRelaxedValidation {
239255
lengthValid || allowedCharactersRuleValid
240256
} else {
241257
lengthValid && allowedCharactersRuleValid
@@ -248,6 +264,7 @@ class CreateUsernameViewModel: ObservableObject {
248264
allowedCharactersRule: allowedCharactersRuleValid ? .valid : .invalid,
249265
costRule: costRule,
250266
usernameBlockedRule: canContinue && isContested ? .loading : .hidden,
267+
contestedAllowed: uiState.contestedAllowed,
251268
hasInvite: uiState.hasInvite,
252269
isInvitationMixed: uiState.isInvitationMixed,
253270
isInvitationForContested: uiState.isInvitationForContested,
@@ -305,7 +322,8 @@ class CreateUsernameViewModel: ObservableObject {
305322
}
306323

307324
private func isLengthValid(username: String) -> Bool {
308-
let minLength = uiState.hasInvite && !uiState.isInvitationForContested ? DW_MIN_USERNAME_NONCONTESTED_LENGTH : DW_MIN_USERNAME_LENGTH
325+
let shouldUseRelaxedMinLength = (uiState.hasInvite && !uiState.isInvitationForContested) || (!uiState.hasInvite && !ALLOW_CONTESTED_USERNAMES_WITHOUT_INVITE)
326+
let minLength = shouldUseRelaxedMinLength ? DW_MIN_USERNAME_NONCONTESTED_LENGTH : DW_MIN_USERNAME_LENGTH
309327

310328
return username.count >= minLength && username.count <= DW_MAX_USERNAME_LENGTH
311329
}
@@ -315,7 +333,8 @@ class CreateUsernameViewModel: ObservableObject {
315333
let containsDigits = username.rangeOfCharacter(from: .decimalDigits) != nil
316334
let startsOrEndsWithHyphen = username.first == "-" || username.last == "-"
317335

318-
if uiState.hasInvite && !uiState.isInvitationForContested {
336+
let shouldUseRelaxedCharacterRules = (uiState.hasInvite && !uiState.isInvitationForContested) || (!uiState.hasInvite && !ALLOW_CONTESTED_USERNAMES_WITHOUT_INVITE)
337+
if shouldUseRelaxedCharacterRules {
319338
return !hasIllegalCharacters && containsDigits && !startsOrEndsWithHyphen
320339
}
321340

0 commit comments

Comments
 (0)