]> git.proxmox.com Git - flutter/proxmox_login_manager.git/blob - lib/proxmox_tfa_form.dart
migrate to sound null safety
[flutter/proxmox_login_manager.git] / lib / proxmox_tfa_form.dart
1 import 'package:flutter/material.dart';
2 import 'package:proxmox_dart_api_client/proxmox_dart_api_client.dart';
3 import 'package:proxmox_login_manager/proxmox_login_form.dart';
4
5 class ProxmoxTfaForm extends StatefulWidget {
6 final ProxmoxApiClient? apiClient;
7
8 const ProxmoxTfaForm({Key? key, this.apiClient}) : super(key: key);
9
10 @override
11 _ProxmoxTfaFormState createState() => _ProxmoxTfaFormState();
12 }
13
14 class _ProxmoxTfaFormState extends State<ProxmoxTfaForm> {
15 final TextEditingController _codeController = TextEditingController();
16 bool _isLoading = false;
17 @override
18 Widget build(BuildContext context) {
19 return Theme(
20 data: ThemeData.dark().copyWith(accentColor: Color(0xFFE47225)),
21 child: Scaffold(
22 backgroundColor: Theme.of(context).primaryColor,
23 extendBodyBehindAppBar: true,
24 appBar: AppBar(
25 elevation: 0.0,
26 backgroundColor: Colors.transparent,
27 leading: IconButton(
28 icon: Icon(Icons.close),
29 onPressed: () => Navigator.of(context).pop(),
30 ),
31 ),
32 body: Stack(
33 alignment: Alignment.center,
34 children: [
35 SingleChildScrollView(
36 child: ConstrainedBox(
37 constraints: BoxConstraints.tightFor(
38 height: MediaQuery.of(context).size.height),
39 child: Padding(
40 padding: const EdgeInsets.all(8.0),
41 child: Column(
42 mainAxisAlignment: MainAxisAlignment.start,
43 crossAxisAlignment: CrossAxisAlignment.center,
44 children: <Widget>[
45 Padding(
46 padding: const EdgeInsets.fromLTRB(0, 100.0, 0, 30.0),
47 child: Icon(
48 Icons.lock,
49 size: 48,
50 ),
51 ),
52 Text(
53 'Verify',
54 style: TextStyle(
55 fontSize: 36,
56 color: Colors.white,
57 fontWeight: FontWeight.bold),
58 ),
59 Text(
60 'Check your second factor provider',
61 style: TextStyle(
62 color: Colors.white38, fontWeight: FontWeight.bold),
63 ),
64 Padding(
65 padding: const EdgeInsets.fromLTRB(0, 50.0, 0, 8.0),
66 child: Container(
67 width: 150,
68 child: TextField(
69 controller: _codeController,
70 textAlign: TextAlign.center,
71 decoration: InputDecoration(labelText: 'Code'),
72 autofocus: true,
73 onSubmitted: (value) => _submitTfaCode()),
74 ),
75 ),
76 Expanded(
77 child: Align(
78 alignment: Alignment.bottomCenter,
79 child: Container(
80 width: MediaQuery.of(context).size.width,
81 child: FlatButton(
82 onPressed: () => _submitTfaCode(),
83 color: Color(0xFFE47225),
84 child: Text('Continue'),
85 disabledColor: Colors.grey,
86 ),
87 ),
88 ),
89 ),
90 ],
91 ),
92 ),
93 ),
94 ),
95 if (_isLoading)
96 ProxmoxProgressOverlay(
97 message: 'Verify One-Time password...',
98 )
99 ],
100 ),
101 ),
102 );
103 }
104
105 Future<void> _submitTfaCode() async {
106 setState(() {
107 _isLoading = true;
108 });
109 try {
110 final client =
111 await widget.apiClient!.finishTfaChallenge(_codeController.text);
112 Navigator.of(context).pop(client);
113 } on ProxmoxApiException catch (e) {
114 showDialog(
115 context: context,
116 builder: (context) => ProxmoxApiErrorDialog(
117 exception: e,
118 ),
119 );
120 } catch (e, trace) {
121 print(e);
122 print(trace);
123 showDialog(
124 context: context,
125 builder: (context) => AlertDialog(
126 title: Text('Connection error'),
127 content: Text('Could not establish connection.'),
128 actions: [
129 FlatButton(
130 onPressed: () => Navigator.of(context).pop(),
131 child: Text('Close'),
132 ),
133 ],
134 ),
135 );
136 }
137 setState(() {
138 _isLoading = false;
139 });
140 }
141 }