From 5a4a3c1546ec42978410457d2b82460e0cb02377 Mon Sep 17 00:00:00 2001 From: dadachi Date: Tue, 28 Apr 2026 18:58:04 +0900 Subject: [PATCH] Wrap String constants in enum Strings namespace Convert the large `extension String` block in `Constants.swift` to a caseless `enum Strings` namespace, matching the existing `NativeAppTemplateConstants` idiom in the same file. Inline the two `cardDateString`/`cardTimeString` literals in `DateFormatter+Extensions.swift` and remove the small extension they lived in. Update call sites across the app and tests from `String.foo` to `Strings.foo`, including dot-shorthand uses for `message:`, `text:`, `buttonTitle:`, and `?.message ==` parameters. Co-Authored-By: Claude Opus 4.7 (1M context) --- NativeAppTemplate/Constants.swift | 2 +- .../Extensions/DateFormatter+Extensions.swift | 9 ++---- .../Network/CertificatePinningDelegate.swift | 2 +- .../NativeAppTemplateEnvironment.swift | 6 ++-- .../LoggedInShopkeeperKeychainStore.swift | 4 +-- .../UI/App Root/AcceptPrivacyView.swift | 6 ++-- .../UI/App Root/AcceptPrivacyViewModel.swift | 4 +-- .../UI/App Root/AcceptTermsView.swift | 6 ++-- .../UI/App Root/AcceptTermsViewModel.swift | 4 +-- .../UI/App Root/AppTabView.swift | 4 +-- .../UI/App Root/ForgotPasswordView.swift | 12 ++++---- .../UI/App Root/ForgotPasswordViewModel.swift | 4 +-- NativeAppTemplate/UI/App Root/MainView.swift | 2 +- .../UI/App Root/OnboardingView.swift | 2 +- .../UI/App Root/OnboardingViewModel.swift | 18 +++++------ .../UI/App Root/PermissionsLoadingView.swift | 4 +-- .../ResendConfirmationInstructionsView.swift | 12 ++++---- ...endConfirmationInstructionsViewModel.swift | 4 +-- .../App Root/SignInEmailAndPasswordView.swift | 24 +++++++-------- .../UI/App Root/SignUpOrSignInView.swift | 10 +++---- .../UI/App Root/SignUpView.swift | 30 +++++++++---------- .../UI/App Root/SignUpViewModel.swift | 2 +- .../UI/Empty States/LoadingView.swift | 2 +- .../UI/Empty States/NeedAppUpdatesView.swift | 8 ++--- .../UI/Empty States/OfflineView.swift | 4 +-- .../UI/Settings/PasswordEditView.swift | 26 ++++++++-------- .../UI/Settings/PasswordEditViewModel.swift | 2 +- .../UI/Settings/SettingsView.swift | 28 ++++++++--------- .../UI/Settings/SettingsViewModel.swift | 4 +-- .../UI/Settings/ShopkeeperEditView.swift | 30 +++++++++---------- .../UI/Settings/ShopkeeperEditViewModel.swift | 10 +++---- .../UI/Shop Detail/ShopDetailView.swift | 6 ++-- .../UI/Shop Detail/ShopDetailViewModel.swift | 4 +-- .../UI/Shop List/ShopCreateView.swift | 24 +++++++-------- .../UI/Shop List/ShopCreateViewModel.swift | 2 +- .../UI/Shop List/ShopListView.swift | 10 +++---- .../ItemTag Detail/ItemTagDetailView.swift | 18 +++++------ .../ItemTagDetailViewModel.swift | 8 ++--- .../ItemTag Detail/ItemTagEditView.swift | 20 ++++++------- .../ItemTag Detail/ItemTagEditViewModel.swift | 2 +- .../ItemTag List/ItemTagCreateView.swift | 20 ++++++------- .../ItemTag List/ItemTagCreateViewModel.swift | 2 +- .../ItemTag List/ItemTagListView.swift | 8 ++--- .../ItemTag List/ItemTagListViewModel.swift | 4 +-- .../Shop Settings/ShopBasicSettingsView.swift | 22 +++++++------- .../ShopBasicSettingsViewModel.swift | 4 +-- .../UI/Shop Settings/ShopSettingsView.swift | 16 +++++----- .../Shop Settings/ShopSettingsViewModel.swift | 4 +-- NativeAppTemplate/Utilities/Utility.swift | 2 +- .../ForgotPasswordViewModelTest.swift | 2 +- .../UI/App Root/OnboardingViewModelTest.swift | 16 +++++----- ...onfirmationInstructionsViewModelTest.swift | 2 +- .../Settings/PasswordEditViewModelTest.swift | 2 +- .../UI/Settings/SettingsViewModelTest.swift | 2 +- .../ShopkeeperEditViewModelTest.swift | 6 ++-- .../Shop List/ShopCreateViewModelTest.swift | 2 +- .../ItemTagDetailViewModelTest.swift | 8 ++--- .../ItemTagEditViewModelTest.swift | 2 +- .../ItemTagCreateViewModelTest.swift | 2 +- .../ItemTagListViewModelTest.swift | 4 +-- .../ShopBasicSettingsViewModelTest.swift | 2 +- .../ShopSettingsViewModelTest.swift | 2 +- 62 files changed, 254 insertions(+), 259 deletions(-) diff --git a/NativeAppTemplate/Constants.swift b/NativeAppTemplate/Constants.swift index 90520ed..af222db 100644 --- a/NativeAppTemplate/Constants.swift +++ b/NativeAppTemplate/Constants.swift @@ -102,7 +102,7 @@ enum NativeAppTemplateConstants { } } -extension String { +enum Strings { #if DEBUG private static let env = ProcessInfo.processInfo.environment static let scheme: String = env["NATEMPLATE_API_SCHEME"] ?? "https" diff --git a/NativeAppTemplate/Extensions/DateFormatter+Extensions.swift b/NativeAppTemplate/Extensions/DateFormatter+Extensions.swift index 945fab1..ae0b4ec 100644 --- a/NativeAppTemplate/Extensions/DateFormatter+Extensions.swift +++ b/NativeAppTemplate/Extensions/DateFormatter+Extensions.swift @@ -5,11 +5,6 @@ import Foundation -extension String { - static let cardDateString: String = "yyyy/MM/dd" - static let cardTimeString: String = "HH:mm" -} - extension ISO8601DateFormatter { convenience init(_ formatOptions: Options, timeZone: TimeZone = TimeZone(secondsFromGMT: 0)!) { self.init() @@ -34,9 +29,9 @@ extension String { } extension DateFormatter { - static let cardDateFormatter: DateFormatter = .formatter(for: .cardDateString) + static let cardDateFormatter: DateFormatter = .formatter(for: "yyyy/MM/dd") - static let cardTimeFormatter: DateFormatter = .formatter(for: .cardTimeString) + static let cardTimeFormatter: DateFormatter = .formatter(for: "HH:mm") static let timeAgoInWordsDateFormatter: DateFormatter = { let dateFormatter = DateFormatter() diff --git a/NativeAppTemplate/Networking/Network/CertificatePinningDelegate.swift b/NativeAppTemplate/Networking/Network/CertificatePinningDelegate.swift index 1cbe7ec..2826410 100644 --- a/NativeAppTemplate/Networking/Network/CertificatePinningDelegate.swift +++ b/NativeAppTemplate/Networking/Network/CertificatePinningDelegate.swift @@ -17,7 +17,7 @@ final class CertificatePinningDelegate: NSObject, URLSessionDelegate { "kIdp6NNEd8wsugYyyIYFsi1ylMCED3hZbSR8ZFsa/A4=" ] - static let pinnedDomain = String.domain + static let pinnedDomain = Strings.domain /// ASN.1 header for EC 256-bit public key (SPKI prefix) private static let ecDsaSecp256r1Asn1Header: [UInt8] = [ diff --git a/NativeAppTemplate/Networking/Network/NativeAppTemplateEnvironment.swift b/NativeAppTemplate/Networking/Network/NativeAppTemplateEnvironment.swift index 05d3a9d..9fd00d2 100644 --- a/NativeAppTemplate/Networking/Network/NativeAppTemplateEnvironment.swift +++ b/NativeAppTemplate/Networking/Network/NativeAppTemplateEnvironment.swift @@ -13,10 +13,10 @@ struct NativeAppTemplateEnvironment: Equatable { } extension NativeAppTemplateEnvironment { - static let urlString = if String.port.isEmpty { - "\(String.scheme)://\(String.domain)" + static let urlString = if Strings.port.isEmpty { + "\(Strings.scheme)://\(Strings.domain)" } else { - "\(String.scheme)://\(String.domain):\(String.port)" + "\(Strings.scheme)://\(Strings.domain):\(Strings.port)" } static let prod = NativeAppTemplateEnvironment(baseURL: URL(string: urlString)!) diff --git a/NativeAppTemplate/Persistence/KeychainStore/LoggedInShopkeeperKeychainStore.swift b/NativeAppTemplate/Persistence/KeychainStore/LoggedInShopkeeperKeychainStore.swift index 15d8084..1f13b34 100644 --- a/NativeAppTemplate/Persistence/KeychainStore/LoggedInShopkeeperKeychainStore.swift +++ b/NativeAppTemplate/Persistence/KeychainStore/LoggedInShopkeeperKeychainStore.swift @@ -7,8 +7,8 @@ import Foundation struct LoggedInShopkeeperKeychainStore: KeychainStore { // Make sure the account name doesn't match the bundle identifier! - var account = String.keychainAccountLoggedInShopkeeper - var service = String.keychainServiceLoggedInShopkeeper + var account = Strings.keychainAccountLoggedInShopkeeper + var service = Strings.keychainServiceLoggedInShopkeeper typealias DataType = LoggedInShopkeeper } diff --git a/NativeAppTemplate/UI/App Root/AcceptPrivacyView.swift b/NativeAppTemplate/UI/App Root/AcceptPrivacyView.swift index e553299..fbb024b 100644 --- a/NativeAppTemplate/UI/App Root/AcceptPrivacyView.swift +++ b/NativeAppTemplate/UI/App Root/AcceptPrivacyView.swift @@ -42,18 +42,18 @@ private extension AcceptPrivacyView { var acceptPrivacyView: some View { VStack { - let agreement = "Please accept updated [\(String.privacyPolicy)](\(String.privacyPolicyUrl))." + let agreement = "Please accept updated [\(Strings.privacyPolicy)](\(Strings.privacyPolicyUrl))." Text(.init(agreement)) .padding(.top, NativeAppTemplateConstants.Spacing.xl) - MainButtonView(title: String.accept, type: .primary(withArrow: false)) { + MainButtonView(title: Strings.accept, type: .primary(withArrow: false)) { viewModel.updateConfirmedPrivacyVersion() } .padding(NativeAppTemplateConstants.Spacing.md) Spacer() } - .navigationTitle(String.privacyPolicyUpdated) + .navigationTitle(Strings.privacyPolicyUpdated) .navigationBarTitleDisplayMode(.inline) } } diff --git a/NativeAppTemplate/UI/App Root/AcceptPrivacyViewModel.swift b/NativeAppTemplate/UI/App Root/AcceptPrivacyViewModel.swift index d4e0c21..764337a 100644 --- a/NativeAppTemplate/UI/App Root/AcceptPrivacyViewModel.swift +++ b/NativeAppTemplate/UI/App Root/AcceptPrivacyViewModel.swift @@ -29,11 +29,11 @@ final class AcceptPrivacyViewModel { do { isUpdating = true try await sessionController.updateConfirmedPrivacyVersion() - messageBus.post(message: Message(level: .success, message: .confirmedPrivacyVersionUpdated)) + messageBus.post(message: Message(level: .success, message: Strings.confirmedPrivacyVersionUpdated)) } catch { messageBus.post(message: Message( level: .error, - message: "\(String.confirmedPrivacyVersionUpdatedError) \(error.codedDescription)", + message: "\(Strings.confirmedPrivacyVersionUpdatedError) \(error.codedDescription)", autoDismiss: false )) } diff --git a/NativeAppTemplate/UI/App Root/AcceptTermsView.swift b/NativeAppTemplate/UI/App Root/AcceptTermsView.swift index a0abb06..7f01b34 100644 --- a/NativeAppTemplate/UI/App Root/AcceptTermsView.swift +++ b/NativeAppTemplate/UI/App Root/AcceptTermsView.swift @@ -42,18 +42,18 @@ private extension AcceptTermsView { var acceptTermsView: some View { VStack { - let agreement = "Please accept updated [\(String.termsOfUse)](\(String.termsOfUseUrl))." + let agreement = "Please accept updated [\(Strings.termsOfUse)](\(Strings.termsOfUseUrl))." Text(.init(agreement)) .padding(.top, NativeAppTemplateConstants.Spacing.xl) - MainButtonView(title: String.accept, type: .primary(withArrow: false)) { + MainButtonView(title: Strings.accept, type: .primary(withArrow: false)) { viewModel.updateConfirmedTermsVersion() } .padding(NativeAppTemplateConstants.Spacing.md) Spacer() } - .navigationTitle(String.termsOfUseUpdated) + .navigationTitle(Strings.termsOfUseUpdated) .navigationBarTitleDisplayMode(.inline) } } diff --git a/NativeAppTemplate/UI/App Root/AcceptTermsViewModel.swift b/NativeAppTemplate/UI/App Root/AcceptTermsViewModel.swift index 36a07a7..2905469 100644 --- a/NativeAppTemplate/UI/App Root/AcceptTermsViewModel.swift +++ b/NativeAppTemplate/UI/App Root/AcceptTermsViewModel.swift @@ -29,11 +29,11 @@ final class AcceptTermsViewModel { do { isUpdating = true try await sessionController.updateConfirmedTermsVersion() - messageBus.post(message: Message(level: .success, message: .confirmedTermsVersionUpdated)) + messageBus.post(message: Message(level: .success, message: Strings.confirmedTermsVersionUpdated)) } catch { messageBus.post(message: Message( level: .error, - message: "\(String.confirmedTermsVersionUpdatedError) \(error.codedDescription)", + message: "\(Strings.confirmedTermsVersionUpdatedError) \(error.codedDescription)", autoDismiss: false )) } diff --git a/NativeAppTemplate/UI/App Root/AppTabView.swift b/NativeAppTemplate/UI/App Root/AppTabView.swift index 3f1a00c..d7ff848 100644 --- a/NativeAppTemplate/UI/App Root/AppTabView.swift +++ b/NativeAppTemplate/UI/App Root/AppTabView.swift @@ -53,7 +53,7 @@ extension AppTabView: View { tab( content: shopListView, navigationPath: $navigationPathShops, - text: .shops, + text: Strings.shops, imageName: "storefront.fill", tab: .shops ) @@ -61,7 +61,7 @@ extension AppTabView: View { tab( content: settingsView, navigationPath: nil, - text: .settings, + text: Strings.settings, imageName: "gearshape.fill", tab: .settings ) diff --git a/NativeAppTemplate/UI/App Root/ForgotPasswordView.swift b/NativeAppTemplate/UI/App Root/ForgotPasswordView.swift index 5baca37..e001651 100644 --- a/NativeAppTemplate/UI/App Root/ForgotPasswordView.swift +++ b/NativeAppTemplate/UI/App Root/ForgotPasswordView.swift @@ -45,27 +45,27 @@ private extension ForgotPasswordView { var forgotPasswordView: some View { Form { Section { - TextField(String.placeholderEmail, text: $viewModel.email) + TextField(Strings.placeholderEmail, text: $viewModel.email) .textContentType(.emailAddress) .autocapitalization(.none) } header: { - Text(String.email) + Text(Strings.email) } footer: { if viewModel.isEmailBlank { - Text(String.emailIsRequired) + Text(Strings.emailIsRequired) .foregroundStyle(.validationError) } else if viewModel.isEmailInvalid { - Text(String.emailIsInvalid) + Text(Strings.emailIsInvalid) .foregroundStyle(.validationError) } } - MainButtonView(title: String.buttonSendMeResetPasswordInstructions, type: .primary(withArrow: false)) { + MainButtonView(title: Strings.buttonSendMeResetPasswordInstructions, type: .primary(withArrow: false)) { viewModel.sendMeResetPasswordInstructionsTapped() } .disabled(viewModel.hasInvalidData) .listRowBackground(Color.clear) } - .navigationTitle(String.forgotYourPassword) + .navigationTitle(Strings.forgotYourPassword) } } diff --git a/NativeAppTemplate/UI/App Root/ForgotPasswordViewModel.swift b/NativeAppTemplate/UI/App Root/ForgotPasswordViewModel.swift index 20c8267..db169c0 100644 --- a/NativeAppTemplate/UI/App Root/ForgotPasswordViewModel.swift +++ b/NativeAppTemplate/UI/App Root/ForgotPasswordViewModel.swift @@ -56,7 +56,7 @@ final class ForgotPasswordViewModel { try await signUpRepository.sendResetPasswordInstruction(sendResetPassword: sendResetPassword) messageBus.post(message: Message( level: .success, - message: .sentResetPasswordInstruction, + message: Strings.sentResetPasswordInstruction, autoDismiss: false )) shouldDismiss = true @@ -64,7 +64,7 @@ final class ForgotPasswordViewModel { UIApplication.dismissKeyboard() messageBus.post(message: Message( level: .error, - message: String.sentResetPasswordInstructionError, + message: Strings.sentResetPasswordInstructionError, autoDismiss: false )) } diff --git a/NativeAppTemplate/UI/App Root/MainView.swift b/NativeAppTemplate/UI/App Root/MainView.swift index 7bad7ca..97e4aa3 100644 --- a/NativeAppTemplate/UI/App Root/MainView.swift +++ b/NativeAppTemplate/UI/App Root/MainView.swift @@ -52,7 +52,7 @@ private extension MainView { case .error: ErrorView( buttonAction: { viewModel?.logout() }, - buttonTitle: .backToStartScreen + buttonTitle: Strings.backToStartScreen ) } } diff --git a/NativeAppTemplate/UI/App Root/OnboardingView.swift b/NativeAppTemplate/UI/App Root/OnboardingView.swift index 709dbe9..235ceba 100644 --- a/NativeAppTemplate/UI/App Root/OnboardingView.swift +++ b/NativeAppTemplate/UI/App Root/OnboardingView.swift @@ -41,7 +41,7 @@ private extension OnboardingView { .tabViewStyle(.page(indexDisplayMode: .always)) .toolbar { ToolbarItem(placement: .navigationBarLeading) { - Link(String.supportWebsite, destination: URL(string: String.supportWebsiteUrl)!) + Link(Strings.supportWebsite, destination: URL(string: Strings.supportWebsiteUrl)!) } ToolbarItem(placement: .navigationBarTrailing) { NavigationLink(destination: SignUpOrSignInView()) { diff --git a/NativeAppTemplate/UI/App Root/OnboardingViewModel.swift b/NativeAppTemplate/UI/App Root/OnboardingViewModel.swift index cd55d85..2469565 100644 --- a/NativeAppTemplate/UI/App Root/OnboardingViewModel.swift +++ b/NativeAppTemplate/UI/App Root/OnboardingViewModel.swift @@ -25,23 +25,23 @@ final class OnboardingViewModel { func onboardingDescription(index: Int) -> String { switch index { case 1: - String.onboardingDescription1 + Strings.onboardingDescription1 case 2: - String.onboardingDescription2 + Strings.onboardingDescription2 case 3: - String.onboardingDescription3 + Strings.onboardingDescription3 case 4: - String.onboardingDescription4 + Strings.onboardingDescription4 case 5: - String.onboardingDescription5 + Strings.onboardingDescription5 case 6: - String.onboardingDescription6 + Strings.onboardingDescription6 case 7: - String.onboardingDescription7 + Strings.onboardingDescription7 case 8: - String.onboardingDescription8 + Strings.onboardingDescription8 default: - String.onboardingDescription1 + Strings.onboardingDescription1 } } } diff --git a/NativeAppTemplate/UI/App Root/PermissionsLoadingView.swift b/NativeAppTemplate/UI/App Root/PermissionsLoadingView.swift index 05ae6e1..2804f68 100644 --- a/NativeAppTemplate/UI/App Root/PermissionsLoadingView.swift +++ b/NativeAppTemplate/UI/App Root/PermissionsLoadingView.swift @@ -15,13 +15,13 @@ struct PermissionsLoadingView: View { isShowingLogoutAlert.toggle() } .alert( - String.forceSignOut, + Strings.forceSignOut, isPresented: $isShowingLogoutAlert ) { Button(role: .destructive) { logout() } label: { - Text(String.signOut) + Text(Strings.signOut) } } } diff --git a/NativeAppTemplate/UI/App Root/ResendConfirmationInstructionsView.swift b/NativeAppTemplate/UI/App Root/ResendConfirmationInstructionsView.swift index aff34fb..50a6b15 100644 --- a/NativeAppTemplate/UI/App Root/ResendConfirmationInstructionsView.swift +++ b/NativeAppTemplate/UI/App Root/ResendConfirmationInstructionsView.swift @@ -45,27 +45,27 @@ private extension ResendConfirmationInstructionsView { var resendConfirmationInstructionsView: some View { Form { Section { - TextField(String.placeholderEmail, text: $viewModel.email) + TextField(Strings.placeholderEmail, text: $viewModel.email) .textContentType(.emailAddress) .autocapitalization(.none) } header: { - Text(String.email) + Text(Strings.email) } footer: { if viewModel.isEmailBlank { - Text(String.emailIsRequired) + Text(Strings.emailIsRequired) .foregroundStyle(.validationError) } else if viewModel.isEmailInvalid { - Text(String.emailIsInvalid) + Text(Strings.emailIsInvalid) .foregroundStyle(.validationError) } } - MainButtonView(title: String.buttonSendMeConfirmationInstructions, type: .primary(withArrow: false)) { + MainButtonView(title: Strings.buttonSendMeConfirmationInstructions, type: .primary(withArrow: false)) { viewModel.sendMeConfirmationInstructionsTapped() } .disabled(viewModel.hasInvalidData) .listRowBackground(Color.clear) } - .navigationTitle(String.didntReceiveConfirmationInstructions) + .navigationTitle(Strings.didntReceiveConfirmationInstructions) } } diff --git a/NativeAppTemplate/UI/App Root/ResendConfirmationInstructionsViewModel.swift b/NativeAppTemplate/UI/App Root/ResendConfirmationInstructionsViewModel.swift index 808178b..949eb72 100644 --- a/NativeAppTemplate/UI/App Root/ResendConfirmationInstructionsViewModel.swift +++ b/NativeAppTemplate/UI/App Root/ResendConfirmationInstructionsViewModel.swift @@ -56,7 +56,7 @@ final class ResendConfirmationInstructionsViewModel { try await signUpRepository.sendConfirmationInstruction(sendConfirmation: sendConfirmation) messageBus.post(message: Message( level: .success, - message: .sentConfirmationInstruction, + message: Strings.sentConfirmationInstruction, autoDismiss: false )) shouldDismiss = true @@ -64,7 +64,7 @@ final class ResendConfirmationInstructionsViewModel { UIApplication.dismissKeyboard() messageBus.post(message: Message( level: .error, - message: String.sentConfirmationInstructionError, + message: Strings.sentConfirmationInstructionError, autoDismiss: false )) } diff --git a/NativeAppTemplate/UI/App Root/SignInEmailAndPasswordView.swift b/NativeAppTemplate/UI/App Root/SignInEmailAndPasswordView.swift index 572b093..5ea70bf 100644 --- a/NativeAppTemplate/UI/App Root/SignInEmailAndPasswordView.swift +++ b/NativeAppTemplate/UI/App Root/SignInEmailAndPasswordView.swift @@ -40,41 +40,41 @@ private extension SignInEmailAndPasswordView { VStack { Form { Section { - TextField(String.placeholderEmail, text: $viewModel.email) + TextField(Strings.placeholderEmail, text: $viewModel.email) .textContentType(.emailAddress) .autocapitalization(.none) .accessibilityIdentifier("SignInEmailAndPasswordView_email_textField") } header: { - Text(String.email) + Text(Strings.email) } footer: { if viewModel.isEmailBlank { - Text(String.emailIsRequired) + Text(Strings.emailIsRequired) .foregroundStyle(.validationError) } else if viewModel.isEmailInvalid { - Text(String.emailIsInvalid) + Text(Strings.emailIsInvalid) .foregroundStyle(.validationError) } } Section { - SecureField(String.placeholderPassword, text: $viewModel.password) + SecureField(Strings.placeholderPassword, text: $viewModel.password) .textContentType(.password) .autocapitalization(.none) .autocorrectionDisabled(true) .accessibilityIdentifier("SignInEmailAndPasswordView_password_secureTextField") } header: { - Text(String.password) + Text(Strings.password) } footer: { if viewModel.isPasswordBlank { - Text(String.passwordIsRequired) + Text(Strings.passwordIsRequired) .foregroundStyle(.validationError) } else if viewModel.hasInvalidDataPassword { - Text(String.passwordIsInvalid) + Text(Strings.passwordIsInvalid) .foregroundStyle(.validationError) } } Section { - MainButtonView(title: String.signIn, type: .primary(withArrow: false)) { + MainButtonView(title: Strings.signIn, type: .primary(withArrow: false)) { viewModel.signIn() } .disabled(viewModel.hasInvalidData) @@ -92,7 +92,7 @@ private extension SignInEmailAndPasswordView { ) ) ) { - Text(String.forgotYourPassword) + Text(Strings.forgotYourPassword) } NavigationLink( @@ -103,10 +103,10 @@ private extension SignInEmailAndPasswordView { ) ) ) { - Text(String.didntReceiveConfirmationInstructions) + Text(Strings.didntReceiveConfirmationInstructions) } } } - .navigationTitle(String.signIn) + .navigationTitle(Strings.signIn) } } diff --git a/NativeAppTemplate/UI/App Root/SignUpOrSignInView.swift b/NativeAppTemplate/UI/App Root/SignUpOrSignInView.swift index 3d5dbe9..0eb40cd 100644 --- a/NativeAppTemplate/UI/App Root/SignUpOrSignInView.swift +++ b/NativeAppTemplate/UI/App Root/SignUpOrSignInView.swift @@ -35,8 +35,8 @@ private extension SignUpOrSignInView { .padding() let agreement = "By signing up or signing in, you agree to the " + - "[\(String.termsOfUse)](\(String.termsOfUseUrl)) " + - "and [\(String.privacyPolicy)](\(String.privacyPolicyUrl))." + "[\(Strings.termsOfUse)](\(Strings.termsOfUseUrl)) " + + "and [\(Strings.privacyPolicy)](\(Strings.privacyPolicyUrl))." Text(.init(agreement)) .padding(.top, NativeAppTemplateConstants.Spacing.sm) .padding(.horizontal, NativeAppTemplateConstants.Spacing.md) @@ -48,7 +48,7 @@ private extension SignUpOrSignInView { messageBus: messageBus ) )) { - MainButtonImageView(title: String.signUpForAnAccount, type: .primary(withArrow: false)) + MainButtonImageView(title: Strings.signUpForAnAccount, type: .primary(withArrow: false)) .padding(.top, NativeAppTemplateConstants.Spacing.xxs) .padding(.horizontal, NativeAppTemplateConstants.Spacing.md) } @@ -62,7 +62,7 @@ private extension SignUpOrSignInView { messageBus: messageBus ) )) { - Text(String.signInToYourAccount) + Text(Strings.signInToYourAccount) .font(.uiLabel) } .padding(.top, NativeAppTemplateConstants.Spacing.xxs) @@ -76,7 +76,7 @@ private extension SignUpOrSignInView { .navigationBarTitleDisplayMode(.inline) .toolbar { ToolbarItem(placement: .navigationBarTrailing) { - Link(String.supportWebsite, destination: URL(string: String.supportWebsiteUrl)!) + Link(Strings.supportWebsite, destination: URL(string: Strings.supportWebsiteUrl)!) } } .background(Color.backgroundColor) diff --git a/NativeAppTemplate/UI/App Root/SignUpView.swift b/NativeAppTemplate/UI/App Root/SignUpView.swift index 97c667a..f142273 100644 --- a/NativeAppTemplate/UI/App Root/SignUpView.swift +++ b/NativeAppTemplate/UI/App Root/SignUpView.swift @@ -44,69 +44,69 @@ private extension SignUpView { NavigationStack { Form { Section { - TextField(String.placeholderFullName, text: $viewModel.name) + TextField(Strings.placeholderFullName, text: $viewModel.name) } header: { - Text(String.fullName) + Text(Strings.fullName) } footer: { - Text(String.fullNameIsRequired) + Text(Strings.fullNameIsRequired) .font(.caption) .foregroundStyle(viewModel.isNameBlank ? .validationError : .clear) } Section { - TextField(String.placeholderEmail, text: $viewModel.email) + TextField(Strings.placeholderEmail, text: $viewModel.email) .textContentType(.emailAddress) .autocapitalization(.none) } header: { - Text(String.email) + Text(Strings.email) } footer: { if viewModel.isEmailBlank { - Text(String.emailIsRequired) + Text(Strings.emailIsRequired) .foregroundStyle(.validationError) } else if viewModel.hasInvalidDataEmail { - Text(String.emailIsInvalid) + Text(Strings.emailIsInvalid) .foregroundStyle(.validationError) } } - Picker(String.timeZone, selection: $viewModel.selectedTimeZone) { + Picker(Strings.timeZone, selection: $viewModel.selectedTimeZone) { ForEach(timeZones.keys, id: \.self) { key in Text(timeZones[key]!).tag(key) } } Section { - SecureField(String.placeholderPassword, text: $viewModel.password) + SecureField(Strings.placeholderPassword, text: $viewModel.password) .textContentType(.password) .autocapitalization(.none) .autocorrectionDisabled(true) } header: { - Text(String.password) + Text(Strings.password) } footer: { VStack(alignment: .leading) { Text("\(Int.minimumPasswordLength) characters minimum.") if viewModel.isPasswordBlank { - Text(String.passwordIsRequired) + Text(Strings.passwordIsRequired) .foregroundStyle(.validationError) } else if viewModel.hasInvalidDataPassword { - Text(String.passwordIsInvalid) + Text(Strings.passwordIsInvalid) .foregroundStyle(.validationError) } } } Section { - MainButtonView(title: String.signUp, type: .primary(withArrow: false)) { + MainButtonView(title: Strings.signUp, type: .primary(withArrow: false)) { viewModel.createShopkeeper() } .disabled(viewModel.hasInvalidData) .listRowBackground(Color.clear) } } - .navigationTitle(String.signUp) + .navigationTitle(Strings.signUp) } .alert( - String.shopkeeperCreatedError, + Strings.shopkeeperCreatedError, isPresented: $viewModel.isShowingAlert ) {} message: { Text(viewModel.errorMessage) diff --git a/NativeAppTemplate/UI/App Root/SignUpViewModel.swift b/NativeAppTemplate/UI/App Root/SignUpViewModel.swift index bbd21ea..4d8f465 100644 --- a/NativeAppTemplate/UI/App Root/SignUpViewModel.swift +++ b/NativeAppTemplate/UI/App Root/SignUpViewModel.swift @@ -102,7 +102,7 @@ final class SignUpViewModel { messageBus.post(message: Message( level: .success, - message: String.signedUpButUnconfirmed, + message: Strings.signedUpButUnconfirmed, autoDismiss: false )) shouldDismiss = true diff --git a/NativeAppTemplate/UI/Empty States/LoadingView.swift b/NativeAppTemplate/UI/Empty States/LoadingView.swift index 1714bb4..904e746 100644 --- a/NativeAppTemplate/UI/Empty States/LoadingView.swift +++ b/NativeAppTemplate/UI/Empty States/LoadingView.swift @@ -11,7 +11,7 @@ struct LoadingView: View { VStack { ProgressView().scaleEffect(1.0, anchor: .center) .padding([.bottom], NativeAppTemplateConstants.Spacing.xs) - Text(String.loading) + Text(Strings.loading) .font(.uiHeadline) } } diff --git a/NativeAppTemplate/UI/Empty States/NeedAppUpdatesView.swift b/NativeAppTemplate/UI/Empty States/NeedAppUpdatesView.swift index 33ebfd1..43fe40e 100644 --- a/NativeAppTemplate/UI/Empty States/NeedAppUpdatesView.swift +++ b/NativeAppTemplate/UI/Empty States/NeedAppUpdatesView.swift @@ -20,17 +20,17 @@ struct NeedAppUpdatesView: View { .frame(width: NativeAppTemplateConstants.Spacing.xxxl) .foregroundStyle(.titleText) .padding() - Text(String.updateApp) + Text(Strings.updateApp) .font(.uiTitle1) .foregroundStyle(.titleText) .padding(.top) - Text(String.installNewVersionApp) + Text(Strings.installNewVersionApp) .foregroundStyle(.contentText) .padding(.top, NativeAppTemplateConstants.Spacing.xxxs) Button { - openURL(URL(string: String.appStoreUrl)!) + openURL(URL(string: Strings.appStoreUrl)!) } label: { - Text(String.updateApp) + Text(Strings.updateApp) } .padding(.top) } diff --git a/NativeAppTemplate/UI/Empty States/OfflineView.swift b/NativeAppTemplate/UI/Empty States/OfflineView.swift index 203c955..9b9b742 100644 --- a/NativeAppTemplate/UI/Empty States/OfflineView.swift +++ b/NativeAppTemplate/UI/Empty States/OfflineView.swift @@ -19,13 +19,13 @@ struct OfflineView: View { .padding() .foregroundStyle(.titleText) - Text(String.noConnection) + Text(Strings.noConnection) .font(.uiTitle1) .foregroundStyle(.titleText) .multilineTextAlignment(.center) .padding(.top) - Text(String.checkInternetConnection) + Text(Strings.checkInternetConnection) .font(.uiLabel) .lineSpacing(NativeAppTemplateConstants.Spacing.xxs) .foregroundStyle(.contentText) diff --git a/NativeAppTemplate/UI/Settings/PasswordEditView.swift b/NativeAppTemplate/UI/Settings/PasswordEditView.swift index c912673..9df3a26 100644 --- a/NativeAppTemplate/UI/Settings/PasswordEditView.swift +++ b/NativeAppTemplate/UI/Settings/PasswordEditView.swift @@ -41,64 +41,64 @@ private extension PasswordEditView { var passwordEditView: some View { Form { Section { - SecureField(String.currentPassword, text: $viewModel.currentPassword) + SecureField(Strings.currentPassword, text: $viewModel.currentPassword) .textContentType(.password) .autocapitalization(.none) .autocorrectionDisabled(true) } header: { - Text(String.currentPassword) + Text(Strings.currentPassword) } footer: { VStack(alignment: .leading) { - Text(String.weNeedYourCurrentPassword) + Text(Strings.weNeedYourCurrentPassword) .font(.uiFootnote) - Text(String.currentPasswordIsRequired) + Text(Strings.currentPasswordIsRequired) .foregroundStyle(Utility.isBlank(viewModel.currentPassword) ? .validationError : .clear) .font(.uiFootnote) } } Section { - SecureField(String.newPassword, text: $viewModel.password) + SecureField(Strings.newPassword, text: $viewModel.password) .textContentType(.password) .autocapitalization(.none) .autocorrectionDisabled(true) } header: { - Text(String.newPassword) + Text(Strings.newPassword) } footer: { VStack(alignment: .leading) { Text("\(viewModel.minimumPasswordLength) characters minimum.") .font(.uiFootnote) if Utility.isBlank(viewModel.password) { - Text(String.newPasswordIsRequired) + Text(Strings.newPasswordIsRequired) .foregroundStyle(.validationError) .font(.uiFootnote) } else if viewModel.hasInvalidDataPassword { - Text(String.passwordIsInvalid) + Text(Strings.passwordIsInvalid) .foregroundStyle(.validationError) .font(.uiFootnote) } } } Section { - SecureField(String.confirmNewPassword, text: $viewModel.passwordConfirmation) + SecureField(Strings.confirmNewPassword, text: $viewModel.passwordConfirmation) .textContentType(.password) .autocapitalization(.none) .autocorrectionDisabled(true) } header: { - Text(String.confirmNewPassword) + Text(Strings.confirmNewPassword) } footer: { - Text(String.confirmNewPasswordIsRequired) + Text(Strings.confirmNewPasswordIsRequired) .font(.uiFootnote) .foregroundStyle(Utility.isBlank(viewModel.passwordConfirmation) ? .validationError : .clear) } } - .navigationTitle(String.updatePassword) + .navigationTitle(Strings.updatePassword) .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Button { viewModel.updatePassword() } label: { - Text(String.save) + Text(Strings.save) } .disabled(viewModel.hasInvalidData) } diff --git a/NativeAppTemplate/UI/Settings/PasswordEditViewModel.swift b/NativeAppTemplate/UI/Settings/PasswordEditViewModel.swift index 8bd96eb..23e42e3 100644 --- a/NativeAppTemplate/UI/Settings/PasswordEditViewModel.swift +++ b/NativeAppTemplate/UI/Settings/PasswordEditViewModel.swift @@ -77,7 +77,7 @@ final class PasswordEditViewModel { ) try await accountPasswordRepository.update(updatePassword: updatePassword) - messageBus.post(message: Message(level: .success, message: .passwordUpdated)) + messageBus.post(message: Message(level: .success, message: Strings.passwordUpdated)) shouldDismiss = true } catch { messageBus.post(message: Message(error: error)) diff --git a/NativeAppTemplate/UI/Settings/SettingsView.swift b/NativeAppTemplate/UI/Settings/SettingsView.swift index 12222a6..59500d8 100644 --- a/NativeAppTemplate/UI/Settings/SettingsView.swift +++ b/NativeAppTemplate/UI/Settings/SettingsView.swift @@ -22,7 +22,7 @@ struct SettingsView: View { var body: some View { VStack(spacing: 0) { List { - Section(header: Text(String.myAccount)) { + Section(header: Text(Strings.myAccount)) { if let shopkeeper = viewModel.shopkeeper { NavigationLink( destination: ShopkeeperEditView( @@ -35,7 +35,7 @@ struct SettingsView: View { ) ) ) { - Label(String.profile, systemImage: "person") + Label(Strings.profile, systemImage: "person") } } @@ -47,37 +47,37 @@ struct SettingsView: View { ) ) ) { - Label(String.password, systemImage: "key") + Label(Strings.password, systemImage: "key") } } .listRowBackground(Color.cardBackground.opacity(0.7)) Section(header: Text(verbatim: "Support")) { - Link(destination: URL(string: String.faqsUrl)!) { - Label(String.faqs, systemImage: "questionmark") + Link(destination: URL(string: Strings.faqsUrl)!) { + Label(Strings.faqs, systemImage: "questionmark") } Link(destination: supportEmailURL) { - Label(String.contact, systemImage: "envelope") + Label(Strings.contact, systemImage: "envelope") } Button { requestReview() } label: { - Label(String.rateApp, systemImage: "hand.thumbsup") + Label(Strings.rateApp, systemImage: "hand.thumbsup") } } .listRowBackground(Color.cardBackground.opacity(0.7)) Section(header: Text(verbatim: "About")) { - Link(destination: URL(string: String.supportWebsiteUrl)!) { + Link(destination: URL(string: Strings.supportWebsiteUrl)!) { Label("Website", systemImage: "globe") } - Link(destination: URL(string: String.privacyPolicyUrl)!) { - Label(String.privacyPolicy, systemImage: "hand.raised") + Link(destination: URL(string: Strings.privacyPolicyUrl)!) { + Label(Strings.privacyPolicy, systemImage: "hand.raised") } - Link(destination: URL(string: String.termsOfUseUrl)!) { - Label(String.termsOfUse, systemImage: "doc.text") + Link(destination: URL(string: Strings.termsOfUseUrl)!) { + Label(Strings.termsOfUse, systemImage: "doc.text") } } .listRowBackground(Color.cardBackground.opacity(0.7)) @@ -113,7 +113,7 @@ struct SettingsView: View { #endif } } - .navigationTitle(String.settings) + .navigationTitle(Strings.settings) .navigationBarTitleDisplayMode(.inline) } @@ -142,6 +142,6 @@ struct SettingsView: View { """ let encodedBody = body.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? "" - return URL(string: "mailto:\(String.supportMail)?body=\(encodedBody)")! + return URL(string: "mailto:\(Strings.supportMail)?body=\(encodedBody)")! } } diff --git a/NativeAppTemplate/UI/Settings/SettingsViewModel.swift b/NativeAppTemplate/UI/Settings/SettingsViewModel.swift index 731311c..70534ab 100644 --- a/NativeAppTemplate/UI/Settings/SettingsViewModel.swift +++ b/NativeAppTemplate/UI/Settings/SettingsViewModel.swift @@ -40,13 +40,13 @@ final class SettingsViewModel { do { try await sessionController.logout() #if DEBUG - messageBus.post(message: Message(level: .success, message: .signedOut)) + messageBus.post(message: Message(level: .success, message: Strings.signedOut)) #endif } catch { #if DEBUG messageBus.post(message: Message( level: .error, - message: "\(String.signedOutError) \(error.codedDescription)", + message: "\(Strings.signedOutError) \(error.codedDescription)", autoDismiss: false )) #endif diff --git a/NativeAppTemplate/UI/Settings/ShopkeeperEditView.swift b/NativeAppTemplate/UI/Settings/ShopkeeperEditView.swift index 7aadfae..f1d866a 100644 --- a/NativeAppTemplate/UI/Settings/ShopkeeperEditView.swift +++ b/NativeAppTemplate/UI/Settings/ShopkeeperEditView.swift @@ -42,32 +42,32 @@ private extension ShopkeeperEditView { var shopkeeperEditView: some View { Form { Section { - TextField(String.placeholderFullName, text: $viewModel.name) + TextField(Strings.placeholderFullName, text: $viewModel.name) } header: { - Text(String.fullName) + Text(Strings.fullName) } footer: { - Text(String.fullNameIsRequired) + Text(Strings.fullNameIsRequired) .foregroundStyle(Utility.isBlank(viewModel.name) ? .validationError : .clear) } Section { - TextField(String.placeholderEmail, text: $viewModel.email) + TextField(Strings.placeholderEmail, text: $viewModel.email) .textContentType(.emailAddress) .autocapitalization(.none) } header: { - Text(String.email) + Text(Strings.email) } footer: { if Utility.isBlank(viewModel.email) { - Text(String.emailIsRequired) + Text(Strings.emailIsRequired) .foregroundStyle(.validationError) } else if viewModel.hasInvalidDataEmail { - Text(String.emailIsInvalid) + Text(Strings.emailIsInvalid) .foregroundStyle(.validationError) } } Section { - Picker(String.timeZone, selection: $viewModel.selectedTimeZone) { + Picker(Strings.timeZone, selection: $viewModel.selectedTimeZone) { ForEach(timeZones.keys, id: \.self) { key in Text(timeZones[key]!).tag(key) } @@ -78,33 +78,33 @@ private extension ShopkeeperEditView { .listRowBackground(Color.clear) Section { - MainButtonView(title: String.deleteMyAccount, type: .destructive(withArrow: false)) { + MainButtonView(title: Strings.deleteMyAccount, type: .destructive(withArrow: false)) { viewModel.isShowingDeleteConfirmationDialog = true } .listRowBackground(Color.clear) } } .alert( - String.deleteMyAccount, + Strings.deleteMyAccount, isPresented: $viewModel.isShowingDeleteConfirmationDialog ) { - Button(String.deleteMyAccount, role: .destructive) { + Button(Strings.deleteMyAccount, role: .destructive) { viewModel.destroyShopkeeper() } - Button(String.cancel, role: .cancel) { + Button(Strings.cancel, role: .cancel) { viewModel.isShowingDeleteConfirmationDialog = false } } message: { - Text(String.areYouSure) + Text(Strings.areYouSure) } - .navigationTitle(String.editProfile) + .navigationTitle(Strings.editProfile) .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Button { viewModel.updateShopkeeper() } label: { - Text(String.save) + Text(Strings.save) } .disabled(viewModel.hasInvalidData) } diff --git a/NativeAppTemplate/UI/Settings/ShopkeeperEditViewModel.swift b/NativeAppTemplate/UI/Settings/ShopkeeperEditViewModel.swift index 7243876..8f728a9 100644 --- a/NativeAppTemplate/UI/Settings/ShopkeeperEditViewModel.swift +++ b/NativeAppTemplate/UI/Settings/ShopkeeperEditViewModel.swift @@ -107,12 +107,12 @@ final class ShopkeeperEditViewModel { if emailUpdated { messageBus.post(message: Message( level: .success, - message: .reconfirmDescription, + message: Strings.reconfirmDescription, autoDismiss: false )) try await sessionController.logout() } else { - messageBus.post(message: Message(level: .success, message: .shopkeeperUpdated)) + messageBus.post(message: Message(level: .success, message: Strings.shopkeeperUpdated)) } shouldDismiss = true @@ -130,11 +130,11 @@ final class ShopkeeperEditViewModel { do { try await signUpRepository.destroy(networkClient: sessionController.client) - messageBus.post(message: Message(level: .success, message: .shopkeeperDeleted)) + messageBus.post(message: Message(level: .success, message: Strings.shopkeeperDeleted)) } catch { messageBus.post(message: Message( level: .error, - message: "\(String.shopkeeperDeletedError) \(error.codedDescription)", + message: "\(Strings.shopkeeperDeletedError) \(error.codedDescription)", autoDismiss: false )) } @@ -144,7 +144,7 @@ final class ShopkeeperEditViewModel { } catch { messageBus.post(message: Message( level: .error, - message: "\(String.shopkeeperDeletedError) \(error.codedDescription)", + message: "\(Strings.shopkeeperDeletedError) \(error.codedDescription)", autoDismiss: false )) } diff --git a/NativeAppTemplate/UI/Shop Detail/ShopDetailView.swift b/NativeAppTemplate/UI/Shop Detail/ShopDetailView.swift index 3ec0919..f318dc8 100644 --- a/NativeAppTemplate/UI/Shop Detail/ShopDetailView.swift +++ b/NativeAppTemplate/UI/Shop Detail/ShopDetailView.swift @@ -51,7 +51,7 @@ private extension ShopDetailView { } func header(shop: Shop) -> some View { - Text(String.shopDetailInstruction) + Text(Strings.shopDetailInstruction) .foregroundStyle(.contentText) .frame(maxWidth: .infinity, alignment: .leading) .padding(.leading) @@ -63,13 +63,13 @@ private extension ShopDetailView { .swipeActions(edge: .trailing, allowsFullSwipe: false) { if itemTag.state == ItemTagState.idled { Button { viewModel.completeTag(itemTagId: itemTag.id) } label: { - Label(String.complete, systemImage: "bolt.fill") + Label(Strings.complete, systemImage: "bolt.fill") .labelStyle(.titleOnly) } .tint(.blue) } else { Button(role: .destructive) { viewModel.idleTag(itemTagId: itemTag.id) } label: { - Label(String.idle, systemImage: "trash") + Label(Strings.idle, systemImage: "trash") .labelStyle(.titleOnly) } .tint(.validationError) diff --git a/NativeAppTemplate/UI/Shop Detail/ShopDetailViewModel.swift b/NativeAppTemplate/UI/Shop Detail/ShopDetailViewModel.swift index 6ba723c..a8b296f 100644 --- a/NativeAppTemplate/UI/Shop Detail/ShopDetailViewModel.swift +++ b/NativeAppTemplate/UI/Shop Detail/ShopDetailViewModel.swift @@ -80,7 +80,7 @@ final class ShopDetailViewModel { messageBus.post( message: Message( level: .error, - message: "\(String.itemTagCompletedError) \(error.codedDescription)", + message: "\(Strings.itemTagCompletedError) \(error.codedDescription)", autoDismiss: false ) ) @@ -101,7 +101,7 @@ final class ShopDetailViewModel { messageBus.post( message: Message( level: .error, - message: "\(String.itemTagIdledError) \(error.codedDescription)", + message: "\(Strings.itemTagIdledError) \(error.codedDescription)", autoDismiss: false ) ) diff --git a/NativeAppTemplate/UI/Shop List/ShopCreateView.swift b/NativeAppTemplate/UI/Shop List/ShopCreateView.swift index dadf7f6..cf67d40 100644 --- a/NativeAppTemplate/UI/Shop List/ShopCreateView.swift +++ b/NativeAppTemplate/UI/Shop List/ShopCreateView.swift @@ -35,59 +35,59 @@ struct ShopCreateView: View { NavigationStack { Form { Section { - TextField(String.name, text: $viewModel.name) + TextField(Strings.name, text: $viewModel.name) .onChange(of: viewModel.name) { viewModel.validateNameLength() } } header: { - Text(String.shopName) + Text(Strings.shopName) } footer: { VStack(alignment: .leading) { - Text(String.shopNameHelp(maximumLength: viewModel.maximumNameLength)) + Text(Strings.shopNameHelp(maximumLength: viewModel.maximumNameLength)) .font(.uiFootnote) - Text(String.shopNameIsInvalid) + Text(Strings.shopNameIsInvalid) .font(.uiFootnote) .foregroundStyle(viewModel.hasInvalidDataName ? .validationError : .clear) } } Section { - TextField(String.descriptionString, text: $viewModel.description, axis: .vertical) + TextField(Strings.descriptionString, text: $viewModel.description, axis: .vertical) .lineLimit(10, reservesSpace: true) .onChange(of: viewModel.description) { viewModel.validateDescriptionLength() } } header: { - Text(String.descriptionString) + Text(Strings.descriptionString) } footer: { VStack(alignment: .leading) { - Text(String.shopDescriptionHelp(maximumLength: viewModel.maximumDescriptionLength)) + Text(Strings.shopDescriptionHelp(maximumLength: viewModel.maximumDescriptionLength)) .font(.uiFootnote) - Text(String.shopDescriptionIsInvalid) + Text(Strings.shopDescriptionIsInvalid) .font(.uiFootnote) .foregroundStyle(viewModel.hasInvalidDataDescription ? .validationError : .clear) } } Section { - Picker(String.timeZone, selection: $viewModel.selectedTimeZone) { + Picker(Strings.timeZone, selection: $viewModel.selectedTimeZone) { ForEach(timeZones.keys, id: \.self) { key in Text(timeZones[key]!).tag(key) } } } } - .navigationTitle(String.addShop) + .navigationTitle(Strings.addShop) .toolbar { ToolbarItem(placement: .navigationBarTrailing) { - Button(String.save) { + Button(Strings.save) { viewModel.createShop() } .disabled(viewModel.hasInvalidData) } ToolbarItem(placement: .navigationBarLeading) { - Button(String.cancel) { + Button(Strings.cancel) { dismiss() } } diff --git a/NativeAppTemplate/UI/Shop List/ShopCreateViewModel.swift b/NativeAppTemplate/UI/Shop List/ShopCreateViewModel.swift index 5adc44a..3c09430 100644 --- a/NativeAppTemplate/UI/Shop List/ShopCreateViewModel.swift +++ b/NativeAppTemplate/UI/Shop List/ShopCreateViewModel.swift @@ -76,7 +76,7 @@ final class ShopCreateViewModel { timeZone: selectedTimeZone ) _ = try await shopRepository.create(shop: shop) - messageBus.post(message: Message(level: .success, message: .shopCreated)) + messageBus.post(message: Message(level: .success, message: Strings.shopCreated)) shouldDismiss = true } catch { messageBus.post(message: Message(error: error)) diff --git a/NativeAppTemplate/UI/Shop List/ShopListView.swift b/NativeAppTemplate/UI/Shop List/ShopListView.swift index 57f6979..b5321b2 100644 --- a/NativeAppTemplate/UI/Shop List/ShopListView.swift +++ b/NativeAppTemplate/UI/Shop List/ShopListView.swift @@ -8,11 +8,11 @@ import TipKit struct TapShopBelowTip: Tip { var title: Text { - Text(String.tapShopBelow) + Text(Strings.tapShopBelow) } var message: Text? { - Text(String.haveFun) + Text(Strings.haveFun) } var image: Image? { @@ -129,7 +129,7 @@ private extension ShopListView { } } } - .navigationTitle(String.shops) + .navigationTitle(Strings.shops) .navigationBarTitleDisplayMode(.inline) .toolbar { if viewModel.leftInShopSlots > 0 { @@ -172,11 +172,11 @@ private extension ShopListView { .frame(width: NativeAppTemplateConstants.Spacing.xxxl) .padding() - Text(String.addShopDescription) + Text(Strings.addShopDescription) .foregroundStyle(.contentText) .padding() - MainButtonView(title: String.addShop, type: .primary(withArrow: false)) { + MainButtonView(title: Strings.addShop, type: .primary(withArrow: false)) { viewModel.showCreateView() } .padding() diff --git a/NativeAppTemplate/UI/Shop Settings/ItemTag Detail/ItemTagDetailView.swift b/NativeAppTemplate/UI/Shop Settings/ItemTag Detail/ItemTagDetailView.swift index d7e9be0..3f5a259 100644 --- a/NativeAppTemplate/UI/Shop Settings/ItemTag Detail/ItemTagDetailView.swift +++ b/NativeAppTemplate/UI/Shop Settings/ItemTag Detail/ItemTagDetailView.swift @@ -67,17 +67,17 @@ private extension ItemTagDetailView { } ) .alert( - String.buttonDeleteItemTag, + Strings.buttonDeleteItemTag, isPresented: $viewModel.isShowingDeleteConfirmationDialog ) { - Button(String.buttonDeleteItemTag, role: .destructive) { + Button(Strings.buttonDeleteItemTag, role: .destructive) { viewModel.destroyItemTag() } - Button(String.cancel, role: .cancel) { + Button(Strings.cancel, role: .cancel) { viewModel.isShowingDeleteConfirmationDialog = false } } message: { - Text(String.areYouSure) + Text(Strings.areYouSure) } .toolbar { toolbarContent } } @@ -102,7 +102,7 @@ private extension ItemTagDetailView { func descriptionSection(itemTag: ItemTag) -> some View { if !itemTag.description.isEmpty { VStack(alignment: .leading, spacing: NativeAppTemplateConstants.Spacing.xxs) { - Text(String.descriptionLabel) + Text(Strings.descriptionLabel) .font(.uiTitle4) .foregroundStyle(.titleText) Text(itemTag.description) @@ -116,7 +116,7 @@ private extension ItemTagDetailView { func completedAtRow(itemTag: ItemTag) -> some View { if let completedAt = itemTag.completedAt, itemTag.state == .completed { HStack { - Text(String.completedAtLabel) + Text(Strings.completedAtLabel) .font(.uiFootnote) .foregroundStyle(.contentText) Text(completedAt.cardDateTimeString) @@ -130,7 +130,7 @@ private extension ItemTagDetailView { func stateToggleButton(itemTag: ItemTag) -> some View { if itemTag.state == .idled { MainButtonView( - title: String.markAsCompleted, + title: Strings.markAsCompleted, type: .primary(withArrow: false) ) { viewModel.completeItemTag() @@ -138,7 +138,7 @@ private extension ItemTagDetailView { .disabled(viewModel.isToggling) } else { MainButtonView( - title: String.markAsIdled, + title: Strings.markAsIdled, type: .secondary(withArrow: false) ) { viewModel.idleItemTag() @@ -153,7 +153,7 @@ private extension ItemTagDetailView { Button { viewModel.isShowingEditSheet.toggle() } label: { - Text(String.edit) + Text(Strings.edit) } } ToolbarItem(placement: .navigationBarTrailing) { diff --git a/NativeAppTemplate/UI/Shop Settings/ItemTag Detail/ItemTagDetailViewModel.swift b/NativeAppTemplate/UI/Shop Settings/ItemTag Detail/ItemTagDetailViewModel.swift index 0488527..d856661 100644 --- a/NativeAppTemplate/UI/Shop Settings/ItemTag Detail/ItemTagDetailViewModel.swift +++ b/NativeAppTemplate/UI/Shop Settings/ItemTag Detail/ItemTagDetailViewModel.swift @@ -57,7 +57,7 @@ final class ItemTagDetailViewModel { } catch { messageBus.post(message: Message( level: .error, - message: "\(String.itemTagCompletedError) \(error.codedDescription)", + message: "\(Strings.itemTagCompletedError) \(error.codedDescription)", autoDismiss: false )) } @@ -78,7 +78,7 @@ final class ItemTagDetailViewModel { } catch { messageBus.post(message: Message( level: .error, - message: "\(String.itemTagIdledError) \(error.codedDescription)", + message: "\(Strings.itemTagIdledError) \(error.codedDescription)", autoDismiss: false )) } @@ -95,11 +95,11 @@ final class ItemTagDetailViewModel { do { try await itemTagRepository.destroy(id: itemTag.id) - messageBus.post(message: Message(level: .success, message: .itemTagDeleted)) + messageBus.post(message: Message(level: .success, message: Strings.itemTagDeleted)) } catch { messageBus.post(message: Message( level: .error, - message: "\(String.itemTagDeletedError) \(error.codedDescription)", + message: "\(Strings.itemTagDeletedError) \(error.codedDescription)", autoDismiss: false )) } diff --git a/NativeAppTemplate/UI/Shop Settings/ItemTag Detail/ItemTagEditView.swift b/NativeAppTemplate/UI/Shop Settings/ItemTag Detail/ItemTagEditView.swift index be6a421..0a24769 100644 --- a/NativeAppTemplate/UI/Shop Settings/ItemTag Detail/ItemTagEditView.swift +++ b/NativeAppTemplate/UI/Shop Settings/ItemTag Detail/ItemTagEditView.swift @@ -45,17 +45,17 @@ private extension ItemTagEditView { NavigationStack { Form { Section { - TextField(String.itemTagNamePlaceholder, text: $viewModel.name) + TextField(Strings.itemTagNamePlaceholder, text: $viewModel.name) .onChange(of: viewModel.name) { viewModel.validateNameLength() } } header: { - Text(String.nameLabel) + Text(Strings.nameLabel) } footer: { VStack(alignment: .leading) { - Text(String.itemTagNameHelp(maximumLength: viewModel.maximumNameLength)) + Text(Strings.itemTagNameHelp(maximumLength: viewModel.maximumNameLength)) .font(.uiFootnote) - Text(String.itemTagNameIsInvalid) + Text(Strings.itemTagNameIsInvalid) .font(.uiFootnote) .foregroundStyle(viewModel.hasInvalidDataName ? .validationError : .clear) } @@ -68,24 +68,24 @@ private extension ItemTagEditView { viewModel.validateDescriptionLength() } } header: { - Text(String.descriptionLabel) + Text(Strings.descriptionLabel) } footer: { VStack(alignment: .leading) { - Text(String.itemTagDescriptionHelp(maximumLength: viewModel.maximumDescriptionLength)) + Text(Strings.itemTagDescriptionHelp(maximumLength: viewModel.maximumDescriptionLength)) .font(.uiFootnote) - Text(String.itemTagDescriptionIsInvalid) + Text(Strings.itemTagDescriptionIsInvalid) .font(.uiFootnote) .foregroundStyle(viewModel.hasInvalidDataDescription ? .validationError : .clear) } } } - .navigationTitle(String.editItemTag) + .navigationTitle(Strings.editItemTag) .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Button { viewModel.updateItemTag() } label: { - Text(String.save) + Text(Strings.save) } .disabled(viewModel.hasInvalidData) } @@ -93,7 +93,7 @@ private extension ItemTagEditView { Button { dismiss() } label: { - Text(String.cancel) + Text(Strings.cancel) } } } diff --git a/NativeAppTemplate/UI/Shop Settings/ItemTag Detail/ItemTagEditViewModel.swift b/NativeAppTemplate/UI/Shop Settings/ItemTag Detail/ItemTagEditViewModel.swift index 808a88f..ba35e86 100644 --- a/NativeAppTemplate/UI/Shop Settings/ItemTag Detail/ItemTagEditViewModel.swift +++ b/NativeAppTemplate/UI/Shop Settings/ItemTag Detail/ItemTagEditViewModel.swift @@ -98,7 +98,7 @@ final class ItemTagEditViewModel { ) _ = try await itemTagRepository.update(id: itemTag.id, itemTag: itemTag) - messageBus.post(message: Message(level: .success, message: .itemTagUpdated)) + messageBus.post(message: Message(level: .success, message: Strings.itemTagUpdated)) } catch { messageBus.post(message: Message(error: error)) } diff --git a/NativeAppTemplate/UI/Shop Settings/ItemTag List/ItemTagCreateView.swift b/NativeAppTemplate/UI/Shop Settings/ItemTag List/ItemTagCreateView.swift index def82bd..1152413 100644 --- a/NativeAppTemplate/UI/Shop Settings/ItemTag List/ItemTagCreateView.swift +++ b/NativeAppTemplate/UI/Shop Settings/ItemTag List/ItemTagCreateView.swift @@ -42,17 +42,17 @@ private extension ItemTagCreateView { NavigationStack { Form { Section { - TextField(String.itemTagNamePlaceholder, text: $viewModel.name) + TextField(Strings.itemTagNamePlaceholder, text: $viewModel.name) .onChange(of: viewModel.name) { viewModel.validateNameLength() } } header: { - Text(String.nameLabel) + Text(Strings.nameLabel) } footer: { VStack(alignment: .leading) { - Text(String.itemTagNameHelp(maximumLength: viewModel.maximumNameLength)) + Text(Strings.itemTagNameHelp(maximumLength: viewModel.maximumNameLength)) .font(.uiFootnote) - Text(String.itemTagNameIsInvalid) + Text(Strings.itemTagNameIsInvalid) .font(.uiFootnote) .foregroundStyle(viewModel.hasInvalidDataName ? .validationError : .clear) } @@ -65,24 +65,24 @@ private extension ItemTagCreateView { viewModel.validateDescriptionLength() } } header: { - Text(String.descriptionLabel) + Text(Strings.descriptionLabel) } footer: { VStack(alignment: .leading) { - Text(String.itemTagDescriptionHelp(maximumLength: viewModel.maximumDescriptionLength)) + Text(Strings.itemTagDescriptionHelp(maximumLength: viewModel.maximumDescriptionLength)) .font(.uiFootnote) - Text(String.itemTagDescriptionIsInvalid) + Text(Strings.itemTagDescriptionIsInvalid) .font(.uiFootnote) .foregroundStyle(viewModel.hasInvalidDataDescription ? .validationError : .clear) } } } - .navigationTitle(String.addItemTag) + .navigationTitle(Strings.addItemTag) .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Button { viewModel.createItemTag() } label: { - Text(String.save) + Text(Strings.save) } .disabled(viewModel.hasInvalidData) } @@ -90,7 +90,7 @@ private extension ItemTagCreateView { Button { dismiss() } label: { - Text(String.cancel) + Text(Strings.cancel) } } } diff --git a/NativeAppTemplate/UI/Shop Settings/ItemTag List/ItemTagCreateViewModel.swift b/NativeAppTemplate/UI/Shop Settings/ItemTag List/ItemTagCreateViewModel.swift index db4498f..ff3bd15 100644 --- a/NativeAppTemplate/UI/Shop Settings/ItemTag List/ItemTagCreateViewModel.swift +++ b/NativeAppTemplate/UI/Shop Settings/ItemTag List/ItemTagCreateViewModel.swift @@ -73,7 +73,7 @@ final class ItemTagCreateViewModel { do { let itemTag = ItemTag(name: name, description: description) _ = try await itemTagRepository.create(shopId: shopId, itemTag: itemTag) - messageBus.post(message: Message(level: .success, message: .itemTagCreated)) + messageBus.post(message: Message(level: .success, message: Strings.itemTagCreated)) } catch { messageBus.post(message: Message(error: error)) } diff --git a/NativeAppTemplate/UI/Shop Settings/ItemTag List/ItemTagListView.swift b/NativeAppTemplate/UI/Shop Settings/ItemTag List/ItemTagListView.swift index ff34ab7..9901a98 100644 --- a/NativeAppTemplate/UI/Shop Settings/ItemTag List/ItemTagListView.swift +++ b/NativeAppTemplate/UI/Shop Settings/ItemTag List/ItemTagListView.swift @@ -73,7 +73,7 @@ private extension ItemTagListView { ) .swipeActions(edge: .trailing, allowsFullSwipe: false) { Button(role: .destructive) { viewModel.destroyItemTag(itemTagId: itemTag.id) } label: { - Label(String.delete, systemImage: "trash") + Label(Strings.delete, systemImage: "trash") .labelStyle(.titleOnly) } .tint(.validationError) @@ -91,7 +91,7 @@ private extension ItemTagListView { } } } - .navigationTitle(String.shopSettingsManageItemTagsLabel) + .navigationTitle(Strings.shopSettingsManageItemTagsLabel) .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Button { @@ -138,11 +138,11 @@ private extension ItemTagListView { .aspectRatio(contentMode: .fit) .frame(width: NativeAppTemplateConstants.Spacing.xxxl) .padding() - Text(String.addItemTagDescription) + Text(Strings.addItemTagDescription) .foregroundStyle(.contentText) .padding() - MainButtonView(title: String.addItemTag, type: .primary(withArrow: false)) { + MainButtonView(title: Strings.addItemTag, type: .primary(withArrow: false)) { viewModel.isShowingCreateSheet.toggle() } .padding() diff --git a/NativeAppTemplate/UI/Shop Settings/ItemTag List/ItemTagListViewModel.swift b/NativeAppTemplate/UI/Shop Settings/ItemTag List/ItemTagListViewModel.swift index d0cd62a..f7bd6c3 100644 --- a/NativeAppTemplate/UI/Shop Settings/ItemTag List/ItemTagListViewModel.swift +++ b/NativeAppTemplate/UI/Shop Settings/ItemTag List/ItemTagListViewModel.swift @@ -71,12 +71,12 @@ final class ItemTagListViewModel { do { try await itemTagRepository.destroy(id: itemTagId) - messageBus.post(message: Message(level: .success, message: .itemTagDeleted)) + messageBus.post(message: Message(level: .success, message: Strings.itemTagDeleted)) reload() } catch { messageBus.post(message: Message( level: .error, - message: "\(String.itemTagDeletedError) \(error.codedDescription)", + message: "\(Strings.itemTagDeletedError) \(error.codedDescription)", autoDismiss: false )) } diff --git a/NativeAppTemplate/UI/Shop Settings/ShopBasicSettingsView.swift b/NativeAppTemplate/UI/Shop Settings/ShopBasicSettingsView.swift index 4a04fc7..4d59e8d 100644 --- a/NativeAppTemplate/UI/Shop Settings/ShopBasicSettingsView.swift +++ b/NativeAppTemplate/UI/Shop Settings/ShopBasicSettingsView.swift @@ -44,42 +44,42 @@ private extension ShopBasicSettingsView { var shopBasicSettingsView: some View { Form { Section { - TextField(String.shopName, text: $viewModel.name) + TextField(Strings.shopName, text: $viewModel.name) .onChange(of: viewModel.name) { viewModel.validateNameLength() } } header: { - Text(String.shopName) + Text(Strings.shopName) } footer: { VStack(alignment: .leading) { - Text(String.shopNameHelp(maximumLength: viewModel.maximumNameLength)) + Text(Strings.shopNameHelp(maximumLength: viewModel.maximumNameLength)) .font(.uiFootnote) - Text(String.shopNameIsInvalid) + Text(Strings.shopNameIsInvalid) .font(.uiFootnote) .foregroundStyle(viewModel.hasInvalidDataName ? .validationError : .clear) } } Section { - TextField(String.descriptionString, text: $viewModel.description, axis: .vertical) + TextField(Strings.descriptionString, text: $viewModel.description, axis: .vertical) .lineLimit(10, reservesSpace: true) .onChange(of: viewModel.description) { viewModel.validateDescriptionLength() } } header: { - Text(String.descriptionString) + Text(Strings.descriptionString) } footer: { VStack(alignment: .leading) { - Text(String.shopDescriptionHelp(maximumLength: viewModel.maximumDescriptionLength)) + Text(Strings.shopDescriptionHelp(maximumLength: viewModel.maximumDescriptionLength)) .font(.uiFootnote) - Text(String.shopDescriptionIsInvalid) + Text(Strings.shopDescriptionIsInvalid) .font(.uiFootnote) .foregroundStyle(viewModel.hasInvalidDataDescription ? .validationError : .clear) } } Section { - Picker(String.timeZone, selection: $viewModel.selectedTimeZone) { + Picker(Strings.timeZone, selection: $viewModel.selectedTimeZone) { ForEach(timeZones.keys, id: \.self) { key in Text(timeZones[key]!).tag(key) } @@ -87,13 +87,13 @@ private extension ShopBasicSettingsView { } } .padding() - .navigationTitle(String.shopSettingsBasicSettingsLabel) + .navigationTitle(Strings.shopSettingsBasicSettingsLabel) .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Button { viewModel.updateShop() } label: { - Text(String.save) + Text(Strings.save) } .disabled(viewModel.hasInvalidData) } diff --git a/NativeAppTemplate/UI/Shop Settings/ShopBasicSettingsViewModel.swift b/NativeAppTemplate/UI/Shop Settings/ShopBasicSettingsViewModel.swift index e373746..ffb87db 100644 --- a/NativeAppTemplate/UI/Shop Settings/ShopBasicSettingsViewModel.swift +++ b/NativeAppTemplate/UI/Shop Settings/ShopBasicSettingsViewModel.swift @@ -13,7 +13,7 @@ final class ShopBasicSettingsViewModel { var isUpdating = false var name = "" var description = "" - var selectedTimeZone = String.defaultTimeZone + var selectedTimeZone = Strings.defaultTimeZone var shouldDismiss: Bool = false private(set) var shop: Shop? @@ -125,7 +125,7 @@ final class ShopBasicSettingsViewModel { timeZone: selectedTimeZone ) _ = try await shopRepository.update(id: shop.id, shop: shop) - messageBus.post(message: Message(level: .success, message: .basicSettingsUpdated)) + messageBus.post(message: Message(level: .success, message: Strings.basicSettingsUpdated)) } catch { messageBus.post(message: Message(error: error)) } diff --git a/NativeAppTemplate/UI/Shop Settings/ShopSettingsView.swift b/NativeAppTemplate/UI/Shop Settings/ShopSettingsView.swift index 1c28cdd..8cf5214 100644 --- a/NativeAppTemplate/UI/Shop Settings/ShopSettingsView.swift +++ b/NativeAppTemplate/UI/Shop Settings/ShopSettingsView.swift @@ -66,7 +66,7 @@ private extension ShopSettingsView { ) ) } label: { - Label(String.shopSettingsBasicSettingsLabel, systemImage: "storefront") + Label(Strings.shopSettingsBasicSettingsLabel, systemImage: "storefront") } .listRowBackground(Color.cardBackground.opacity(0.7)) } @@ -82,13 +82,13 @@ private extension ShopSettingsView { ) ) } label: { - Label(String.shopSettingsManageItemTagsLabel, systemImage: "rectangle.stack") + Label(Strings.shopSettingsManageItemTagsLabel, systemImage: "rectangle.stack") } .listRowBackground(Color.cardBackground.opacity(0.7)) } Section { - MainButtonView(title: String.deleteShop, type: .destructive(withArrow: false)) { + MainButtonView(title: Strings.deleteShop, type: .destructive(withArrow: false)) { viewModel.isShowingDeleteConfirmationDialog = true } .listRowBackground(Color.clear) @@ -101,19 +101,19 @@ private extension ShopSettingsView { reload() } } - .navigationTitle(String.shopSettingsLabel) + .navigationTitle(Strings.shopSettingsLabel) .alert( - String.deleteShop, + Strings.deleteShop, isPresented: $viewModel.isShowingDeleteConfirmationDialog ) { - Button(String.deleteShop, role: .destructive) { + Button(Strings.deleteShop, role: .destructive) { viewModel.destroyShop() } - Button(String.cancel, role: .cancel) { + Button(Strings.cancel, role: .cancel) { viewModel.isShowingDeleteConfirmationDialog = false } } message: { - Text(String.areYouSure) + Text(Strings.areYouSure) } } diff --git a/NativeAppTemplate/UI/Shop Settings/ShopSettingsViewModel.swift b/NativeAppTemplate/UI/Shop Settings/ShopSettingsViewModel.swift index 8c8cf0c..c5eea20 100644 --- a/NativeAppTemplate/UI/Shop Settings/ShopSettingsViewModel.swift +++ b/NativeAppTemplate/UI/Shop Settings/ShopSettingsViewModel.swift @@ -59,12 +59,12 @@ final class ShopSettingsViewModel { isDeleting = true do { try await shopRepository.destroy(id: shop.id) - messageBus.post(message: .init(level: .success, message: .shopDeleted)) + messageBus.post(message: .init(level: .success, message: Strings.shopDeleted)) sessionController.shouldPopToRootView = true } catch { messageBus.post(message: .init( level: .error, - message: "\(String.shopDeletedError) \(error.codedDescription)", + message: "\(Strings.shopDeletedError) \(error.codedDescription)", autoDismiss: false )) try await sessionController.logout() diff --git a/NativeAppTemplate/Utilities/Utility.swift b/NativeAppTemplate/Utilities/Utility.swift index dc5fd7d..9c580e6 100644 --- a/NativeAppTemplate/Utilities/Utility.swift +++ b/NativeAppTemplate/Utilities/Utility.swift @@ -8,7 +8,7 @@ import os enum Utility { static func currentTimeZone() -> String { - let defaultTimeZone = String.defaultTimeZone + let defaultTimeZone = Strings.defaultTimeZone let timeZoneHourFormatted = currentTimeZoneHourFormatted() let timeZoneArray = TimeZone.current.identifier.components(separatedBy: "/") diff --git a/NativeAppTemplateTests/UI/App Root/ForgotPasswordViewModelTest.swift b/NativeAppTemplateTests/UI/App Root/ForgotPasswordViewModelTest.swift index 315bbaa..321067c 100644 --- a/NativeAppTemplateTests/UI/App Root/ForgotPasswordViewModelTest.swift +++ b/NativeAppTemplateTests/UI/App Root/ForgotPasswordViewModelTest.swift @@ -104,7 +104,7 @@ struct ForgotPasswordViewModelTest { @Test func messageTypesForForgotPassword() { // Test the types of messages that would be posted - let successMessage = Message(level: .success, message: .sentResetPasswordInstruction) + let successMessage = Message(level: .success, message: Strings.sentResetPasswordInstruction) let errorMessage = Message(level: .error, message: "Email not found", autoDismiss: false) #expect(successMessage.level == .success) diff --git a/NativeAppTemplateTests/UI/App Root/OnboardingViewModelTest.swift b/NativeAppTemplateTests/UI/App Root/OnboardingViewModelTest.swift index e66ca07..a6b6f16 100644 --- a/NativeAppTemplateTests/UI/App Root/OnboardingViewModelTest.swift +++ b/NativeAppTemplateTests/UI/App Root/OnboardingViewModelTest.swift @@ -68,9 +68,9 @@ struct OnboardingViewModelTest { viewModel.reload() // Test valid indices (1-based indexing in the switch case) - #expect(viewModel.onboardingDescription(index: 1) == String.onboardingDescription1) - #expect(viewModel.onboardingDescription(index: 2) == String.onboardingDescription2) - #expect(viewModel.onboardingDescription(index: 3) == String.onboardingDescription3) + #expect(viewModel.onboardingDescription(index: 1) == Strings.onboardingDescription1) + #expect(viewModel.onboardingDescription(index: 2) == Strings.onboardingDescription2) + #expect(viewModel.onboardingDescription(index: 3) == Strings.onboardingDescription3) } @Test @@ -89,9 +89,9 @@ struct OnboardingViewModelTest { // Test invalid indices - should return default (onboardingDescription1) let result = viewModel.onboardingDescription(index: 0) - #expect(result == String.onboardingDescription1) + #expect(result == Strings.onboardingDescription1) let result2 = viewModel.onboardingDescription(index: 99) - #expect(result2 == String.onboardingDescription1) + #expect(result2 == Strings.onboardingDescription1) } @Test @@ -106,9 +106,9 @@ struct OnboardingViewModelTest { viewModel.reload() let expectedDescriptions = [ - String.onboardingDescription1, String.onboardingDescription2, String.onboardingDescription3, - String.onboardingDescription4, String.onboardingDescription5, String.onboardingDescription6, - String.onboardingDescription7, String.onboardingDescription8 + Strings.onboardingDescription1, Strings.onboardingDescription2, Strings.onboardingDescription3, + Strings.onboardingDescription4, Strings.onboardingDescription5, Strings.onboardingDescription6, + Strings.onboardingDescription7, Strings.onboardingDescription8 ] for index in 1...8 { diff --git a/NativeAppTemplateTests/UI/App Root/ResendConfirmationInstructionsViewModelTest.swift b/NativeAppTemplateTests/UI/App Root/ResendConfirmationInstructionsViewModelTest.swift index ea5790b..4fbc066 100644 --- a/NativeAppTemplateTests/UI/App Root/ResendConfirmationInstructionsViewModelTest.swift +++ b/NativeAppTemplateTests/UI/App Root/ResendConfirmationInstructionsViewModelTest.swift @@ -104,7 +104,7 @@ struct ResendConfirmationViewModelTest { @Test func messageTypesForResendConfirmation() { // Test the types of messages that would be posted - let successMessage = Message(level: .success, message: .sentConfirmationInstruction) + let successMessage = Message(level: .success, message: Strings.sentConfirmationInstruction) let errorMessage = Message(level: .error, message: "Email not found", autoDismiss: false) #expect(successMessage.level == .success) diff --git a/NativeAppTemplateTests/UI/Settings/PasswordEditViewModelTest.swift b/NativeAppTemplateTests/UI/Settings/PasswordEditViewModelTest.swift index e398a0d..a803f11 100644 --- a/NativeAppTemplateTests/UI/Settings/PasswordEditViewModelTest.swift +++ b/NativeAppTemplateTests/UI/Settings/PasswordEditViewModelTest.swift @@ -139,7 +139,7 @@ struct PasswordEditViewModelTest { #expect(viewModel.shouldDismiss == true) #expect(messageBus.currentMessage != nil) #expect(messageBus.currentMessage?.level == .success) - #expect(messageBus.currentMessage?.message == .passwordUpdated) + #expect(messageBus.currentMessage?.message == Strings.passwordUpdated) } @Test diff --git a/NativeAppTemplateTests/UI/Settings/SettingsViewModelTest.swift b/NativeAppTemplateTests/UI/Settings/SettingsViewModelTest.swift index 1d98987..954a063 100644 --- a/NativeAppTemplateTests/UI/Settings/SettingsViewModelTest.swift +++ b/NativeAppTemplateTests/UI/Settings/SettingsViewModelTest.swift @@ -100,7 +100,7 @@ struct SettingsViewModelTest { #if DEBUG #expect(messageBus.currentMessage != nil) #expect(messageBus.currentMessage?.level == .success) - #expect(messageBus.currentMessage?.message == .signedOut) + #expect(messageBus.currentMessage?.message == Strings.signedOut) #endif } diff --git a/NativeAppTemplateTests/UI/Settings/ShopkeeperEditViewModelTest.swift b/NativeAppTemplateTests/UI/Settings/ShopkeeperEditViewModelTest.swift index c475057..a26b83d 100644 --- a/NativeAppTemplateTests/UI/Settings/ShopkeeperEditViewModelTest.swift +++ b/NativeAppTemplateTests/UI/Settings/ShopkeeperEditViewModelTest.swift @@ -234,7 +234,7 @@ struct ShopkeeperEditViewModelTest { // swiftlint:disable:this type_body_length #expect(viewModel.shouldDismiss == true) #expect(messageBus.currentMessage != nil) #expect(messageBus.currentMessage?.level == .success) - #expect(messageBus.currentMessage?.message == .reconfirmDescription) + #expect(messageBus.currentMessage?.message == Strings.reconfirmDescription) #expect(messageBus.currentMessage?.autoDismiss == false) #expect(sessionController.userState == .notLoggedIn) // Should be logged out } @@ -260,7 +260,7 @@ struct ShopkeeperEditViewModelTest { // swiftlint:disable:this type_body_length #expect(messageBus.currentMessage != nil) #expect(messageBus.currentMessage?.level == .success) - #expect(messageBus.currentMessage?.message == .shopkeeperUpdated) + #expect(messageBus.currentMessage?.message == Strings.shopkeeperUpdated) #expect(sessionController.userState == .loggedIn) // Should remain logged in } @@ -338,7 +338,7 @@ struct ShopkeeperEditViewModelTest { // swiftlint:disable:this type_body_length #expect(tabViewModel.selectedTab == .shops) #expect(messageBus.currentMessage != nil) #expect(messageBus.currentMessage?.level == .success) - #expect(messageBus.currentMessage?.message == .shopkeeperDeleted) + #expect(messageBus.currentMessage?.message == Strings.shopkeeperDeleted) #expect(sessionController.shopkeeper == nil) } diff --git a/NativeAppTemplateTests/UI/Shop List/ShopCreateViewModelTest.swift b/NativeAppTemplateTests/UI/Shop List/ShopCreateViewModelTest.swift index 3eadf87..3562a6d 100644 --- a/NativeAppTemplateTests/UI/Shop List/ShopCreateViewModelTest.swift +++ b/NativeAppTemplateTests/UI/Shop List/ShopCreateViewModelTest.swift @@ -140,7 +140,7 @@ struct ShopCreateViewModelTest { let latestShop = try #require(shopRepository.shops.last) - let message = String.shopCreated + let message = Strings.shopCreated #expect(viewModel.messageBus.currentMessage?.message == message) #expect(viewModel.isCreating) diff --git a/NativeAppTemplateTests/UI/Shop Settings/ItemTag Detail/ItemTagDetailViewModelTest.swift b/NativeAppTemplateTests/UI/Shop Settings/ItemTag Detail/ItemTagDetailViewModelTest.swift index f9694b7..2c83fd5 100644 --- a/NativeAppTemplateTests/UI/Shop Settings/ItemTag Detail/ItemTagDetailViewModelTest.swift +++ b/NativeAppTemplateTests/UI/Shop Settings/ItemTag Detail/ItemTagDetailViewModelTest.swift @@ -183,7 +183,7 @@ struct ItemTagDetailViewModelTest { #expect(viewModel.isToggling == false) #expect(messageBus.currentMessage?.level == .error) let errorMessage = try #require(messageBus.currentMessage?.message) - #expect(errorMessage.contains(String.itemTagCompletedError)) + #expect(errorMessage.contains(Strings.itemTagCompletedError)) } @Test @@ -245,7 +245,7 @@ struct ItemTagDetailViewModelTest { #expect(viewModel.isToggling == false) #expect(messageBus.currentMessage?.level == .error) let errorMessage = try #require(messageBus.currentMessage?.message) - #expect(errorMessage.contains(String.itemTagIdledError)) + #expect(errorMessage.contains(Strings.itemTagIdledError)) } @Test @@ -297,7 +297,7 @@ struct ItemTagDetailViewModelTest { #expect(viewModel.shouldDismiss == true) #expect(messageBus.currentMessage != nil) #expect(messageBus.currentMessage?.level == .success) - #expect(messageBus.currentMessage?.message == .itemTagDeleted) + #expect(messageBus.currentMessage?.message == Strings.itemTagDeleted) #expect(itemTagRepository.itemTags.count == 0) } @@ -332,7 +332,7 @@ struct ItemTagDetailViewModelTest { #expect(messageBus.currentMessage?.level == .error) #expect(messageBus.currentMessage?.autoDismiss == false) let errorMessage = try #require(messageBus.currentMessage?.message) - #expect(errorMessage.contains(String.itemTagDeletedError)) + #expect(errorMessage.contains(Strings.itemTagDeletedError)) #expect(itemTagRepository.itemTags.count == 1) } diff --git a/NativeAppTemplateTests/UI/Shop Settings/ItemTag Detail/ItemTagEditViewModelTest.swift b/NativeAppTemplateTests/UI/Shop Settings/ItemTag Detail/ItemTagEditViewModelTest.swift index 5164635..5c9c294 100644 --- a/NativeAppTemplateTests/UI/Shop Settings/ItemTag Detail/ItemTagEditViewModelTest.swift +++ b/NativeAppTemplateTests/UI/Shop Settings/ItemTag Detail/ItemTagEditViewModelTest.swift @@ -280,7 +280,7 @@ struct ItemTagEditViewModelTest { #expect(viewModel.shouldDismiss == true) #expect(messageBus.currentMessage != nil) #expect(messageBus.currentMessage?.level == .success) - #expect(messageBus.currentMessage?.message == .itemTagUpdated) + #expect(messageBus.currentMessage?.message == Strings.itemTagUpdated) let updatedItemTag = itemTagRepository.findBy(id: itemTagId) #expect(updatedItemTag.name == "Updated name") diff --git a/NativeAppTemplateTests/UI/Shop Settings/ItemTag List/ItemTagCreateViewModelTest.swift b/NativeAppTemplateTests/UI/Shop Settings/ItemTag List/ItemTagCreateViewModelTest.swift index 89c4807..f516cac 100644 --- a/NativeAppTemplateTests/UI/Shop Settings/ItemTag List/ItemTagCreateViewModelTest.swift +++ b/NativeAppTemplateTests/UI/Shop Settings/ItemTag List/ItemTagCreateViewModelTest.swift @@ -142,7 +142,7 @@ struct ItemTagCreateViewModelTest { #expect(viewModel.shouldDismiss == true) #expect(messageBus.currentMessage != nil) #expect(messageBus.currentMessage?.level == .success) - #expect(messageBus.currentMessage?.message == .itemTagCreated) + #expect(messageBus.currentMessage?.message == Strings.itemTagCreated) #expect(itemTagRepository.itemTags.count == 1) #expect(itemTagRepository.itemTags.first?.name == "Buy milk") #expect(itemTagRepository.itemTags.first?.description == "From the corner store.") diff --git a/NativeAppTemplateTests/UI/Shop Settings/ItemTag List/ItemTagListViewModelTest.swift b/NativeAppTemplateTests/UI/Shop Settings/ItemTag List/ItemTagListViewModelTest.swift index 06eb73a..c6ce285 100644 --- a/NativeAppTemplateTests/UI/Shop Settings/ItemTag List/ItemTagListViewModelTest.swift +++ b/NativeAppTemplateTests/UI/Shop Settings/ItemTag List/ItemTagListViewModelTest.swift @@ -248,7 +248,7 @@ struct ItemTagListViewModelTest { #expect(viewModel.isDeleting == false) #expect(messageBus.currentMessage != nil) #expect(messageBus.currentMessage?.level == .success) - #expect(messageBus.currentMessage?.message == .itemTagDeleted) + #expect(messageBus.currentMessage?.message == Strings.itemTagDeleted) #expect(itemTagRepository.itemTags.count == 4) // One deleted #expect(itemTagRepository.itemTags.first { $0.id == itemTagIdToDelete } == nil) } @@ -277,7 +277,7 @@ struct ItemTagListViewModelTest { #expect(messageBus.currentMessage?.level == .error) #expect(messageBus.currentMessage?.autoDismiss == false) let errorMessage = try #require(messageBus.currentMessage?.message) - #expect(errorMessage.contains(String.itemTagDeletedError)) + #expect(errorMessage.contains(Strings.itemTagDeletedError)) #expect(itemTagRepository.itemTags.count == 5) // Nothing deleted } diff --git a/NativeAppTemplateTests/UI/Shop Settings/ShopBasicSettingsViewModelTest.swift b/NativeAppTemplateTests/UI/Shop Settings/ShopBasicSettingsViewModelTest.swift index 434ecf1..40818d8 100644 --- a/NativeAppTemplateTests/UI/Shop Settings/ShopBasicSettingsViewModelTest.swift +++ b/NativeAppTemplateTests/UI/Shop Settings/ShopBasicSettingsViewModelTest.swift @@ -291,7 +291,7 @@ struct ShopBasicSettingsViewModelTest { #expect(latestShop.timeZone == newTimeZone) #expect(latestShop.description == newDescription) - let message = String.basicSettingsUpdated + let message = Strings.basicSettingsUpdated #expect(viewModel.messageBus.currentMessage?.message == message) #expect(viewModel.isUpdating == false) diff --git a/NativeAppTemplateTests/UI/Shop Settings/ShopSettingsViewModelTest.swift b/NativeAppTemplateTests/UI/Shop Settings/ShopSettingsViewModelTest.swift index 18988cd..3560648 100644 --- a/NativeAppTemplateTests/UI/Shop Settings/ShopSettingsViewModelTest.swift +++ b/NativeAppTemplateTests/UI/Shop Settings/ShopSettingsViewModelTest.swift @@ -168,7 +168,7 @@ struct ShopSettingsViewModelTest { await destroyShopTask.value #expect(viewModel.messageBus.currentMessage?.message == - "\(String.shopDeletedError) [NATI-2001] \(message) [Status: \(httpResponseCode)]") + "\(Strings.shopDeletedError) [NATI-2001] \(message) [Status: \(httpResponseCode)]") #expect(viewModel.isDeleting) #expect(viewModel.isBusy) #expect(sessionController.userState == .notLoggedIn)