Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/camera/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.5.4+2

* Fix Android NullPointerException on devices with only front-facing camera.

## 0.5.4+1

* Fix Android pause and resume video crash when executing in APIs below 24.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,32 +77,31 @@ static CamcorderProfile getBestAvailableCamcorderProfileForResolutionPreset(
// All of these cases deliberately fall through to get the best available profile.
case max:
if (CamcorderProfile.hasProfile(cameraId, CamcorderProfile.QUALITY_HIGH)) {
return CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
return CamcorderProfile.get(cameraId, CamcorderProfile.QUALITY_HIGH);
}
case ultraHigh:
if (CamcorderProfile.hasProfile(cameraId, CamcorderProfile.QUALITY_2160P)) {
return CamcorderProfile.get(CamcorderProfile.QUALITY_2160P);
return CamcorderProfile.get(cameraId, CamcorderProfile.QUALITY_2160P);
}
case veryHigh:
if (CamcorderProfile.hasProfile(cameraId, CamcorderProfile.QUALITY_1080P)) {
return CamcorderProfile.get(CamcorderProfile.QUALITY_1080P);
return CamcorderProfile.get(cameraId, CamcorderProfile.QUALITY_1080P);
}
case high:
if (CamcorderProfile.hasProfile(cameraId, CamcorderProfile.QUALITY_720P)) {
return CamcorderProfile.get(CamcorderProfile.QUALITY_720P);
return CamcorderProfile.get(cameraId, CamcorderProfile.QUALITY_720P);
}
case medium:
if (CamcorderProfile.hasProfile(cameraId, CamcorderProfile.QUALITY_480P)) {
return CamcorderProfile.get(CamcorderProfile.QUALITY_480P);
return CamcorderProfile.get(cameraId, CamcorderProfile.QUALITY_480P);
}
case low:
if (CamcorderProfile.hasProfile(cameraId, CamcorderProfile.QUALITY_QVGA)) {
return CamcorderProfile.get(CamcorderProfile.QUALITY_QVGA);
return CamcorderProfile.get(cameraId, CamcorderProfile.QUALITY_QVGA);
}
default:
if (CamcorderProfile.hasProfile(
Integer.parseInt(cameraName), CamcorderProfile.QUALITY_LOW)) {
return CamcorderProfile.get(CamcorderProfile.QUALITY_LOW);
if (CamcorderProfile.hasProfile(cameraId, CamcorderProfile.QUALITY_LOW)) {
return CamcorderProfile.get(cameraId, CamcorderProfile.QUALITY_LOW);
} else {
throw new IllegalArgumentException(
"No capture session available for current capture session.");
Expand Down
2 changes: 1 addition & 1 deletion packages/camera/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: camera
description: A Flutter plugin for getting information about and controlling the
camera on Android and iOS. Supports previewing the camera feed, capturing images, capturing video,
and streaming image buffers to dart.
version: 0.5.4+1
version: 0.5.4+2

authors:
- Flutter Team <[email protected]>
Expand Down
4 changes: 4 additions & 0 deletions packages/google_maps_flutter/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.5.21+2

* Fix more `prefer_const_constructors` analyzer warnings in example app.

## 0.5.21+1

* Fix `prefer_const_constructors` analyzer warnings in example app.
Expand Down
6 changes: 3 additions & 3 deletions packages/google_maps_flutter/example/lib/padding.dart
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ class MarkerIconsBodyState extends State<MarkerIconsBody> {
),
),
),
Spacer(),
const Spacer(),
Flexible(
flex: 2,
child: TextField(
Expand All @@ -110,7 +110,7 @@ class MarkerIconsBodyState extends State<MarkerIconsBody> {
),
),
),
Spacer(),
const Spacer(),
Flexible(
flex: 2,
child: TextField(
Expand All @@ -122,7 +122,7 @@ class MarkerIconsBodyState extends State<MarkerIconsBody> {
),
),
),
Spacer(),
const Spacer(),
Flexible(
flex: 2,
child: TextField(
Expand Down
2 changes: 1 addition & 1 deletion packages/google_maps_flutter/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: google_maps_flutter
description: A Flutter plugin for integrating Google Maps in iOS and Android applications.
author: Flutter Team <[email protected]>
homepage: https://github.com/flutter/plugins/tree/master/packages/google_maps_flutter
version: 0.5.21+1
version: 0.5.21+2

dependencies:
flutter:
Expand Down
5 changes: 5 additions & 0 deletions packages/google_sign_in/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 4.0.8

* Get rid of `MethodCompleter` and serialize async actions using chained futures.
This prevents a bug when sign in methods are being used in error handling zones.

## 4.0.7

* Switch from using `api` to `implementation` for dependency on `play-services-auth`,
Expand Down
117 changes: 53 additions & 64 deletions packages/google_sign_in/lib/google_sign_in.dart
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -230,50 +230,57 @@ class GoogleSignIn {
}

Future<void> _ensureInitialized() {
if (_initialization == null) {
_initialization = channel.invokeMethod<void>('init', <String, dynamic>{
'signInOption': (signInOption ?? SignInOption.standard).toString(),
'scopes': scopes ?? <String>[],
'hostedDomain': hostedDomain,
})
..catchError((dynamic _) {
// Invalidate initialization if it errored out.
_initialization = null;
});
}
return _initialization;
return _initialization ??=
channel.invokeMethod<void>('init', <String, dynamic>{
'signInOption': (signInOption ?? SignInOption.standard).toString(),
'scopes': scopes ?? <String>[],
'hostedDomain': hostedDomain,
})
..catchError((dynamic _) {
// Invalidate initialization if it errored out.
_initialization = null;
});
}

/// Keeps track of the most recently scheduled method call.
_MethodCompleter _lastMethodCompleter;
/// The most recently scheduled method call.
Future<void> _lastMethodCall;

/// Returns a [Future] that completes with a success after [future], whether
/// it completed with a value or an error.
static Future<void> _waitFor(Future<void> future) {
final Completer<void> completer = Completer<void>();
future.whenComplete(completer.complete).catchError((dynamic _) {
// Ignore if previous call completed with an error.
});
return completer.future;
}

/// Adds call to [method] in a queue for execution.
///
/// At most one in flight call is allowed to prevent concurrent (out of order)
/// updates to [currentUser] and [onCurrentUserChanged].
Future<GoogleSignInAccount> _addMethodCall(String method) {
if (_lastMethodCompleter == null) {
_lastMethodCompleter = _MethodCompleter(method)
..complete(_callMethod(method));
return _lastMethodCompleter.future;
Future<GoogleSignInAccount> _addMethodCall(String method) async {
Future<GoogleSignInAccount> response;
if (_lastMethodCall == null) {
response = _callMethod(method);
} else {
response = _lastMethodCall.then((_) {
// If after the last completed call `currentUser` is not `null` and requested
// method is a sign in method, re-use the same authenticated user
// instead of making extra call to the native side.
const List<String> kSignInMethods = <String>[
'signIn',
'signInSilently'
];
if (kSignInMethods.contains(method) && _currentUser != null) {
return _currentUser;
} else {
return _callMethod(method);
}
});
}

final _MethodCompleter completer = _MethodCompleter(method);
_lastMethodCompleter.future.whenComplete(() {
// If after the last completed call currentUser is not null and requested
// method is a sign in method, re-use the same authenticated user
// instead of making extra call to the native side.
const List<String> kSignInMethods = <String>['signIn', 'signInSilently'];
if (kSignInMethods.contains(method) && _currentUser != null) {
completer.complete(_currentUser);
} else {
completer.complete(_callMethod(method));
}
}).catchError((dynamic _) {
// Ignore if previous call completed with an error.
});
_lastMethodCompleter = completer;
return _lastMethodCompleter.future;
_lastMethodCall = _waitFor(response);
return response;
}

/// The currently signed in account, or null if the user is signed out.
Expand All @@ -296,12 +303,17 @@ class GoogleSignIn {
/// returned Future completes with [PlatformException] whose `code` can be
/// either [kSignInRequiredError] (when there is no authenticated user) or
/// [kSignInFailedError] (when an unknown error occurred).
Future<GoogleSignInAccount> signInSilently({bool suppressErrors = true}) {
final Future<GoogleSignInAccount> result = _addMethodCall('signInSilently');
if (suppressErrors) {
return result.catchError((dynamic _) => null);
Future<GoogleSignInAccount> signInSilently(
{bool suppressErrors = true}) async {
try {
return await _addMethodCall('signInSilently');
} catch (_) {
if (suppressErrors) {
return null;
} else {
rethrow;
}
}
return result;
}

/// Returns a future that resolves to whether a user is currently signed in.
Expand Down Expand Up @@ -334,26 +346,3 @@ class GoogleSignIn {
/// authentication.
Future<GoogleSignInAccount> disconnect() => _addMethodCall('disconnect');
}

class _MethodCompleter {
_MethodCompleter(this.method);

final String method;
final Completer<GoogleSignInAccount> _completer =
Completer<GoogleSignInAccount>();

Future<void> complete(FutureOr<GoogleSignInAccount> value) async {
if (value is Future<GoogleSignInAccount>) {
try {
_completer.complete(await value);
} catch (e, stacktrace) {
_completer.completeError(e, stacktrace);
}
} else {
_completer.complete(value);
}
}

bool get isCompleted => _completer.isCompleted;
Future<GoogleSignInAccount> get future => _completer.future;
}
2 changes: 1 addition & 1 deletion packages/google_sign_in/pubspec.yaml
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ description: Flutter plugin for Google Sign-In, a secure authentication system
for signing in with a Google account on Android and iOS.
author: Flutter Team <[email protected]>
homepage: https://github.com/flutter/plugins/tree/master/packages/google_sign_in
version: 4.0.7
version: 4.0.8

flutter:
plugin:
Expand Down
29 changes: 27 additions & 2 deletions packages/google_sign_in/test/google_sign_in_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,11 @@ void main() {
responses = Map<String, dynamic>.from(kDefaultResponses);
channel.setMockMethodCallHandler((MethodCall methodCall) {
log.add(methodCall);
return Future<dynamic>.value(responses[methodCall.method]);
final dynamic response = responses[methodCall.method];
if (response != null && response is Exception) {
return Future<dynamic>.error('$response');
}
return Future<dynamic>.value(response);
});
googleSignIn = GoogleSignIn();
log.clear();
Expand Down Expand Up @@ -142,6 +146,27 @@ void main() {
]);
});

test('signIn works even if a previous call throws error in other zone',
() async {
responses['signInSilently'] = Exception('Not a user');
await runZoned(() async {
expect(await googleSignIn.signInSilently(), isNull);
}, onError: (dynamic e, dynamic st) {});
expect(await googleSignIn.signIn(), isNotNull);
expect(
log,
<Matcher>[
isMethodCall('init', arguments: <String, dynamic>{
'signInOption': 'SignInOption.standard',
'scopes': <String>[],
'hostedDomain': null,
}),
isMethodCall('signInSilently', arguments: null),
isMethodCall('signIn', arguments: null),
],
);
});

test('concurrent calls of the same method trigger sign in once', () async {
final List<Future<GoogleSignInAccount>> futures =
<Future<GoogleSignInAccount>>[
Expand Down Expand Up @@ -170,7 +195,7 @@ void main() {
});

test('can sign in after previously failed attempt', () async {
responses['signInSilently'] = <String, dynamic>{'error': 'Not a user'};
responses['signInSilently'] = Exception('Not a user');
expect(await googleSignIn.signInSilently(), isNull);
expect(await googleSignIn.signIn(), isNotNull);
expect(
Expand Down
5 changes: 5 additions & 0 deletions packages/url_launcher/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@

## 5.1.3

* Always launch url from the top most UIViewController in iOS.

## 5.1.2

* Update AGP and gradle.
Expand Down
Loading