diff --git a/packages/camera/camera/CHANGELOG.md b/packages/camera/camera/CHANGELOG.md index f7db10b19c99..13c00402449a 100644 --- a/packages/camera/camera/CHANGELOG.md +++ b/packages/camera/camera/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.10.3 + +* Adds back use of Optional type. + ## 0.10.2+1 * Updates code for stricter lint checks. diff --git a/packages/camera/camera/lib/src/camera_controller.dart b/packages/camera/camera/lib/src/camera_controller.dart index b201074f3810..7a396c1589f9 100644 --- a/packages/camera/camera/lib/src/camera_controller.dart +++ b/packages/camera/camera/lib/src/camera_controller.dart @@ -3,6 +3,7 @@ // found in the LICENSE file. import 'dart:async'; +import 'dart:collection'; import 'dart:math'; import 'package:camera_platform_interface/camera_platform_interface.dart'; @@ -160,10 +161,10 @@ class CameraValue { bool? exposurePointSupported, bool? focusPointSupported, DeviceOrientation? deviceOrientation, - DeviceOrientation? lockedCaptureOrientation, - DeviceOrientation? recordingOrientation, + Optional? lockedCaptureOrientation, + Optional? recordingOrientation, bool? isPreviewPaused, - DeviceOrientation? previewPauseOrientation, + Optional? previewPauseOrientation, }) { return CameraValue( isInitialized: isInitialized ?? this.isInitialized, @@ -180,12 +181,16 @@ class CameraValue { exposurePointSupported ?? this.exposurePointSupported, focusPointSupported: focusPointSupported ?? this.focusPointSupported, deviceOrientation: deviceOrientation ?? this.deviceOrientation, - lockedCaptureOrientation: - lockedCaptureOrientation ?? this.lockedCaptureOrientation, - recordingOrientation: recordingOrientation ?? this.recordingOrientation, + lockedCaptureOrientation: lockedCaptureOrientation == null + ? this.lockedCaptureOrientation + : lockedCaptureOrientation.orNull, + recordingOrientation: recordingOrientation == null + ? this.recordingOrientation + : recordingOrientation.orNull, isPreviewPaused: isPreviewPaused ?? this.isPreviewPaused, - previewPauseOrientation: - previewPauseOrientation ?? this.previewPauseOrientation, + previewPauseOrientation: previewPauseOrientation == null + ? this.previewPauseOrientation + : previewPauseOrientation.orNull, ); } @@ -353,8 +358,8 @@ class CameraController extends ValueNotifier { await CameraPlatform.instance.pausePreview(_cameraId); value = value.copyWith( isPreviewPaused: true, - previewPauseOrientation: - value.lockedCaptureOrientation ?? value.deviceOrientation); + previewPauseOrientation: Optional.of( + value.lockedCaptureOrientation ?? value.deviceOrientation)); } on PlatformException catch (e) { throw CameraException(e.code, e.message); } @@ -367,7 +372,9 @@ class CameraController extends ValueNotifier { } try { await CameraPlatform.instance.resumePreview(_cameraId); - value = value.copyWith(isPreviewPaused: false); + value = value.copyWith( + isPreviewPaused: false, + previewPauseOrientation: const Optional.absent()); } on PlatformException catch (e) { throw CameraException(e.code, e.message); } @@ -498,9 +505,9 @@ class CameraController extends ValueNotifier { value = value.copyWith( isRecordingVideo: true, isRecordingPaused: false, - isStreamingImages: onAvailable != null, - recordingOrientation: - value.lockedCaptureOrientation ?? value.deviceOrientation); + recordingOrientation: Optional.of( + value.lockedCaptureOrientation ?? value.deviceOrientation), + isStreamingImages: onAvailable != null); } on PlatformException catch (e) { throw CameraException(e.code, e.message); } @@ -525,7 +532,10 @@ class CameraController extends ValueNotifier { try { final XFile file = await CameraPlatform.instance.stopVideoRecording(_cameraId); - value = value.copyWith(isRecordingVideo: false); + value = value.copyWith( + isRecordingVideo: false, + recordingOrientation: const Optional.absent(), + ); return file; } on PlatformException catch (e) { throw CameraException(e.code, e.message); @@ -743,7 +753,8 @@ class CameraController extends ValueNotifier { await CameraPlatform.instance.lockCaptureOrientation( _cameraId, orientation ?? value.deviceOrientation); value = value.copyWith( - lockedCaptureOrientation: orientation ?? value.deviceOrientation); + lockedCaptureOrientation: Optional.of( + orientation ?? value.deviceOrientation)); } on PlatformException catch (e) { throw CameraException(e.code, e.message); } @@ -763,7 +774,8 @@ class CameraController extends ValueNotifier { Future unlockCaptureOrientation() async { try { await CameraPlatform.instance.unlockCaptureOrientation(_cameraId); - value = value.copyWith(); + value = value.copyWith( + lockedCaptureOrientation: const Optional.absent()); } on PlatformException catch (e) { throw CameraException(e.code, e.message); } @@ -834,3 +846,112 @@ class CameraController extends ValueNotifier { } } } + +/// A value that might be absent. +/// +/// Used to represent [DeviceOrientation]s that are optional but also able +/// to be cleared. +@immutable +class Optional extends IterableBase { + /// Constructs an empty Optional. + const Optional.absent() : _value = null; + + /// Constructs an Optional of the given [value]. + /// + /// Throws [ArgumentError] if [value] is null. + Optional.of(T value) : _value = value { + // TODO(cbracken): Delete and make this ctor const once mixed-mode + // execution is no longer around. + ArgumentError.checkNotNull(value); + } + + /// Constructs an Optional of the given [value]. + /// + /// If [value] is null, returns [absent()]. + const Optional.fromNullable(T? value) : _value = value; + + final T? _value; + + /// True when this optional contains a value. + bool get isPresent => _value != null; + + /// True when this optional contains no value. + bool get isNotPresent => _value == null; + + /// Gets the Optional value. + /// + /// Throws [StateError] if [value] is null. + T get value { + if (_value == null) { + throw StateError('value called on absent Optional.'); + } + return _value!; + } + + /// Executes a function if the Optional value is present. + void ifPresent(void Function(T value) ifPresent) { + if (isPresent) { + ifPresent(_value as T); + } + } + + /// Execution a function if the Optional value is absent. + void ifAbsent(void Function() ifAbsent) { + if (!isPresent) { + ifAbsent(); + } + } + + /// Gets the Optional value with a default. + /// + /// The default is returned if the Optional is [absent()]. + /// + /// Throws [ArgumentError] if [defaultValue] is null. + T or(T defaultValue) { + return _value ?? defaultValue; + } + + /// Gets the Optional value, or `null` if there is none. + T? get orNull => _value; + + /// Transforms the Optional value. + /// + /// If the Optional is [absent()], returns [absent()] without applying the transformer. + /// + /// The transformer must not return `null`. If it does, an [ArgumentError] is thrown. + Optional transform(S Function(T value) transformer) { + return _value == null + ? Optional.absent() + : Optional.of(transformer(_value as T)); + } + + /// Transforms the Optional value. + /// + /// If the Optional is [absent()], returns [absent()] without applying the transformer. + /// + /// Returns [absent()] if the transformer returns `null`. + Optional transformNullable(S? Function(T value) transformer) { + return _value == null + ? Optional.absent() + : Optional.fromNullable(transformer(_value as T)); + } + + @override + Iterator get iterator => + isPresent ? [_value as T].iterator : Iterable.empty().iterator; + + /// Delegates to the underlying [value] hashCode. + @override + int get hashCode => _value.hashCode; + + /// Delegates to the underlying [value] operator==. + @override + bool operator ==(Object o) => o is Optional && o._value == _value; + + @override + String toString() { + return _value == null + ? 'Optional { absent }' + : 'Optional { value: $_value }'; + } +} diff --git a/packages/camera/camera/pubspec.yaml b/packages/camera/camera/pubspec.yaml index fb62665e2e39..1b902ab61f0a 100644 --- a/packages/camera/camera/pubspec.yaml +++ b/packages/camera/camera/pubspec.yaml @@ -4,7 +4,7 @@ description: A Flutter plugin for controlling the camera. Supports previewing Dart. repository: https://github.com/flutter/plugins/tree/main/packages/camera/camera issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22 -version: 0.10.2+1 +version: 0.10.3 environment: sdk: ">=2.14.0 <3.0.0" diff --git a/packages/camera/camera/test/camera_preview_test.dart b/packages/camera/camera/test/camera_preview_test.dart index 7c4378749ebc..6677fcf90393 100644 --- a/packages/camera/camera/test/camera_preview_test.dart +++ b/packages/camera/camera/test/camera_preview_test.dart @@ -133,8 +133,11 @@ void main() { isInitialized: true, isRecordingVideo: true, deviceOrientation: DeviceOrientation.portraitUp, - lockedCaptureOrientation: DeviceOrientation.landscapeRight, - recordingOrientation: DeviceOrientation.landscapeLeft, + lockedCaptureOrientation: + const Optional.fromNullable( + DeviceOrientation.landscapeRight), + recordingOrientation: const Optional.fromNullable( + DeviceOrientation.landscapeLeft), previewSize: const Size(480, 640), ); @@ -164,8 +167,11 @@ void main() { controller.value = controller.value.copyWith( isInitialized: true, deviceOrientation: DeviceOrientation.portraitUp, - lockedCaptureOrientation: DeviceOrientation.landscapeRight, - recordingOrientation: DeviceOrientation.landscapeLeft, + lockedCaptureOrientation: + const Optional.fromNullable( + DeviceOrientation.landscapeRight), + recordingOrientation: const Optional.fromNullable( + DeviceOrientation.landscapeLeft), previewSize: const Size(480, 640), ); @@ -195,7 +201,8 @@ void main() { controller.value = controller.value.copyWith( isInitialized: true, deviceOrientation: DeviceOrientation.portraitUp, - recordingOrientation: DeviceOrientation.landscapeLeft, + recordingOrientation: const Optional.fromNullable( + DeviceOrientation.landscapeLeft), previewSize: const Size(480, 640), ); diff --git a/packages/camera/camera/test/camera_test.dart b/packages/camera/camera/test/camera_test.dart index 44a48d160d37..ab8354f7ba05 100644 --- a/packages/camera/camera/test/camera_test.dart +++ b/packages/camera/camera/test/camera_test.dart @@ -1166,7 +1166,8 @@ void main() { cameraController.value = cameraController.value.copyWith( isPreviewPaused: false, deviceOrientation: DeviceOrientation.portraitUp, - lockedCaptureOrientation: DeviceOrientation.landscapeRight); + lockedCaptureOrientation: + Optional.of(DeviceOrientation.landscapeRight)); await cameraController.pausePreview(); diff --git a/packages/camera/camera_android/CHANGELOG.md b/packages/camera/camera_android/CHANGELOG.md index 0aec0be2b442..0cb9957d029d 100644 --- a/packages/camera/camera_android/CHANGELOG.md +++ b/packages/camera/camera_android/CHANGELOG.md @@ -1,5 +1,6 @@ -## NEXT +## 0.10.3 +* Adds back use of Optional type. * Updates minimum Flutter version to 3.0. ## 0.10.2+3 diff --git a/packages/camera/camera_android/example/lib/camera_controller.dart b/packages/camera/camera_android/example/lib/camera_controller.dart index 79bf4e8b01e1..8139dcdb0220 100644 --- a/packages/camera/camera_android/example/lib/camera_controller.dart +++ b/packages/camera/camera_android/example/lib/camera_controller.dart @@ -3,6 +3,7 @@ // found in the LICENSE file. import 'dart:async'; +import 'dart:collection'; import 'package:camera_platform_interface/camera_platform_interface.dart'; import 'package:flutter/foundation.dart'; @@ -108,10 +109,10 @@ class CameraValue { bool? exposurePointSupported, bool? focusPointSupported, DeviceOrientation? deviceOrientation, - DeviceOrientation? lockedCaptureOrientation, - DeviceOrientation? recordingOrientation, + Optional? lockedCaptureOrientation, + Optional? recordingOrientation, bool? isPreviewPaused, - DeviceOrientation? previewPauseOrientation, + Optional? previewPauseOrientation, }) { return CameraValue( isInitialized: isInitialized ?? this.isInitialized, @@ -124,12 +125,16 @@ class CameraValue { exposureMode: exposureMode ?? this.exposureMode, focusMode: focusMode ?? this.focusMode, deviceOrientation: deviceOrientation ?? this.deviceOrientation, - lockedCaptureOrientation: - lockedCaptureOrientation ?? this.lockedCaptureOrientation, - recordingOrientation: recordingOrientation ?? this.recordingOrientation, + lockedCaptureOrientation: lockedCaptureOrientation == null + ? this.lockedCaptureOrientation + : lockedCaptureOrientation.orNull, + recordingOrientation: recordingOrientation == null + ? this.recordingOrientation + : recordingOrientation.orNull, isPreviewPaused: isPreviewPaused ?? this.isPreviewPaused, - previewPauseOrientation: - previewPauseOrientation ?? this.previewPauseOrientation, + previewPauseOrientation: previewPauseOrientation == null + ? this.previewPauseOrientation + : previewPauseOrientation.orNull, ); } @@ -257,14 +262,16 @@ class CameraController extends ValueNotifier { await CameraPlatform.instance.pausePreview(_cameraId); value = value.copyWith( isPreviewPaused: true, - previewPauseOrientation: - value.lockedCaptureOrientation ?? value.deviceOrientation); + previewPauseOrientation: Optional.of( + value.lockedCaptureOrientation ?? value.deviceOrientation)); } /// Resumes the current camera preview Future resumePreview() async { await CameraPlatform.instance.resumePreview(_cameraId); - value = value.copyWith(isPreviewPaused: false); + value = value.copyWith( + isPreviewPaused: false, + previewPauseOrientation: const Optional.absent()); } /// Captures an image and returns the file where it was saved. @@ -307,8 +314,8 @@ class CameraController extends ValueNotifier { isRecordingVideo: true, isRecordingPaused: false, isStreamingImages: streamCallback != null, - recordingOrientation: - value.lockedCaptureOrientation ?? value.deviceOrientation); + recordingOrientation: Optional.of( + value.lockedCaptureOrientation ?? value.deviceOrientation)); } /// Stops the video recording and returns the file where it was saved. @@ -324,6 +331,7 @@ class CameraController extends ValueNotifier { value = value.copyWith( isRecordingVideo: false, isRecordingPaused: false, + recordingOrientation: const Optional.absent(), ); return file; } @@ -392,12 +400,16 @@ class CameraController extends ValueNotifier { Future lockCaptureOrientation() async { await CameraPlatform.instance .lockCaptureOrientation(_cameraId, value.deviceOrientation); - value = value.copyWith(lockedCaptureOrientation: value.deviceOrientation); + value = value.copyWith( + lockedCaptureOrientation: + Optional.of(value.deviceOrientation)); } /// Unlocks the capture orientation. Future unlockCaptureOrientation() async { await CameraPlatform.instance.unlockCaptureOrientation(_cameraId); + value = value.copyWith( + lockedCaptureOrientation: const Optional.absent()); } /// Sets the focus mode for taking pictures. @@ -431,3 +443,112 @@ class CameraController extends ValueNotifier { } } } + +/// A value that might be absent. +/// +/// Used to represent [DeviceOrientation]s that are optional but also able +/// to be cleared. +@immutable +class Optional extends IterableBase { + /// Constructs an empty Optional. + const Optional.absent() : _value = null; + + /// Constructs an Optional of the given [value]. + /// + /// Throws [ArgumentError] if [value] is null. + Optional.of(T value) : _value = value { + // TODO(cbracken): Delete and make this ctor const once mixed-mode + // execution is no longer around. + ArgumentError.checkNotNull(value); + } + + /// Constructs an Optional of the given [value]. + /// + /// If [value] is null, returns [absent()]. + const Optional.fromNullable(T? value) : _value = value; + + final T? _value; + + /// True when this optional contains a value. + bool get isPresent => _value != null; + + /// True when this optional contains no value. + bool get isNotPresent => _value == null; + + /// Gets the Optional value. + /// + /// Throws [StateError] if [value] is null. + T get value { + if (_value == null) { + throw StateError('value called on absent Optional.'); + } + return _value!; + } + + /// Executes a function if the Optional value is present. + void ifPresent(void Function(T value) ifPresent) { + if (isPresent) { + ifPresent(_value as T); + } + } + + /// Execution a function if the Optional value is absent. + void ifAbsent(void Function() ifAbsent) { + if (!isPresent) { + ifAbsent(); + } + } + + /// Gets the Optional value with a default. + /// + /// The default is returned if the Optional is [absent()]. + /// + /// Throws [ArgumentError] if [defaultValue] is null. + T or(T defaultValue) { + return _value ?? defaultValue; + } + + /// Gets the Optional value, or `null` if there is none. + T? get orNull => _value; + + /// Transforms the Optional value. + /// + /// If the Optional is [absent()], returns [absent()] without applying the transformer. + /// + /// The transformer must not return `null`. If it does, an [ArgumentError] is thrown. + Optional transform(S Function(T value) transformer) { + return _value == null + ? Optional.absent() + : Optional.of(transformer(_value as T)); + } + + /// Transforms the Optional value. + /// + /// If the Optional is [absent()], returns [absent()] without applying the transformer. + /// + /// Returns [absent()] if the transformer returns `null`. + Optional transformNullable(S? Function(T value) transformer) { + return _value == null + ? Optional.absent() + : Optional.fromNullable(transformer(_value as T)); + } + + @override + Iterator get iterator => + isPresent ? [_value as T].iterator : Iterable.empty().iterator; + + /// Delegates to the underlying [value] hashCode. + @override + int get hashCode => _value.hashCode; + + /// Delegates to the underlying [value] operator==. + @override + bool operator ==(Object o) => o is Optional && o._value == _value; + + @override + String toString() { + return _value == null + ? 'Optional { absent }' + : 'Optional { value: $_value }'; + } +} diff --git a/packages/camera/camera_android/pubspec.yaml b/packages/camera/camera_android/pubspec.yaml index 30d6153cece6..fed2d29fb59f 100644 --- a/packages/camera/camera_android/pubspec.yaml +++ b/packages/camera/camera_android/pubspec.yaml @@ -2,7 +2,7 @@ name: camera_android description: Android implementation of the camera plugin. repository: https://github.com/flutter/plugins/tree/main/packages/camera/camera_android issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22 -version: 0.10.2+3 +version: 0.10.3 environment: sdk: ">=2.14.0 <3.0.0" diff --git a/packages/camera/camera_avfoundation/CHANGELOG.md b/packages/camera/camera_avfoundation/CHANGELOG.md index caa69b6296b8..f0605b7914cc 100644 --- a/packages/camera/camera_avfoundation/CHANGELOG.md +++ b/packages/camera/camera_avfoundation/CHANGELOG.md @@ -1,5 +1,6 @@ -## NEXT +## 0.9.11 +* Adds back use of Optional type. * Updates minimum Flutter version to 3.0. ## 0.9.10+2 diff --git a/packages/camera/camera_avfoundation/example/lib/camera_controller.dart b/packages/camera/camera_avfoundation/example/lib/camera_controller.dart index 47c1f6f0415b..524186816aab 100644 --- a/packages/camera/camera_avfoundation/example/lib/camera_controller.dart +++ b/packages/camera/camera_avfoundation/example/lib/camera_controller.dart @@ -3,6 +3,7 @@ // found in the LICENSE file. import 'dart:async'; +import 'dart:collection'; import 'package:camera_platform_interface/camera_platform_interface.dart'; import 'package:flutter/foundation.dart'; @@ -108,10 +109,10 @@ class CameraValue { bool? exposurePointSupported, bool? focusPointSupported, DeviceOrientation? deviceOrientation, - DeviceOrientation? lockedCaptureOrientation, - DeviceOrientation? recordingOrientation, + Optional? lockedCaptureOrientation, + Optional? recordingOrientation, bool? isPreviewPaused, - DeviceOrientation? previewPauseOrientation, + Optional? previewPauseOrientation, }) { return CameraValue( isInitialized: isInitialized ?? this.isInitialized, @@ -124,12 +125,16 @@ class CameraValue { exposureMode: exposureMode ?? this.exposureMode, focusMode: focusMode ?? this.focusMode, deviceOrientation: deviceOrientation ?? this.deviceOrientation, - lockedCaptureOrientation: - lockedCaptureOrientation ?? this.lockedCaptureOrientation, - recordingOrientation: recordingOrientation ?? this.recordingOrientation, + lockedCaptureOrientation: lockedCaptureOrientation == null + ? this.lockedCaptureOrientation + : lockedCaptureOrientation.orNull, + recordingOrientation: recordingOrientation == null + ? this.recordingOrientation + : recordingOrientation.orNull, isPreviewPaused: isPreviewPaused ?? this.isPreviewPaused, - previewPauseOrientation: - previewPauseOrientation ?? this.previewPauseOrientation, + previewPauseOrientation: previewPauseOrientation == null + ? this.previewPauseOrientation + : previewPauseOrientation.orNull, ); } @@ -257,14 +262,16 @@ class CameraController extends ValueNotifier { await CameraPlatform.instance.pausePreview(_cameraId); value = value.copyWith( isPreviewPaused: true, - previewPauseOrientation: - value.lockedCaptureOrientation ?? value.deviceOrientation); + previewPauseOrientation: Optional.of( + value.lockedCaptureOrientation ?? value.deviceOrientation)); } /// Resumes the current camera preview Future resumePreview() async { await CameraPlatform.instance.resumePreview(_cameraId); - value = value.copyWith(isPreviewPaused: false); + value = value.copyWith( + isPreviewPaused: false, + previewPauseOrientation: const Optional.absent()); } /// Captures an image and returns the file where it was saved. @@ -307,8 +314,8 @@ class CameraController extends ValueNotifier { isRecordingVideo: true, isRecordingPaused: false, isStreamingImages: streamCallback != null, - recordingOrientation: - value.lockedCaptureOrientation ?? value.deviceOrientation); + recordingOrientation: Optional.of( + value.lockedCaptureOrientation ?? value.deviceOrientation)); } /// Stops the video recording and returns the file where it was saved. @@ -321,7 +328,10 @@ class CameraController extends ValueNotifier { final XFile file = await CameraPlatform.instance.stopVideoRecording(_cameraId); - value = value.copyWith(isRecordingVideo: false); + value = value.copyWith( + isRecordingVideo: false, + recordingOrientation: const Optional.absent(), + ); return file; } @@ -389,12 +399,16 @@ class CameraController extends ValueNotifier { Future lockCaptureOrientation() async { await CameraPlatform.instance .lockCaptureOrientation(_cameraId, value.deviceOrientation); - value = value.copyWith(lockedCaptureOrientation: value.deviceOrientation); + value = value.copyWith( + lockedCaptureOrientation: + Optional.of(value.deviceOrientation)); } /// Unlocks the capture orientation. Future unlockCaptureOrientation() async { await CameraPlatform.instance.unlockCaptureOrientation(_cameraId); + value = value.copyWith( + lockedCaptureOrientation: const Optional.absent()); } /// Sets the focus mode for taking pictures. @@ -428,3 +442,112 @@ class CameraController extends ValueNotifier { } } } + +/// A value that might be absent. +/// +/// Used to represent [DeviceOrientation]s that are optional but also able +/// to be cleared. +@immutable +class Optional extends IterableBase { + /// Constructs an empty Optional. + const Optional.absent() : _value = null; + + /// Constructs an Optional of the given [value]. + /// + /// Throws [ArgumentError] if [value] is null. + Optional.of(T value) : _value = value { + // TODO(cbracken): Delete and make this ctor const once mixed-mode + // execution is no longer around. + ArgumentError.checkNotNull(value); + } + + /// Constructs an Optional of the given [value]. + /// + /// If [value] is null, returns [absent()]. + const Optional.fromNullable(T? value) : _value = value; + + final T? _value; + + /// True when this optional contains a value. + bool get isPresent => _value != null; + + /// True when this optional contains no value. + bool get isNotPresent => _value == null; + + /// Gets the Optional value. + /// + /// Throws [StateError] if [value] is null. + T get value { + if (_value == null) { + throw StateError('value called on absent Optional.'); + } + return _value!; + } + + /// Executes a function if the Optional value is present. + void ifPresent(void Function(T value) ifPresent) { + if (isPresent) { + ifPresent(_value as T); + } + } + + /// Execution a function if the Optional value is absent. + void ifAbsent(void Function() ifAbsent) { + if (!isPresent) { + ifAbsent(); + } + } + + /// Gets the Optional value with a default. + /// + /// The default is returned if the Optional is [absent()]. + /// + /// Throws [ArgumentError] if [defaultValue] is null. + T or(T defaultValue) { + return _value ?? defaultValue; + } + + /// Gets the Optional value, or `null` if there is none. + T? get orNull => _value; + + /// Transforms the Optional value. + /// + /// If the Optional is [absent()], returns [absent()] without applying the transformer. + /// + /// The transformer must not return `null`. If it does, an [ArgumentError] is thrown. + Optional transform(S Function(T value) transformer) { + return _value == null + ? Optional.absent() + : Optional.of(transformer(_value as T)); + } + + /// Transforms the Optional value. + /// + /// If the Optional is [absent()], returns [absent()] without applying the transformer. + /// + /// Returns [absent()] if the transformer returns `null`. + Optional transformNullable(S? Function(T value) transformer) { + return _value == null + ? Optional.absent() + : Optional.fromNullable(transformer(_value as T)); + } + + @override + Iterator get iterator => + isPresent ? [_value as T].iterator : Iterable.empty().iterator; + + /// Delegates to the underlying [value] hashCode. + @override + int get hashCode => _value.hashCode; + + /// Delegates to the underlying [value] operator==. + @override + bool operator ==(Object o) => o is Optional && o._value == _value; + + @override + String toString() { + return _value == null + ? 'Optional { absent }' + : 'Optional { value: $_value }'; + } +} diff --git a/packages/camera/camera_avfoundation/pubspec.yaml b/packages/camera/camera_avfoundation/pubspec.yaml index 9461d934a81d..b272a4c5c68d 100644 --- a/packages/camera/camera_avfoundation/pubspec.yaml +++ b/packages/camera/camera_avfoundation/pubspec.yaml @@ -2,7 +2,7 @@ name: camera_avfoundation description: iOS implementation of the camera plugin. repository: https://github.com/flutter/plugins/tree/main/packages/camera/camera_avfoundation issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22 -version: 0.9.10+2 +version: 0.9.11 environment: sdk: ">=2.14.0 <3.0.0"