Skip to content
This repository has been archived by the owner on Feb 22, 2023. It is now read-only.

Commit

Permalink
[camera_web] Add support for pausing and resuming the camera preview (#…
Browse files Browse the repository at this point in the history
…4239)

* chore: update camera_platform_interface to 2.1.0
* feat: add pause to Camera
* test: add Camera pause test
* feat: add pausePreview and resumePreview implementation
* test: add pausePreview and resumePreview tests
  • Loading branch information
bselwe authored Aug 13, 2021
1 parent c8570fc commit ebf4d59
Show file tree
Hide file tree
Showing 5 changed files with 210 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,24 @@ void main() {
});
});

group('pause', () {
testWidgets('pauses the camera stream', (tester) async {
final camera = Camera(
textureId: textureId,
cameraService: cameraService,
);

await camera.initialize();
await camera.play();

expect(camera.videoElement.paused, isFalse);

camera.pause();

expect(camera.videoElement.paused, isTrue);
});
});

group('stop', () {
testWidgets('resets the camera stream', (tester) async {
final camera = Camera(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1459,6 +1459,135 @@ void main() {
});
});

group('pausePreview', () {
testWidgets('calls pause on the camera', (tester) async {
final camera = MockCamera();

// Save the camera in the camera plugin.
(CameraPlatform.instance as CameraPlugin).cameras[cameraId] = camera;

await CameraPlatform.instance.pausePreview(cameraId);

verify(camera.pause).called(1);
});

group('throws PlatformException', () {
testWidgets(
'with notFound error '
'if the camera does not exist', (tester) async {
expect(
() async => await CameraPlatform.instance.pausePreview(cameraId),
throwsA(
isA<PlatformException>().having(
(e) => e.code,
'code',
CameraErrorCode.notFound.toString(),
),
),
);
});

testWidgets('when pause throws DomException', (tester) async {
final camera = MockCamera();
final exception = FakeDomException(DomException.NOT_SUPPORTED);

when(camera.pause).thenThrow(exception);

// Save the camera in the camera plugin.
(CameraPlatform.instance as CameraPlugin).cameras[cameraId] = camera;

expect(
() async => await CameraPlatform.instance.pausePreview(cameraId),
throwsA(
isA<PlatformException>().having(
(e) => e.code,
'code',
exception.name,
),
),
);
});
});
});

group('resumePreview', () {
testWidgets('calls play on the camera', (tester) async {
final camera = MockCamera();

when(camera.play).thenAnswer((_) async => {});

// Save the camera in the camera plugin.
(CameraPlatform.instance as CameraPlugin).cameras[cameraId] = camera;

await CameraPlatform.instance.resumePreview(cameraId);

verify(camera.play).called(1);
});

group('throws PlatformException', () {
testWidgets(
'with notFound error '
'if the camera does not exist', (tester) async {
expect(
() async => await CameraPlatform.instance.resumePreview(cameraId),
throwsA(
isA<PlatformException>().having(
(e) => e.code,
'code',
CameraErrorCode.notFound.toString(),
),
),
);
});

testWidgets('when play throws DomException', (tester) async {
final camera = MockCamera();
final exception = FakeDomException(DomException.NOT_SUPPORTED);

when(camera.play).thenThrow(exception);

// Save the camera in the camera plugin.
(CameraPlatform.instance as CameraPlugin).cameras[cameraId] = camera;

expect(
() async => await CameraPlatform.instance.resumePreview(cameraId),
throwsA(
isA<PlatformException>().having(
(e) => e.code,
'code',
exception.name,
),
),
);
});

testWidgets('when play throws CameraWebException', (tester) async {
final camera = MockCamera();
final exception = CameraWebException(
cameraId,
CameraErrorCode.unknown,
'description',
);

when(camera.play).thenThrow(exception);

// Save the camera in the camera plugin.
(CameraPlatform.instance as CameraPlugin).cameras[cameraId] = camera;

expect(
() async => await CameraPlatform.instance.resumePreview(cameraId),
throwsA(
isA<PlatformException>().having(
(e) => e.code,
'code',
exception.code.toString(),
),
),
);
});
});
});

testWidgets(
'buildPreview returns an HtmlElementView '
'with an appropriate view type', (tester) async {
Expand Down Expand Up @@ -1993,6 +2122,42 @@ void main() {

await streamQueue.cancel();
});

testWidgets(
'emits a CameraErrorEvent '
'on resumePreview error', (tester) async {
final exception = CameraWebException(
cameraId,
CameraErrorCode.unknown,
'description',
);

when(camera.play).thenThrow(exception);

final Stream<CameraErrorEvent> eventStream =
CameraPlatform.instance.onCameraError(cameraId);

final streamQueue = StreamQueue(eventStream);

expect(
() async => await CameraPlatform.instance.resumePreview(cameraId),
throwsA(
isA<PlatformException>(),
),
);

expect(
await streamQueue.next,
equals(
CameraErrorEvent(
cameraId,
'Error code: ${exception.code}, error message: ${exception.description}',
),
),
);

await streamQueue.cancel();
});
});

testWidgets('onVideoRecordedEvent throws UnimplementedError',
Expand Down
5 changes: 5 additions & 0 deletions packages/camera/camera_web/lib/src/camera.dart
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,11 @@ class Camera {
await videoElement.play();
}

/// Pauses the camera stream on the current frame.
void pause() async {
videoElement.pause();
}

/// Stops the camera stream and resets the camera source.
void stop() {
final tracks = videoElement.srcObject?.getTracks();
Expand Down
21 changes: 21 additions & 0 deletions packages/camera/camera_web/lib/src/camera_web.dart
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,27 @@ class CameraPlugin extends CameraPlatform {
}
}

@override
Future<void> pausePreview(int cameraId) async {
try {
getCamera(cameraId).pause();
} on html.DomException catch (e) {
throw PlatformException(code: e.name, message: e.message);
}
}

@override
Future<void> resumePreview(int cameraId) async {
try {
await getCamera(cameraId).play();
} on html.DomException catch (e) {
throw PlatformException(code: e.name, message: e.message);
} on CameraWebException catch (e) {
_addCameraErrorEvent(e);
throw PlatformException(code: e.code.toString(), message: e.description);
}
}

@override
Widget buildPreview(int cameraId) {
return HtmlElementView(
Expand Down
2 changes: 1 addition & 1 deletion packages/camera/camera_web/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ flutter:
fileName: camera_web.dart

dependencies:
camera_platform_interface: ^2.0.1
camera_platform_interface: ^2.1.0
flutter:
sdk: flutter
flutter_web_plugins:
Expand Down

0 comments on commit ebf4d59

Please sign in to comment.