Skip to content

Commit fbb34c7

Browse files
committed
[IMPROV] Mobile WEB camera selection should be better
1 parent f32aa4f commit fbb34c7

File tree

4 files changed

+51
-9
lines changed

4 files changed

+51
-9
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 2.0.10
2+
3+
- Improved back camera selection for WEB on mobile
4+
15
## 2.0.9+1
26

37
- Fix a bad import causing mobile builds to fail

lib/src/web/flutter_qr_web.dart

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -118,14 +118,49 @@ class _WebQrViewState extends State<WebQrView> {
118118
}
119119

120120
try {
121-
var constraints = UserMediaOptions(
122-
video: VideoOptions(
123-
facingMode: (facing == CameraFacing.front ? 'user' : 'environment'),
124-
));
125-
// dart style, not working properly:
126-
// var stream =
127-
// await html.window.navigator.mediaDevices.getUserMedia(constraints);
128-
// straight JS:
121+
final UserMediaOptions constraints;
122+
switch (facing) {
123+
case CameraFacing.front:
124+
constraints = UserMediaOptions(
125+
video: VideoOptions(facingMode: 'user'),
126+
);
127+
break;
128+
case CameraFacing.unknown:
129+
// fall through
130+
case CameraFacing.back:
131+
final List<web.MediaDeviceInfo> devices =
132+
(await enumerateDevices().toDart).toDart;
133+
134+
final List<web.MediaDeviceInfo> backCameras = devices
135+
.where(
136+
(device) =>
137+
device.kind == 'videoinput' &&
138+
device.label.toLowerCase().contains('back'),
139+
)
140+
.toList();
141+
142+
// attempt to find a main/primary camera. If none, use last back camera entry if it exists
143+
final web.MediaDeviceInfo? idealCameraMediaInfo = backCameras
144+
.where(
145+
(camera) =>
146+
camera.label.toLowerCase().contains('main') ||
147+
camera.label.toLowerCase().contains('primary'),
148+
)
149+
.lastOrNull ??
150+
backCameras.lastOrNull;
151+
152+
constraints = UserMediaOptions(
153+
video: idealCameraMediaInfo != null
154+
? VideoOptions(
155+
deviceId:
156+
DeviceIdOptions(exact: idealCameraMediaInfo.deviceId),
157+
)
158+
: VideoOptions(
159+
facingMode: "environment",
160+
),
161+
);
162+
}
163+
129164
if (_controller == null) {
130165
_controller = QRViewControllerWeb(this);
131166
widget.onPlatformViewCreated(_controller!);

lib/src/web/media.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ import 'package:web/web.dart' as web;
1010
@JS('getUserMedia')
1111
external JSPromise<web.MediaStream> getUserMedia(UserMediaOptions constraints);
1212

13+
@JS('enumerateDevices')
14+
external JSPromise<JSArray<web.MediaDeviceInfo>> enumerateDevices();
15+
1316
@JS()
1417
extension type UserMediaOptions._(JSObject _) implements JSObject {
1518
external VideoOptions? get video;

pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: qr_code_scanner_plus
22
description: QR code scanner that can be embedded inside flutter. It uses zxing in Android and MTBBarcode scanner in iOS.
3-
version: 2.0.9+1
3+
version: 2.0.10
44
homepage: https://vespr.xyz
55
repository: https://github.com/vespr-wallet/qr_code_scanner_plus
66

0 commit comments

Comments
 (0)