Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Shared common scanner #3883

Merged
merged 10 commits into from
Apr 18, 2023
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.224.3/containers/ubuntu
{
"image": "docker.io/cirrusci/flutter:beta",
"image": "docker.io/cirrusci/flutter:stable",
"forwardPorts": [
3000
],
"customizations": {
"vscode": {
"extensions": [
"Dart-Code.flutter"
"Dart-Code.flutter",
"dart-code.dart-code"
]
}
}
Expand Down
26 changes: 26 additions & 0 deletions packages/scanner/ml_kit/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
migrate_working_dir/

# IntelliJ related
*.iml
*.ipr
*.iws
.idea/


# Flutter/Dart/Pub related
# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
/pubspec.lock
**/doc/api/
.dart_tool/
.packages
build/
30 changes: 30 additions & 0 deletions packages/scanner/ml_kit/.metadata
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled.

version:
revision: eb6d86ee27deecba4a83536aa20f366a6044895c
channel: stable

project_type: plugin

# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: eb6d86ee27deecba4a83536aa20f366a6044895c
base_revision: eb6d86ee27deecba4a83536aa20f366a6044895c
- platform: android
create_revision: eb6d86ee27deecba4a83536aa20f366a6044895c
base_revision: eb6d86ee27deecba4a83536aa20f366a6044895c

# User provided section

# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'
2 changes: 2 additions & 0 deletions packages/scanner/ml_kit/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Shared rules
include: package:openfoodfacts_flutter_lints/flutter.yaml
3 changes: 3 additions & 0 deletions packages/scanner/ml_kit/lib/scanner_ml_kit.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
library app_store_uri;

export 'src/scanner_ml_kit.dart';
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,63 @@ import 'dart:async';

import 'package:flutter/material.dart';
import 'package:mobile_scanner/mobile_scanner.dart';
import 'package:smooth_app/generic_lib/design_constants.dart';
import 'package:smooth_app/helpers/analytics_helper.dart';
import 'package:smooth_app/helpers/camera_helper.dart';
import 'package:smooth_app/helpers/haptic_feedback_helper.dart';
import 'package:smooth_app/pages/scan/scan_header.dart';
import 'package:smooth_app/pages/scan/smooth_barcode_scanner_visor.dart';
import 'package:smooth_app/widgets/screen_visibility.dart';
import 'package:scanner_shared/scanner_shared.dart';
import 'package:visibility_detector/visibility_detector.dart';

/// Empty implementation for an [AppStore]
M123-dev marked this conversation as resolved.
Show resolved Hide resolved
class ScannerMLKit extends Scanner {
const ScannerMLKit();

@override
String getType() => 'ML Kit';

@override
Widget getScanner({
required Future<bool> Function(String) onScan,
required Future<void> Function() hapticFeedback,
required Function(BuildContext)? onCameraFlashError,
required Function(String msg, String category,
{int? eventValue, String? barcode})
trackCustomEvent,
required bool hasMoreThanOneCamera,
required Widget scanHeader,
}) {
return _SmoothBarcodeScannerMLKit(
onScan: onScan,
hapticFeedback: hapticFeedback,
trackCustomEvent: trackCustomEvent,
onCameraFlashError: onCameraFlashError,
hasMoreThanOneCamera: hasMoreThanOneCamera,
scanHeader: scanHeader,
);
}
}

/// Barcode scanner based on MLKit.
class SmoothBarcodeScannerMLKit extends StatefulWidget {
const SmoothBarcodeScannerMLKit(
this.onScan, {
this.onCameraFlashError,
class _SmoothBarcodeScannerMLKit extends StatefulWidget {
const _SmoothBarcodeScannerMLKit({
required this.onScan,
required this.hapticFeedback,
required this.trackCustomEvent,
required this.onCameraFlashError,
required this.hasMoreThanOneCamera,
required this.scanHeader,
});

final Future<bool> Function(String) onScan;
final Future<void> Function() hapticFeedback;

final Function(String msg, String category,
{int? eventValue, String? barcode}) trackCustomEvent;
final Function(BuildContext)? onCameraFlashError;
final bool hasMoreThanOneCamera;
final Widget scanHeader;

@override
State<StatefulWidget> createState() => _SmoothBarcodeScannerMLKitState();
}

class _SmoothBarcodeScannerMLKitState extends State<SmoothBarcodeScannerMLKit>
class _SmoothBarcodeScannerMLKitState extends State<_SmoothBarcodeScannerMLKit>
with SingleTickerProviderStateMixin {
// just 1D formats and ios supported
static const List<BarcodeFormat> _barcodeFormats = <BarcodeFormat>[
Expand All @@ -43,7 +76,7 @@ class _SmoothBarcodeScannerMLKitState extends State<SmoothBarcodeScannerMLKit>

bool _isStarted = true;

bool get _showFlipCameraButton => CameraHelper.hasMoreThanOneCamera;
bool get _showFlipCameraButton => widget.hasMoreThanOneCamera;

final MobileScannerController _controller = MobileScannerController(
torchEnabled: false,
Expand All @@ -67,9 +100,8 @@ class _SmoothBarcodeScannerMLKitState extends State<SmoothBarcodeScannerMLKit>
await _controller.start();
_isStarted = true;
} on Exception {
AnalyticsHelper.trackEvent(
AnalyticsEvent.scanStrangeRestart,
);
widget.trackCustomEvent(
Scanner.ANALYTICS_STRANGE_RESTART, Scanner.ANALYTICS_CATEGORY);
}
}

Expand All @@ -81,17 +113,16 @@ class _SmoothBarcodeScannerMLKitState extends State<SmoothBarcodeScannerMLKit>
await _controller.stop();
_isStarted = false;
} on Exception {
AnalyticsHelper.trackEvent(
AnalyticsEvent.scanStrangeRestop,
);
widget.trackCustomEvent(
Scanner.ANALYTICS_STRANGE_RESTOP, Scanner.ANALYTICS_CATEGORY);
}
}

@override
Widget build(BuildContext context) => VisibilityDetector(
key: const ValueKey<String>('VisibilityDetector'),
onVisibilityChanged: (final VisibilityInfo info) async {
if (info.visible) {
if (info.visibleBounds.height > 0.0) {
M123-dev marked this conversation as resolved.
Show resolved Hide resolved
await _start();
} else {
await _stop();
Expand All @@ -107,7 +138,7 @@ class _SmoothBarcodeScannerMLKitState extends State<SmoothBarcodeScannerMLKit>
MobileScannerException error,
Widget? child,
) =>
EMPTY_WIDGET,
const SizedBox.shrink(),
M123-dev marked this conversation as resolved.
Show resolved Hide resolved
onDetect: (final BarcodeCapture capture) async {
for (final Barcode barcode in capture.barcodes) {
final String? string = barcode.displayValue;
Expand All @@ -123,9 +154,9 @@ class _SmoothBarcodeScannerMLKitState extends State<SmoothBarcodeScannerMLKit>
child: SmoothBarcodeScannerVisor(),
),
),
const Align(
Align(
alignment: Alignment.topCenter,
child: ScanHeader(),
child: widget.scanHeader,
M123-dev marked this conversation as resolved.
Show resolved Hide resolved
),
Align(
alignment: Alignment.bottomCenter,
Expand Down Expand Up @@ -156,7 +187,7 @@ class _SmoothBarcodeScannerMLKitState extends State<SmoothBarcodeScannerMLKit>
},
),
onPressed: () async {
SmoothHapticFeedback.click();
widget.hapticFeedback.call();
await _controller.switchCamera();
},
),
Expand All @@ -168,7 +199,7 @@ class _SmoothBarcodeScannerMLKitState extends State<SmoothBarcodeScannerMLKit>
Widget? child,
) {
if (state != true) {
return EMPTY_WIDGET;
return const SizedBox.shrink();
}
return IconButton(
color: Colors.white,
Expand All @@ -194,7 +225,7 @@ class _SmoothBarcodeScannerMLKitState extends State<SmoothBarcodeScannerMLKit>
},
),
onPressed: () async {
SmoothHapticFeedback.click();
widget.hapticFeedback.call();

try {
await _controller.toggleTorch();
Expand Down
24 changes: 24 additions & 0 deletions packages/scanner/ml_kit/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: scanner_ml_kit
description: Scanner implementation using ML Kit
version: 1.0.0
publish_to: "none"

environment:
sdk: ">=2.19.0 <3.0.0"

dependencies:
flutter:
sdk: flutter

mobile_scanner: 3.2.0
scanner_shared:
path: ../shared

visibility_detector: 0.4.0+2

dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: 2.0.1
openfoodfacts_flutter_lints:
git: https://github.com/openfoodfacts/openfoodfacts_flutter_lints.git
8 changes: 8 additions & 0 deletions packages/scanner/ml_kit/test/scanner_zxing_test.dart
M123-dev marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import 'package:flutter_test/flutter_test.dart';

// The CI needs at least one test
void main() {
testWidgets('Fake test', (WidgetTester tester) async {
expect(true, true);
});
}
30 changes: 30 additions & 0 deletions packages/scanner/shared/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
migrate_working_dir/

# IntelliJ related
*.iml
*.ipr
*.iws
.idea/

# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/

# Flutter/Dart/Pub related
# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
/pubspec.lock
**/doc/api/
.dart_tool/
.packages
build/
10 changes: 10 additions & 0 deletions packages/scanner/shared/.metadata
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.

version:
revision: eb6d86ee27deecba4a83536aa20f366a6044895c
channel: stable

project_type: package
2 changes: 2 additions & 0 deletions packages/scanner/shared/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Shared rules
include: package:openfoodfacts_flutter_lints/flutter.yaml
5 changes: 5 additions & 0 deletions packages/scanner/shared/lib/scanner_shared.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
library app_store_shared;

export 'src/scanner.dart';
export 'src/scanner_mocked.dart';
export 'src/scanner_visor.dart';
23 changes: 23 additions & 0 deletions packages/scanner/shared/lib/src/scanner.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import 'package:flutter/material.dart';

/// Base class for the Scanner interface…
abstract class Scanner {
const Scanner();

static const String ANALYTICS_CATEGORY = 'scanning';
static const String ANALYTICS_STRANGE_RESTART = 'strange restart';
static const String ANALYTICS_STRANGE_RESTOP = 'strange restop';

String getType();

Widget getScanner({
required Future<bool> Function(String) onScan,
required Future<void> Function() hapticFeedback,
required Function(BuildContext)? onCameraFlashError,
required Function(String msg, String category,
{int? eventValue, String? barcode})
trackCustomEvent,
required bool hasMoreThanOneCamera,
required Widget scanHeader,
});
}
24 changes: 24 additions & 0 deletions packages/scanner/shared/lib/src/scanner_mocked.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import 'package:flutter/material.dart';

import 'package:scanner_shared/scanner_shared.dart';

/// Empty implementation for an [AppStore]
class MockedScanner extends Scanner {
const MockedScanner();

@override
String getType() => 'Mocked';

@override
Widget getScanner({
required Future<bool> Function(String) onScan,
required Future<void> Function() hapticFeedback,
required Function(BuildContext)? onCameraFlashError,
required Function(String msg, String category,
{int? eventValue, String? barcode})
trackCustomEvent,
required bool hasMoreThanOneCamera,
required Widget scanHeader,
}) =>
Container();
}
Loading