Skip to content

Commit

Permalink
fix: 4564 - product immediately visible even if not on the server yet (
Browse files Browse the repository at this point in the history
…#4584)

* fix: 4564 - product immediately visible even if not on the server yet

Impacted files:
* `fetched_product.dart`: moved code from `ProductRefresher`
* `product_cards_helper.dart`: unrelated bug fix
* `product_dialog_helper.dart`: special case when the product was created locally but not uploaded/refreshed yet
* `product_field_editor.dart`: unrelated bug fix
* `product_list_item_simple.dart`: moved code to model
* `product_model.dart`: special case when the product was created locally but not uploaded/refreshed yet
* `product_refresher.dart`: moved code to `FetchedProduct`; minor refactoring
* `smooth_product_card_found.dart`: added a banner for product with pending changes.
* `up_to_date_product_provider.dart`: minor refactoring

* fix: 4564 - removed the "pending..." banner

Impacted file:
* `smooth_product_card_found.dart`: removed the "pending..." banner
  • Loading branch information
monsieurtanuki committed Sep 19, 2023
1 parent 05d0490 commit e84826b
Show file tree
Hide file tree
Showing 9 changed files with 202 additions and 197 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -56,111 +56,110 @@ class SmoothProductCardFound extends StatelessWidget {
);
final ProductCompatibilityHelper helper =
ProductCompatibilityHelper.product(matchedProduct);
return Padding(
padding: const EdgeInsets.symmetric(
horizontal: MEDIUM_SPACE,
vertical: SMALL_SPACE,
),
child: InkWell(
borderRadius: ROUNDED_BORDER_RADIUS,
onTap: onTap ??
() {
AppNavigator.of(context).push(
final Widget child = InkWell(
borderRadius: ROUNDED_BORDER_RADIUS,
onTap: onTap ??
() => AppNavigator.of(context).push(
AppRoutes.PRODUCT(
product.barcode!,
heroTag: heroTag,
),
extra: product,
);
},
onLongPress: () {
onLongPress?.call();
},
child: Hero(
tag: heroTag,
child: Material(
type: MaterialType.transparency,
child: Ink(
decoration: BoxDecoration(
borderRadius: ROUNDED_BORDER_RADIUS,
color: backgroundColor ??
(isDarkMode ? Colors.black : Colors.white),
),
child: SmoothCard(
elevation: elevation,
color: Colors.transparent,
padding: const EdgeInsets.all(VERY_SMALL_SPACE),
child: Row(
children: <Widget>[
SmoothMainProductImage(
product: product,
width: screenSize.width * 0.20,
height: screenSize.width * 0.20,
),
const Padding(
padding: EdgeInsetsDirectional.only(
start: VERY_SMALL_SPACE)),
Expanded(
child: SizedBox(
height: screenSize.width * 0.2,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
getProductName(product, appLocalizations),
overflow: TextOverflow.ellipsis,
style: themeData.textTheme.headlineMedium,
),
Text(
getProductBrands(product, appLocalizations),
overflow: TextOverflow.ellipsis,
style: themeData.textTheme.titleMedium,
),
Row(
children: <Widget>[
Icon(
Icons.circle,
size: 15,
color: helper.getButtonColor(isDarkMode),
),
const Padding(
padding: EdgeInsetsDirectional.only(
start: VERY_SMALL_SPACE),
),
Expanded(
child: FittedBox(
fit: BoxFit.scaleDown,
alignment: AlignmentDirectional.centerStart,
child: Text(
helper.getSubtitle(appLocalizations),
style: themeData.textTheme.bodyMedium,
),
onLongPress: () => onLongPress?.call(),
child: Hero(
tag: heroTag,
child: Material(
type: MaterialType.transparency,
child: Ink(
decoration: BoxDecoration(
borderRadius: ROUNDED_BORDER_RADIUS,
color:
backgroundColor ?? (isDarkMode ? Colors.black : Colors.white),
),
child: SmoothCard(
elevation: elevation,
color: Colors.transparent,
padding: const EdgeInsets.all(VERY_SMALL_SPACE),
child: Row(
children: <Widget>[
SmoothMainProductImage(
product: product,
width: screenSize.width * 0.20,
height: screenSize.width * 0.20,
),
const Padding(
padding:
EdgeInsetsDirectional.only(start: VERY_SMALL_SPACE),
),
Expanded(
child: SizedBox(
height: screenSize.width * 0.2,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
getProductName(product, appLocalizations),
overflow: TextOverflow.ellipsis,
style: themeData.textTheme.headlineMedium,
),
Text(
getProductBrands(product, appLocalizations),
overflow: TextOverflow.ellipsis,
style: themeData.textTheme.titleMedium,
),
Row(
children: <Widget>[
Icon(
Icons.circle,
size: 15,
color: helper.getButtonColor(isDarkMode),
),
const Padding(
padding: EdgeInsetsDirectional.only(
start: VERY_SMALL_SPACE),
),
Expanded(
child: FittedBox(
fit: BoxFit.scaleDown,
alignment: AlignmentDirectional.centerStart,
child: Text(
helper.getSubtitle(appLocalizations),
style: themeData.textTheme.bodyMedium,
),
),
],
),
],
),
),
],
),
],
),
),
const Padding(
padding:
EdgeInsetsDirectional.only(start: VERY_SMALL_SPACE),
),
const Padding(
padding:
EdgeInsetsDirectional.only(start: VERY_SMALL_SPACE),
),
Padding(
padding: const EdgeInsets.all(VERY_SMALL_SPACE),
child: Column(
children: scores,
),
Padding(
padding: const EdgeInsets.all(VERY_SMALL_SPACE),
child: Column(
children: scores,
),
),
],
),
),
],
),
),
),
),
),
);
// TODO(monsieurtanuki): check localDatabase.upToDate.hasPendingChanges and display a "pending changes" mark if relevant
return Padding(
padding: const EdgeInsets.symmetric(
horizontal: MEDIUM_SPACE,
vertical: SMALL_SPACE,
),
child: child,
);
}
}
26 changes: 26 additions & 0 deletions packages/smooth_app/lib/data_models/fetched_product.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:openfoodfacts/openfoodfacts.dart';

/// Status of a "fetch [Product]" operation
Expand Down Expand Up @@ -60,4 +61,29 @@ class FetchedProduct {

/// When relevant, host of the query that we couldn't even ping.
final String? failedPingedHost;

String getErrorTitle(
final AppLocalizations appLocalizations,
) {
switch (status) {
case FetchedProductStatus.ok:
return 'Not supposed to happen...';
case FetchedProductStatus.userCancelled:
return 'Not supposed to happen either...';
case FetchedProductStatus.internetNotFound:
return appLocalizations.product_refresher_internet_not_found;
case FetchedProductStatus.internetError:
if (connectivityResult == ConnectivityResult.none) {
return appLocalizations.product_refresher_internet_not_connected;
}
if (failedPingedHost != null) {
return appLocalizations.product_refresher_internet_no_ping(
failedPingedHost,
);
}
return appLocalizations.product_refresher_internet_no_ping(
exceptionString,
);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@ class UpToDateProductProvider {
return result;
}

/// Returns true if there are pending operations for that [barcode].
bool hasPendingChanges(final String barcode) =>
_changes.hasNotTerminatedOperations(barcode);

// TODO(monsieurtanuki): move code to off-dart Product?
Product copy(final Product source) => Product.fromJson(
jsonDecode(jsonEncode(source.toJson())) as Map<String, dynamic>,
Expand Down
5 changes: 4 additions & 1 deletion packages/smooth_app/lib/helpers/product_cards_helper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@ import 'package:smooth_app/generic_lib/design_constants.dart';
import 'package:smooth_app/generic_lib/widgets/smooth_card.dart';
import 'package:smooth_app/helpers/image_field_extension.dart';
import 'package:smooth_app/helpers/ui_helpers.dart';
import 'package:smooth_app/query/product_query.dart';

String getProductName(Product product, AppLocalizations appLocalizations) =>
product.productName ?? appLocalizations.unknownProductName;
product.productName ??
product.productNameInLanguages?[ProductQuery.getLanguage()] ??
appLocalizations.unknownProductName;

String getProductBrands(Product product, AppLocalizations appLocalizations) {
final String? brands = product.brands;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ class ProductDialogHelper {
if (product != null) {
return FetchedProduct.found(product);
}
if (localDatabase.upToDate.hasPendingChanges(barcode)) {
return FetchedProduct.found(Product(barcode: barcode));
}
return openUniqueProductSearch();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:provider/provider.dart';
import 'package:smooth_app/cards/product_cards/smooth_product_card_found.dart';
import 'package:smooth_app/cards/product_cards/smooth_product_card_template.dart';
import 'package:smooth_app/data_models/fetched_product.dart';
import 'package:smooth_app/data_models/product_list.dart';
import 'package:smooth_app/database/local_database.dart';
import 'package:smooth_app/generic_lib/design_constants.dart';
Expand All @@ -32,19 +31,17 @@ class ProductListItemSimple extends StatefulWidget {

class _ProductListItemSimpleState extends State<ProductListItemSimple> {
late final ProductModel _model;
late final LocalDatabase _localDatabase;

@override
void initState() {
super.initState();
_localDatabase = context.read<LocalDatabase>();
_model = ProductModel(widget.barcode, _localDatabase);
_localDatabase.upToDate.showInterest(widget.barcode);
final LocalDatabase localDatabase = context.read<LocalDatabase>();
_model = ProductModel(widget.barcode, localDatabase);
}

@override
void dispose() {
_localDatabase.upToDate.loseInterest(widget.barcode);
_model.dispose();
super.dispose();
}

Expand Down Expand Up @@ -96,15 +93,7 @@ class _ProductListItemSimpleState extends State<ProductListItemSimple> {
},
);

String _getErrorMessage(AppLocalizations appLocalizations) {
switch (_model.downloadingStatus) {
case null:
break;
case FetchedProductStatus.internetNotFound:
return appLocalizations.product_internet_error;
default:
return appLocalizations.error_occurred;
}
return _model.loadingError ?? 'Error';
}
String _getErrorMessage(final AppLocalizations appLocalizations) =>
_model.loadingError?.getErrorTitle(appLocalizations) ??
appLocalizations.error_occurred;
}
Loading

0 comments on commit e84826b

Please sign in to comment.