diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000000..f4528bea839 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,7 @@ + +# These owners will be the default owners for everything in +# the repo. Unless a later match takes precedence, +# review when someone opens a pull request. +# For more on how to customize the CODEOWNERS file - https://help.github.com/en/articles/about-code-owners + +* @openfoodfacts/openfoodfacts-ios diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 1dbbb9ac21e..229bb926426 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -4,5 +4,7 @@ updates: directory: "/" schedule: interval: daily - time: "04:00" - open-pull-requests-limit: 10 +- package-ecosystem: github-actions + directory: "/" + schedule: + interval: daily diff --git a/.github/workflows/crowdin.yml b/.github/workflows/crowdin.yml index 6c010e1107f..e79a9872f65 100644 --- a/.github/workflows/crowdin.yml +++ b/.github/workflows/crowdin.yml @@ -2,7 +2,7 @@ name: Crowdin Action on: push: - branches: [ develop ] + branches: [ crowdin-trigger ] jobs: synchronize-with-crowdin: @@ -14,7 +14,7 @@ jobs: uses: actions/checkout@v2 - name: crowdin action - uses: crowdin/github-action@1.1.2 + uses: crowdin/github-action@1.3.3 with: upload_translations: true # default is false # Use this option to upload translations for a single specified language diff --git a/.github/workflows/ios-release-sentry.yml b/.github/workflows/ios-release-sentry.yml index 13a095b2ce2..2458d9ff909 100644 --- a/.github/workflows/ios-release-sentry.yml +++ b/.github/workflows/ios-release-sentry.yml @@ -19,7 +19,7 @@ jobs: AUTH_KEY_FILE_DECRYPTKEY: ${{ secrets.AUTH_KEY_FILE_DECRYPTKEY }} - name: Set up Ruby 2.6 - uses: actions/setup-ruby@v1.1.2 + uses: actions/setup-ruby@v1.1.3 with: ruby-version: 2.6.x diff --git a/README.md b/README.md index 570473f90c9..904e48af30d 100644 --- a/README.md +++ b/README.md @@ -19,13 +19,7 @@ Open Food Facts on iPhone and iPad has 0,5M users and 1,6M products. Each contribution you make will have a large impact on food transparency worldwide. Finding the right issue or feature will help you have even more more impact. Feel free to ask for feedback on the #android channel before you start work, and to document what you intend to code. ### Features you can work on -- [ ] [Show additives evaluation on cards](https://github.com/openfoodfacts/openfoodfacts-ios/issues/173) -- [ ] [Add a mode to compare 2 (or more) products](https://github.com/openfoodfacts/openfoodfacts-ios/issues/153) -- [ ] Add a [Lists system (shopping list, nutritional intake, scan history…)]((https://github.com/openfoodfacts/openfoodfacts-ios/issues/881) -- [ ] [Add a prompt to extract ingredients when photo is already present](https://github.com/openfoodfacts/openfoodfacts-ios/issues/171) so that we can have a simple way to NOVA, vegetarian, vegan, additive status -- [ ] Finish the [new product page revamp based on the Attributes API](https://github.com/openfoodfacts/openfoodfacts-ios/pull/780) -- [ ] Add support for cosmetics (Open Beauty Facts) and other products [#687](https://github.com/openfoodfacts/openfoodfacts-ios/issues/687) and [#160](https://github.com/openfoodfacts/openfoodfacts-ios/issues/160) -- [ ] [Cache viewed products on-device so that they load fast and regardless of network conditions](https://github.com/openfoodfacts/openfoodfacts-ios/issues/882) +- [ ] [What can I work on ?](https://github.com/openfoodfacts/openfoodfacts-ios/issues/912) ## Join the team ! @@ -44,32 +38,6 @@ OpenFoodFacts [has a Slack chat room where we discuss and support each other](ht - [x] Image upload - [x] Night mode -### Issues -Here are issues and feature requests you can work on: - -#### Search issues -- [ ] [Disable search as you type: it does not work and causes performance issues on the server P1 bug search](https://github.com/openfoodfacts/openfoodfacts-ios/issues/553) - -#### Scan issues -- [ ] [Card is completely blank if no name/brand/quantity/image is selected](https://github.com/openfoodfacts/openfoodfacts-ios/issues/180) - -#### History issues -- [ ] [Offline scans are not added to your history](https://github.com/openfoodfacts/openfoodfacts-ios/issues/267) -- [ ] [Allow to export the product history](https://github.com/openfoodfacts/openfoodfacts-ios/issues/53) - -#### Product editing issues -- [ ] [Add a prompt to extract Ingredients when photo is already present](https://github.com/openfoodfacts/openfoodfacts-ios/issues/171) - -#### Refactoring issues -- [ ] [Storyboardify app](https://github.com/openfoodfacts/openfoodfacts-ios/issues/403) -- [ ] [Try to support iOS 9 again](https://github.com/openfoodfacts/openfoodfacts-ios/issues/115) - -#### Onboarding new users -- [ ] [Add a dynamic changelog](https://github.com/openfoodfacts/openfoodfacts-ios/issues/335) - -#### Viewing products -- [ ] [Traces are not translated](https://github.com/openfoodfacts/openfoodfacts-ios/issues/245) - ## Building ### Quick & automatic setup @@ -108,16 +76,8 @@ brew cask install fastlane fastlane snapshot ``` ##### Roadmap on automatic screenshot generation: -- [ ] Create a GitHub Action to run screenshot generation and upload the output to the OFF server (or somewhere else) -- [ ] fixing the Scan screenshot generation, and adding a way to set the background of the barcode scanner with an arbitrary image, per country -- [ ] fixing History screenshot population with products -- [ ] Adding the proposed fix to clean the top bar with 100% battery, and a fixed time -- [ ] Adding `fastlane frameit` to the Fastlane file, so that we can get versions wrapped in physical devices -- [ ] fixing Chinese screenshot generation -- [ ] Ensure we can generate for 1 of (iPhone 11 Pro Max, iPhone 11, iPhone XS Max, iPhone XR), 1 of (iPhone 6s Plus, iPhone 7 Plus, iPhone 8 Plus), 1 of (3rd generation iPad Pro) -- [ ] Extra: For debugging purposes, it would be great to have other screen resolutions (iPhone 11 Pro, iPhone X, iPhone XS) (iPhone 6, iPhone 6s, iPhone 7, iPhone 8) (iPhone SE) (iPhone 4s) - -Configuration: https://github.com/openfoodfacts/openfoodfacts-ios/blob/01ea37e5247978a52d491181bb7dd2fb384214af/Snapshots/SnapshotConfiguration.swift +* [Our priorities](https://github.com/openfoodfacts/openfoodfacts-ios/issues/913) +* [Configuration file](https://github.com/openfoodfacts/openfoodfacts-ios/blob/01ea37e5247978a52d491181bb7dd2fb384214af/Snapshots/SnapshotConfiguration.swift) ### Style and conventions - SwiftLint diff --git a/Sources/Localization/cs.lproj/Localizable.strings b/Sources/Localization/cs.lproj/Localizable.strings index 54bf66a579d..478f9fd2f0b 100644 --- a/Sources/Localization/cs.lproj/Localizable.strings +++ b/Sources/Localization/cs.lproj/Localizable.strings @@ -154,7 +154,7 @@ "product-detail.page-title.ingredients" = "Složení"; "product-detail.page-title.nutrition" = "Nutriční hodnoty"; "product-detail.page-title.nutrition-table" = "Výživové tabulky"; -"product-detail.page-title.environment-impact" = "Prostředí"; +"product-detail.page-title.environment-impact" = "Životní prostředí"; // Product detail summary info rows labels "product-detail.summary.barcode" = "Čárový kód"; @@ -184,7 +184,7 @@ "product-detail.ingredients.allergens-list.missing-infos" = "Tento produkt ještě nemá seznam přísad, a proto nelze detekci alergenu dokončit."; "product-detail.ingredients.allergens-list.offline-product" = "Tento produkt byl načten z offline databáze, a proto nebylo možné provést detekci alergenu."; "product-detail.ingredients.traces-list" = "Stopy"; -"product-detail.ingredients.additives-list" = "Přísady"; +"product-detail.ingredients.additives-list" = "Aditiva"; "product-detail.ingredients.palm-oil-ingredients" = "Suroviny z palmového oleje"; "product-detail.ingredients.possible-palm-oil-ingredients" = "Přísady, které mohou být z palmového oleje"; "product-detail.ingredients.vitamins-list" = "Vitamíny"; diff --git a/Sources/Localization/en.lproj/Localizable.strings b/Sources/Localization/en.lproj/Localizable.strings index 30a81f0629f..c0f75af5988 100644 --- a/Sources/Localization/en.lproj/Localizable.strings +++ b/Sources/Localization/en.lproj/Localizable.strings @@ -31,7 +31,7 @@ // Product Scanner "product-scanner.overlay.user-help" = "Scan the barcode of the product"; -"product-scanner.overlay.extended-user-help" = "Can't find a barcode. \nCenter the barcode in the screen.\nMake sure the barcode is well lit."; +"product-scanner.overlay.extended-user-help" = "Barcode not detected. \nCenter the barcode in the screen.\nMake sure the barcode is well lit."; /* Title of the view controller in which user can scan. Keep it short. */ "product-scanner.view-title" = "Scanner"; /* Banner message shown to the user when the server returned an error while trying to fetch a product given its barcode */ @@ -101,7 +101,7 @@ "product-add.titles.license-explaination" = "Note: the pictures you send are published under the free licence Creative Commons Attribution & ShareAlike."; "product-add.titles.product-info" = "Product Information"; -"product-add.label.brand-example" = "Examples: Coca-Cola, Nestle, etc…"; +"product-add.label.brand-example" = "Examples: Coca-Cola, Nestle, etc."; "product-add.label.product-name" = "Name"; "product-add.label.category" = "Category"; "product-add.label.quantity" = "Quantity"; @@ -215,7 +215,7 @@ "product-detail.environment.ecoscore.d" = "Strong impact on the environment"; "product-detail.environment.ecoscore.e" = "Very strong impact on the environment"; "product-detail.environment.ecoscore.unknown" = "Eco-score unknown"; -"product-detail.environment.ecoscore.incite" = "Please add packaging info, so we can calculate the Eco-score"; +"product-detail.environment.ecoscore.incite" = "Please add packaging information so that the Eco-score can be calculated"; // Nutrition levels "nutrition-level.title" = "Nutrient levels per 100 g/100mL"; diff --git a/Sources/Localization/he.lproj/Localizable.strings b/Sources/Localization/he.lproj/Localizable.strings index ddef0d4d375..3d4a3eb36a0 100644 --- a/Sources/Localization/he.lproj/Localizable.strings +++ b/Sources/Localization/he.lproj/Localizable.strings @@ -175,7 +175,7 @@ "product-detail.ingredients.nova.1" = "מזון עם עיבוד מזערי או נטול"; "product-detail.ingredients.nova.2" = "רכיבים קולינריים מעובדים"; "product-detail.ingredients.nova.3" = "מזון מעובד"; -"product-detail.ingredients.nova.4" = "מוצרי מזון ושתייה מעובדים ביותר"; +"product-detail.ingredients.nova.4" = "מוצרי מזון ושתייה אולטרה מעובדים"; "product-detail.ingredients.nova.unknown" = "לא ניתן לחשב את רמת ה־NOVA לעיבוד מזון"; "product-detail.ingredients.nova.incite" = "יש להוסיף מרכיבים ו/או קטגוריות כדי לחשב NOVA."; "product-detail.ingredients.ingredients-list" = "רשימת מרכיבים"; diff --git a/Sources/Localization/lol.lproj/Localizable.strings b/Sources/Localization/lol.lproj/Localizable.strings index 17dfbe6673b..cc9d10d3a1c 100644 --- a/Sources/Localization/lol.lproj/Localizable.strings +++ b/Sources/Localization/lol.lproj/Localizable.strings @@ -26,12 +26,12 @@ "product-search.error-view.title" = "crwdns154314:0crwdne154314:0"; "product-search.error-view.subtitle" = "crwdns154316:0crwdne154316:0"; "product-search.initial-view.slogan" = "crwdns154318:0crwdne154318:0"; -"product-search.initial-view.offline.title-loading" = "crwdns154320:0%dcrwdnd154320:0%%crwdne154320:0"; +"product-search.initial-view.offline.title-loading" = "crwdns154320:0%dcrwdne154320:0"; "product-search.initial-view.offline.subtitle" = "crwdns154322:0%dcrwdne154322:0"; // Product Scanner "product-scanner.overlay.user-help" = "crwdns154324:0crwdne154324:0"; -"product-scanner.overlay.extended-user-help" = "crwdns181586:0crwdne181586:0"; +"product-scanner.overlay.extended-user-help" = "crwdns187519:0crwdne187519:0"; /* Title of the view controller in which user can scan. Keep it short. */ "product-scanner.view-title" = "crwdns154328:0crwdne154328:0"; /* Banner message shown to the user when the server returned an error while trying to fetch a product given its barcode */ @@ -101,7 +101,7 @@ "product-add.titles.license-explaination" = "crwdns154422:0crwdne154422:0"; "product-add.titles.product-info" = "crwdns154424:0crwdne154424:0"; -"product-add.label.brand-example" = "crwdns154426:0crwdne154426:0"; +"product-add.label.brand-example" = "crwdns187521:0crwdne187521:0"; "product-add.label.product-name" = "crwdns154428:0crwdne154428:0"; "product-add.label.category" = "crwdns154430:0crwdne154430:0"; "product-add.label.quantity" = "crwdns154432:0crwdne154432:0"; @@ -215,7 +215,7 @@ "product-detail.environment.ecoscore.d" = "crwdns157394:0crwdne157394:0"; "product-detail.environment.ecoscore.e" = "crwdns157396:0crwdne157396:0"; "product-detail.environment.ecoscore.unknown" = "crwdns154596:0crwdne154596:0"; -"product-detail.environment.ecoscore.incite" = "crwdns154598:0crwdne154598:0"; +"product-detail.environment.ecoscore.incite" = "crwdns187523:0crwdne187523:0"; // Nutrition levels "nutrition-level.title" = "crwdns154600:0crwdne154600:0"; diff --git a/Sources/Localization/nl-BE.lproj/Localizable.strings b/Sources/Localization/nl-BE.lproj/Localizable.strings index 62dc483ea71..658384a1cac 100644 --- a/Sources/Localization/nl-BE.lproj/Localizable.strings +++ b/Sources/Localization/nl-BE.lproj/Localizable.strings @@ -176,7 +176,7 @@ "product-detail.ingredients.nova.2" = "Berwerkte ingrediënten"; "product-detail.ingredients.nova.3" = "Bewerkte levensmiddelen"; "product-detail.ingredients.nova.4" = "Ultra-bewerkte levensmiddelen en dranken"; -"product-detail.ingredients.nova.unknown" = "The NOVA level of food processing could not be calculated"; +"product-detail.ingredients.nova.unknown" = "Het voedselverwerkings-NOVA-niveau kon niet worden berekend"; "product-detail.ingredients.nova.incite" = "Voeg ingrediënten en / of categorieën toe om NOVA te berekenen."; "product-detail.ingredients.ingredients-list" = "Lijst van ingrediënten"; "product-detail.ingredients.allergens-list" = "Stoffen of producten die allergieën of intoleranties veroorzaken"; @@ -214,7 +214,7 @@ "product-detail.environment.ecoscore.c" = "Eco-score C"; "product-detail.environment.ecoscore.d" = "Eco-score D"; "product-detail.environment.ecoscore.e" = "Eco-score E"; -"product-detail.environment.ecoscore.unknown" = "Eco-score unknown"; +"product-detail.environment.ecoscore.unknown" = "Eco-score onbekend"; "product-detail.environment.ecoscore.incite" = "Please add packaging info, so we can calculate the Eco-score"; // Nutrition levels diff --git a/Sources/Localization/nl-BE.lproj/PhotoLibrary.strings b/Sources/Localization/nl-BE.lproj/PhotoLibrary.strings index d7c5f0bf66e..5f7fcb2e86c 100644 --- a/Sources/Localization/nl-BE.lproj/PhotoLibrary.strings +++ b/Sources/Localization/nl-BE.lproj/PhotoLibrary.strings @@ -7,10 +7,10 @@ */ "CANCEL" = "Annuleer"; "RETAKE" = "Opnieuw"; -"STREAM_SHARED_BY_ME_SUBTITLE" = "From You"; -"STREAM_SHARED_BY_SUBTITLE" = "From %@"; -"ALBUM_IMAGE_COUNT_FORMAT" = "%@ Photos"; -"ALBUM_VIDEO_COUNT_FORMAT" = "%@ Videos"; -"1_ALBUM_PHOTO" = "1 Photo"; -"1_ALBUM_VIDEO" = "1 Video"; +"STREAM_SHARED_BY_ME_SUBTITLE" = "Van jou"; +"STREAM_SHARED_BY_SUBTITLE" = "Van %@"; +"ALBUM_IMAGE_COUNT_FORMAT" = "%@ Foto's"; +"ALBUM_VIDEO_COUNT_FORMAT" = "%@ Video's"; +"1_ALBUM_PHOTO" = "1 foto"; +"1_ALBUM_VIDEO" = "1 video"; "ALBUM_TWO_TYPES_LABEL_COMMAS" = "%@, %@"; diff --git a/Sources/Localization/nl-BE.lproj/PhotoLibraryServices.strings b/Sources/Localization/nl-BE.lproj/PhotoLibraryServices.strings index 1026ce75b4b..2af6745e89e 100644 --- a/Sources/Localization/nl-BE.lproj/PhotoLibraryServices.strings +++ b/Sources/Localization/nl-BE.lproj/PhotoLibraryServices.strings @@ -6,5 +6,5 @@ */ "PHOTOS" = "Foto's"; -"CAMERA_ROLL" = "Camera roll"; -"ALL_SCREENSHOTS" = "Screenshots"; +"CAMERA_ROLL" = "Filmrol"; +"ALL_SCREENSHOTS" = "Schermafbeeldingen"; diff --git a/Sources/Localization/nl-BE.lproj/PhotosUI.strings b/Sources/Localization/nl-BE.lproj/PhotosUI.strings index 67c5ce92e06..2f08e0e91f3 100644 --- a/Sources/Localization/nl-BE.lproj/PhotosUI.strings +++ b/Sources/Localization/nl-BE.lproj/PhotosUI.strings @@ -5,8 +5,8 @@ Created by arnaud on 19/12/2020. */ -"ALL_PHOTOS_IN_LIBRARY" = "Moments"; -"PXUserCollectionsSectionTitle" = "My Albums"; -"FULL_PHOTOS_GRID_ZOOM_LEVEL_TITLE" = "Moments"; -"NO_PHOTOS_OR_VIDEOS" = "No Photos or Videos"; -"EMPTY_ALBUM_LIST_MESSAGE_iPhone" = "You can take photos and videos using camera, or sync photos and videos onto your iPhone using iTunes"; +"ALL_PHOTOS_IN_LIBRARY" = "Momenten"; +"PXUserCollectionsSectionTitle" = "Mijn albums"; +"FULL_PHOTOS_GRID_ZOOM_LEVEL_TITLE" = "Momenten"; +"NO_PHOTOS_OR_VIDEOS" = "Geen foto's of video's"; +"EMPTY_ALBUM_LIST_MESSAGE_iPhone" = "Je kunt foto's en video's maken met de camera, of foto's en video's synchroniseren naar je iPhone met behulp van iTunes"; diff --git a/Sources/ViewControllers/Settings/SettingsTableViewController.swift b/Sources/ViewControllers/Settings/SettingsTableViewController.swift index 3d79a7ce4b9..75db9ce2139 100644 --- a/Sources/ViewControllers/Settings/SettingsTableViewController.swift +++ b/Sources/ViewControllers/Settings/SettingsTableViewController.swift @@ -34,12 +34,14 @@ class SettingsTableViewController: UITableViewController, MFMailComposeViewContr @IBOutlet weak var creditsCell: UITableViewCell! @IBOutlet weak var contactCell: UITableViewCell! + @IBOutlet weak var bottomLink: UIButton! var dataManager: DataManagerProtocol! override func viewDidLoad() { super.viewDidLoad() self.title = "settings.tab-bar.item".localized + configureForDynamicType() } override func viewWillAppear(_ animated: Bool) { @@ -149,3 +151,11 @@ class SettingsTableViewController: UITableViewController, MFMailComposeViewContr controller.dismiss(animated: true, completion: nil) } } + +private extension SettingsTableViewController { + func configureForDynamicType() { + tableView.rowHeight = UITableView.automaticDimension + tableView.estimatedRowHeight = 200 + bottomLink.titleLabel?.adjustsFontForContentSizeCategory = true + } +} diff --git a/Sources/Views/Settings/Settings.storyboard b/Sources/Views/Settings/Settings.storyboard index bfae10c2183..f1988badd79 100644 --- a/Sources/Views/Settings/Settings.storyboard +++ b/Sources/Views/Settings/Settings.storyboard @@ -1,11 +1,12 @@ - + - + + @@ -16,9 +17,9 @@ - - - + - - -