Skip to content

Commit 664de8f

Browse files
committed
Wrong commit, this one is the one that added sign in with google
1 parent a5a3899 commit 664de8f

19 files changed

+633
-165
lines changed

.metadata

+5-20
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# This file should be version controlled and should not be manually edited.
55

66
version:
7-
revision: "abb292a07e20d696c4568099f918f6c5f330e6b0"
7+
revision: "7482962148e8d758338d8a28f589f317e1e42ba4"
88
channel: "stable"
99

1010
project_type: app
@@ -13,26 +13,11 @@ project_type: app
1313
migration:
1414
platforms:
1515
- platform: root
16-
create_revision: abb292a07e20d696c4568099f918f6c5f330e6b0
17-
base_revision: abb292a07e20d696c4568099f918f6c5f330e6b0
18-
- platform: android
19-
create_revision: abb292a07e20d696c4568099f918f6c5f330e6b0
20-
base_revision: abb292a07e20d696c4568099f918f6c5f330e6b0
21-
- platform: ios
22-
create_revision: abb292a07e20d696c4568099f918f6c5f330e6b0
23-
base_revision: abb292a07e20d696c4568099f918f6c5f330e6b0
24-
- platform: linux
25-
create_revision: abb292a07e20d696c4568099f918f6c5f330e6b0
26-
base_revision: abb292a07e20d696c4568099f918f6c5f330e6b0
27-
- platform: macos
28-
create_revision: abb292a07e20d696c4568099f918f6c5f330e6b0
29-
base_revision: abb292a07e20d696c4568099f918f6c5f330e6b0
16+
create_revision: 7482962148e8d758338d8a28f589f317e1e42ba4
17+
base_revision: 7482962148e8d758338d8a28f589f317e1e42ba4
3018
- platform: web
31-
create_revision: abb292a07e20d696c4568099f918f6c5f330e6b0
32-
base_revision: abb292a07e20d696c4568099f918f6c5f330e6b0
33-
- platform: windows
34-
create_revision: abb292a07e20d696c4568099f918f6c5f330e6b0
35-
base_revision: abb292a07e20d696c4568099f918f6c5f330e6b0
19+
create_revision: 7482962148e8d758338d8a28f589f317e1e42ba4
20+
base_revision: 7482962148e8d758338d8a28f589f317e1e42ba4
3621

3722
# User provided section
3823

android/app/google-services.json

+8
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,14 @@
1313
}
1414
},
1515
"oauth_client": [
16+
{
17+
"client_id": "967077780131-km45i3ho23r6pt5693h0h506bq5jqbk3.apps.googleusercontent.com",
18+
"client_type": 1,
19+
"android_info": {
20+
"package_name": "com.example.testnote",
21+
"certificate_hash": "3044d864082ae54438901572970cb4904f111c51"
22+
}
23+
},
1624
{
1725
"client_id": "967077780131-g9t7g577rsafrl40ko75k1i5kc435ns6.apps.googleusercontent.com",
1826
"client_type": 3

lib/login.dart

+198-15
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,48 @@
1+
import 'dart:async';
2+
import 'dart:math';
3+
4+
import 'package:app_links/app_links.dart';
5+
import 'package:flutter/foundation.dart';
16
import 'package:flutter/material.dart';
27
import 'package:firebase_auth/firebase_auth.dart';
8+
import 'package:google_sign_in/google_sign_in.dart';
9+
import 'package:url_launcher/url_launcher.dart';
10+
11+
class GoogleSignInArgs {
12+
const GoogleSignInArgs(
13+
{required this.clientId,
14+
required this.redirectUri,
15+
required this.scope,
16+
required this.responseType,
17+
required this.prompt,
18+
required this.nonce});
19+
20+
/// The OAuth client id of your Google app.
21+
///
22+
/// See https://developers.google.com/identity/gsi/web/guides/get-google-api-clientid.
23+
final String clientId;
24+
25+
// The authentication scopes.
26+
///
27+
/// See https://developers.google.com/identity/protocols/oauth2/scopes.
28+
final String scope;
29+
30+
/// The authentication response types (e.g. token, id_token, code).
31+
final String responseType;
32+
33+
/// A list of prompts to present the user.
34+
final String prompt;
35+
36+
/// Cryptographic nonce used to prevent replay attacks.
37+
///
38+
/// It may be required when using an id_token as a response type.
39+
/// The response from Google should include the same nonce inside the id_token.
40+
final String nonce;
41+
42+
/// The URL where the user will be redirected after
43+
/// completing the authentication in the browser.
44+
final String redirectUri;
45+
}
346

447
class LoginPage extends StatefulWidget {
548
const LoginPage({super.key});
@@ -12,9 +55,66 @@ class _LoginPageState extends State<LoginPage> {
1255
final TextEditingController _emailController = TextEditingController();
1356
final TextEditingController _passwordController = TextEditingController();
1457
final FirebaseAuth _auth = FirebaseAuth.instance;
15-
bool _isLoggedIn = false;
58+
// bool _isLoggedIn = false;
1659
bool _isError = false;
1760
String _loggedInEmail = '';
61+
late StreamSubscription<Uri> listener;
62+
@override
63+
void initState() {
64+
super.initState();
65+
if (defaultTargetPlatform == TargetPlatform.macOS ||
66+
defaultTargetPlatform == TargetPlatform.linux ||
67+
defaultTargetPlatform == TargetPlatform.windows) {
68+
listener = AppLinks().uriLinkStream.listen((uri) async {
69+
if (uri.scheme != 'notease') return;
70+
if (uri.path != '/google-auth') return;
71+
72+
final authenticationIdToken = uri.queryParameters['id_token'];
73+
final authenticationAccessToken = uri.queryParameters['access_token'];
74+
75+
// Authentication completed, you may use the access token to
76+
// access user-specific data from Google.
77+
//
78+
// At this step, you may want to verify that the nonce
79+
// from the id token matches the one you generated previously.
80+
//
81+
// Example:
82+
// Signing-in with Firebase Auth credentials using the retrieved
83+
// id and access tokens.
84+
// print("signing in...");
85+
setState(() {
86+
_loggedInEmail = "Signing you in...";
87+
});
88+
final credential = GoogleAuthProvider.credential(
89+
idToken: authenticationIdToken,
90+
accessToken: authenticationAccessToken,
91+
);
92+
93+
await _auth.signInWithCredential(credential);
94+
if (_auth.currentUser == null) {
95+
setState(() {
96+
_loggedInEmail = "Something went wrong!";
97+
});
98+
}
99+
});
100+
}
101+
_auth.authStateChanges().listen((User? user) {
102+
if (user != null) {
103+
// if (mounted) {
104+
// setState(() {
105+
// _isLoggedIn = true;
106+
// _loggedInEmail = user.email ?? '';
107+
// });
108+
// }
109+
if (defaultTargetPlatform == TargetPlatform.macOS ||
110+
defaultTargetPlatform == TargetPlatform.linux ||
111+
defaultTargetPlatform == TargetPlatform.windows) {
112+
listener.cancel();
113+
}
114+
Navigator.pop(context);
115+
}
116+
});
117+
}
18118

19119
@override
20120
Widget build(BuildContext context) {
@@ -48,35 +148,118 @@ class _LoginPageState extends State<LoginPage> {
48148
onPressed: () async {
49149
try {
50150
if (_auth.currentUser == null) {
51-
final UserCredential userCredential =
52-
await _auth.signInWithEmailAndPassword(
151+
_auth.signInWithEmailAndPassword(
53152
email: _emailController.text,
54153
password: _passwordController.text,
55154
);
56-
final User? user = userCredential.user;
155+
}
156+
} on Exception catch (e) {
157+
if (mounted) {
57158
setState(() {
58-
_isLoggedIn = true;
59-
_loggedInEmail = user?.email ?? '';
60-
Navigator.pop(context);
159+
_isError = true;
160+
_loggedInEmail = 'Error: ${e.toString()}';
61161
});
62162
}
163+
}
164+
},
165+
child: const Text('Login'),
166+
),
167+
if (_isError) Text(_loggedInEmail) else const Text('Not logged in'),
168+
169+
// Add a Google sign-in button
170+
ElevatedButton(
171+
onPressed: () async {
172+
try {
173+
await signInWithGoogle();
63174
} on Exception catch (e) {
64175
setState(() {
65176
_isError = true;
66-
_loggedInEmail = 'Error: ${e.toString()}';
177+
_loggedInEmail = e.toString();
67178
});
68179
}
69180
},
70-
child: const Text('Login'),
181+
child: const Text('Sign in with Google'),
71182
),
72-
if (_isLoggedIn)
73-
Text('Logged in as $_loggedInEmail')
74-
else if (_isError)
75-
Text(_loggedInEmail)
76-
else
77-
const Text('Not logged in')
78183
],
79184
),
80185
);
81186
}
187+
188+
Future<bool> signInWithGoogle() async {
189+
if (kIsWeb) {
190+
// Create a new provider
191+
GoogleAuthProvider googleProvider = GoogleAuthProvider();
192+
193+
// googleProvider
194+
// .addScope('https://www.googleapis.com/auth/contacts.readonly');
195+
googleProvider.setCustomParameters({'login_hint': '[email protected]'});
196+
197+
// Once signed in, return the UserCredential
198+
_auth.signInWithPopup(googleProvider);
199+
return true;
200+
} else if (defaultTargetPlatform == TargetPlatform.android ||
201+
defaultTargetPlatform == TargetPlatform.iOS) {
202+
final GoogleSignInAccount? googleUser = await GoogleSignIn().signIn();
203+
204+
// Obtain the auth details from the request
205+
final GoogleSignInAuthentication? googleAuth =
206+
await googleUser?.authentication;
207+
208+
// Create a new credential
209+
final credential = GoogleAuthProvider.credential(
210+
accessToken: googleAuth?.accessToken,
211+
idToken: googleAuth?.idToken,
212+
);
213+
// Once signed in, return the UserCredential
214+
_auth.signInWithCredential(credential);
215+
return true;
216+
} else if (defaultTargetPlatform == TargetPlatform.macOS ||
217+
defaultTargetPlatform == TargetPlatform.linux ||
218+
defaultTargetPlatform == TargetPlatform.windows) {
219+
final signInArgs = GoogleSignInArgs(
220+
// The OAuth client id of your Google app.
221+
clientId:
222+
'967077780131-g9t7g577rsafrl40ko75k1i5kc435ns6.apps.googleusercontent.com',
223+
// The URI to your redirect web page.
224+
redirectUri: 'https://notease-redirect.web.app',
225+
// Basic scopes to retrieve the user's email and profile details.
226+
scope: [
227+
'https://www.googleapis.com/auth/userinfo.email',
228+
'https://www.googleapis.com/auth/userinfo.profile',
229+
].join(' '),
230+
responseType: 'token id_token',
231+
// Prompts the user for consent and to select an account.
232+
prompt: 'select_account consent',
233+
// Random secure nonce to be checked after the sign-in flow completes.
234+
nonce: generateNonce(),
235+
);
236+
final authUri = Uri(
237+
scheme: 'https',
238+
host: 'accounts.google.com',
239+
path: '/o/oauth2/v2/auth',
240+
queryParameters: {
241+
'scope': signInArgs.scope,
242+
'response_type': signInArgs.responseType,
243+
'redirect_uri': signInArgs.redirectUri,
244+
'client_id': signInArgs.clientId,
245+
'nonce': signInArgs.nonce,
246+
'prompt': signInArgs.prompt,
247+
},
248+
);
249+
await launchUrl(authUri);
250+
throw Exception("Check your browser to login!");
251+
}
252+
throw UnimplementedError("Error!");
253+
}
254+
255+
String generateNonce({int length = 32}) {
256+
const characters =
257+
'0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._';
258+
final random = Random.secure();
259+
260+
return List.generate(
261+
length,
262+
(_) => characters[random.nextInt(characters.length)],
263+
).join();
264+
}
82265
}

lib/main.dart

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,21 @@
1+
// import 'dart:io';
2+
3+
import 'package:flutter/foundation.dart';
14
import 'package:flutter/material.dart';
25
import 'package:testnote/home.dart';
36
import 'package:firebase_core/firebase_core.dart';
47
import 'firebase_options.dart';
8+
import 'package:testnote/none.dart'
9+
if (dart.library.io) 'package:testnote/windows.dart';
510

611
void main() async {
712
WidgetsFlutterBinding.ensureInitialized();
813
await Firebase.initializeApp(
914
options: DefaultFirebaseOptions.currentPlatform,
1015
);
16+
if (defaultTargetPlatform == TargetPlatform.windows) {
17+
await register('notease');
18+
}
1119
runApp(const NotepadApp());
1220
}
1321

@@ -17,7 +25,7 @@ class NotepadApp extends StatelessWidget {
1725
@override
1826
Widget build(BuildContext context) {
1927
return MaterialApp(
20-
title: 'Notepad',
28+
title: 'Notease',
2129
theme: ThemeData(
2230
primarySwatch: Colors.purple,
2331
visualDensity: VisualDensity.adaptivePlatformDensity,

lib/none.dart

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Future<void> register(String scheme) async {}

lib/register.dart

Whitespace-only changes.

lib/windows.dart

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import 'dart:io';
2+
3+
import 'package:win32_registry/win32_registry.dart';
4+
5+
Future<void> register(String scheme) async {
6+
String appPath = Platform.resolvedExecutable;
7+
8+
String protocolRegKey = 'Software\\Classes\\$scheme';
9+
RegistryValue protocolRegValue = const RegistryValue(
10+
'URL Protocol',
11+
RegistryValueType.string,
12+
'',
13+
);
14+
String protocolCmdRegKey = 'shell\\open\\command';
15+
RegistryValue protocolCmdRegValue = RegistryValue(
16+
'',
17+
RegistryValueType.string,
18+
'"$appPath" "%1"',
19+
);
20+
21+
final regKey = Registry.currentUser.createKey(protocolRegKey);
22+
regKey.createValue(protocolRegValue);
23+
regKey.createKey(protocolCmdRegKey).createValue(protocolCmdRegValue);
24+
}

linux/flutter/generated_plugin_registrant.cc

+8
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,14 @@
66

77
#include "generated_plugin_registrant.h"
88

9+
#include <gtk/gtk_plugin.h>
10+
#include <url_launcher_linux/url_launcher_plugin.h>
911

1012
void fl_register_plugins(FlPluginRegistry* registry) {
13+
g_autoptr(FlPluginRegistrar) gtk_registrar =
14+
fl_plugin_registry_get_registrar_for_plugin(registry, "GtkPlugin");
15+
gtk_plugin_register_with_registrar(gtk_registrar);
16+
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
17+
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
18+
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
1119
}

linux/flutter/generated_plugins.cmake

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
#
44

55
list(APPEND FLUTTER_PLUGIN_LIST
6+
gtk
7+
url_launcher_linux
68
)
79

810
list(APPEND FLUTTER_FFI_PLUGIN_LIST

0 commit comments

Comments
 (0)