11 import 'package:flutter/foundation.dart' show kIsWeb;
22 import 'package:flutter/material.dart';
33 import 'package:flutter_facebook_auth/flutter_facebook_auth.dart';
44 import 'package:parse_server_sdk_flutter/parse_server_sdk.dart';
55
66 void main() async {
77 WidgetsFlutterBinding.ensureInitialized();
88
99 final keyApplicationId = 'YOUR_APP_ID_HERE';
1010 final keyClientKey = 'YOUR_CLIENT_KEY_HERE';
1111 final keyParseServerUrl = 'https://parseapi.back4app.com';
1212
1313 await Parse().initialize(keyApplicationId, keyParseServerUrl,
1414 clientKey: keyClientKey, debug: true);
1515
1616 if (kIsWeb) {
1717
1818 FacebookAuth.i.webInitialize(
1919 appId: "YOUR_FACEBOOK_APP_ID",
2020 cookie: true,
2121 xfbml: true,
2222 version: "v9.0",
2323 );
2424 }
2525
2626 runApp(MyApp());
2727 }
2828
2929 class MyApp extends StatelessWidget {
3030 Future<bool> hasUserLogged() async {
3131 ParseUser? currentUser = await ParseUser.currentUser() as ParseUser?;
3232 if (currentUser == null) {
3333 return false;
3434 }
3535
3636 final ParseResponse? parseResponse =
3737 await ParseUser.getCurrentUserFromServer(currentUser.sessionToken!);
3838
3939 if (parseResponse?.success == null || !parseResponse!.success) {
4040
4141 await currentUser.logout();
4242 return false;
4343 } else {
4444 return true;
4545 }
4646 }
4747
4848 @override
4949 Widget build(BuildContext context) {
5050 return MaterialApp(
5151 title: 'Flutter - Sign In with Facebook',
5252 theme: ThemeData(
5353 primarySwatch: Colors.blue,
5454 visualDensity: VisualDensity.adaptivePlatformDensity,
5555 ),
5656 home: FutureBuilder<bool>(
5757 future: hasUserLogged(),
5858 builder: (context, snapshot) {
5959 switch (snapshot.connectionState) {
6060 case ConnectionState.none:
6161 case ConnectionState.waiting:
6262 return Scaffold(
6363 body: Center(
6464 child: Container(
6565 width: 100,
6666 height: 100,
6767 child: CircularProgressIndicator()),
6868 ),
6969 );
7070 default:
7171 if (snapshot.hasData && snapshot.data!) {
7272 return UserPage();
7373 } else {
7474 return HomePage();
7575 }
7676 }
7777 }),
7878 );
7979 }
8080 }
8181
8282 class HomePage extends StatefulWidget {
8383 @override
8484 _HomePageState createState() => _HomePageState();
8585 }
8686
8787 class _HomePageState extends State<HomePage> {
8888 @override
8989 Widget build(BuildContext context) {
9090 return Scaffold(
9191 appBar: AppBar(
9292 title: const Text('Flutter - Sign In with Facebook'),
9393 ),
9494 body: Center(
9595 child: SingleChildScrollView(
9696 padding: const EdgeInsets.all(8),
9797 child: Column(
9898 crossAxisAlignment: CrossAxisAlignment.stretch,
9999 children: [
100100 Container(
101101 height: 200,
102102 child: Image.network(
103103 'http://blog.back4app.com/wp-content/uploads/2017/11/logo-b4a-1-768x175-1.png'),
104104 ),
105105 Center(
106106 child: const Text('Flutter on Back4App',
107107 style:
108108 TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
109109 ),
110110 SizedBox(
111111 height: 100,
112112 ),
113113 Container(
114114 height: 50,
115115 child: ElevatedButton(
116116 child: const Text('Sign In with Facebook'),
117117 onPressed: () => doSignInFacebook(),
118118 ),
119119 ),
120120 SizedBox(
121121 height: 16,
122122 ),
123123 ],
124124 ),
125125 ),
126126 ));
127127 }
128128
129129 void doSignInFacebook() async {
130130 late ParseResponse parseResponse;
131131 try {
132132
133133 final AccessToken? currentAccessToken =
134134 await FacebookAuth.instance.accessToken;
135135 if (currentAccessToken != null) {
136136
137137 await FacebookAuth.instance.logOut();
138138 }
139139
140140
141141 final LoginResult result = await FacebookAuth.instance.login();
142142
143143 if (result.status != LoginStatus.success) {
144144 Message.showError(context: context, message: result.message!);
145145 return;
146146 }
147147
148148 final AccessToken accessToken = result.accessToken!;
149149
150150
151151
152152
153153
154154 parseResponse = await ParseUser.loginWith('facebook',
155155 facebook(accessToken.token, accessToken.userId, accessToken.expires));
156156
157157 if (parseResponse.success) {
158158 final ParseUser parseUser = await ParseUser.currentUser() as ParseUser;
159159
160160
161161 final userData = await FacebookAuth.instance.getUserData();
162162
163163
164164 if (userData.containsKey('email')) {
165165 parseUser.emailAddress = userData['email'];
166166 }
167167
168168 if (userData.containsKey('name')) {
169169 parseUser.set<String>('name', userData['name']);
170170 }
171171 if (userData["picture"]["data"]["url"] != null) {
172172 parseUser.set<String>('photoURL', userData["picture"]["data"]["url"]);
173173 }
174174
175175 await FacebookAuth.instance.logOut();
176176 parseResponse = await parseUser.save();
177177
178178 if (parseResponse.success) {
179179 Message.showSuccess(
180180 context: context,
181181 message: 'User was successfully with Sign In Facebook!',
182182 onPressed: () async {
183183 Navigator.pushAndRemoveUntil(
184184 context,
185185 MaterialPageRoute(builder: (context) => UserPage()),
186186 (Route<dynamic> route) => false,
187187 );
188188 });
189189 } else {
190190 Message.showError(
191191 context: context, message: parseResponse.error!.message);
192192 }
193193 } else {
194194 Message.showError(
195195 context: context, message: parseResponse.error!.message);
196196 }
197197 } on Exception catch (e) {
198198 print(e.toString());
199199 Message.showError(context: context, message: e.toString());
200200 }
201201 }
202202 }
203203
204204 class UserPage extends StatelessWidget {
205205 Future<ParseUser?> getUser() async {
206206 return await ParseUser.currentUser() as ParseUser?;
207207 }
208208
209209 @override
210210 Widget build(BuildContext context) {
211211 void doUserLogout() async {
212212 final currentUser = await ParseUser.currentUser() as ParseUser;
213213 var response = await currentUser.logout();
214214 if (response.success) {
215215 Message.showSuccess(
216216 context: context,
217217 message: 'User was successfully logout!',
218218 onPressed: () {
219219 Navigator.pushAndRemoveUntil(
220220 context,
221221 MaterialPageRoute(builder: (context) => HomePage()),
222222 (Route<dynamic> route) => false,
223223 );
224224 });
225225 } else {
226226 Message.showError(context: context, message: response.error!.message);
227227 }
228228 }
229229
230230 return Scaffold(
231231 appBar: AppBar(
232232 title: Text('Flutter - Sign In with Facebook'),
233233 ),
234234 body: FutureBuilder<ParseUser?>(
235235 future: getUser(),
236236 builder: (context, snapshot) {
237237 switch (snapshot.connectionState) {
238238 case ConnectionState.none:
239239 case ConnectionState.waiting:
240240 return Center(
241241 child: Container(
242242 width: 100,
243243 height: 100,
244244 child: CircularProgressIndicator()),
245245 );
246246 default:
247247 return Padding(
248248 padding: const EdgeInsets.all(8.0),
249249 child: Column(
250250 crossAxisAlignment: CrossAxisAlignment.stretch,
251251 mainAxisAlignment: MainAxisAlignment.center,
252252 children: [
253253 Center(
254254 child: Text(
255255 'Hello, ${snapshot.data!.get<String>('name')}')),
256256 SizedBox(
257257 height: 16,
258258 ),
259259 Container(
260260 height: 50,
261261 child: ElevatedButton(
262262 child: const Text('Logout'),
263263 onPressed: () => doUserLogout(),
264264 ),
265265 ),
266266 ],
267267 ),
268268 );
269269 }
270270 }));
271271 }
272272 }
273273
274274 class Message {
275275 static void showSuccess(
276276 {required BuildContext context,
277277 required String message,
278278 VoidCallback? onPressed}) {
279279 showDialog(
280280 context: context,
281281 builder: (BuildContext context) {
282282 return AlertDialog(
283283 title: const Text("Success!"),
284284 content: Text(message),
285285 actions: <Widget>[
286286 new ElevatedButton(
287287 child: const Text("OK"),
288288 onPressed: () {
289289 Navigator.of(context).pop();
290290 if (onPressed != null) {
291291 onPressed();
292292 }
293293 },
294294 ),
295295 ],
296296 );
297297 },
298298 );
299299 }
300300
301301 static void showError(
302302 {required BuildContext context,
303303 required String message,
304304 VoidCallback? onPressed}) {
305305 showDialog(
306306 context: context,
307307 builder: (BuildContext context) {
308308 return AlertDialog(
309309 title: const Text("Error!"),
310310 content: Text(message),
311311 actions: <Widget>[
312312 new ElevatedButton(
313313 child: const Text("OK"),
314314 onPressed: () {
315315 Navigator.of(context).pop();
316316 if (onPressed != null) {
317317 onPressed();
318318 }
319319 },
320320 ),
321321 ],
322322 );
323323 },
324324 );
325325 }
326326 }