Skip to content

Commit

Permalink
feat: openfoodfacts#2169 - new simple input page for "Stores" (openfo…
Browse files Browse the repository at this point in the history
…odfacts#2195)

New files:
* `simple_input_page.dart`: Simple input page: we have a list of labels, we add, we remove, we save.
* `simple_input_page_helpers.dart`: Helpers for Simple Input Page.

Impacted files:
* `category_picker_page.dart`: refactored
* `edit_ingredients_page.dart`: refactored
* `edit_product_page.dart`: added an "edit store" button; refactored
* `nutrition_page_loaded.dart`: refactored
* `product_query.dart`: added fields for stores
* `product_refresher.dart`: now we return the saved and refreshed product instead of a mere bool
  • Loading branch information
monsieurtanuki authored Jun 7, 2022
1 parent 803a678 commit efe7f8d
Show file tree
Hide file tree
Showing 8 changed files with 351 additions and 26 deletions.
1 change: 1 addition & 0 deletions packages/smooth_app/lib/database/product_query.dart
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ abstract class ProductQuery {
ProductField.SELECTED_IMAGE,
ProductField.QUANTITY,
ProductField.SERVING_SIZE,
ProductField.STORES,
ProductField.PACKAGING_QUANTITY,
ProductField.NUTRIMENTS,
ProductField.NUTRIENT_LEVELS,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,12 +161,12 @@ class _CategoryPickerPageState extends State<CategoryPickerPage> {
tag
]; // TODO(monsieurtanuki): is the last leaf good enough or should we go down to the roots?

final bool savedAndRefreshed = await ProductRefresher().saveAndRefresh(
final Product? savedAndRefreshed = await ProductRefresher().saveAndRefresh(
context: context,
localDatabase: localDatabase,
product: product,
);
if (savedAndRefreshed) {
if (savedAndRefreshed != null) {
if (!mounted) {
return;
}
Expand Down
31 changes: 21 additions & 10 deletions packages/smooth_app/lib/pages/product/common/product_refresher.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,26 @@ import 'package:smooth_app/generic_lib/loading_dialog.dart';

/// Refreshes a product on the BE then on the local database.
class ProductRefresher {
Future<bool> saveAndRefresh({
/// Returns a saved and refreshed [Product] if successful, or null.
Future<Product?> saveAndRefresh({
required final BuildContext context,
required final LocalDatabase localDatabase,
required final Product product,
}) async {
final AppLocalizations appLocalizations = AppLocalizations.of(context);
final bool? savedAndRefreshed = await LoadingDialog.run<bool>(
final _MetaProductRefresher? savedAndRefreshed =
await LoadingDialog.run<_MetaProductRefresher>(
future: _saveAndRefresh(product, localDatabase),
context: context,
title: appLocalizations.nutrition_page_update_running,
);
if (savedAndRefreshed == null) {
// probably the end user stopped the dialog
return false;
return null;
}
if (!savedAndRefreshed) {
if (savedAndRefreshed.product == null) {
await LoadingDialog.error(context: context);
return false;
return null;
}
await showDialog<void>(
context: context,
Expand All @@ -38,11 +40,11 @@ class ProductRefresher {
),
),
);
return true;
return savedAndRefreshed.product;
}

/// Saves a product on the BE and refreshes the local database
Future<bool> _saveAndRefresh(
Future<_MetaProductRefresher> _saveAndRefresh(
final Product inputProduct,
final LocalDatabase localDatabase,
) async {
Expand All @@ -52,7 +54,7 @@ class ProductRefresher {
inputProduct,
);
if (status.error != null) {
return false;
return _MetaProductRefresher.error(status.error);
}
final ProductQueryConfiguration configuration = ProductQueryConfiguration(
inputProduct.barcode!,
Expand All @@ -65,11 +67,20 @@ class ProductRefresher {
);
if (result.product != null) {
await DaoProduct(localDatabase).put(result.product!);
return true;
localDatabase.notifyListeners();
return _MetaProductRefresher.product(result.product);
}
} catch (e) {
//
}
return false;
return const _MetaProductRefresher.error(null);
}
}

class _MetaProductRefresher {
const _MetaProductRefresher.error(this.error) : product = null;
const _MetaProductRefresher.product(this.product) : error = null;

final String? error;
final Product? product;
}
Original file line number Diff line number Diff line change
Expand Up @@ -148,12 +148,12 @@ class _EditIngredientsPageState extends State<EditIngredientsPage> {
Future<void> _updateIngredientsText(String ingredientsText) async {
widget.product.ingredientsText = ingredientsText;
final LocalDatabase localDatabase = context.read<LocalDatabase>();
final bool savedAndRefreshed = await ProductRefresher().saveAndRefresh(
final Product? savedAndRefreshed = await ProductRefresher().saveAndRefresh(
context: context,
localDatabase: localDatabase,
product: widget.product,
);
if (savedAndRefreshed) {
if (savedAndRefreshed != null) {
if (!mounted) {
return;
}
Expand Down
48 changes: 38 additions & 10 deletions packages/smooth_app/lib/pages/product/edit_product_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import 'package:smooth_app/pages/product/edit_ingredients_page.dart';
import 'package:smooth_app/pages/product/nutrition_page_loaded.dart';
import 'package:smooth_app/pages/product/ordered_nutrients_cache.dart';
import 'package:smooth_app/pages/product/product_image_gallery_view.dart';
import 'package:smooth_app/pages/product/simple_input_page.dart';
import 'package:smooth_app/pages/product/simple_input_page_helpers.dart';

/// Page where we can indirectly edit all data about a product.
class EditProductPage extends StatefulWidget {
Expand All @@ -23,14 +25,21 @@ class EditProductPage extends StatefulWidget {

class _EditProductPageState extends State<EditProductPage> {
int _changes = 0;
late Product _product;

@override
void initState() {
super.initState();
_product = widget.product;
}

@override
Widget build(BuildContext context) {
final AppLocalizations appLocalizations = AppLocalizations.of(context);
return Scaffold(
appBar: AppBar(
title: AutoSizeText(
getProductName(widget.product, appLocalizations),
getProductName(_product, appLocalizations),
maxLines: 2,
),
systemOverlayStyle: const SystemUiOverlayStyle(
Expand All @@ -52,9 +61,8 @@ class _EditProductPageState extends State<EditProductPage> {
title: Text(
appLocalizations.edit_product_form_item_barcode,
),
subtitle: widget.product.barcode == null
? null
: Text(widget.product.barcode!),
subtitle:
_product.barcode == null ? null : Text(_product.barcode!),
),
_ListTitleItem(
title: appLocalizations.edit_product_form_item_details_title,
Expand All @@ -65,7 +73,7 @@ class _EditProductPageState extends State<EditProductPage> {
context,
MaterialPageRoute<bool>(
builder: (BuildContext context) =>
AddBasicDetailsPage(widget.product),
AddBasicDetailsPage(_product),
),
);
if (refreshed ?? false) {
Expand All @@ -78,15 +86,15 @@ class _EditProductPageState extends State<EditProductPage> {
subtitle: appLocalizations.edit_product_form_item_photos_subtitle,
onTap: () async {
final List<ProductImageData> allProductImagesData =
getAllProductImagesData(widget.product, appLocalizations);
getAllProductImagesData(_product, appLocalizations);
final bool? refreshed = await Navigator.push<bool>(
context,
MaterialPageRoute<bool>(
builder: (BuildContext context) => ProductImageGalleryView(
productImageData: allProductImagesData.first,
allProductImagesData: allProductImagesData,
title: allProductImagesData.first.title,
barcode: widget.product.barcode,
barcode: _product.barcode,
),
),
);
Expand All @@ -106,7 +114,7 @@ class _EditProductPageState extends State<EditProductPage> {
context,
MaterialPageRoute<bool>(
builder: (BuildContext context) => EditIngredientsPage(
product: widget.product,
product: _product,
),
),
);
Expand All @@ -118,6 +126,26 @@ class _EditProductPageState extends State<EditProductPage> {
_ListTitleItem(
title: appLocalizations.edit_product_form_item_packaging_title,
),
_ListTitleItem(
title: 'Stores', // TODO(monsieurtanuki): translate
onTap: () async {
final Product? refreshed = await Navigator.push<Product>(
context,
MaterialPageRoute<Product>(
builder: (BuildContext context) => SimpleInputPage(
SimpleInputPageStoreHelper(
_product,
appLocalizations,
),
),
),
);
if (refreshed != null) {
_product = refreshed;
}
return;
},
),
_ListTitleItem(
title:
appLocalizations.edit_product_form_item_nutrition_facts_title,
Expand All @@ -136,7 +164,7 @@ class _EditProductPageState extends State<EditProductPage> {
context,
MaterialPageRoute<bool>(
builder: (BuildContext context) => NutritionPageLoaded(
widget.product,
_product,
cache.orderedNutrients,
),
),
Expand All @@ -145,7 +173,7 @@ class _EditProductPageState extends State<EditProductPage> {
_changes++;
}
},
)
),
],
),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -455,12 +455,12 @@ class _NutritionPageLoadedState extends State<NutritionPageLoaded> {
// minimal product: we only want to save the nutrients
final Product inputProduct = _nutritionContainer.getProduct();

final bool savedAndRefreshed = await ProductRefresher().saveAndRefresh(
final Product? savedAndRefreshed = await ProductRefresher().saveAndRefresh(
context: context,
localDatabase: localDatabase,
product: inputProduct,
);
if (savedAndRefreshed) {
if (savedAndRefreshed != null) {
if (!mounted) {
return;
}
Expand Down
Loading

0 comments on commit efe7f8d

Please sign in to comment.