mobile bluesky app made with flutter
lazurite.stormlightlabs.org/
mobile
bluesky
flutter
1import 'dart:async';
2
3import 'package:flutter/material.dart';
4import 'package:flutter_bloc/flutter_bloc.dart';
5import 'package:go_router/go_router.dart';
6import 'package:lazurite/features/auth/bloc/auth_bloc.dart';
7
8class OAuthCallbackScreen extends StatefulWidget {
9 const OAuthCallbackScreen({required this.callbackUri, super.key});
10
11 static const String routePath = '/oauth/callback';
12 static const String compatibilityRoutePath = '/callback';
13
14 final Uri callbackUri;
15
16 @override
17 State<OAuthCallbackScreen> createState() => _OAuthCallbackScreenState();
18}
19
20class _OAuthCallbackScreenState extends State<OAuthCallbackScreen> {
21 bool _submitted = false;
22
23 @override
24 void initState() {
25 super.initState();
26 unawaited(_consumeCallback());
27 }
28
29 Future<void> _consumeCallback() async {
30 final handled = await context.read<AuthBloc>().handleOAuthRedirectUri(widget.callbackUri);
31 if (!mounted) {
32 return;
33 }
34
35 if (!handled) {
36 _submitted = true;
37 context.go('/login');
38 return;
39 }
40
41 _submitted = true;
42 context.go('/login');
43 }
44
45 @override
46 Widget build(BuildContext context) {
47 final busy = !_submitted;
48 return Scaffold(
49 body: Center(
50 child: Padding(
51 padding: const EdgeInsets.all(24),
52 child: Column(
53 mainAxisSize: MainAxisSize.min,
54 children: [
55 if (busy)
56 const SizedBox(width: 28, height: 28, child: CircularProgressIndicator(strokeWidth: 2.4))
57 else
58 const Icon(Icons.check_circle_outline, size: 30),
59 const SizedBox(height: 12),
60 Text(
61 busy ? 'Finalizing sign in...' : 'Returning to Lazurite...',
62 style: Theme.of(context).textTheme.titleMedium,
63 textAlign: TextAlign.center,
64 ),
65 ],
66 ),
67 ),
68 ),
69 );
70 }
71}