diff --git a/Nextcloud Cookbook iOS Client.xcodeproj/project.pbxproj b/Nextcloud Cookbook iOS Client.xcodeproj/project.pbxproj index 1bcdb04..8ceea9b 100644 --- a/Nextcloud Cookbook iOS Client.xcodeproj/project.pbxproj +++ b/Nextcloud Cookbook iOS Client.xcodeproj/project.pbxproj @@ -328,7 +328,7 @@ attributes = { BuildIndependentTargetsInParallel = 1; LastSwiftUpdateCheck = 1430; - LastUpgradeCheck = 1430; + LastUpgradeCheck = 1500; TargetAttributes = { A701717D2AA8E71900064C43 = { CreatedOnToolsVersion = 14.3; @@ -466,6 +466,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; @@ -495,9 +496,11 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -524,6 +527,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; @@ -553,9 +557,11 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 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; @@ -580,6 +586,7 @@ "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; DEVELOPMENT_ASSET_PATHS = "\"Nextcloud Cookbook iOS Client/Preview Content\""; DEVELOPMENT_TEAM = EF2ABA36D9; ENABLE_HARDENED_RUNTIME = YES; @@ -601,7 +608,7 @@ LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 14.0; - MARKETING_VERSION = 1.4; + MARKETING_VERSION = 1.5; PRODUCT_BUNDLE_IDENTIFIER = "VincentMeilinger.Nextcloud-Cookbook-iOS-Client"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = auto; @@ -622,6 +629,7 @@ "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; DEVELOPMENT_ASSET_PATHS = "\"Nextcloud Cookbook iOS Client/Preview Content\""; DEVELOPMENT_TEAM = EF2ABA36D9; ENABLE_HARDENED_RUNTIME = YES; @@ -643,7 +651,7 @@ LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 14.0; - MARKETING_VERSION = 1.4; + MARKETING_VERSION = 1.5; PRODUCT_BUNDLE_IDENTIFIER = "VincentMeilinger.Nextcloud-Cookbook-iOS-Client"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = auto; @@ -662,6 +670,7 @@ BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = EF2ABA36D9; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 16.4; @@ -685,6 +694,7 @@ BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = EF2ABA36D9; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 16.4; @@ -707,6 +717,7 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = EF2ABA36D9; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 16.4; @@ -729,6 +740,7 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = EF2ABA36D9; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 16.4; diff --git a/Nextcloud Cookbook iOS Client/Data/DurationComponents.swift b/Nextcloud Cookbook iOS Client/Data/DurationComponents.swift index 7e9a74f..774d877 100644 --- a/Nextcloud Cookbook iOS Client/Data/DurationComponents.swift +++ b/Nextcloud Cookbook iOS Client/Data/DurationComponents.swift @@ -71,7 +71,7 @@ class DurationComponents: ObservableObject { } } - static func ptToText(_ ptString: String) -> String { + static func ptToText(_ ptString: String) -> String? { let hourRegex = /([0-9]{1,2})H/ let minuteRegex = /([0-9]{1,2})M/ @@ -93,7 +93,7 @@ class DurationComponents: ObservableObject { } else if intHour != 0 && intMinute == 0 { return "\(intHour) h" } else { - return "-" + return nil } } } diff --git a/Nextcloud Cookbook iOS Client/Localizable.xcstrings b/Nextcloud Cookbook iOS Client/Localizable.xcstrings index fc6fd89..7897851 100644 --- a/Nextcloud Cookbook iOS Client/Localizable.xcstrings +++ b/Nextcloud Cookbook iOS Client/Localizable.xcstrings @@ -24,7 +24,14 @@ } }, "-" : { - + "localizations" : { + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "-" + } + } + } }, ":" : { "localizations" : { @@ -93,7 +100,14 @@ } }, "%lld h" : { - + "localizations" : { + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld h" + } + } + } }, "%lld h, %lld min" : { "localizations" : { @@ -102,11 +116,24 @@ "state" : "new", "value" : "%1$lld h, %2$lld min" } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "%1$lld h, %2$lld min" + } } } }, "%lld min" : { - + "localizations" : { + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld min" + } + } + } }, "%lld." : { "localizations" : { @@ -329,7 +356,14 @@ } }, "Bad URL" : { - + "localizations" : { + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "URL incorrect" + } + } + } }, "Cancel" : { "localizations" : { @@ -420,7 +454,14 @@ } }, "Connection error" : { - + "localizations" : { + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Erreur de connexion" + } + } + } }, "Cookbook Client" : { "localizations" : { @@ -885,13 +926,34 @@ } }, "Import" : { - + "localizations" : { + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Importer" + } + } + } }, "Import Recipe" : { - + "localizations" : { + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Importer une recette" + } + } + } }, "Import recipe from a website" : { - + "localizations" : { + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Importer une recette depuis un site web" + } + } + } }, "Ingredients" : { "localizations" : { @@ -1356,13 +1418,34 @@ } }, "Parsing error" : { - + "localizations" : { + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Erreur d'analyse" + } + } + } }, "Paste the url of a recipe you would like to import in the above, and we will try to fill in the fields for you. This feature does not work with every website. If your favourite website is not supported, feel free to reach out for help. You can find the contact details in the app settings." : { - + "localizations" : { + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Collez l'URL d'une recette que vous souhaitez importer ci-dessus, et nous tenterons de remplir les champs pour vous. Cette fonctionnalité ne fonctionne pas avec tous les sites web. Si votre site préféré n'est pas pris en charge, n'hésitez pas à nous contacter pour obtenir de l'aide. Vous pouvez trouver les coordonnées dans les paramètres de l'application." + } + } + } }, "Please check the entered URL." : { - + "localizations" : { + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Veuillez vérifier l'URL saisie." + } + } + } }, "Please check your credentials and internet connection." : { "localizations" : { @@ -1739,7 +1822,14 @@ } }, "This website might not be currently supported. If this appears incorrect, you can use the support options in the app settings to raise awareness about this issue." : { - + "localizations" : { + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ce site web pourrait ne pas être pris en charge actuellement. Si cela semble incorrect, vous pouvez utiliser les options de support dans les paramètres de l'application pour signaler ce problème." + } + } + } }, "Title" : { "localizations" : { @@ -1852,7 +1942,14 @@ } }, "Unable to load website content. Please check your internet connection." : { - + "localizations" : { + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Impossible de télécharger le contenu du site web. Veuillez vérifier votre connexion Internet." + } + } + } }, "Unable to upload your recipe. Please check your internet connection." : { "localizations" : { @@ -1899,7 +1996,14 @@ } }, "URL (e.g. example.com/recipe)" : { - + "localizations" : { + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "URL (par exemple, example.com/recette)" + } + } + } }, "Validate" : { "localizations" : { diff --git a/Nextcloud Cookbook iOS Client/Views/RecipeDetailView.swift b/Nextcloud Cookbook iOS Client/Views/RecipeDetailView.swift index d298e87..0f6f2d0 100644 --- a/Nextcloud Cookbook iOS Client/Views/RecipeDetailView.swift +++ b/Nextcloud Cookbook iOS Client/Views/RecipeDetailView.swift @@ -83,7 +83,7 @@ struct RecipeDetailView: View { .navigationBarTitleDisplayMode(.inline) .navigationTitle(showTitle ? recipe.name : "") .toolbar { - if let recipeDetail = recipeDetail { + if recipeDetail != nil { Button { presentEditView = true } label: { @@ -123,26 +123,26 @@ fileprivate struct RecipeDurationSection: View { var body: some View { LazyVGrid(columns: [GridItem(.adaptive(minimum: 150), alignment: .leading)]) { - if let prepTime = recipeDetail.prepTime { + if let prepTime = recipeDetail.prepTime, let time = DurationComponents.ptToText(prepTime) { VStack(alignment: .leading) { SecondaryLabel(text: LocalizedStringKey("Preparation")) - Text(DurationComponents.ptToText(prepTime)) + Text(time) .lineLimit(1) }.padding() } - if let cookTime = recipeDetail.cookTime { + if let cookTime = recipeDetail.cookTime, let time = DurationComponents.ptToText(cookTime) { VStack(alignment: .leading) { SecondaryLabel(text: LocalizedStringKey("Cooking")) - Text(DurationComponents.ptToText(cookTime)) + Text(time) .lineLimit(1) }.padding() } - if let totalTime = recipeDetail.totalTime { + if let totalTime = recipeDetail.totalTime, let time = DurationComponents.ptToText(totalTime) { VStack(alignment: .leading) { SecondaryLabel(text: LocalizedStringKey("Total time")) - Text(DurationComponents.ptToText(totalTime)) + Text(time) .lineLimit(1) }.padding() } diff --git a/Nextcloud Cookbook iOS Client/Views/RecipeEditView.swift b/Nextcloud Cookbook iOS Client/Views/RecipeEditView.swift index 6432df5..76a71e2 100644 --- a/Nextcloud Cookbook iOS Client/Views/RecipeEditView.swift +++ b/Nextcloud Cookbook iOS Client/Views/RecipeEditView.swift @@ -66,9 +66,6 @@ struct RecipeEditView: View { if viewModel.showImportSection { Section { TextField("URL (e.g. example.com/recipe)", text: $viewModel.importURL) - .onSubmit { - viewModel.importRecipe() - } Button { viewModel.importRecipe() } label: {