Skip to content

Commit

Permalink
feat: 3880 - added a "get photo" button on the edit packaging compone…
Browse files Browse the repository at this point in the history
…nt page (#3942)

Impacted files:
* `edit_new_packagings.dart`: added a "get photo" button on top; refactored with the up-to-date provider
* `image_field_extension.dart`: new `getPhotoButton` method
* `nutrition_page_loaded.dart`: refactored with the up-to-date provider and the new `getPhotoButton` method
  • Loading branch information
monsieurtanuki committed May 13, 2023
1 parent 6e72ff0 commit 72e98df
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 47 deletions.
21 changes: 21 additions & 0 deletions packages/smooth_app/lib/helpers/image_field_extension.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:openfoodfacts/openfoodfacts.dart';
import 'package:smooth_app/generic_lib/buttons/smooth_large_button_with_icon.dart';
import 'package:smooth_app/pages/product/product_image_swipeable_view.dart';

extension ImageFieldSmoothieExtension on ImageField {
static const List<ImageField> orderedMain = <ImageField>[
Expand Down Expand Up @@ -112,4 +115,22 @@ extension ImageFieldSmoothieExtension on ImageField {
return appLocalizations.other_interesting_photo_button_label;
}
}

Widget getPhotoButton(
final BuildContext context,
final Product product,
) =>
SmoothLargeButtonWithIcon(
onPressed: () async => Navigator.push(
context,
MaterialPageRoute<void>(
builder: (_) => ProductImageSwipeableView.imageField(
imageField: this,
product: product,
),
),
),
icon: Icons.camera_alt,
text: getProductImageButtonText(AppLocalizations.of(context)),
);
}
50 changes: 30 additions & 20 deletions packages/smooth_app/lib/pages/product/edit_new_packagings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import 'package:smooth_app/generic_lib/design_constants.dart';
import 'package:smooth_app/generic_lib/dialogs/smooth_alert_dialog.dart';
import 'package:smooth_app/generic_lib/widgets/smooth_card.dart';
import 'package:smooth_app/helpers/analytics_helper.dart';
import 'package:smooth_app/helpers/image_field_extension.dart';
import 'package:smooth_app/helpers/product_cards_helper.dart';
import 'package:smooth_app/pages/image_crop_page.dart';
import 'package:smooth_app/pages/product/edit_new_packagings_component.dart';
Expand Down Expand Up @@ -37,17 +38,14 @@ class _EditNewPackagingsState extends State<EditNewPackagings> {
late final LocalDatabase _localDatabase;
late final NumberFormat _decimalNumberFormat;
late final NumberFormat _unitNumberFormat;
late Product _product;
late final Product _initialProduct;

late bool? _packagingsComplete;

final List<EditNewPackagingsHelper> _helpers = <EditNewPackagingsHelper>[];
String get _barcode => _initialProduct.barcode!;

void _initPackagings() {
if (widget.product.packagings != null) {
widget.product.packagings!.forEach(_addPackagingToControllers);
}
_packagingsComplete = widget.product.packagingsComplete;
}
final List<EditNewPackagingsHelper> _helpers = <EditNewPackagingsHelper>[];

void _addPackagingToControllers(
final ProductPackaging packaging, {
Expand All @@ -71,20 +69,24 @@ class _EditNewPackagingsState extends State<EditNewPackagings> {
@override
void initState() {
super.initState();
_initialProduct = widget.product;
_decimalNumberFormat = SimpleInputNumberField.getNumberFormat(
decimal: true,
);
_unitNumberFormat = SimpleInputNumberField.getNumberFormat(
decimal: false,
);
_initPackagings();
if (_initialProduct.packagings != null) {
_initialProduct.packagings!.forEach(_addPackagingToControllers);
}
_packagingsComplete = _initialProduct.packagingsComplete;
_localDatabase = context.read<LocalDatabase>();
_localDatabase.upToDate.showInterest(widget.product.barcode!);
_localDatabase.upToDate.showInterest(_barcode);
}

@override
void dispose() {
_localDatabase.upToDate.loseInterest(widget.product.barcode!);
_localDatabase.upToDate.loseInterest(_barcode);
for (final EditNewPackagingsHelper helper in _helpers) {
helper.dispose();
}
Expand All @@ -94,7 +96,15 @@ class _EditNewPackagingsState extends State<EditNewPackagings> {
@override
Widget build(BuildContext context) {
final AppLocalizations appLocalizations = AppLocalizations.of(context);
context.watch<LocalDatabase>();
_product = _localDatabase.upToDate.getLocalUpToDate(_initialProduct);
final List<Widget> children = <Widget>[];
children.add(
Padding(
padding: const EdgeInsets.all(SMALL_SPACE),
child: ImageField.PACKAGING.getPhotoButton(context, _product),
),
);
for (int index = 0; index < _helpers.length; index++) {
// needed for deleteCallback (if not final, will take unreachable value)
final int deleteIndex = index;
Expand All @@ -106,7 +116,7 @@ class _EditNewPackagingsState extends State<EditNewPackagings> {
deleteCallback: () =>
setState(() => _removePackagingAt(deleteIndex)),
helper: _helpers[index],
categories: widget.product.categories,
categories: _product.categories,
),
),
);
Expand Down Expand Up @@ -164,7 +174,7 @@ class _EditNewPackagingsState extends State<EditNewPackagings> {
onPressed: () async => confirmAndUploadNewPicture(
this,
imageField: ImageField.OTHER,
barcode: widget.product.barcode!,
barcode: _barcode,
language: ProductQuery.getLanguage(),
),
iconData: Icons.add_a_photo,
Expand Down Expand Up @@ -197,9 +207,9 @@ class _EditNewPackagingsState extends State<EditNewPackagings> {
child: SmoothScaffold(
appBar: SmoothAppBar(
title: Text(appLocalizations.edit_packagings_title),
subTitle: widget.product.productName != null
subTitle: _product.productName != null
? Text(
widget.product.productName!,
_product.productName!,
maxLines: 1,
overflow: TextOverflow.ellipsis,
)
Expand Down Expand Up @@ -241,16 +251,16 @@ class _EditNewPackagingsState extends State<EditNewPackagings> {
p1.numberOfUnits != p2.numberOfUnits;

bool _hasPackagingsChanged(final List<ProductPackaging> packagings) {
if (widget.product.packagings == null) {
if (_product.packagings == null) {
return packagings.isNotEmpty;
}
if (widget.product.packagings!.length != packagings.length) {
if (_product.packagings!.length != packagings.length) {
return true;
}
for (int i = 0; i < packagings.length; i++) {
if (_isPackagingDifferent(
packagings[i],
widget.product.packagings![i],
_product.packagings![i],
)) {
return true;
}
Expand All @@ -263,7 +273,7 @@ class _EditNewPackagingsState extends State<EditNewPackagings> {
/// Parameter [saving] tells about the context: are we leaving the page,
/// or have we clicked on the "save" button?
Future<bool> _mayExitPage({required final bool saving}) async {
final Product changedProduct = Product(barcode: widget.product.barcode);
final Product changedProduct = Product(barcode: _barcode);
bool changed = false;

final List<ProductPackaging> packagings = _getPackagingsFromControllers();
Expand All @@ -272,7 +282,7 @@ class _EditNewPackagingsState extends State<EditNewPackagings> {
changedProduct.packagings = packagings;
}

if (_packagingsComplete != widget.product.packagingsComplete) {
if (_packagingsComplete != _product.packagingsComplete) {
changed = true;
changedProduct.packagingsComplete = _packagingsComplete;
}
Expand All @@ -297,7 +307,7 @@ class _EditNewPackagingsState extends State<EditNewPackagings> {

AnalyticsHelper.trackProductEdit(
AnalyticsEditEvents.packagingComponents,
changedProduct.barcode!,
_barcode,
true,
);

Expand Down
52 changes: 25 additions & 27 deletions packages/smooth_app/lib/pages/product/nutrition_page_loaded.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,18 @@ import 'package:intl/intl.dart';
import 'package:openfoodfacts/openfoodfacts.dart';
import 'package:provider/provider.dart';
import 'package:smooth_app/background/background_task_details.dart';
import 'package:smooth_app/generic_lib/buttons/smooth_large_button_with_icon.dart';
import 'package:smooth_app/database/local_database.dart';
import 'package:smooth_app/generic_lib/design_constants.dart';
import 'package:smooth_app/generic_lib/dialogs/smooth_alert_dialog.dart';
import 'package:smooth_app/generic_lib/widgets/smooth_card.dart';
import 'package:smooth_app/helpers/analytics_helper.dart';
import 'package:smooth_app/helpers/image_field_extension.dart';
import 'package:smooth_app/helpers/text_input_formatters_helper.dart';
import 'package:smooth_app/pages/product/common/product_refresher.dart';
import 'package:smooth_app/pages/product/may_exit_page_helper.dart';
import 'package:smooth_app/pages/product/nutrition_add_nutrient_button.dart';
import 'package:smooth_app/pages/product/nutrition_container.dart';
import 'package:smooth_app/pages/product/ordered_nutrients_cache.dart';
import 'package:smooth_app/pages/product/product_image_swipeable_view.dart';
import 'package:smooth_app/pages/product/simple_input_number_field.dart';
import 'package:smooth_app/pages/text_field_helper.dart';
import 'package:smooth_app/widgets/smooth_app_bar.dart';
Expand Down Expand Up @@ -86,6 +86,7 @@ class NutritionPageLoaded extends StatefulWidget {
}

class _NutritionPageLoadedState extends State<NutritionPageLoaded> {
late final LocalDatabase _localDatabase;
late final NumberFormat _decimalNumberFormat;
late final NutritionContainer _nutritionContainer;

Expand All @@ -94,21 +95,27 @@ class _NutritionPageLoadedState extends State<NutritionPageLoaded> {
TextEditingControllerWithInitialValue? _servingController;
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
late Product _product;
late final Product _initialProduct;

String get _barcode => _initialProduct.barcode!;

@override
void initState() {
super.initState();
_product = widget.product;
_initialProduct = widget.product;
_nutritionContainer = NutritionContainer(
orderedNutrients: widget.orderedNutrients,
product: _product,
product: _initialProduct,
);
_decimalNumberFormat =
SimpleInputNumberField.getNumberFormat(decimal: true);
_localDatabase = context.read<LocalDatabase>();
_localDatabase.upToDate.showInterest(_barcode);
}

@override
void dispose() {
_localDatabase.upToDate.loseInterest(_barcode);
for (final TextEditingControllerWithInitialValue controller
in _controllers.values) {
controller.dispose();
Expand All @@ -120,6 +127,9 @@ class _NutritionPageLoadedState extends State<NutritionPageLoaded> {
@override
Widget build(BuildContext context) {
final AppLocalizations appLocalizations = AppLocalizations.of(context);
context.watch<LocalDatabase>();
_product = _localDatabase.upToDate.getLocalUpToDate(_initialProduct);

final List<Widget> children = <Widget>[];

// List of focus nodes for all text fields except the serving one.
Expand All @@ -128,7 +138,12 @@ class _NutritionPageLoadedState extends State<NutritionPageLoaded> {
children.add(_switchNoNutrition(appLocalizations));

if (!_nutritionContainer.noNutritionData) {
children.add(_goToPicture(appLocalizations));
children.add(
Padding(
padding: const EdgeInsets.symmetric(vertical: MEDIUM_SPACE),
child: ImageField.NUTRITION.getPhotoButton(context, _product),
),
);
children.add(_getServingField(appLocalizations));
children.add(_getServingSwitch(appLocalizations));

Expand Down Expand Up @@ -179,11 +194,11 @@ class _NutritionPageLoadedState extends State<NutritionPageLoaded> {
appBar: SmoothAppBar(
title: AutoSizeText(
appLocalizations.nutrition_page_title,
maxLines: widget.product.productName?.isNotEmpty == true ? 1 : 2,
maxLines: _product.productName?.isNotEmpty == true ? 1 : 2,
),
subTitle: widget.product.productName != null
subTitle: _product.productName != null
? Text(
widget.product.productName!,
_product.productName!,
maxLines: 1,
overflow: TextOverflow.ellipsis,
)
Expand Down Expand Up @@ -344,23 +359,6 @@ class _NutritionPageLoadedState extends State<NutritionPageLoaded> {
),
);

Widget _goToPicture(final AppLocalizations appLocalizations) => Padding(
padding: const EdgeInsets.symmetric(vertical: MEDIUM_SPACE),
child: SmoothLargeButtonWithIcon(
onPressed: () async => Navigator.push(
context,
MaterialPageRoute<void>(
builder: (_) => ProductImageSwipeableView.imageField(
imageField: ImageField.NUTRITION,
product: _product,
),
),
),
icon: Icons.camera_alt,
text: appLocalizations.nutrition_facts_photo,
),
);

/// Returns `true` if any value differs with initial state.
bool _isEdited() {
if (_servingController != null && _servingController!.valueHasChanged) {
Expand Down Expand Up @@ -425,7 +423,7 @@ class _NutritionPageLoadedState extends State<NutritionPageLoaded> {
}

final Product? changedProduct =
_getChangedProduct(Product(barcode: widget.product.barcode));
_getChangedProduct(Product(barcode: _barcode));
if (changedProduct == null) {
if (!mounted) {
return false;
Expand All @@ -441,7 +439,7 @@ class _NutritionPageLoadedState extends State<NutritionPageLoaded> {

AnalyticsHelper.trackProductEdit(
AnalyticsEditEvents.nutrition_Facts,
changedProduct.barcode!,
_barcode,
true,
);
await BackgroundTaskDetails.addTask(
Expand Down

0 comments on commit 72e98df

Please sign in to comment.