mirror of
https://github.com/openfoodfacts/smooth-app.git
synced 2025-08-06 18:25:11 +08:00
362 lines
14 KiB
Dart
362 lines
14 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_svg/flutter_svg.dart';
|
|
import 'package:openfoodfacts/openfoodfacts.dart';
|
|
import 'package:package_info_plus/package_info_plus.dart';
|
|
import 'package:smooth_app/cards/category_cards/svg_cache.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/helpers/app_helper.dart';
|
|
import 'package:smooth_app/helpers/global_vars.dart';
|
|
import 'package:smooth_app/helpers/launch_url_helper.dart';
|
|
import 'package:smooth_app/helpers/user_feedback_helper.dart';
|
|
import 'package:smooth_app/pages/guides/guide/guide_nutriscore_v2.dart';
|
|
import 'package:smooth_app/pages/preferences/abstract_user_preferences.dart';
|
|
import 'package:smooth_app/pages/preferences/user_preferences_item.dart';
|
|
import 'package:smooth_app/pages/preferences/user_preferences_list_tile.dart';
|
|
import 'package:smooth_app/pages/preferences/user_preferences_page.dart';
|
|
import 'package:smooth_app/query/product_query.dart';
|
|
|
|
/// Display of "FAQ" for the preferences page.
|
|
class UserPreferencesFaq extends AbstractUserPreferences {
|
|
UserPreferencesFaq({
|
|
required super.context,
|
|
required super.userPreferences,
|
|
required super.appLocalizations,
|
|
required super.themeData,
|
|
});
|
|
|
|
@override
|
|
PreferencePageType getPreferencePageType() => PreferencePageType.FAQ;
|
|
|
|
@override
|
|
String getTitleString() => appLocalizations.faq;
|
|
|
|
@override
|
|
IconData getLeadingIconData() => Icons.question_mark;
|
|
|
|
@override
|
|
String? getHeaderAsset() => 'assets/preferences/faq.svg';
|
|
|
|
@override
|
|
Color? getHeaderColor() => const Color(0xFFDFF7E8);
|
|
|
|
@override
|
|
List<UserPreferencesItem> getChildren() => <UserPreferencesItem>[
|
|
_getListTile(
|
|
title: appLocalizations.faq,
|
|
leadingIconData: Icons.question_mark,
|
|
url: _getFAQUrl(),
|
|
),
|
|
_getNutriListTile(
|
|
title: appLocalizations.nutriscore_generic,
|
|
url: 'https://world.openfoodfacts.org/nutriscore',
|
|
svg: SvgCache.getAssetsCacheForNutriscore(NutriScoreValue.b, false),
|
|
),
|
|
_getListTile(
|
|
title: appLocalizations.faq_nutriscore_nutriscore,
|
|
leadingSvg: SvgCache.getAssetsCacheForNutriscore(NutriScoreValue.b, true),
|
|
onTap: () => Navigator.of(context, rootNavigator: true).push(
|
|
MaterialPageRoute<void>(
|
|
builder: (BuildContext context) => const GuideNutriscoreV2(),
|
|
),
|
|
),
|
|
|
|
/// Hide the icon
|
|
icon: const Icon(Icons.info, size: 0.0),
|
|
),
|
|
_getNutriListTile(
|
|
title: appLocalizations.environmental_score_generic,
|
|
url: 'https://world.openfoodfacts.org/ecoscore',
|
|
svg: 'assets/cache/green-score-b.svg',
|
|
),
|
|
_getNutriListTile(
|
|
title: appLocalizations.nova_group_generic,
|
|
url: 'https://world.openfoodfacts.org/nova',
|
|
svg: 'assets/cache/nova-group-4.svg',
|
|
),
|
|
_getNutriListTile(
|
|
title: appLocalizations.nutrition_facts,
|
|
url: 'https://world.openfoodfacts.org/traffic-lights',
|
|
svg: 'assets/cache/low.svg',
|
|
leadingSvgWidth: 1.5 * DEFAULT_ICON_SIZE,
|
|
),
|
|
_getListTile(
|
|
title: appLocalizations.discover,
|
|
leadingIconData: Icons.travel_explore,
|
|
url: ProductQuery.replaceSubdomain(
|
|
'https://world.openfoodfacts.org/discover',
|
|
),
|
|
),
|
|
_getListTile(
|
|
title: appLocalizations.how_to_contribute,
|
|
leadingIconData: Icons.volunteer_activism,
|
|
url: ProductQuery.replaceSubdomain(
|
|
'https://world.openfoodfacts.org/contribute',
|
|
),
|
|
),
|
|
_getListTile(
|
|
title: appLocalizations.feed_back,
|
|
leadingIconData: Icons.add_comment,
|
|
url: UserFeedbackHelper.getFeedbackFormLink(),
|
|
),
|
|
_getListTile(
|
|
title: appLocalizations.faq_title_partners,
|
|
leadingIconData: Icons.handshake_outlined,
|
|
url: ProductQuery.replaceSubdomain(
|
|
'https://world.openfoodfacts.org/partners',
|
|
),
|
|
),
|
|
_getListTile(
|
|
title: appLocalizations.faq_title_vision,
|
|
leadingIconData: Icons.remove_red_eye_outlined,
|
|
url: ProductQuery.replaceSubdomain(
|
|
'https://world.openfoodfacts.org/open-food-facts-vision-mission-values-and-programs',
|
|
),
|
|
),
|
|
/*
|
|
// temporarily (?) hiding "install OxF" links
|
|
// cf. https://github.com/openfoodfacts/smooth-app/issues/6413
|
|
if (Platform.isAndroid || Platform.isIOS)
|
|
_getListTile(
|
|
title: appLocalizations.faq_title_install_beauty,
|
|
// for the record those svg files were edited, because svg flutter
|
|
// does not support the styles
|
|
// eg. <style>.b{fill:#008c8c;}.c{fill:#fff;}</style> is not taken into account
|
|
// and the initial rect creates a background we don't need
|
|
leadingSvg: _isDark
|
|
? 'assets/app/RVB_ICON_BLACK_BG_OBF.svg'
|
|
: 'assets/app/RVB_ICON_WHITE_BG_OBF.svg',
|
|
url: Platform.isAndroid
|
|
? 'https://play.google.com/store/apps/details?id=org.openbeautyfacts.scanner&hl=${ProductQuery.getLanguage().offTag}'
|
|
: 'https://apps.apple.com/${ProductQuery.getLanguage().offTag}/app/open-beauty-facts/id1122926380',
|
|
),
|
|
if (Platform.isAndroid)
|
|
_getListTile(
|
|
title: appLocalizations.faq_title_install_pet,
|
|
leadingSvg: _isDark
|
|
? 'assets/app/RVB_ICON_BLACK_BG_OPFF.svg'
|
|
: 'assets/app/RVB_ICON_WHITE_BG_OPFF.svg',
|
|
url:
|
|
'https://play.google.com/store/apps/details?id=org.openpetfoodfacts.scanner&hl=${ProductQuery.getLanguage().offTag}',
|
|
),
|
|
if (Platform.isAndroid)
|
|
_getListTile(
|
|
title: appLocalizations.faq_title_install_product,
|
|
leadingSvg: _isDark
|
|
? 'assets/app/RVB_ICON_BLACK_BG_OPF.svg'
|
|
: 'assets/app/RVB_ICON_WHITE_BG_OPF.svg',
|
|
url:
|
|
'https://play.google.com/store/apps/details?id=org.openproductsfacts.scanner&hl=${ProductQuery.getLanguage().offTag}',
|
|
),
|
|
*/
|
|
_getListTile(
|
|
title: appLocalizations.about_this_app,
|
|
leadingIconData: Icons.info,
|
|
onTap: () async => _about(),
|
|
icon: getForwardIcon(),
|
|
),
|
|
];
|
|
|
|
UserPreferencesItem _getListTile({
|
|
required final String title,
|
|
final IconData? leadingIconData,
|
|
final String? leadingSvg,
|
|
final double? leadingSvgWidth,
|
|
final String? url,
|
|
final VoidCallback? onTap,
|
|
final Icon? icon,
|
|
}) => UserPreferencesItemSimple(
|
|
labels: <String>[title],
|
|
builder: (_) => UserPreferencesListTile(
|
|
title: Text(title),
|
|
onTap:
|
|
onTap ??
|
|
() async =>
|
|
LaunchUrlHelper.launchURLInWebViewOrBrowser(context, url!),
|
|
trailing:
|
|
icon ??
|
|
UserPreferencesListTile.getTintedIcon(Icons.open_in_new, context),
|
|
leading: SizedBox(
|
|
width: 2 * DEFAULT_ICON_SIZE,
|
|
height: 2 * DEFAULT_ICON_SIZE,
|
|
child: Center(
|
|
child: leadingIconData != null
|
|
? UserPreferencesListTile.getTintedIcon(leadingIconData, context)
|
|
: leadingSvg == null
|
|
? null
|
|
: SvgPicture.asset(
|
|
leadingSvg,
|
|
width: leadingSvgWidth ?? 2 * DEFAULT_ICON_SIZE,
|
|
package: AppHelper.APP_PACKAGE,
|
|
),
|
|
),
|
|
),
|
|
externalLink: url != null,
|
|
),
|
|
);
|
|
|
|
UserPreferencesItem _getNutriListTile({
|
|
required final String title,
|
|
required final String url,
|
|
required final String svg,
|
|
final double? leadingSvgWidth,
|
|
}) => _getListTile(
|
|
title: title,
|
|
leadingSvg: svg,
|
|
leadingSvgWidth: leadingSvgWidth,
|
|
url: ProductQuery.replaceSubdomain(url),
|
|
);
|
|
|
|
static const String _iconLightAssetPath =
|
|
'assets/app/release_icon_light_transparent_no_border.svg';
|
|
static const String _iconDarkAssetPath =
|
|
'assets/app/release_icon_dark_transparent_no_border.svg';
|
|
|
|
Future<void> _about() async {
|
|
final PackageInfo packageInfo = await PackageInfo.fromPlatform();
|
|
if (!context.mounted) {
|
|
return;
|
|
}
|
|
showDialog<void>(
|
|
context: context,
|
|
builder: (BuildContext context) {
|
|
final String logo = Theme.of(context).brightness == Brightness.light
|
|
? _iconLightAssetPath
|
|
: _iconDarkAssetPath;
|
|
|
|
return SmoothAlertDialog(
|
|
body: Column(
|
|
children: <Widget>[
|
|
Row(
|
|
children: <Widget>[
|
|
SvgPicture.asset(
|
|
logo,
|
|
width: MediaQuery.sizeOf(context).width * 0.1,
|
|
package: AppHelper.APP_PACKAGE,
|
|
),
|
|
const SizedBox(width: SMALL_SPACE),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: <Widget>[
|
|
FittedBox(
|
|
child: Text(
|
|
packageInfo.appName,
|
|
style: themeData.textTheme.displayLarge,
|
|
),
|
|
),
|
|
Text(
|
|
'${packageInfo.version}+${packageInfo.buildNumber}-${GlobalVars.scannerLabel.name}-${GlobalVars.storeLabel.name}',
|
|
style: themeData.textTheme.titleSmall,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(height: VERY_LARGE_SPACE),
|
|
SingleChildScrollView(
|
|
child: IconTheme(
|
|
data: const IconThemeData(size: 16.0),
|
|
child: Column(
|
|
children: <Widget>[
|
|
FractionallySizedBox(
|
|
widthFactor: 0.9,
|
|
child: Text(appLocalizations.whatIsOff),
|
|
),
|
|
const SizedBox(height: VERY_SMALL_SPACE),
|
|
SmoothAlertContentButton(
|
|
onPressed: () async =>
|
|
LaunchUrlHelper.launchURLInWebViewOrBrowser(
|
|
context,
|
|
ProductQuery.replaceSubdomain(
|
|
'https://world.openfoodfacts.org/who-we-are',
|
|
),
|
|
),
|
|
label: appLocalizations.learnMore,
|
|
icon: Icons.open_in_new,
|
|
),
|
|
const SizedBox(height: VERY_SMALL_SPACE),
|
|
SmoothAlertContentButton(
|
|
onPressed: () async =>
|
|
LaunchUrlHelper.launchURLInWebViewOrBrowser(
|
|
context,
|
|
ProductQuery.replaceSubdomain(
|
|
'https://world.openfoodfacts.org/terms-of-use',
|
|
),
|
|
),
|
|
label: appLocalizations.termsOfUse,
|
|
icon: Icons.open_in_new,
|
|
),
|
|
const SizedBox(height: VERY_SMALL_SPACE),
|
|
SmoothAlertContentButton(
|
|
onPressed: () async =>
|
|
LaunchUrlHelper.launchURLInWebViewOrBrowser(
|
|
context,
|
|
ProductQuery.replaceSubdomain(
|
|
'https://world.openfoodfacts.org/legal',
|
|
),
|
|
),
|
|
label: appLocalizations.legalNotices,
|
|
icon: Icons.open_in_new,
|
|
),
|
|
const SizedBox(height: VERY_SMALL_SPACE),
|
|
SmoothAlertContentButton(
|
|
onPressed: () =>
|
|
LaunchUrlHelper.launchURLInWebViewOrBrowser(
|
|
context,
|
|
ProductQuery.replaceSubdomain(
|
|
'https://world.openfoodfacts.org/privacy',
|
|
),
|
|
),
|
|
label: appLocalizations.privacy_policy,
|
|
icon: Icons.open_in_new,
|
|
),
|
|
const SizedBox(height: VERY_SMALL_SPACE),
|
|
SmoothAlertContentButton(
|
|
onPressed: () => showLicensePage(
|
|
context: context,
|
|
applicationName: packageInfo.appName,
|
|
applicationVersion: packageInfo.version,
|
|
applicationIcon: SvgPicture.asset(
|
|
logo,
|
|
height: MediaQuery.sizeOf(context).height * 0.1,
|
|
),
|
|
),
|
|
label: appLocalizations.licenses,
|
|
icon: Icons.info,
|
|
),
|
|
const SizedBox(height: SMALL_SPACE),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
negativeAction: SmoothActionButton(
|
|
onPressed: () => Navigator.of(context, rootNavigator: true).pop(),
|
|
text: appLocalizations.close,
|
|
),
|
|
);
|
|
},
|
|
);
|
|
}
|
|
|
|
String _getFAQUrl() {
|
|
final OpenFoodFactsLanguage language = ProductQuery.getLanguage();
|
|
|
|
// TODO(teolemon): regularly check for additional translations
|
|
return switch (language) {
|
|
OpenFoodFactsLanguage.FRENCH =>
|
|
'https://support.openfoodfacts.org/help/fr-fr',
|
|
OpenFoodFactsLanguage.ITALIAN =>
|
|
'https://support.openfoodfacts.org/help/it-it',
|
|
OpenFoodFactsLanguage.GERMAN =>
|
|
'https://support.openfoodfacts.org/help/de-de',
|
|
OpenFoodFactsLanguage.SPANISH =>
|
|
'https://support.openfoodfacts.org/help/es-es',
|
|
_ => 'https://support.openfoodfacts.org/help',
|
|
};
|
|
}
|
|
}
|