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