-
-
Notifications
You must be signed in to change notification settings - Fork 285
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: 3919 - select languages for new product images (#4255)
* feat: 3919 - select languages for new product images New file: * `add_new_product_helper.dart`: Helper classes for `AddNewProductPage` that was getting too big. Impacted files: * `add_basic_details_page.dart`: minor refactoring * `add_new_product_page.dart`: moved code to new file `add_new_product_helper.dart`; refactored the trackers with new class `AnalyticsProductTracker`; refactored the access to image edit * `add_simple_input_button.dart`: minor refactoring * `crop_page.dart`: minor refactoring * `edit_new_packagings.dart`: minor refactoring * `edit_ocr_page.dart`: minor refactoring * `edit_product_page.dart`: minor refactoring * `image_crop_page.dart`: minor refactoring * `image_field_extension.dart`: minor refactoring * `nutrition_page_loaded.dart`: minor refactoring * `product_cards_helper.dart`: minor refactoring * `product_field_editor.dart`: minor refactoring * `product_image_carousel.dart`: minor refactoring * `product_image_carousel_item.dart`: renamed from `image_upload_card.dart` * `product_image_gallery_view.dart`: minor refactoring * `product_image_local_button.dart`: minor refactoring * `product_image_server_button.dart`: minor refactoring * `product_image_swipeable_view.dart`: minor refactoring * `product_image_viewer.dart`: minor refactoring * `product_refresher.dart`: minor refactoring * `uploaded_image_gallery.dart`: minor refactoring * feat: 3919 - merge conflict fixes * feat: 3919 - conflict fix --------- Co-authored-by: Pierre Slamich <[email protected]>
- Loading branch information
1 parent
b84cd3c
commit 75683db
Showing
22 changed files
with
508 additions
and
331 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
202 changes: 202 additions & 0 deletions
202
packages/smooth_app/lib/pages/product/add_new_product_helper.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,202 @@ | ||
import 'package:flutter/material.dart'; | ||
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | ||
import 'package:openfoodfacts/openfoodfacts.dart'; | ||
import 'package:smooth_app/data_models/product_image_data.dart'; | ||
import 'package:smooth_app/database/transient_file.dart'; | ||
import 'package:smooth_app/generic_lib/buttons/smooth_large_button_with_icon.dart'; | ||
import 'package:smooth_app/generic_lib/design_constants.dart'; | ||
import 'package:smooth_app/generic_lib/svg_icon_chip.dart'; | ||
import 'package:smooth_app/helpers/analytics_helper.dart'; | ||
import 'package:smooth_app/helpers/product_cards_helper.dart'; | ||
import 'package:smooth_app/pages/product/product_field_editor.dart'; | ||
import 'package:smooth_app/query/product_query.dart'; | ||
|
||
/// Tracks (only the first time) when a [check] is true. | ||
class AnalyticsProductTracker { | ||
AnalyticsProductTracker({ | ||
required this.analyticsEvent, | ||
required this.barcode, | ||
required this.check, | ||
}); | ||
|
||
final AnalyticsEvent analyticsEvent; | ||
final String barcode; | ||
final bool Function() check; | ||
|
||
bool _already = false; | ||
|
||
void track() { | ||
if (_already) { | ||
return; | ||
} | ||
if (!check()) { | ||
return; | ||
} | ||
_already = true; | ||
AnalyticsHelper.trackEvent(analyticsEvent, barcode: barcode); | ||
} | ||
} | ||
|
||
/// Card title for "Add new product" page. | ||
class AddNewProductTitle extends StatelessWidget { | ||
const AddNewProductTitle( | ||
this.label, { | ||
this.maxLines, | ||
}); | ||
|
||
final String label; | ||
final int? maxLines; | ||
|
||
@override | ||
Widget build(BuildContext context) => Text( | ||
label, | ||
style: Theme.of(context).textTheme.displaySmall, | ||
maxLines: maxLines, | ||
); | ||
} | ||
|
||
/// Card subtitle for "Add new product" page. | ||
class AddNewProductSubTitle extends StatelessWidget { | ||
const AddNewProductSubTitle(this.label); | ||
|
||
final String label; | ||
|
||
@override | ||
Widget build(BuildContext context) => Text(label); | ||
} | ||
|
||
/// Standard button in the "Add new product" page. | ||
class AddNewProductButton extends StatelessWidget { | ||
const AddNewProductButton( | ||
this.label, | ||
this.iconData, | ||
this.onPressed, { | ||
required this.done, | ||
}); | ||
|
||
final String label; | ||
final IconData iconData; | ||
final VoidCallback? onPressed; | ||
final bool done; | ||
|
||
static const IconData doneIconData = Icons.check; | ||
static const IconData todoIconData = Icons.add; | ||
static const IconData cameraIconData = Icons.camera_alt; | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
final ThemeData themeData = Theme.of(context); | ||
final bool dark = themeData.brightness == Brightness.dark; | ||
final Color? darkGrey = Colors.grey[700]; | ||
final Color? lightGrey = Colors.grey[300]; | ||
return Padding( | ||
padding: const EdgeInsets.symmetric(vertical: SMALL_SPACE), | ||
child: SmoothLargeButtonWithIcon( | ||
text: label, | ||
icon: iconData, | ||
onPressed: onPressed, | ||
trailing: Icons.edit, | ||
backgroundColor: onPressed == null | ||
? (dark ? darkGrey : lightGrey) | ||
: done | ||
? Colors.green[700] | ||
: themeData.colorScheme.secondary, | ||
foregroundColor: onPressed == null | ||
? (dark ? lightGrey : darkGrey) | ||
: done | ||
? Colors.white | ||
: themeData.colorScheme.onSecondary, | ||
), | ||
); | ||
} | ||
} | ||
|
||
/// Standard "editor" button in the "Add new product" page. | ||
class AddNewProductEditorButton extends StatelessWidget { | ||
const AddNewProductEditorButton( | ||
this.product, | ||
this.editor, { | ||
this.forceIconData, | ||
this.disabled = false, | ||
required this.isLoggedInMandatory, | ||
}); | ||
|
||
final Product product; | ||
final ProductFieldEditor editor; | ||
final IconData? forceIconData; | ||
final bool disabled; | ||
final bool isLoggedInMandatory; | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
final bool done = editor.isPopulated(product); | ||
return AddNewProductButton( | ||
editor.getLabel(AppLocalizations.of(context)), | ||
forceIconData ?? | ||
(done | ||
? AddNewProductButton.doneIconData | ||
: AddNewProductButton.todoIconData), | ||
disabled | ||
? null | ||
: () async => editor.edit( | ||
context: context, | ||
product: product, | ||
isLoggedInMandatory: isLoggedInMandatory, | ||
), | ||
done: done, | ||
); | ||
} | ||
} | ||
|
||
class AddNewProductScoreIcon extends StatelessWidget { | ||
const AddNewProductScoreIcon({ | ||
required this.iconUrl, | ||
required this.defaultIconUrl, | ||
}); | ||
|
||
final String? iconUrl; | ||
final String defaultIconUrl; | ||
|
||
@override | ||
Widget build(BuildContext context) => SvgIconChip( | ||
iconUrl ?? defaultIconUrl, | ||
height: MediaQuery.of(context).size.height * .2, | ||
); | ||
} | ||
|
||
/// Helper for the "Add new product" page. | ||
class AddNewProductHelper { | ||
bool isMainImagePopulated( | ||
final ProductImageData productImageData, | ||
final String barcode, | ||
) => | ||
TransientFile.fromProductImageData( | ||
productImageData, | ||
barcode, | ||
ProductQuery.getLanguage(), | ||
).getImageProvider() != | ||
null; | ||
|
||
bool isOneMainImagePopulated(final Product product) { | ||
final List<ProductImageData> productImagesData = getProductMainImagesData( | ||
product, | ||
ProductQuery.getLanguage(), | ||
includeOther: false, | ||
); | ||
for (final ProductImageData productImageData in productImagesData) { | ||
if (isMainImagePopulated(productImageData, product.barcode!)) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
} | ||
|
||
/// Possible actions on that page. | ||
enum EditProductAction { | ||
openPage, | ||
leaveEmpty, | ||
ingredients, | ||
category, | ||
nutritionFacts; | ||
} |
Oops, something went wrong.