Skip to content

Commit

Permalink
feat: 5318 - added a "price privacy warning" dialog (openfoodfacts#5343)
Browse files Browse the repository at this point in the history
Impacted files:
* `app_en.arb`: added 2 labels for the "price privacy warning" dialog
* `background_task_add_price.dart`: now using new off-dart methods
* `knowledge_panel_action_card.dart`: minor off-dart impact
* `price_model.dart`: refactored
* `product_price_add_page.dart`: added the "price privacy warning" dialog the very first time and in an app bar button
* `product_price_item.dart`: now using new off-dart method
* `product_prices_page.dart`: now using new off-dart method
* `pubspec.lock`: wtf
* `pubspec.yaml`: upgraded of `openfoodfacts` to `3.11.0`
* `user_preferences.dart`: added flag for "price privacy warning"
* `user_preferences_account.dart`: now using new off-dart method
  • Loading branch information
monsieurtanuki authored Jun 8, 2024
1 parent 2dd4575 commit e94d61f
Show file tree
Hide file tree
Showing 11 changed files with 106 additions and 76 deletions.
24 changes: 2 additions & 22 deletions packages/smooth_app/lib/background/background_task_add_price.dart
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ class BackgroundTaskAddPrice extends BackgroundTask {
cropY1 = json[_jsonTagY1] as int? ?? 0,
cropX2 = json[_jsonTagX2] as int? ?? 0,
cropY2 = json[_jsonTagY2] as int? ?? 0,
proofType = getProofTypeFromOffTag(json[_jsonTagProofType] as String)!,
proofType = ProofType.fromOffTag(json[_jsonTagProofType] as String)!,
date = JsonHelper.stringTimestampToDate(json[_jsonTagDate] as String),
currency = getCurrencyFromName(json[_jsonTagCurrency] as String)!,
currency = Currency.fromName(json[_jsonTagCurrency] as String)!,
locationOSMId = json[_jsonTagOSMId] as int,
locationOSMType =
LocationOSMType.fromOffTag(json[_jsonTagOSMType] as String)!,
Expand Down Expand Up @@ -358,26 +358,6 @@ class BackgroundTaskAddPrice extends BackgroundTask {
}
}

// TODO(monsieurtanuki): move it to off-dart
static Currency? getCurrencyFromName(final String name) {
for (final Currency currency in Currency.values) {
if (currency.name == name) {
return currency;
}
}
return null;
}

// TODO(monsieurtanuki): move it to off-dart
static ProofType? getProofTypeFromOffTag(final String offTag) {
for (final ProofType value in ProofType.values) {
if (value.offTag == offTag) {
return value;
}
}
return null;
}

@override
bool isDeduplicable() => false;
}
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ class UserPreferences extends ChangeNotifier {
/// Vibrations / haptic feedback
static const String _TAG_HAPTIC_FEEDBACK_IN_APP = 'haptic_feedback_enabled';

/// Price privacy warning
static const String TAG_PRICE_PRIVACY_WARNING = 'price_privacy_warning';

/// Attribute group that is not collapsed
static const String _TAG_ACTIVE_ATTRIBUTE_GROUP = 'activeAttributeGroup';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class KnowledgePanelActionCard extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
SmoothHtmlWidget(element.html),
if (element.html != null) SmoothHtmlWidget(element.html!),
const SizedBox(height: SMALL_SPACE),
...actionWidgets,
],
Expand Down
2 changes: 2 additions & 0 deletions packages/smooth_app/lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -1704,6 +1704,8 @@
"prices_proof_price_tag": "Price tag",
"prices_proof_mandatory": "You need to select a proof!",
"prices_add_validation_error": "Validation error",
"prices_privacy_warning_title": "Privacy warning",
"prices_privacy_warning_message": "Prices will be public, along with the store they refer to.\nThat might allow people who know about your Open Food Facts pseudonym to:\n* infer in which area you live\n* know what you are buying\nIf you are uneasy with that, please change your pseudonym, or create a new Open Food Facts account and log into the app with it.",
"dev_preferences_import_history_result_success": "Done",
"@dev_preferences_import_history_result_success": {
"description": "User dev preferences - Import history - Result successful"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -289,21 +289,16 @@ class UserPreferencesAccount extends AbstractUserPreferences {
}) =>
_getListTile(
title,
() async => LaunchUrlHelper.launchURL(_getPriceUrl(path)),
() async => LaunchUrlHelper.launchURL(
OpenPricesAPIClient.getUri(
path: path,
uriHelper: ProductQuery.uriProductHelper,
).toString(),
),
Icons.open_in_new,
myCount: myCount,
);

String _getPriceUrl(final String path) {
final UriProductHelper uriProductHelper = ProductQuery.uriProductHelper;
final Uri uri = Uri(
scheme: uriProductHelper.scheme,
host: uriProductHelper.getHost('prices'),
path: path,
);
return uri.toString();
}

Future<bool?> _confirmLogout() async => showDialog<bool>(
context: context,
builder: (BuildContext context) {
Expand Down
46 changes: 27 additions & 19 deletions packages/smooth_app/lib/pages/prices/price_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -76,28 +76,33 @@ class PriceModel with ChangeNotifier {
set paidPrice(final String value) => _paidPrice = value;
set priceWithoutDiscount(final String value) => _priceWithoutDiscount = value;

late Currency _checkedCurrency;
late double _checkedPaidPrice;
double? _checkedPriceWithoutDiscount;

double? validateDouble(final String value) =>
double.tryParse(value) ??
double.tryParse(
value.replaceAll(',', '.'),
);

Future<String?> addPrice(final BuildContext context) async {
/// Returns the error message of the parameter check, or null if OK.
Future<String?> checkParameters(final BuildContext context) async {
final AppLocalizations appLocalizations = AppLocalizations.of(context);
if (cropParameters == null) {
return appLocalizations.prices_proof_mandatory;
}

final UserPreferences userPreferences = context.read<UserPreferences>();
final Currency currency =
_checkedCurrency =
CurrencySelectorHelper().getSelected(userPreferences.userCurrencyCode);

final double paidPrice = validateDouble(_paidPrice)!;
double? priceWithoutDiscount;
_checkedPaidPrice = validateDouble(_paidPrice)!;
_checkedPriceWithoutDiscount = null;
if (promo) {
if (_priceWithoutDiscount.isNotEmpty) {
priceWithoutDiscount = validateDouble(_priceWithoutDiscount);
if (priceWithoutDiscount == null) {
_checkedPriceWithoutDiscount = validateDouble(_priceWithoutDiscount);
if (_checkedPriceWithoutDiscount == null) {
return appLocalizations.prices_amount_price_incorrect;
}
}
Expand All @@ -107,19 +112,22 @@ class PriceModel with ChangeNotifier {
return appLocalizations.prices_location_mandatory;
}

await BackgroundTaskAddPrice.addTask(
cropObject: cropParameters!,
locationOSMId: location!.osmId,
locationOSMType: location!.osmType,
date: date,
proofType: proofType,
currency: currency,
barcode: barcode,
priceIsDiscounted: promo,
price: paidPrice,
priceWithoutDiscount: priceWithoutDiscount,
context: context,
);
return null;
}

/// Adds the related background task.
Future<void> addTask(final BuildContext context) async =>
BackgroundTaskAddPrice.addTask(
cropObject: cropParameters!,
locationOSMId: location!.osmId,
locationOSMType: location!.osmType,
date: date,
proofType: proofType,
currency: _checkedCurrency,
barcode: barcode,
priceIsDiscounted: promo,
price: _checkedPaidPrice,
priceWithoutDiscount: _checkedPriceWithoutDiscount,
context: context,
);
}
51 changes: 50 additions & 1 deletion packages/smooth_app/lib/pages/prices/product_price_add_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:openfoodfacts/openfoodfacts.dart';
import 'package:provider/provider.dart';
import 'package:smooth_app/data_models/preferences/user_preferences.dart';
import 'package:smooth_app/database/dao_osm_location.dart';
import 'package:smooth_app/database/local_database.dart';
import 'package:smooth_app/generic_lib/design_constants.dart';
Expand Down Expand Up @@ -88,6 +89,12 @@ class _ProductPriceAddPageState extends State<ProductPriceAddPage> {
maxLines: 1,
),
subTitle: Text(widget.product.barcode!),
actions: <Widget>[
IconButton(
icon: const Icon(Icons.info),
onPressed: () async => _doesAcceptWarning(justInfo: true),
),
],
),
body: const SingleChildScrollView(
padding: EdgeInsets.all(LARGE_SPACE),
Expand Down Expand Up @@ -115,7 +122,7 @@ class _ProductPriceAddPageState extends State<ProductPriceAddPage> {

String? error;
try {
error = await _model.addPrice(context);
error = await _model.checkParameters(context);
} catch (e) {
error = e.toString();
}
Expand All @@ -136,6 +143,26 @@ class _ProductPriceAddPageState extends State<ProductPriceAddPage> {
if (!context.mounted) {
return;
}

final UserPreferences userPreferences =
context.read<UserPreferences>();
const String flagTag = UserPreferences.TAG_PRICE_PRIVACY_WARNING;
final bool? already = userPreferences.getFlag(flagTag);
if (already != true) {
final bool? accepts = await _doesAcceptWarning(justInfo: false);
if (accepts != true) {
return;
}
await userPreferences.setFlag(flagTag, true);
}
if (!context.mounted) {
return;
}

await _model.addTask(context);
if (!context.mounted) {
return;
}
Navigator.of(context).pop();
},
icon: const Icon(Icons.send),
Expand All @@ -145,4 +172,26 @@ class _ProductPriceAddPageState extends State<ProductPriceAddPage> {
),
);
}

Future<bool?> _doesAcceptWarning({required final bool justInfo}) async {
final AppLocalizations appLocalizations = AppLocalizations.of(context);
return showDialog<bool>(
context: context,
builder: (final BuildContext context) => SmoothAlertDialog(
title: appLocalizations.prices_privacy_warning_title,
actionsAxis: Axis.vertical,
body: Text(appLocalizations.prices_privacy_warning_message),
positiveAction: SmoothActionButton(
text: appLocalizations.okay,
onPressed: () => Navigator.of(context).pop(true),
),
negativeAction: justInfo
? null
: SmoothActionButton(
text: appLocalizations.cancel,
onPressed: () => Navigator.of(context).pop(),
),
),
);
}
}
17 changes: 7 additions & 10 deletions packages/smooth_app/lib/pages/prices/product_price_item.dart
Original file line number Diff line number Diff line change
Expand Up @@ -96,16 +96,13 @@ class ProductPriceItem extends StatelessWidget {
),
if (price.proof?.filePath != null)
ElevatedButton(
onPressed: () async {
final UriProductHelper uriProductHelper =
ProductQuery.uriProductHelper;
final Uri uri = Uri(
scheme: uriProductHelper.scheme,
host: uriProductHelper.getHost('prices'),
path: 'img/${price.proof?.filePath}',
);
return LaunchUrlHelper.launchURL(uri.toString());
},
onPressed: () async => LaunchUrlHelper.launchURL(
price.proof!
.getFileUrl(
uriProductHelper: ProductQuery.uriProductHelper,
)
.toString(),
),
child: const Icon(Icons.image),
),
],
Expand Down
14 changes: 5 additions & 9 deletions packages/smooth_app/lib/pages/prices/product_prices_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,12 @@ class _ProductPricesPageState extends State<ProductPricesPage>
IconButton(
tooltip: appLocalizations.prices_app_button,
icon: const Icon(Icons.open_in_new),
onPressed: () async {
final UriProductHelper uriProductHelper =
ProductQuery.uriProductHelper;
final Uri uri = Uri(
scheme: uriProductHelper.scheme,
host: uriProductHelper.getHost('prices'),
onPressed: () async => LaunchUrlHelper.launchURL(
OpenPricesAPIClient.getUri(
path: 'app/products/${upToDateProduct.barcode!}',
);
return LaunchUrlHelper.launchURL(uri.toString());
},
uriHelper: ProductQuery.uriProductHelper,
).toString(),
),
),
],
),
Expand Down
4 changes: 2 additions & 2 deletions packages/smooth_app/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1108,10 +1108,10 @@ packages:
dependency: "direct main"
description:
name: openfoodfacts
sha256: ab05acea8a91a4cef6cbed9064af261a8921c60c5cc253298d9024c1b0ff8674
sha256: "90a853e7536d0f97a665b18cd602055215520bf424765ef06930e4be25b760ba"
url: "https://pub.dev"
source: hosted
version: "3.10.0"
version: "3.11.0"
openfoodfacts_flutter_lints:
dependency: "direct dev"
description:
Expand Down
2 changes: 1 addition & 1 deletion packages/smooth_app/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ dependencies:
path: ../scanner/zxing


openfoodfacts: 3.10.0
openfoodfacts: 3.11.0
# openfoodfacts:
# path: ../../../openfoodfacts-dart

Expand Down

0 comments on commit e94d61f

Please sign in to comment.