Skip to content

Commit 8e1638b

Browse files
dadachiclaude
andcommitted
Cleanup: dead Date helper, swiftier String predicates, README env vars
- Drop unused cardTimeAgoInWordsDateString and its timeAgoInWordsDateFormatter - Move isBlank and validateEmail from Utility static helpers to String computed-property extensions (isBlank, isValidEmail) and update all call sites in production and tests - Fold UtilityTest cases into StringExtensionsTest and delete UtilityTest - README: clarify that Xcode is in practice the only NATEMPLATE_API_* env var injector, so the hardcoded fallbacks are what keep Debug builds working when launched from SpringBoard or after Xcode disconnects Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent f2a02ac commit 8e1638b

21 files changed

Lines changed: 120 additions & 143 deletions

NativeAppTemplate/Extensions/Date+Extensions.swift

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,4 @@ extension Date {
2424
var cardDateTimeString: String {
2525
"\(cardDateString) \(cardTimeString)"
2626
}
27-
28-
var cardTimeAgoInWordsDateString: String {
29-
let formatter = DateFormatter.timeAgoInWordsDateFormatter
30-
return formatter.string(from: self)
31-
}
3227
}

NativeAppTemplate/Extensions/DateFormatter+Extensions.swift

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,6 @@ extension DateFormatter {
3333

3434
static let cardTimeFormatter: DateFormatter = .formatter(for: "HH:mm")
3535

36-
static let timeAgoInWordsDateFormatter: DateFormatter = {
37-
let dateFormatter = DateFormatter()
38-
dateFormatter.dateStyle = .short
39-
dateFormatter.timeStyle = .medium
40-
dateFormatter.doesRelativeDateFormatting = true
41-
return dateFormatter
42-
}()
43-
4436
static func formatter(for dateString: String) -> DateFormatter {
4537
let dateFormatter = DateFormatter()
4638
dateFormatter.dateFormat = dateString

NativeAppTemplate/Extensions/String+Extensions.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,13 @@ extension String {
3535
isAlphanumeric()
3636
}
3737
}
38+
39+
var isBlank: Bool {
40+
trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
41+
}
42+
43+
var isValidEmail: Bool {
44+
let emailRegex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
45+
return NSPredicate(format: "SELF MATCHES %@", emailRegex).evaluate(with: self)
46+
}
3847
}

NativeAppTemplate/UI/App Root/ForgotPasswordViewModel.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,23 +25,23 @@ final class ForgotPasswordViewModel {
2525
}
2626

2727
var hasInvalidData: Bool {
28-
if Utility.isBlank(email) {
28+
if email.isBlank {
2929
return true
3030
}
3131

32-
if !Utility.validateEmail(email) {
32+
if !email.isValidEmail {
3333
return true
3434
}
3535

3636
return false
3737
}
3838

3939
var isEmailBlank: Bool {
40-
Utility.isBlank(email)
40+
email.isBlank
4141
}
4242

4343
var isEmailInvalid: Bool {
44-
!Utility.isBlank(email) && !Utility.validateEmail(email)
44+
!email.isBlank && !email.isValidEmail
4545
}
4646

4747
func sendMeResetPasswordInstructionsTapped() {

NativeAppTemplate/UI/App Root/ResendConfirmationInstructionsViewModel.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,23 +25,23 @@ final class ResendConfirmationInstructionsViewModel {
2525
}
2626

2727
var hasInvalidData: Bool {
28-
if Utility.isBlank(email) {
28+
if email.isBlank {
2929
return true
3030
}
3131

32-
if !Utility.validateEmail(email) {
32+
if !email.isValidEmail {
3333
return true
3434
}
3535

3636
return false
3737
}
3838

3939
var isEmailBlank: Bool {
40-
Utility.isBlank(email)
40+
email.isBlank
4141
}
4242

4343
var isEmailInvalid: Bool {
44-
!Utility.isBlank(email) && !Utility.validateEmail(email)
44+
!email.isBlank && !email.isValidEmail
4545
}
4646

4747
func sendMeConfirmationInstructionsTapped() {

NativeAppTemplate/UI/App Root/SignInEmailAndPasswordViewModel.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@ final class SignInEmailAndPasswordViewModel {
2525
}
2626

2727
var hasInvalidData: Bool {
28-
if Utility.isBlank(email) || Utility.isBlank(password) {
28+
if email.isBlank || password.isBlank {
2929
return true
3030
}
3131

32-
if !Utility.validateEmail(email) {
32+
if !email.isValidEmail {
3333
return true
3434
}
3535

@@ -41,23 +41,23 @@ final class SignInEmailAndPasswordViewModel {
4141
}
4242

4343
var hasInvalidDataPassword: Bool {
44-
if Utility.isBlank(password) {
44+
if password.isBlank {
4545
return true
4646
}
4747

4848
return false
4949
}
5050

5151
var isEmailBlank: Bool {
52-
Utility.isBlank(email)
52+
email.isBlank
5353
}
5454

5555
var isEmailInvalid: Bool {
56-
Utility.isBlank(email) || !Utility.validateEmail(email)
56+
email.isBlank || !email.isValidEmail
5757
}
5858

5959
var isPasswordBlank: Bool {
60-
Utility.isBlank(password)
60+
password.isBlank
6161
}
6262

6363
func signIn() {

NativeAppTemplate/UI/App Root/SignUpViewModel.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ final class SignUpViewModel {
3131
}
3232

3333
var hasInvalidData: Bool {
34-
if Utility.isBlank(name) {
34+
if name.isBlank {
3535
return true
3636
}
3737

@@ -47,19 +47,19 @@ final class SignUpViewModel {
4747
}
4848

4949
var hasInvalidDataEmail: Bool {
50-
if Utility.isBlank(email) {
50+
if email.isBlank {
5151
return true
5252
}
5353

54-
if !Utility.validateEmail(email) {
54+
if !email.isValidEmail {
5555
return true
5656
}
5757

5858
return false
5959
}
6060

6161
var hasInvalidDataPassword: Bool {
62-
if Utility.isBlank(password) {
62+
if password.isBlank {
6363
return true
6464
}
6565

@@ -71,15 +71,15 @@ final class SignUpViewModel {
7171
}
7272

7373
var isNameBlank: Bool {
74-
Utility.isBlank(name)
74+
name.isBlank
7575
}
7676

7777
var isEmailBlank: Bool {
78-
Utility.isBlank(email)
78+
email.isBlank
7979
}
8080

8181
var isPasswordBlank: Bool {
82-
Utility.isBlank(password)
82+
password.isBlank
8383
}
8484

8585
func createShopkeeper() {

NativeAppTemplate/UI/Settings/PasswordEditView.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ private extension PasswordEditView {
5252
Text(Strings.weNeedYourCurrentPassword)
5353
.font(.uiFootnote)
5454
Text(Strings.currentPasswordIsRequired)
55-
.foregroundStyle(Utility.isBlank(viewModel.currentPassword) ? .validationError : .clear)
55+
.foregroundStyle(viewModel.currentPassword.isBlank ? .validationError : .clear)
5656
.font(.uiFootnote)
5757
}
5858
}
@@ -68,7 +68,7 @@ private extension PasswordEditView {
6868
Text("\(viewModel.minimumPasswordLength) characters minimum.")
6969
.font(.uiFootnote)
7070

71-
if Utility.isBlank(viewModel.password) {
71+
if viewModel.password.isBlank {
7272
Text(Strings.newPasswordIsRequired)
7373
.foregroundStyle(.validationError)
7474
.font(.uiFootnote)
@@ -89,7 +89,7 @@ private extension PasswordEditView {
8989
} footer: {
9090
Text(Strings.confirmNewPasswordIsRequired)
9191
.font(.uiFootnote)
92-
.foregroundStyle(Utility.isBlank(viewModel.passwordConfirmation) ? .validationError : .clear)
92+
.foregroundStyle(viewModel.passwordConfirmation.isBlank ? .validationError : .clear)
9393
}
9494
}
9595
.navigationTitle(Strings.updatePassword)

NativeAppTemplate/UI/Settings/PasswordEditViewModel.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ final class PasswordEditViewModel {
3131
}
3232

3333
var hasInvalidData: Bool {
34-
if Utility.isBlank(currentPassword) ||
35-
Utility.isBlank(password) ||
36-
Utility.isBlank(passwordConfirmation) {
34+
if currentPassword.isBlank ||
35+
password.isBlank ||
36+
passwordConfirmation.isBlank {
3737
return true
3838
}
3939

@@ -45,7 +45,7 @@ final class PasswordEditViewModel {
4545
}
4646

4747
var hasInvalidDataPassword: Bool {
48-
if Utility.isBlank(password) {
48+
if password.isBlank {
4949
return true
5050
}
5151

NativeAppTemplate/UI/Settings/ShopkeeperEditView.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ private extension ShopkeeperEditView {
4747
Text(Strings.fullName)
4848
} footer: {
4949
Text(Strings.fullNameIsRequired)
50-
.foregroundStyle(Utility.isBlank(viewModel.name) ? .validationError : .clear)
50+
.foregroundStyle(viewModel.name.isBlank ? .validationError : .clear)
5151
}
5252

5353
Section {
@@ -57,7 +57,7 @@ private extension ShopkeeperEditView {
5757
} header: {
5858
Text(Strings.email)
5959
} footer: {
60-
if Utility.isBlank(viewModel.email) {
60+
if viewModel.email.isBlank {
6161
Text(Strings.emailIsRequired)
6262
.foregroundStyle(.validationError)
6363
} else if viewModel.hasInvalidDataEmail {

0 commit comments

Comments
 (0)