forked from flutter/photobooth
-
Notifications
You must be signed in to change notification settings - Fork 5
feat(camera_web): add camera options #2
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
Closed
bselwe
wants to merge
12
commits into
feat/use-flutter-camera-platform-interface
from
feat/camera-options
Closed
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
f6b20c7
feat: add camera options
bselwe 2d1f830
test: add camera options tests
bselwe 9e40a07
refactor: rename constrain to constraint
bselwe 631587a
docs: add camera options comments
bselwe 4aafe91
docs: update camera options comments
bselwe 4d62678
test: update camera options tests
bselwe df619dc
refactor: remove unnecessary async toJson
bselwe f2f347b
refactor: add Constraint suffix to FacingMode and VideoSize
bselwe 12effbb
refactor: make CameraType a class rather than an enum
bselwe 3a28a8d
refactor: remove Constraint in favor of two FacingModeConstraint cons…
bselwe 026e73d
fix: FacingModeConstraint toJson
bselwe 50b2c00
refactor: remove enabled video constraint
bselwe File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
150 changes: 150 additions & 0 deletions
150
packages/camera/camera_web/lib/src/types/camera_options.dart
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,150 @@ | ||
| /// Options used to create a camera with the given | ||
| /// [audio] and [video] media constraints. | ||
| /// | ||
| /// These options represent web `MediaStreamConstraints` | ||
| /// and can be used to request the browser for media streams | ||
| /// with the requested types of media. | ||
| /// | ||
| /// https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamConstraints | ||
| class CameraOptions { | ||
| /// Creates a new instance of [CameraOptions] | ||
| /// with the given [audio] and [video] constraints. | ||
| const CameraOptions({ | ||
| AudioConstraints? audio, | ||
| VideoConstraints? video, | ||
| }) : audio = audio ?? const AudioConstraints(), | ||
| video = video ?? const VideoConstraints(); | ||
|
|
||
| final AudioConstraints audio; | ||
| final VideoConstraints video; | ||
|
|
||
| Map<String, dynamic> toJson() { | ||
| return { | ||
| 'audio': audio.toJson(), | ||
| 'video': video.toJson(), | ||
| }; | ||
| } | ||
| } | ||
|
|
||
| /// The camera type used in [FacingModeConstraint]. | ||
| /// | ||
| /// Specifies whether the requested camera should be facing away | ||
| /// or toward the user. | ||
| class CameraType { | ||
| const CameraType._(this._type); | ||
|
|
||
| final String _type; | ||
|
|
||
| @override | ||
| String toString() => _type; | ||
|
|
||
| /// The camera is facing away from the user, viewing their environment. | ||
| /// This includes the back camera on a smartphone. | ||
| static const CameraType environment = CameraType._('environment'); | ||
|
|
||
| /// The camera is facing toward the user. | ||
| /// This includes the front camera on a smartphone. | ||
| static const CameraType user = CameraType._('user'); | ||
| } | ||
|
|
||
| /// Indicates the direction in which the desired camera should be pointing. | ||
| class FacingModeConstraint { | ||
| /// Creates a new instance of [FacingModeConstraint] | ||
| /// with the given [ideal] and [exact] constraints. | ||
| const FacingModeConstraint._({this.ideal, this.exact}); | ||
|
|
||
| /// Creates a new instance of [FacingModeConstraint] | ||
| /// with [ideal] constraint set to [type]. | ||
| /// | ||
| /// If this constraint is used, then the camera would ideally have | ||
| /// the desired facing [type] but it may be considered optional. | ||
| factory FacingModeConstraint(CameraType type) => | ||
| FacingModeConstraint._(ideal: type); | ||
|
|
||
| /// Creates a new instance of [FacingModeConstraint] | ||
| /// with [exact] constraint set to [type]. | ||
| /// | ||
| /// If this constraint is used, then the camera must have | ||
| /// the desired facing [type] to be considered acceptable. | ||
| factory FacingModeConstraint.exact(CameraType type) => | ||
| FacingModeConstraint._(exact: type); | ||
|
|
||
| final CameraType? ideal; | ||
| final CameraType? exact; | ||
|
|
||
| Object? toJson() { | ||
| return { | ||
| if (ideal != null) 'ideal': ideal.toString(), | ||
| if (exact != null) 'exact': exact.toString(), | ||
| }; | ||
| } | ||
| } | ||
|
|
||
| /// Indicates whether the audio track is requested. | ||
| /// | ||
| /// By default, the audio track is not requested. | ||
| class AudioConstraints { | ||
ditman marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| /// Creates a new instance of [AudioConstraints] | ||
| /// with the given [enabled] constraint | ||
| /// indicating whether the audio track is requested. | ||
| const AudioConstraints({this.enabled = false}); | ||
|
|
||
| final bool enabled; | ||
|
|
||
| Object toJson() => enabled; | ||
| } | ||
|
|
||
| /// Defines constraints that the video track must have | ||
| /// to be considered acceptable. | ||
| class VideoConstraints { | ||
| /// Creates a new instance of [VideoConstraints] | ||
| /// with the given constraints. | ||
| const VideoConstraints({ | ||
| this.facingMode, | ||
| this.width, | ||
| this.height, | ||
| this.deviceId, | ||
| }); | ||
|
|
||
| final FacingModeConstraint? facingMode; | ||
| final VideoSizeConstraint? width; | ||
| final VideoSizeConstraint? height; | ||
| final String? deviceId; | ||
|
|
||
| Object toJson() { | ||
| final json = <String, dynamic>{}; | ||
|
|
||
| if (width != null) json['width'] = width!.toJson(); | ||
| if (height != null) json['height'] = height!.toJson(); | ||
| if (facingMode != null) json['facingMode'] = facingMode!.toJson(); | ||
| if (deviceId != null) json['deviceId'] = deviceId!; | ||
|
|
||
| return json; | ||
| } | ||
| } | ||
|
|
||
| /// The size of the requested video track used in | ||
| /// [VideoConstraints.width] and [VideoConstraints.height]. | ||
| /// | ||
| /// The obtained camera will have a size between [minimum] and [maximum] | ||
| /// with ideally a size of [ideal]. The size is determined by | ||
| /// the capabilities of the hardware and the other specified constraints. | ||
| class VideoSizeConstraint { | ||
| /// Creates a new instance of [VideoSizeConstraint] with the given | ||
| /// [minimum], [ideal] and [maximum] constraints. | ||
| const VideoSizeConstraint({this.minimum, this.ideal, this.maximum}); | ||
|
|
||
| final int? minimum; | ||
| final int? ideal; | ||
| final int? maximum; | ||
|
|
||
| Object toJson() { | ||
| final json = <String, dynamic>{}; | ||
|
|
||
| if (ideal != null) json['ideal'] = ideal; | ||
| if (minimum != null) json['min'] = minimum; | ||
| if (maximum != null) json['max'] = maximum; | ||
|
|
||
| return json; | ||
| } | ||
| } | ||
124 changes: 124 additions & 0 deletions
124
packages/camera/camera_web/test/src/types/camera_options_test.dart
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,124 @@ | ||
| // ignore_for_file: prefer_const_constructors | ||
|
|
||
| @TestOn('chrome') | ||
ditman marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| import 'package:camera_web/src/types/camera_options.dart'; | ||
| import 'package:flutter_test/flutter_test.dart'; | ||
|
|
||
| void main() { | ||
| group('CameraOptions', () { | ||
| test('serializes correctly', () async { | ||
| final cameraOptions = CameraOptions( | ||
| audio: AudioConstraints(enabled: true), | ||
| video: VideoConstraints( | ||
| facingMode: FacingModeConstraint.exact(CameraType.user), | ||
| ), | ||
| ); | ||
|
|
||
| expect( | ||
| cameraOptions.toJson(), | ||
| equals({ | ||
| 'audio': cameraOptions.audio.toJson(), | ||
| 'video': cameraOptions.video.toJson(), | ||
| }), | ||
| ); | ||
| }); | ||
| }); | ||
|
|
||
| group('FacingModeConstraint', () { | ||
| group('ideal', () { | ||
| test( | ||
| 'serializes correctly ' | ||
| 'for environment camera type', () { | ||
| expect( | ||
| FacingModeConstraint( | ||
| CameraType.environment, | ||
| ).toJson(), | ||
| equals({'ideal': 'environment'}), | ||
| ); | ||
| }); | ||
|
|
||
| test( | ||
| 'serializes correctly ' | ||
| 'for user camera type', () { | ||
| expect( | ||
| FacingModeConstraint( | ||
| CameraType.user, | ||
| ).toJson(), | ||
| equals({'ideal': 'user'}), | ||
| ); | ||
| }); | ||
| }); | ||
|
|
||
| group('exact', () { | ||
| test( | ||
| 'serializes correctly ' | ||
| 'for environment camera type', () { | ||
| expect( | ||
| FacingModeConstraint.exact( | ||
| CameraType.environment, | ||
| ).toJson(), | ||
| equals({'exact': 'environment'}), | ||
| ); | ||
| }); | ||
|
|
||
| test( | ||
| 'serializes correctly ' | ||
| 'for user camera type', () { | ||
| expect( | ||
| FacingModeConstraint.exact( | ||
| CameraType.user, | ||
| ).toJson(), | ||
| equals({'exact': 'user'}), | ||
| ); | ||
| }); | ||
| }); | ||
| }); | ||
|
|
||
| group('AudioConstraints', () { | ||
| test('serializes correctly', () { | ||
| expect( | ||
| AudioConstraints(enabled: true).toJson(), | ||
| equals(true), | ||
| ); | ||
| }); | ||
| }); | ||
|
|
||
| group('VideoConstraints', () { | ||
| test('serializes correctly', () async { | ||
| final videoConstraints = VideoConstraints( | ||
| facingMode: FacingModeConstraint.exact(CameraType.user), | ||
| width: VideoSizeConstraint(ideal: 100, maximum: 100), | ||
| height: VideoSizeConstraint(ideal: 50, maximum: 50), | ||
| deviceId: 'deviceId', | ||
| ); | ||
|
|
||
| expect( | ||
| videoConstraints.toJson(), | ||
| equals({ | ||
| 'facingMode': videoConstraints.facingMode!.toJson(), | ||
| 'width': videoConstraints.width!.toJson(), | ||
| 'height': videoConstraints.height!.toJson(), | ||
| 'deviceId': 'deviceId', | ||
| }), | ||
| ); | ||
| }); | ||
|
|
||
| group('VideoSizeConstraint ', () { | ||
| test('serializes correctly', () { | ||
| expect( | ||
| VideoSizeConstraint( | ||
| ideal: 400, | ||
| minimum: 200, | ||
| maximum: 400, | ||
| ).toJson(), | ||
| equals({ | ||
| 'ideal': 400, | ||
| 'min': 200, | ||
| 'max': 400, | ||
| }), | ||
| ); | ||
| }); | ||
| }); | ||
| }); | ||
| } | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.