Skip to content
This repository has been archived by the owner on Jun 11, 2021. It is now read-only.

[google_sign_in_dart] Null safety migration #29

Open
wants to merge 18 commits into
base: develop
Choose a base branch
from
Open
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
18 changes: 6 additions & 12 deletions google_sign_in_dart/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,19 @@ mainly used on Desktop.
1. Run `flutter pub get`
1. Import
```dart
import 'package:google_sign_in/google_sign_in.dart';
import 'package:google_sign_in_dartio/google_sign_in_dartio.dart';
```
1. Register the package
```dart
import 'package:flutter/material.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:google_sign_in_dartio/google_sign_in_dartio.dart';

void main() {
```dart
Future<void> main() async {
if (isDesktop) {
GoogleSignInPlatform.register(clientId: <clientId>);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good

await GoogleSignInDart.register(clientId: <clientId>);
}

runApp(MyApp());
}
```
Note: You might want to `await` for the `register` method to finish before calling any `GoogleSignIn` methods when your app starts.
Note: You should ensure the `register` method completes before calling any `GoogleSignIn` methods when your app starts.

### Usage
You can use the normal `GoogleSignIn` methods.
Expand All @@ -54,12 +49,11 @@ keep the user logged in, you need to deploy a oAuth code exchange endpoint. Once
the package like this.

import 'package:flutter/material.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:google_sign_in_dartio/google_sign_in_dartio.dart';

void main() {
Future<void> main() async {
if (isDesktop) {
GoogleSignInPlatform.register(
await GoogleSignInDart.register(
clientId: <clientId>,
exchangeEndpoint: <endpoint>,
);
Expand Down
75 changes: 38 additions & 37 deletions google_sign_in_dart/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,25 @@
// ignore_for_file: public_member_api_docs

import 'dart:async';
import 'dart:convert';

import 'package:collection/collection.dart' show IterableExtension;
import 'package:extension_google_sign_in_as_googleapis_auth/extension_google_sign_in_as_googleapis_auth.dart';
import 'package:flutter/foundation.dart';
import 'package:html_unescape/html_unescape.dart';
import 'package:flutter/material.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:google_sign_in_dartio/google_sign_in_dartio.dart';
import 'package:googleapis/gmail/v1.dart';
import 'package:googleapis/people/v1.dart';
import 'package:googleapis_auth/auth.dart';
import 'package:googleapis_auth/googleapis_auth.dart';
import 'package:html_unescape/html_unescape.dart';

import 'platform_js.dart' if (dart.library.io) 'platform_io.dart';

GoogleSignIn _googleSignIn = GoogleSignIn(
scopes: <String>['email', 'profile', PeopleApi.ContactsReadonlyScope]);
GoogleSignIn _googleSignIn = GoogleSignIn(scopes: <String>[
'email',
'profile',
PeopleServiceApi.contactsReadonlyScope
]);

Future<void> main() async {
if (isDesktop) {
Expand All @@ -46,11 +49,11 @@ class SignInDemo extends StatefulWidget {
}

class SignInDemoState extends State<SignInDemo> {
StreamSubscription<GoogleSignInAccount> sub;
AuthClient _client;
GoogleSignInAccount _currentUser;
String _contactText;
String _emailText;
late StreamSubscription<GoogleSignInAccount?> sub;
AuthClient? _client;
GoogleSignInAccount? _currentUser;
String? _contactText;
String? _emailText;

@override
void initState() {
Expand All @@ -59,7 +62,7 @@ class SignInDemoState extends State<SignInDemo> {
_googleSignIn.signInSilently();
}

Future<void> _onUserChanged(GoogleSignInAccount account) async {
Future<void> _onUserChanged(GoogleSignInAccount? account) async {
setState(() => _currentUser = account);
if (_currentUser != null) {
_client = await _googleSignIn.authenticatedClient();
Expand All @@ -70,27 +73,26 @@ class SignInDemoState extends State<SignInDemo> {
Future<void> _handleGetContact() async {
setState(() => _contactText = 'Loading contact info...');

final PeopleConnectionsResourceApi connectionsApi =
PeopleApi(_client).people.connections;
final PeopleConnectionsResource connectionsApi =
PeopleServiceApi(_client!).people.connections;

final ListConnectionsResponse listResult = await connectionsApi.list(
'people/me',
requestMask_includeField: 'person.names',
);

String contact;
final List<Person> connections = listResult.connections;
String? contact;
final List<Person>? connections = listResult.connections;
if (connections != null && connections.isNotEmpty) {
connections.shuffle();
final Person person = connections.firstWhere(
final Person? person = connections.firstWhereOrNull(
(Person person) =>
person.names.any((Name name) => name.displayName != null),
orElse: () => null,
person.names!.any((Name name) => name.displayName != null),
);

if (person != null) {
final Name name =
person.names.firstWhere((Name name) => name.displayName != null);
person.names!.firstWhere((Name name) => name.displayName != null);
contact = name.displayName;
}
}
Expand All @@ -108,24 +110,23 @@ class SignInDemoState extends State<SignInDemo> {
setState(() => _emailText = 'Loading emails...');

final bool granted = await _googleSignIn
.requestScopes(<String>[GmailApi.GmailReadonlyScope]);
.requestScopes(<String>[GmailApi.gmailReadonlyScope]);

if (!granted) {
setState(() => _emailText = 'Gmail scope was not granted by the user.');
return;
}

_client = await _googleSignIn.authenticatedClient();
final UsersMessagesResourceApi messagesApi =
GmailApi(_client).users.messages;
final UsersMessagesResource messagesApi = GmailApi(_client!).users.messages;

final ListMessagesResponse listResult = await messagesApi.list('me');

String messageSnippet;
if (listResult.messages != null && listResult.messages.isNotEmpty) {
for (Message message in listResult.messages..shuffle()) {
message = await messagesApi.get('me', message.id, format: 'FULL');
final String snippet = message.snippet;
String? messageSnippet;
if (listResult.messages != null && listResult.messages!.isNotEmpty) {
for (Message message in listResult.messages!..shuffle()) {
message = await messagesApi.get('me', message.id!, format: 'FULL');
final String? snippet = message.snippet;
if (snippet != null && snippet.trim().isNotEmpty) {
messageSnippet = HtmlUnescape().convert(snippet);
break;
Expand Down Expand Up @@ -176,7 +177,7 @@ class SignInDemoState extends State<SignInDemo> {
children: <Widget>[
const Text('You are not currently signed in.'),
const SizedBox(height: 16.0),
RaisedButton(
ElevatedButton(
onPressed: _handleSignIn,
child: const Text('SIGN IN'),
),
Expand All @@ -190,21 +191,21 @@ class SignInDemoState extends State<SignInDemo> {
ListTile(
leading: kIsWeb
? GoogleUserCircleAvatar(
identity: _currentUser,
identity: _currentUser!,
)
: ClipOval(
child: Image.network(
_currentUser.photoUrl ??
_currentUser!.photoUrl ??
'https://lh3.googleusercontent.com/a/default-user=s160-c',
),
),
title: Text(_currentUser.displayName ?? ''),
subtitle: Text(_currentUser.email ?? ''),
title: Text(_currentUser!.displayName ?? ''),
subtitle: Text(_currentUser!.email),
),
if (_contactText != null)
ListTile(
title: Text(
_contactText,
_contactText!,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
Expand All @@ -213,26 +214,26 @@ class SignInDemoState extends State<SignInDemo> {
if (_emailText != null)
ListTile(
title: Text(
_emailText,
_emailText!,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
subtitle: const Text('Gmail Api'),
),
ButtonBar(
children: <Widget>[
FlatButton(
TextButton(
onPressed: _handleSignOut,
child: const Text('SIGN OUT'),
),
FlatButton(
TextButton(
onPressed: () {
_handleGetContact();
_handleGetEmail();
},
child: const Text('REFRESH'),
),
FlatButton(
TextButton(
onPressed: _handleGetEmail,
child: const Text('ADD GMAIL SCOPE'),
),
Expand Down
76 changes: 17 additions & 59 deletions google_sign_in_dart/example/macos/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,74 +9,32 @@ project 'Runner', {
'Release' => :release,
}

def parse_KV_file(file, separator='=')
file_abs_path = File.expand_path(file)
if !File.exists? file_abs_path
return [];
def flutter_root
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__)
unless File.exist?(generated_xcode_build_settings_path)
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first"
end
pods_ary = []
skip_line_start_symbols = ["#", "/"]
File.foreach(file_abs_path) { |line|
next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ }
plugin = line.split(pattern=separator)
if plugin.length == 2
podname = plugin[0].strip()
path = plugin[1].strip()
podpath = File.expand_path("#{path}", file_abs_path)
pods_ary.push({:name => podname, :path => podpath});
else
puts "Invalid plugin specification: #{line}"
end
}
return pods_ary
end

def pubspec_supports_macos(file)
file_abs_path = File.expand_path(file)
if !File.exists? file_abs_path
return false;
File.foreach(generated_xcode_build_settings_path) do |line|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
return matches[1].strip if matches
end
File.foreach(file_abs_path) { |line|
return true if line =~ /^\s*macos:/
}
return false
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\""
end

require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)

flutter_macos_podfile_setup

target 'Runner' do
use_frameworks!
use_modular_headers!

# Prepare symlinks folder. We use symlinks to avoid having Podfile.lock
# referring to absolute paths on developers' machines.
ephemeral_dir = File.join('Flutter', 'ephemeral')
symlink_dir = File.join(ephemeral_dir, '.symlinks')
symlink_plugins_dir = File.join(symlink_dir, 'plugins')
system("rm -rf #{symlink_dir}")
system("mkdir -p #{symlink_plugins_dir}")
flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__))
end

# Flutter Pods
generated_xcconfig = parse_KV_file(File.join(ephemeral_dir, 'Flutter-Generated.xcconfig'))
if generated_xcconfig.empty?
puts "Flutter-Generated.xcconfig must exist. If you're running pod install manually, make sure flutter packages get is executed first."
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_macos_build_settings(target)
end
generated_xcconfig.map { |p|
if p[:name] == 'FLUTTER_FRAMEWORK_DIR'
symlink = File.join(symlink_dir, 'flutter')
File.symlink(File.dirname(p[:path]), symlink)
pod 'FlutterMacOS', :path => File.join(symlink, File.basename(p[:path]))
end
}

# Plugin Pods
plugin_pods = parse_KV_file('../.flutter-plugins')
plugin_pods.map { |p|
symlink = File.join(symlink_plugins_dir, p[:name])
File.symlink(p[:path], symlink)
if pubspec_supports_macos(File.join(symlink, 'pubspec.yaml'))
pod p[:name], :path => File.join(symlink, 'macos')
end
}
end

# Prevent Cocoapods from embedding a second Flutter framework and causing an error with the new Xcode build system.
install! 'cocoapods', :disable_input_output_paths => true
24 changes: 7 additions & 17 deletions google_sign_in_dart/example/macos/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,38 +1,28 @@
PODS:
- FlutterMacOS (1.0.0)
- shared_preferences (0.0.1)
- shared_preferences_macos (0.0.1):
- FlutterMacOS
- url_launcher (0.0.1)
- url_launcher_macos (0.0.1):
- FlutterMacOS

DEPENDENCIES:
- FlutterMacOS (from `Flutter/ephemeral/.symlinks/flutter/darwin-x64`)
- shared_preferences (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences/macos`)
- FlutterMacOS (from `Flutter/ephemeral`)
- shared_preferences_macos (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_macos/macos`)
- url_launcher (from `Flutter/ephemeral/.symlinks/plugins/url_launcher/macos`)
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)

EXTERNAL SOURCES:
FlutterMacOS:
:path: Flutter/ephemeral/.symlinks/flutter/darwin-x64
shared_preferences:
:path: Flutter/ephemeral/.symlinks/plugins/shared_preferences/macos
:path: Flutter/ephemeral
shared_preferences_macos:
:path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_macos/macos
url_launcher:
:path: Flutter/ephemeral/.symlinks/plugins/url_launcher/macos
url_launcher_macos:
:path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos

SPEC CHECKSUMS:
FlutterMacOS: 15bea8a44d2fa024068daa0140371c020b4b6ff9
shared_preferences: 9fec34d1bd906196a4da48fcf6c3ad521cc00b8d
shared_preferences_macos: 5e5c2839894accb56b7d23328905b757f2bafaf6
url_launcher: af78307ef9bafff91273b34f1c6c0c86a0004fd7
url_launcher_macos: 76867a28e24e0b6b98bfd65f157b64108e6d477a
FlutterMacOS: 57701585bf7de1b3fc2bb61f6378d73bbdea8424
shared_preferences_macos: 480ce071d0666e37cef23fe6c702293a3d21799e
url_launcher_macos: 45af3d61de06997666568a7149c1be98b41c95d4

PODFILE CHECKSUM: d8ba9b3e9e93c62c74a660b46c6fcb09f03991a7
PODFILE CHECKSUM: 6eac6b3292e5142cfc23bdeb71848a40ec51c14c

COCOAPODS: 1.9.3
COCOAPODS: 1.10.1
Loading