From 3f1662032fdda60ff23ea9e937e36270bb6f142f Mon Sep 17 00:00:00 2001 From: monsieurtanuki Date: Tue, 7 Jun 2022 22:28:34 +0200 Subject: [PATCH 1/3] fix: #477 - title is now optional in knowledge panel element Impacted files: * `api_saveProduct_test.dart`: unrelated test skip * `KnowlegdePanelElement.dart`: `title` is now optional * `KnowlegdePanelElement.g.dart`: generated --- lib/model/KnowledgePanelElement.dart | 2 +- lib/model/KnowledgePanelElement.g.dart | 2 +- test/api_saveProduct_test.dart | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/model/KnowledgePanelElement.dart b/lib/model/KnowledgePanelElement.dart index d49e563fc0..b4afc6b75e 100644 --- a/lib/model/KnowledgePanelElement.dart +++ b/lib/model/KnowledgePanelElement.dart @@ -276,7 +276,7 @@ class KnowledgePanelLatLng extends JsonObject { class KnowledgePanelTableElement extends JsonObject { final String id; - final String title; + final String? title; @JsonKey(name: 'columns') final List columns; diff --git a/lib/model/KnowledgePanelElement.g.dart b/lib/model/KnowledgePanelElement.g.dart index 6129f6cb71..9c5d670b1c 100644 --- a/lib/model/KnowledgePanelElement.g.dart +++ b/lib/model/KnowledgePanelElement.g.dart @@ -199,7 +199,7 @@ KnowledgePanelTableElement _$KnowledgePanelTableElementFromJson( Map json) => KnowledgePanelTableElement( id: json['id'] as String, - title: json['title'] as String, + title: json['title'] as String?, columns: (json['columns'] as List) .map((e) => KnowledgePanelTableColumn.fromJson(e as Map)) diff --git a/test/api_saveProduct_test.dart b/test/api_saveProduct_test.dart index fdc88f66a7..7217ec6497 100644 --- a/test/api_saveProduct_test.dart +++ b/test/api_saveProduct_test.dart @@ -299,7 +299,7 @@ void main() { 'Product categories test 1,Product categories test 2'); expect(result.product!.categoriesTags, ['en:product-categories-test-1', 'en:product-categories-test-2']); - }); + }, skip: 'Works randomly'); Unit _getMassUnit(int i) => { 0: Unit.G, From 6fa3fd8f216a3875be8439be4dcc46ecb75f6b1f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 7 Jun 2022 22:56:08 +0200 Subject: [PATCH 2/3] chore(master): release 1.18.1 (#480) (amended) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- CHANGELOG.md | 7 +++++++ version.txt | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a16f9df57a..e9dae2d675 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [1.18.1](https://github.com/openfoodfacts/openfoodfacts-dart/compare/v1.18.0...v1.18.1) (2022-06-07) + + +### Bug Fixes + +* [#477](https://github.com/openfoodfacts/openfoodfacts-dart/issues/477) - title is now optional in knowledge panel element ([#479](https://github.com/openfoodfacts/openfoodfacts-dart/issues/479)) ([4e7ffb2](https://github.com/openfoodfacts/openfoodfacts-dart/commit/4e7ffb2f4fca53b64c43f2c55f32895b6f068d30)) + ## [1.18.0](https://github.com/openfoodfacts/openfoodfacts-dart/compare/v1.17.1...v1.18.0) (2022-06-03) diff --git a/version.txt b/version.txt index 84cc529467..ec6d649be6 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.18.0 +1.18.1 From 7e12d2c19f2cdaf5b1596cdacf9ffca59c7368aa Mon Sep 17 00:00:00 2001 From: monsieurtanuki Date: Sun, 26 Jun 2022 09:14:22 +0200 Subject: [PATCH 3/3] feat: #494 - added OCR for packaging New files: * `OcrPackagingResult.dart`: Result from OCR applied to packaging. * `OcrPackagingResult.g.dart`: generated. Impacted files: * `OcrPackagingResult.dart`: mere refactoring in order to match the new `OcrPackagingResult` class. * `openfoodfacts.dart`: new OCR method `extractPackaging`; refactored `extractIngredients` and fixed a bug. --- lib/model/OcrIngredientsResult.dart | 24 ++++++++------- lib/model/OcrPackagingResult.dart | 28 ++++++++++++++++++ lib/model/OcrPackagingResult.g.dart | 21 ++++++++++++++ lib/openfoodfacts.dart | 45 ++++++++++++++++++++++++----- 4 files changed, 99 insertions(+), 19 deletions(-) create mode 100644 lib/model/OcrPackagingResult.dart create mode 100644 lib/model/OcrPackagingResult.g.dart diff --git a/lib/model/OcrIngredientsResult.dart b/lib/model/OcrIngredientsResult.dart index d84fdd638e..c60692cf81 100644 --- a/lib/model/OcrIngredientsResult.dart +++ b/lib/model/OcrIngredientsResult.dart @@ -3,8 +3,21 @@ import '../interface/JsonObject.dart'; part 'OcrIngredientsResult.g.dart'; +/// Result from OCR applied to ingredients. @JsonSerializable() class OcrIngredientsResult extends JsonObject { + const OcrIngredientsResult({ + this.status, + this.ingredientsTextFromImageOrig, + this.ingredientsTextFromImage, + }); + + factory OcrIngredientsResult.fromJson(Map json) => + _$OcrIngredientsResultFromJson(json); + + @override + Map toJson() => _$OcrIngredientsResultToJson(this); + final int? status; @JsonKey(name: 'ingredients_text_from_image_orig') @@ -12,15 +25,4 @@ class OcrIngredientsResult extends JsonObject { @JsonKey(name: 'ingredients_text_from_image') final String? ingredientsTextFromImage; - - const OcrIngredientsResult( - {this.status, - this.ingredientsTextFromImageOrig, - this.ingredientsTextFromImage}); - - factory OcrIngredientsResult.fromJson(Map json) => - _$OcrIngredientsResultFromJson(json); - - @override - Map toJson() => _$OcrIngredientsResultToJson(this); } diff --git a/lib/model/OcrPackagingResult.dart b/lib/model/OcrPackagingResult.dart new file mode 100644 index 0000000000..f0cb684383 --- /dev/null +++ b/lib/model/OcrPackagingResult.dart @@ -0,0 +1,28 @@ +import 'package:json_annotation/json_annotation.dart'; +import '../interface/JsonObject.dart'; + +part 'OcrPackagingResult.g.dart'; + +/// Result from OCR applied to packaging. +@JsonSerializable() +class OcrPackagingResult extends JsonObject { + const OcrPackagingResult({ + this.status, + this.textFromImageOrig, + this.textFromImage, + }); + + factory OcrPackagingResult.fromJson(Map json) => + _$OcrPackagingResultFromJson(json); + + @override + Map toJson() => _$OcrPackagingResultToJson(this); + + final int? status; + + @JsonKey(name: 'packaging_text_from_image_orig') + final String? textFromImageOrig; + + @JsonKey(name: 'packaging_text_from_image') + final String? textFromImage; +} diff --git a/lib/model/OcrPackagingResult.g.dart b/lib/model/OcrPackagingResult.g.dart new file mode 100644 index 0000000000..4345e60669 --- /dev/null +++ b/lib/model/OcrPackagingResult.g.dart @@ -0,0 +1,21 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'OcrPackagingResult.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +OcrPackagingResult _$OcrPackagingResultFromJson(Map json) => + OcrPackagingResult( + status: json['status'] as int?, + textFromImageOrig: json['packaging_text_from_image_orig'] as String?, + textFromImage: json['packaging_text_from_image'] as String?, + ); + +Map _$OcrPackagingResultToJson(OcrPackagingResult instance) => + { + 'status': instance.status, + 'packaging_text_from_image_orig': instance.textFromImageOrig, + 'packaging_text_from_image': instance.textFromImage, + }; diff --git a/lib/openfoodfacts.dart b/lib/openfoodfacts.dart index befdb878c3..da19f709e8 100644 --- a/lib/openfoodfacts.dart +++ b/lib/openfoodfacts.dart @@ -8,6 +8,7 @@ import 'package:http/http.dart'; import 'package:openfoodfacts/interface/JsonObject.dart'; import 'package:openfoodfacts/model/KnowledgePanels.dart'; import 'package:openfoodfacts/model/OcrIngredientsResult.dart'; +import 'package:openfoodfacts/model/OcrPackagingResult.dart'; import 'package:openfoodfacts/model/OrderedNutrients.dart'; import 'package:openfoodfacts/model/ProductFreshness.dart'; import 'package:openfoodfacts/model/ProductImage.dart'; @@ -700,26 +701,54 @@ class OpenFoodAPIClient { OcrField ocrField = OcrField.GOOGLE_CLOUD_VISION, QueryType? queryType, }) async { - var ocrUri = UriHelper.getPostUri( + final Uri uri = UriHelper.getPostUri( path: '/cgi/ingredients.pl', queryType: queryType, ); - Map queryParameters = { + final Map queryParameters = { 'code': barcode, 'process_image': '1', 'id': 'ingredients_${language.code}', - 'ocr_engine': OcrField.GOOGLE_CLOUD_VISION.key + 'ocr_engine': ocrField.key }; - Response response = await HttpHelper().doPostRequest( - ocrUri, + final Response response = await HttpHelper().doPostRequest( + uri, queryParameters, user, queryType: queryType, ); + return OcrIngredientsResult.fromJson( + json.decode(utf8.decode(response.bodyBytes)) as Map, + ); + } - OcrIngredientsResult result = OcrIngredientsResult.fromJson( - json.decode(utf8.decode(response.bodyBytes))); - return result; + /// Extracts the text from packaging image with OCR. + static Future extractPackaging( + final User user, + final String barcode, + final OpenFoodFactsLanguage language, { + final OcrField ocrField = OcrField.GOOGLE_CLOUD_VISION, + final QueryType? queryType, + }) async { + final Uri uri = UriHelper.getPostUri( + path: '/cgi/packaging.pl', + queryType: queryType, + ); + final Map queryParameters = { + 'code': barcode, + 'process_image': '1', + 'id': 'packaging_${language.code}', + 'ocr_engine': ocrField.key + }; + final Response response = await HttpHelper().doPostRequest( + uri, + queryParameters, + user, + queryType: queryType, + ); + return OcrPackagingResult.fromJson( + json.decode(utf8.decode(response.bodyBytes)) as Map, + ); } /// Give user suggestion based on autocompleted outputs