3
3
// found in the LICENSE file.
4
4
5
5
import 'dart:async' ;
6
+ import 'dart:collection' ;
6
7
import 'dart:math' ;
7
8
8
9
import 'package:camera_platform_interface/camera_platform_interface.dart' ;
@@ -160,10 +161,10 @@ class CameraValue {
160
161
bool ? exposurePointSupported,
161
162
bool ? focusPointSupported,
162
163
DeviceOrientation ? deviceOrientation,
163
- DeviceOrientation ? lockedCaptureOrientation,
164
- DeviceOrientation ? recordingOrientation,
164
+ Optional < DeviceOrientation > ? lockedCaptureOrientation,
165
+ Optional < DeviceOrientation > ? recordingOrientation,
165
166
bool ? isPreviewPaused,
166
- DeviceOrientation ? previewPauseOrientation,
167
+ Optional < DeviceOrientation > ? previewPauseOrientation,
167
168
}) {
168
169
return CameraValue (
169
170
isInitialized: isInitialized ?? this .isInitialized,
@@ -180,12 +181,16 @@ class CameraValue {
180
181
exposurePointSupported ?? this .exposurePointSupported,
181
182
focusPointSupported: focusPointSupported ?? this .focusPointSupported,
182
183
deviceOrientation: deviceOrientation ?? this .deviceOrientation,
183
- lockedCaptureOrientation:
184
- lockedCaptureOrientation ?? this .lockedCaptureOrientation,
185
- recordingOrientation: recordingOrientation ?? this .recordingOrientation,
184
+ lockedCaptureOrientation: lockedCaptureOrientation == null
185
+ ? this .lockedCaptureOrientation
186
+ : lockedCaptureOrientation.orNull,
187
+ recordingOrientation: recordingOrientation == null
188
+ ? this .recordingOrientation
189
+ : recordingOrientation.orNull,
186
190
isPreviewPaused: isPreviewPaused ?? this .isPreviewPaused,
187
- previewPauseOrientation:
188
- previewPauseOrientation ?? this .previewPauseOrientation,
191
+ previewPauseOrientation: previewPauseOrientation == null
192
+ ? this .previewPauseOrientation
193
+ : previewPauseOrientation.orNull,
189
194
);
190
195
}
191
196
@@ -353,8 +358,8 @@ class CameraController extends ValueNotifier<CameraValue> {
353
358
await CameraPlatform .instance.pausePreview (_cameraId);
354
359
value = value.copyWith (
355
360
isPreviewPaused: true ,
356
- previewPauseOrientation:
357
- value.lockedCaptureOrientation ?? value.deviceOrientation);
361
+ previewPauseOrientation: Optional < DeviceOrientation >. of (
362
+ value.lockedCaptureOrientation ?? value.deviceOrientation)) ;
358
363
} on PlatformException catch (e) {
359
364
throw CameraException (e.code, e.message);
360
365
}
@@ -367,7 +372,9 @@ class CameraController extends ValueNotifier<CameraValue> {
367
372
}
368
373
try {
369
374
await CameraPlatform .instance.resumePreview (_cameraId);
370
- value = value.copyWith (isPreviewPaused: false );
375
+ value = value.copyWith (
376
+ isPreviewPaused: false ,
377
+ previewPauseOrientation: const Optional <DeviceOrientation >.absent ());
371
378
} on PlatformException catch (e) {
372
379
throw CameraException (e.code, e.message);
373
380
}
@@ -498,9 +505,9 @@ class CameraController extends ValueNotifier<CameraValue> {
498
505
value = value.copyWith (
499
506
isRecordingVideo: true ,
500
507
isRecordingPaused: false ,
501
- isStreamingImages : onAvailable != null ,
502
- recordingOrientation :
503
- value.lockedCaptureOrientation ?? value.deviceOrientation );
508
+ recordingOrientation : Optional < DeviceOrientation >. of (
509
+ value.lockedCaptureOrientation ?? value.deviceOrientation),
510
+ isStreamingImages : onAvailable != null );
504
511
} on PlatformException catch (e) {
505
512
throw CameraException (e.code, e.message);
506
513
}
@@ -525,7 +532,10 @@ class CameraController extends ValueNotifier<CameraValue> {
525
532
try {
526
533
final XFile file =
527
534
await CameraPlatform .instance.stopVideoRecording (_cameraId);
528
- value = value.copyWith (isRecordingVideo: false );
535
+ value = value.copyWith (
536
+ isRecordingVideo: false ,
537
+ recordingOrientation: const Optional <DeviceOrientation >.absent (),
538
+ );
529
539
return file;
530
540
} on PlatformException catch (e) {
531
541
throw CameraException (e.code, e.message);
@@ -743,7 +753,8 @@ class CameraController extends ValueNotifier<CameraValue> {
743
753
await CameraPlatform .instance.lockCaptureOrientation (
744
754
_cameraId, orientation ?? value.deviceOrientation);
745
755
value = value.copyWith (
746
- lockedCaptureOrientation: orientation ?? value.deviceOrientation);
756
+ lockedCaptureOrientation: Optional <DeviceOrientation >.of (
757
+ orientation ?? value.deviceOrientation));
747
758
} on PlatformException catch (e) {
748
759
throw CameraException (e.code, e.message);
749
760
}
@@ -763,7 +774,8 @@ class CameraController extends ValueNotifier<CameraValue> {
763
774
Future <void > unlockCaptureOrientation () async {
764
775
try {
765
776
await CameraPlatform .instance.unlockCaptureOrientation (_cameraId);
766
- value = value.copyWith ();
777
+ value = value.copyWith (
778
+ lockedCaptureOrientation: const Optional <DeviceOrientation >.absent ());
767
779
} on PlatformException catch (e) {
768
780
throw CameraException (e.code, e.message);
769
781
}
@@ -834,3 +846,112 @@ class CameraController extends ValueNotifier<CameraValue> {
834
846
}
835
847
}
836
848
}
849
+
850
+ /// A value that might be absent.
851
+ ///
852
+ /// Used to represent [DeviceOrientation] s that are optional but also able
853
+ /// to be cleared.
854
+ @immutable
855
+ class Optional <T > extends IterableBase <T > {
856
+ /// Constructs an empty Optional.
857
+ const Optional .absent () : _value = null ;
858
+
859
+ /// Constructs an Optional of the given [value] .
860
+ ///
861
+ /// Throws [ArgumentError] if [value] is null.
862
+ Optional .of (T value) : _value = value {
863
+ // TODO(cbracken): Delete and make this ctor const once mixed-mode
864
+ // execution is no longer around.
865
+ ArgumentError .checkNotNull (value);
866
+ }
867
+
868
+ /// Constructs an Optional of the given [value] .
869
+ ///
870
+ /// If [value] is null, returns [absent()] .
871
+ const Optional .fromNullable (T ? value) : _value = value;
872
+
873
+ final T ? _value;
874
+
875
+ /// True when this optional contains a value.
876
+ bool get isPresent => _value != null ;
877
+
878
+ /// True when this optional contains no value.
879
+ bool get isNotPresent => _value == null ;
880
+
881
+ /// Gets the Optional value.
882
+ ///
883
+ /// Throws [StateError] if [value] is null.
884
+ T get value {
885
+ if (_value == null ) {
886
+ throw StateError ('value called on absent Optional.' );
887
+ }
888
+ return _value! ;
889
+ }
890
+
891
+ /// Executes a function if the Optional value is present.
892
+ void ifPresent (void Function (T value) ifPresent) {
893
+ if (isPresent) {
894
+ ifPresent (_value as T );
895
+ }
896
+ }
897
+
898
+ /// Execution a function if the Optional value is absent.
899
+ void ifAbsent (void Function () ifAbsent) {
900
+ if (! isPresent) {
901
+ ifAbsent ();
902
+ }
903
+ }
904
+
905
+ /// Gets the Optional value with a default.
906
+ ///
907
+ /// The default is returned if the Optional is [absent()] .
908
+ ///
909
+ /// Throws [ArgumentError] if [defaultValue] is null.
910
+ T or (T defaultValue) {
911
+ return _value ?? defaultValue;
912
+ }
913
+
914
+ /// Gets the Optional value, or `null` if there is none.
915
+ T ? get orNull => _value;
916
+
917
+ /// Transforms the Optional value.
918
+ ///
919
+ /// If the Optional is [absent()] , returns [absent()] without applying the transformer.
920
+ ///
921
+ /// The transformer must not return `null` . If it does, an [ArgumentError] is thrown.
922
+ Optional <S > transform <S >(S Function (T value) transformer) {
923
+ return _value == null
924
+ ? Optional <S >.absent ()
925
+ : Optional <S >.of (transformer (_value as T ));
926
+ }
927
+
928
+ /// Transforms the Optional value.
929
+ ///
930
+ /// If the Optional is [absent()] , returns [absent()] without applying the transformer.
931
+ ///
932
+ /// Returns [absent()] if the transformer returns `null` .
933
+ Optional <S > transformNullable <S >(S ? Function (T value) transformer) {
934
+ return _value == null
935
+ ? Optional <S >.absent ()
936
+ : Optional <S >.fromNullable (transformer (_value as T ));
937
+ }
938
+
939
+ @override
940
+ Iterator <T > get iterator =>
941
+ isPresent ? < T > [_value as T ].iterator : Iterable <T >.empty ().iterator;
942
+
943
+ /// Delegates to the underlying [value] hashCode.
944
+ @override
945
+ int get hashCode => _value.hashCode;
946
+
947
+ /// Delegates to the underlying [value] operator==.
948
+ @override
949
+ bool operator == (Object o) => o is Optional <T > && o._value == _value;
950
+
951
+ @override
952
+ String toString () {
953
+ return _value == null
954
+ ? 'Optional { absent }'
955
+ : 'Optional { value: $_value }' ;
956
+ }
957
+ }
0 commit comments