Skip to content

Commit cb8f42b

Browse files
ValentinVignalKyleFin
authored andcommitted
[google_sign_in] Use a transparent image as a placeholder for the GoogleUserCircleAvatar (flutter#4391)
1 parent 52a74fa commit cb8f42b

File tree

6 files changed

+142
-2
lines changed

6 files changed

+142
-2
lines changed

packages/google_sign_in/google_sign_in/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 5.2.1
2+
3+
Change the placeholder of the GoogleUserCircleAvatar to a transparent image.
4+
15
## 5.2.0
26

37
* Add `GoogleSignInAccount.serverAuthCode`. Mark `GoogleSignInAuthentication.serverAuthCode` as deprecated.

packages/google_sign_in/google_sign_in/lib/widgets.dart

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,10 +106,22 @@ class GoogleUserCircleAvatar extends StatelessWidget {
106106
FadeInImage.memoryNetwork(
107107
// This creates a transparent placeholder image, so that
108108
// [placeholder] shows through.
109-
placeholder: Uint8List((size.round() * size.round())),
109+
placeholder: _transparentImage,
110110
image: sizedPhotoUrl,
111111
)
112112
]),
113113
));
114114
}
115115
}
116+
117+
/// This is an transparent 1x1 gif image.
118+
///
119+
/// Those bytes come from `resources/transparentImage.gif`.
120+
final Uint8List _transparentImage = Uint8List.fromList(
121+
[
122+
0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x01, 0x00, 0x01, 0x00, 0x80, 0x00, //
123+
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x21, 0xf9, 0x04, 0x01, 0x00, //
124+
0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, //
125+
0x00, 0x02, 0x01, 0x44, 0x00, 0x3B
126+
],
127+
);

packages/google_sign_in/google_sign_in/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ description: Flutter plugin for Google Sign-In, a secure authentication system
33
for signing in with a Google account on Android and iOS.
44
repository: https://github.com/flutter/plugins/tree/master/packages/google_sign_in/google_sign_in
55
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+google_sign_in%22
6-
version: 5.2.0
6+
version: 5.2.1
77

88
environment:
99
sdk: ">=2.14.0 <3.0.0"
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
`transparentImage.gif` is a 1x1 transparent gif which comes from [this wikimedia page](https://commons.wikimedia.org/wiki/File:Transparent.gif):
2+
3+
![](transparentImage.gif)
4+
5+
This is the image used a placeholder for the `GoogleCircleAvatar` widget.
6+
7+
The variable `_transparentImage` in `lib/widgets.dart` is the list of bytes of `transparentImage.gif`.
Loading
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import 'dart:async';
6+
import 'dart:io';
7+
import 'dart:typed_data';
8+
9+
import 'package:flutter/material.dart';
10+
import 'package:flutter_test/flutter_test.dart';
11+
import 'package:google_sign_in/google_sign_in.dart';
12+
13+
/// A instantiable class that extends [GoogleIdentity]
14+
class _TestGoogleIdentity extends GoogleIdentity {
15+
_TestGoogleIdentity({
16+
required this.id,
17+
required this.email,
18+
this.photoUrl,
19+
});
20+
21+
final String id;
22+
final String email;
23+
24+
final String? photoUrl;
25+
26+
@override
27+
String? get displayName => null;
28+
29+
@override
30+
String? get serverAuthCode => null;
31+
}
32+
33+
/// A mocked [HttpClient] which always returns a [_MockHttpRequest].
34+
class _MockHttpClient extends Fake implements HttpClient {
35+
@override
36+
bool autoUncompress = true;
37+
38+
@override
39+
Future<HttpClientRequest> getUrl(Uri url) {
40+
return Future<HttpClientRequest>.value(_MockHttpRequest());
41+
}
42+
}
43+
44+
/// A mocked [HttpClientRequest] which always returns a [_MockHttpClientResponse].
45+
class _MockHttpRequest extends Fake implements HttpClientRequest {
46+
@override
47+
Future<HttpClientResponse> close() {
48+
return Future<HttpClientResponse>.value(_MockHttpResponse());
49+
}
50+
}
51+
52+
/// Arbitrary valid image returned by the [_MockHttpResponse].
53+
///
54+
/// This is an transparent 1x1 gif image.
55+
/// It doesn't have to match the placeholder used in [GoogleUserCircleAvatar].
56+
///
57+
/// Those bytes come from `resources/transparentImage.gif`.
58+
final Uint8List _transparentImage = Uint8List.fromList(
59+
[
60+
0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x01, 0x00, 0x01, 0x00, 0x80, 0x00, //
61+
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x21, 0xf9, 0x04, 0x01, 0x00, //
62+
0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, //
63+
0x00, 0x02, 0x01, 0x44, 0x00, 0x3B
64+
],
65+
);
66+
67+
/// A mocked [HttpClientResponse] which is empty and has a [statusCode] of 200
68+
/// and returns valid image.
69+
class _MockHttpResponse extends Fake implements HttpClientResponse {
70+
final Stream<Uint8List> _delegate =
71+
Stream<Uint8List>.value(_transparentImage);
72+
73+
@override
74+
int get contentLength => -1;
75+
76+
@override
77+
HttpClientResponseCompressionState get compressionState {
78+
return HttpClientResponseCompressionState.decompressed;
79+
}
80+
81+
@override
82+
StreamSubscription<Uint8List> listen(void Function(Uint8List event)? onData,
83+
{Function? onError, void Function()? onDone, bool? cancelOnError}) {
84+
return _delegate.listen(onData,
85+
onError: onError, onDone: onDone, cancelOnError: cancelOnError);
86+
}
87+
88+
@override
89+
int get statusCode => 200;
90+
}
91+
92+
void main() {
93+
testWidgets('It should build the GoogleUserCircleAvatar successfully',
94+
(WidgetTester tester) async {
95+
final GoogleIdentity identity = _TestGoogleIdentity(
96+
97+
id: 'userId',
98+
photoUrl: 'photoUrl',
99+
);
100+
tester.binding.window.physicalSizeTestValue = Size(100, 100);
101+
102+
await HttpOverrides.runZoned(
103+
() async {
104+
await tester.pumpWidget(MaterialApp(
105+
home: SizedBox(
106+
height: 100,
107+
width: 100,
108+
child: GoogleUserCircleAvatar(
109+
identity: identity,
110+
),
111+
),
112+
));
113+
},
114+
createHttpClient: (SecurityContext? c) => _MockHttpClient(),
115+
);
116+
});
117+
}

0 commit comments

Comments
 (0)