Skip to content

Commit

Permalink
feat: 999 - added "bool? product.isImageLocked" method (#1000)
Browse files Browse the repository at this point in the history
* feat: 999 - added "bool? product.isImageLocked" method

Impacted files:
* `api_get_product_test.dart`: new test "check if images are locked"
* `product.dart`: added field `owner` and methods around images - `isImageLocked`, `getLocalizedImage` and `getRawImage`
* `product.g.dart`: generated
* `product_fields.dart`: added field `OWNER`

* Minor fix
  • Loading branch information
monsieurtanuki authored Nov 25, 2024
1 parent d7664de commit 8a01b5c
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 0 deletions.
58 changes: 58 additions & 0 deletions lib/src/model/product.dart
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,61 @@ class Product extends JsonObject {
/// Images may be returned in multiple sizes
List<ProductImage>? getMainImages() => _getImageSubset(true);

bool? isImageLocked(
final ImageField imageField,
final OpenFoodFactsLanguage language,
) {
if (owner == null) {
return null;
}
final ProductImage? localizedImage = getLocalizedImage(
imageField,
language,
);
final String? imageId = localizedImage?.imgid;
if (imageId == null) {
return null;
}
final ProductImage? rawImage = getRawImage(imageId);
if (rawImage == null) {
return null;
}
return rawImage.contributor == owner;
}

ProductImage? getLocalizedImage(
final ImageField imageField,
final OpenFoodFactsLanguage language,
) {
if (images == null) {
return null;
}
for (final ProductImage productImage in images!) {
if (productImage.field == imageField &&
productImage.language == language) {
if (productImage.rev == null) {
return null;
}
return productImage;
}
}
return null;
}

ProductImage? getRawImage(final String imageId) {
if (images == null) {
return null;
}
for (final ProductImage productImage in images!) {
if (!productImage.isMain) {
if (productImage.imgid == imageId) {
return productImage;
}
}
}
return null;
}

List<ProductImage>? _getImageSubset(final bool isMain) {
if (images == null) {
return null;
Expand Down Expand Up @@ -537,6 +592,9 @@ class Product extends JsonObject {
@JsonKey(name: 'owner_fields')
Map<String, int>? ownerFields;

@JsonKey()
String? owner;

/// Expiration date / best before. Just a string, no format control.
@JsonKey(name: 'expiration_date')
String? expirationDate;
Expand Down
2 changes: 2 additions & 0 deletions lib/src/model/product.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions lib/src/utils/product_fields.dart
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ enum ProductField implements OffTagged {
EXPIRATION_DATE(offTag: 'expiration_date'),
OBSOLETE(offTag: 'obsolete'),
OWNER_FIELDS(offTag: 'owner_fields'),
OWNER(offTag: 'owner'),

/// All data as RAW from the server. E.g. packagings are only Strings there.
RAW(offTag: 'raw'),
Expand Down
57 changes: 57 additions & 0 deletions test/api_get_product_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1259,6 +1259,63 @@ void main() {
}
});

test('check if images are locked', () async {
Future<void> checkLocked(
final String barcode,
final OpenFoodFactsLanguage language,
final Map<ImageField, bool> areLocked,
) async {
final ProductResultV3 result = await getProductV3InProd(
ProductQueryConfiguration(
barcode,
fields: [
ProductField.OWNER,
ProductField.IMAGES,
],
version: ProductQueryVersion.v3,
),
);
expect(result.status, ProductResultV3.statusSuccess);
expect(result.product, isNotNull);
for (final MapEntry<ImageField, bool> entry in areLocked.entries) {
expect(result.product!.isImageLocked(entry.key, language), entry.value);
}
}

await checkLocked(
'3560070800292',
OpenFoodFactsLanguage.FRENCH,
<ImageField, bool>{
ImageField.FRONT: true,
ImageField.INGREDIENTS: false,
ImageField.NUTRITION: false,
ImageField.PACKAGING: false,
},
);

await checkLocked(
'7300400481588',
OpenFoodFactsLanguage.FRENCH,
<ImageField, bool>{
ImageField.FRONT: true,
ImageField.INGREDIENTS: false,
ImageField.NUTRITION: false,
ImageField.PACKAGING: false,
},
);

await checkLocked(
'3240931543390',
OpenFoodFactsLanguage.FRENCH,
<ImageField, bool>{
ImageField.FRONT: true,
ImageField.INGREDIENTS: true,
ImageField.NUTRITION: true,
ImageField.PACKAGING: true,
},
);
});

group('$OpenFoodAPIClient get new packagings field', () {
const String barcode = '3661344723290';
const OpenFoodFactsLanguage language = OpenFoodFactsLanguage.FRENCH;
Expand Down

0 comments on commit 8a01b5c

Please sign in to comment.