fix: Camera fix (#946)

Co-authored-by: monsieurtanuki <fabrice_fontaine@hotmail.com>
This commit is contained in:
Marvin M
2022-01-13 20:12:43 +01:00
committed by GitHub
parent 7e1f1752b2
commit 120bc180c6
13 changed files with 117 additions and 64 deletions

View File

@ -1,7 +1,6 @@
import 'dart:math'; import 'dart:math';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/painting.dart';
import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart'; import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart';
import 'package:openfoodfacts/model/KnowledgePanel.dart'; import 'package:openfoodfacts/model/KnowledgePanel.dart';
import 'package:openfoodfacts/model/KnowledgePanelElement.dart'; import 'package:openfoodfacts/model/KnowledgePanelElement.dart';

View File

@ -1,4 +1,3 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:openfoodfacts/model/Product.dart'; import 'package:openfoodfacts/model/Product.dart';

View File

@ -1,4 +1,3 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:openfoodfacts/model/Product.dart'; import 'package:openfoodfacts/model/Product.dart';

View File

@ -1,6 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:openfoodfacts/model/Product.dart';
import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:openfoodfacts/openfoodfacts.dart';
import 'package:smooth_app/cards/product_cards/product_image_carousel.dart'; import 'package:smooth_app/cards/product_cards/product_image_carousel.dart';
import 'package:smooth_app/cards/product_cards/product_title_card.dart'; import 'package:smooth_app/cards/product_cards/product_title_card.dart';

View File

@ -24,6 +24,7 @@ class UserPreferences extends ChangeNotifier {
'lastVisitedOnboardingPage'; 'lastVisitedOnboardingPage';
static const String _TAG_PREFIX_FLAG = 'FLAG_PREFIX_'; static const String _TAG_PREFIX_FLAG = 'FLAG_PREFIX_';
static const String _TAG_DEV_MODE = 'devMode'; static const String _TAG_DEV_MODE = 'devMode';
static const String _TAG_CAMERA_DECLINE = 'declined_camera_use_once';
Future<void> init(final ProductPreferences productPreferences) async { Future<void> init(final ProductPreferences productPreferences) async {
if (_sharedPreferences.getBool(_TAG_INIT) != null) { if (_sharedPreferences.getBool(_TAG_INIT) != null) {
@ -80,6 +81,13 @@ class UserPreferences extends ChangeNotifier {
: OnboardingPage.values[pageIndex]; : OnboardingPage.values[pageIndex];
} }
Future<void> setCameraDecline(final bool declined) async {
_sharedPreferences.setBool(_TAG_CAMERA_DECLINE, declined);
}
bool get cameraDeclinedOnce =>
_sharedPreferences.getBool(_TAG_CAMERA_DECLINE) ?? false;
String _getFlagTag(final String key) => _TAG_PREFIX_FLAG + key; String _getFlagTag(final String key) => _TAG_PREFIX_FLAG + key;
Future<void> setFlag( Future<void> setFlag(

View File

@ -1,6 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:openfoodfacts/model/OrderedNutrients.dart'; import 'package:openfoodfacts/model/OrderedNutrients.dart';
import 'package:openfoodfacts/model/Product.dart';
import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:openfoodfacts/openfoodfacts.dart';
import 'package:openfoodfacts/utils/CountryHelper.dart'; import 'package:openfoodfacts/utils/CountryHelper.dart';
import 'package:smooth_app/database/product_query.dart'; import 'package:smooth_app/database/product_query.dart';

View File

@ -6,7 +6,6 @@ import 'package:openfoodfacts/interface/JsonObject.dart';
import 'package:openfoodfacts/model/Nutriments.dart'; import 'package:openfoodfacts/model/Nutriments.dart';
import 'package:openfoodfacts/model/OrderedNutrient.dart'; import 'package:openfoodfacts/model/OrderedNutrient.dart';
import 'package:openfoodfacts/model/OrderedNutrients.dart'; import 'package:openfoodfacts/model/OrderedNutrients.dart';
import 'package:openfoodfacts/model/Product.dart';
import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:openfoodfacts/openfoodfacts.dart';
import 'package:openfoodfacts/utils/UnitHelper.dart'; import 'package:openfoodfacts/utils/UnitHelper.dart';
import 'package:smooth_app/database/product_query.dart'; import 'package:smooth_app/database/product_query.dart';

View File

@ -1,9 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:openfoodfacts/model/Attribute.dart'; import 'package:openfoodfacts/model/Attribute.dart';
import 'package:openfoodfacts/model/AttributeGroup.dart'; import 'package:openfoodfacts/model/AttributeGroup.dart';
import 'package:openfoodfacts/model/Product.dart';
import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:openfoodfacts/openfoodfacts.dart';
import 'package:openfoodfacts/personalized_search/preference_importance.dart'; import 'package:openfoodfacts/personalized_search/preference_importance.dart';
import 'package:smooth_app/cards/data_cards/score_card.dart'; import 'package:smooth_app/cards/data_cards/score_card.dart';

View File

@ -35,31 +35,37 @@ class _ContinuousScanPageState extends State<ContinuousScanPage> {
final double carouselHeight = constraints.maxHeight / final double carouselHeight = constraints.maxHeight /
1.81; // roughly 55% of the available height 1.81; // roughly 55% of the available height
final double viewFinderBottomOffset = carouselHeight / 2.0; final double viewFinderBottomOffset = carouselHeight / 2.0;
final List<Widget> children = getScannerWidgets(
context,
constraints,
_model,
);
//Insert scanner at the right position
children.insert(
1,
SmoothRevealAnimation(
delay: 400,
startOffset: Offset.zero,
animationCurve: Curves.easeInOutBack,
child: QRView(
overlay: QrScannerOverlayShape(
// We use [SmoothViewFinder] instead of the overlay.
overlayColor: Colors.transparent,
// This offset adjusts the scanning area on iOS.
cutOutBottomOffset: viewFinderBottomOffset,
),
key: _scannerViewKey,
onQRViewCreated: setupScanner,
),
),
);
return Scaffold( return Scaffold(
appBar: AppBar(toolbarHeight: 0.0), appBar: AppBar(toolbarHeight: 0.0),
body: Stack( body: Stack(
children: <Widget>[ children: children,
SmoothRevealAnimation(
delay: 400,
startOffset: Offset.zero,
animationCurve: Curves.easeInOutBack,
child: QRView(
overlay: QrScannerOverlayShape(
// We use [SmoothViewFinder] instead of the overlay.
overlayColor: Colors.transparent,
// This offset adjusts the scanning area on iOS.
cutOutBottomOffset: viewFinderBottomOffset,
),
key: _scannerViewKey,
onQRViewCreated: setupScanner,
),
),
...getScannerWidgets(
context,
constraints,
_model,
),
],
), ),
); );
}, },

View File

@ -102,28 +102,33 @@ class MLKitScannerPageState extends State<MLKitScannerPage> {
return LayoutBuilder( return LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) { builder: (BuildContext context, BoxConstraints constraints) {
return Stack( final List<Widget> children = getScannerWidgets(
fit: StackFit.expand, context,
children: <Widget>[ constraints,
SmoothRevealAnimation( _model,
delay: 400, );
startOffset: Offset.zero,
animationCurve: Curves.easeInOutBack, //Inserting the scanner at the right position
child: Transform.scale( children.insert(
scale: scale, 1,
child: Center( SmoothRevealAnimation(
child: CameraPreview( delay: 400,
_controller!, startOffset: Offset.zero,
), animationCurve: Curves.easeInOutBack,
child: Transform.scale(
scale: scale,
child: Center(
child: CameraPreview(
_controller!,
), ),
), ),
), ),
...getScannerWidgets( ),
context, );
constraints,
_model, return Stack(
), fit: StackFit.expand,
], children: children,
); );
}, },
); );

View File

@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:smooth_app/data_models/continuous_scan_model.dart'; import 'package:smooth_app/data_models/continuous_scan_model.dart';
import 'package:smooth_app/data_models/user_preferences.dart'; import 'package:smooth_app/data_models/user_preferences.dart';
@ -33,6 +34,24 @@ class _ScanPageState extends State<ScanPage> {
setState(() {}); setState(() {});
} }
Future<PermissionStatus> _permissionCheck(
UserPreferences userPreferences) async {
final PermissionStatus status = await Permission.camera.status;
//If is denied, is not restricted by for example parental control and is not already declined once
if (status.isDenied &&
!status.isRestricted &&
!userPreferences.cameraDeclinedOnce) {
final PermissionStatus newStatus = await Permission.camera.request();
if (!newStatus.isGranted && !newStatus.isLimited) {
userPreferences.setCameraDecline(true);
}
return newStatus;
} else {
return status;
}
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final UserPreferences userPreferences = context.read<UserPreferences>(); final UserPreferences userPreferences = context.read<UserPreferences>();
@ -40,20 +59,43 @@ class _ScanPageState extends State<ScanPage> {
return const Center(child: CircularProgressIndicator()); return const Center(child: CircularProgressIndicator());
} }
final Widget child; return FutureBuilder<PermissionStatus>(
future: _permissionCheck(userPreferences),
builder: (
BuildContext context,
AsyncSnapshot<PermissionStatus> snapshot,
) {
if (!snapshot.hasData) {
return const Center(child: CircularProgressIndicator());
} else if (snapshot.hasError) {
return const Center(child: Text('Error'));
}
if (userPreferences.getFlag( // TODO(M123): show no camera access screen
UserPreferencesDevMode.userPreferencesFlagUseMLKit, if (snapshot.data!.isDenied ||
) ?? snapshot.data!.isPermanentlyDenied ||
true) { snapshot.data!.isRestricted) {
child = const MLKitScannerPage(); const Center(
} else { child: Text('No camera access granted'),
child = const ContinuousScanPage(); );
} }
return ChangeNotifierProvider<ContinuousScanModel>( final Widget child;
create: (BuildContext context) => _model!,
child: child, if (userPreferences.getFlag(
UserPreferencesDevMode.userPreferencesFlagUseMLKit,
) ??
true) {
child = const MLKitScannerPage();
} else {
child = const ContinuousScanPage();
}
return ChangeNotifierProvider<ContinuousScanModel>(
create: (BuildContext context) => _model!,
child: child,
);
},
); );
} }
} }

View File

@ -96,8 +96,8 @@ List<Widget> getScannerWidgets(
padding: qrScannerPadding, padding: qrScannerPadding,
child: SvgPicture.asset( child: SvgPicture.asset(
'assets/actions/scanner_alt_2.svg', 'assets/actions/scanner_alt_2.svg',
width: 60.0, width: scannerSize.width,
height: 6, height: scannerSize.height,
color: Colors.white, color: Colors.white,
), ),
), ),

View File

@ -29,10 +29,10 @@ dependencies:
matomo: ^1.1.0 matomo: ^1.1.0
modal_bottom_sheet: ^2.0.0 modal_bottom_sheet: ^2.0.0
openfoodfacts: ^1.10.0 openfoodfacts: ^1.10.0
# Uncomment those lines if you want to use a local version of the openfoodfacts package
# openfoodfacts: # openfoodfacts:
# path: ../../../openfoodfacts-dart # path: ../../../openfoodfacts-dart
package_info_plus: ^1.3.0 package_info_plus: ^1.3.0
permission_handler: ^8.3.0
photo_view: ^0.13.0 photo_view: ^0.13.0
provider: ^6.0.2 provider: ^6.0.2
qr_code_scanner: ^0.6.1 qr_code_scanner: ^0.6.1