Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 0 additions & 120 deletions NativeAppTemplate.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1268,103 +1268,6 @@
};
name = Release;
};
016595AF2824E3D800203F7F /* Beta configuration for PBXProject "NativeAppTemplate" */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = NNYDL5U3V3;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 17.2;
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = iphoneos;
STRING_CATALOG_GENERATE_SYMBOLS = YES;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_STRICT_CONCURRENCY = complete;
SWIFT_VERSION = 6.0;
VALIDATE_PRODUCT = YES;
};
name = Beta;
};
016595B02824E3D800203F7F /* Beta configuration for PBXNativeTarget "NativeAppTemplate" */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = "";
BUNDLE_ID_SUFFIX = .beta;
CODE_SIGN_ENTITLEMENTS = "";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 9;
DEVELOPMENT_ASSET_PATHS = "\"NativeAppTemplate/Preview Content\"";
ENABLE_PREVIEWS = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
INFOPLIST_FILE = NativeAppTemplate/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "NativeAppTemplate Free";
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.business";
IPHONEOS_DEPLOYMENT_TARGET = 26.2;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 3.1.1;
PRODUCT_BUNDLE_IDENTIFIER = "com.nativeapptemplate.NativeAppTemplateFree.ios${SAMPLE_CODE_DISAMBIGUATOR}$(BUNDLE_ID_SUFFIX)";
PRODUCT_NAME = NativeAppTemplate;
SAMPLE_CODE_DISAMBIGUATOR = "${DEVELOPMENT_TEAM}";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Beta;
};
01D19B4A2D4DE33500BDEAB7 /* Debug configuration for PBXNativeTarget "NativeAppTemplateTests" */ = {
isa = XCBuildConfiguration;
buildSettings = {
Expand Down Expand Up @@ -1406,26 +1309,6 @@
};
name = Release;
};
01D19B4C2D4DE33500BDEAB7 /* Beta configuration for PBXNativeTarget "NativeAppTemplateTests" */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GCC_C_LANGUAGE_STANDARD = gnu17;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 26.2;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.nativeapptemplate.NativeAppTemplateTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = NO;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/NativeAppTemplate.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/NativeAppTemplate";
};
name = Beta;
};
/* End XCBuildConfiguration section */

/* Begin XCConfigurationList section */
Expand All @@ -1434,7 +1317,6 @@
buildConfigurations = (
011F6E10259EF16600BED22E /* Debug configuration for PBXProject "NativeAppTemplate" */,
011F6E11259EF16600BED22E /* Release configuration for PBXProject "NativeAppTemplate" */,
016595AF2824E3D800203F7F /* Beta configuration for PBXProject "NativeAppTemplate" */,
);
defaultConfigurationName = Release;
};
Expand All @@ -1443,7 +1325,6 @@
buildConfigurations = (
011F6E13259EF16600BED22E /* Debug configuration for PBXNativeTarget "NativeAppTemplate" */,
011F6E14259EF16600BED22E /* Release configuration for PBXNativeTarget "NativeAppTemplate" */,
016595B02824E3D800203F7F /* Beta configuration for PBXNativeTarget "NativeAppTemplate" */,
);
defaultConfigurationName = Release;
};
Expand All @@ -1452,7 +1333,6 @@
buildConfigurations = (
01D19B4A2D4DE33500BDEAB7 /* Debug configuration for PBXNativeTarget "NativeAppTemplateTests" */,
01D19B4B2D4DE33500BDEAB7 /* Release configuration for PBXNativeTarget "NativeAppTemplateTests" */,
01D19B4C2D4DE33500BDEAB7 /* Beta configuration for PBXNativeTarget "NativeAppTemplateTests" */,
);
defaultConfigurationName = Release;
};
Expand Down
5 changes: 0 additions & 5 deletions NativeAppTemplate/Extensions/Date+Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,4 @@ extension Date {
var cardDateTimeString: String {
"\(cardDateString) \(cardTimeString)"
}

var cardTimeAgoInWordsDateString: String {
let formatter = DateFormatter.timeAgoInWordsDateFormatter
return formatter.string(from: self)
}
}
8 changes: 0 additions & 8 deletions NativeAppTemplate/Extensions/DateFormatter+Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,6 @@ extension DateFormatter {

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

static let timeAgoInWordsDateFormatter: DateFormatter = {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .short
dateFormatter.timeStyle = .medium
dateFormatter.doesRelativeDateFormatting = true
return dateFormatter
}()

static func formatter(for dateString: String) -> DateFormatter {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = dateString
Expand Down
33 changes: 6 additions & 27 deletions NativeAppTemplate/Extensions/String+Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,15 @@
// NativeAppTemplate
//

import UIKit
import Foundation

extension String {
/// Generates a `UIImage` instance from this string using a specified
/// attributes and size.
///
/// - Parameters:
/// - attributes: to draw this string with. Default is `nil`.
/// - size: of the image to return.
/// - Returns: a `UIImage` instance from this string using a specified
/// attributes and size, or `nil` if the operation fails.
func image(withAttributes attributes: [NSAttributedString.Key: Any]? = nil, size: CGSize? = nil) -> UIImage? {
let size = size ?? (self as NSString).size(withAttributes: attributes)
return UIGraphicsImageRenderer(size: size).image { _ in
(self as NSString).draw(
in: CGRect(origin: .zero, size: size),
withAttributes: attributes
)
}
var isBlank: Bool {
trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
}

func isAlphanumeric() -> Bool {
rangeOfCharacter(from: CharacterSet.alphanumerics.inverted) == nil && !isEmpty
}

func isAlphanumeric(ignoreDiacritics: Bool = false) -> Bool {
if ignoreDiacritics {
range(of: "[^a-zA-Z0-9]", options: .regularExpression) == nil && !isEmpty
} else {
isAlphanumeric()
}
var isValidEmail: Bool {
let emailRegex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
return NSPredicate(format: "SELF MATCHES %@", emailRegex).evaluate(with: self)
}
}
8 changes: 4 additions & 4 deletions NativeAppTemplate/UI/App Root/ForgotPasswordViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,23 @@ final class ForgotPasswordViewModel {
}

var hasInvalidData: Bool {
if Utility.isBlank(email) {
if email.isBlank {
return true
}

if !Utility.validateEmail(email) {
if !email.isValidEmail {
return true
}

return false
}

var isEmailBlank: Bool {
Utility.isBlank(email)
email.isBlank
}

var isEmailInvalid: Bool {
!Utility.isBlank(email) && !Utility.validateEmail(email)
!email.isBlank && !email.isValidEmail
}

func sendMeResetPasswordInstructionsTapped() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,23 @@ final class ResendConfirmationInstructionsViewModel {
}

var hasInvalidData: Bool {
if Utility.isBlank(email) {
if email.isBlank {
return true
}

if !Utility.validateEmail(email) {
if !email.isValidEmail {
return true
}

return false
}

var isEmailBlank: Bool {
Utility.isBlank(email)
email.isBlank
}

var isEmailInvalid: Bool {
!Utility.isBlank(email) && !Utility.validateEmail(email)
!email.isBlank && !email.isValidEmail
}

func sendMeConfirmationInstructionsTapped() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ final class SignInEmailAndPasswordViewModel {
}

var hasInvalidData: Bool {
if Utility.isBlank(email) || Utility.isBlank(password) {
if email.isBlank || password.isBlank {
return true
}

if !Utility.validateEmail(email) {
if !email.isValidEmail {
return true
}

Expand All @@ -41,23 +41,23 @@ final class SignInEmailAndPasswordViewModel {
}

var hasInvalidDataPassword: Bool {
if Utility.isBlank(password) {
if password.isBlank {
return true
}

return false
}

var isEmailBlank: Bool {
Utility.isBlank(email)
email.isBlank
}

var isEmailInvalid: Bool {
Utility.isBlank(email) || !Utility.validateEmail(email)
email.isBlank || !email.isValidEmail
}

var isPasswordBlank: Bool {
Utility.isBlank(password)
password.isBlank
}

func signIn() {
Expand Down
14 changes: 7 additions & 7 deletions NativeAppTemplate/UI/App Root/SignUpViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ final class SignUpViewModel {
}

var hasInvalidData: Bool {
if Utility.isBlank(name) {
if name.isBlank {
return true
}

Expand All @@ -47,19 +47,19 @@ final class SignUpViewModel {
}

var hasInvalidDataEmail: Bool {
if Utility.isBlank(email) {
if email.isBlank {
return true
}

if !Utility.validateEmail(email) {
if !email.isValidEmail {
return true
}

return false
}

var hasInvalidDataPassword: Bool {
if Utility.isBlank(password) {
if password.isBlank {
return true
}

Expand All @@ -71,15 +71,15 @@ final class SignUpViewModel {
}

var isNameBlank: Bool {
Utility.isBlank(name)
name.isBlank
}

var isEmailBlank: Bool {
Utility.isBlank(email)
email.isBlank
}

var isPasswordBlank: Bool {
Utility.isBlank(password)
password.isBlank
}

func createShopkeeper() {
Expand Down
6 changes: 3 additions & 3 deletions NativeAppTemplate/UI/Settings/PasswordEditView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ private extension PasswordEditView {
Text(Strings.weNeedYourCurrentPassword)
.font(.uiFootnote)
Text(Strings.currentPasswordIsRequired)
.foregroundStyle(Utility.isBlank(viewModel.currentPassword) ? .validationError : .clear)
.foregroundStyle(viewModel.currentPassword.isBlank ? .validationError : .clear)
.font(.uiFootnote)
}
}
Expand All @@ -68,7 +68,7 @@ private extension PasswordEditView {
Text("\(viewModel.minimumPasswordLength) characters minimum.")
.font(.uiFootnote)

if Utility.isBlank(viewModel.password) {
if viewModel.password.isBlank {
Text(Strings.newPasswordIsRequired)
.foregroundStyle(.validationError)
.font(.uiFootnote)
Expand All @@ -89,7 +89,7 @@ private extension PasswordEditView {
} footer: {
Text(Strings.confirmNewPasswordIsRequired)
.font(.uiFootnote)
.foregroundStyle(Utility.isBlank(viewModel.passwordConfirmation) ? .validationError : .clear)
.foregroundStyle(viewModel.passwordConfirmation.isBlank ? .validationError : .clear)
}
}
.navigationTitle(Strings.updatePassword)
Expand Down
Loading
Loading