two_factor_authentication_page.dart 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. import 'package:flutter/material.dart';
  2. import 'package:flutter/services.dart';
  3. import 'package:photos/services/user_service.dart';
  4. import 'package:photos/ui/lifecycle_event_handler.dart';
  5. import 'package:pinput/pin_put/pin_put.dart';
  6. class TwoFactorAuthenticationPage extends StatefulWidget {
  7. final String sessionID;
  8. const TwoFactorAuthenticationPage(this.sessionID, {Key? key})
  9. : super(key: key);
  10. @override
  11. State<TwoFactorAuthenticationPage> createState() =>
  12. _TwoFactorAuthenticationPageState();
  13. }
  14. class _TwoFactorAuthenticationPageState
  15. extends State<TwoFactorAuthenticationPage> {
  16. final _pinController = TextEditingController();
  17. final _pinPutDecoration = BoxDecoration(
  18. border: Border.all(color: const Color.fromRGBO(45, 194, 98, 1.0)),
  19. borderRadius: BorderRadius.circular(15.0),
  20. );
  21. String _code = "";
  22. late LifecycleEventHandler _lifecycleEventHandler;
  23. @override
  24. void initState() {
  25. _lifecycleEventHandler = LifecycleEventHandler(
  26. resumeCallBack: () async {
  27. if (mounted) {
  28. final data = await Clipboard.getData(Clipboard.kTextPlain);
  29. if (data != null && data.text != null && data.text!.length == 6) {
  30. _pinController.text = data.text!;
  31. }
  32. }
  33. },
  34. );
  35. WidgetsBinding.instance.addObserver(_lifecycleEventHandler);
  36. super.initState();
  37. }
  38. @override
  39. void dispose() {
  40. WidgetsBinding.instance.removeObserver(_lifecycleEventHandler);
  41. super.dispose();
  42. }
  43. @override
  44. Widget build(BuildContext context) {
  45. return Scaffold(
  46. appBar: AppBar(
  47. title: const Text(
  48. "Two-factor authentication",
  49. ),
  50. ),
  51. body: _getBody(),
  52. );
  53. }
  54. Widget _getBody() {
  55. return Column(
  56. crossAxisAlignment: CrossAxisAlignment.stretch,
  57. mainAxisAlignment: MainAxisAlignment.center,
  58. mainAxisSize: MainAxisSize.max,
  59. children: [
  60. const Text(
  61. "Enter the 6-digit code from\nyour authenticator app",
  62. style: TextStyle(
  63. height: 1.4,
  64. fontSize: 16,
  65. ),
  66. textAlign: TextAlign.center,
  67. ),
  68. const Padding(padding: EdgeInsets.all(32)),
  69. Padding(
  70. padding: const EdgeInsets.fromLTRB(40, 0, 40, 0),
  71. child: PinPut(
  72. fieldsCount: 6,
  73. onSubmit: (String code) {
  74. _verifyTwoFactorCode(code);
  75. },
  76. onChanged: (String pin) {
  77. setState(() {
  78. _code = pin;
  79. });
  80. },
  81. controller: _pinController,
  82. submittedFieldDecoration: _pinPutDecoration.copyWith(
  83. borderRadius: BorderRadius.circular(20.0),
  84. ),
  85. selectedFieldDecoration: _pinPutDecoration,
  86. followingFieldDecoration: _pinPutDecoration.copyWith(
  87. borderRadius: BorderRadius.circular(5.0),
  88. border: Border.all(
  89. color: const Color.fromRGBO(45, 194, 98, 0.5),
  90. ),
  91. ),
  92. inputDecoration: const InputDecoration(
  93. focusedBorder: InputBorder.none,
  94. border: InputBorder.none,
  95. counterText: '',
  96. ),
  97. autofocus: true,
  98. ),
  99. ),
  100. const Padding(padding: EdgeInsets.all(24)),
  101. Container(
  102. padding: const EdgeInsets.fromLTRB(80, 0, 80, 0),
  103. width: double.infinity,
  104. height: 64,
  105. child: OutlinedButton(
  106. onPressed: _code.length == 6
  107. ? () async {
  108. _verifyTwoFactorCode(_code);
  109. }
  110. : null,
  111. child: const Text("Verify"),
  112. ),
  113. ),
  114. const Padding(padding: EdgeInsets.all(30)),
  115. GestureDetector(
  116. behavior: HitTestBehavior.opaque,
  117. onTap: () {
  118. UserService.instance.recoverTwoFactor(context, widget.sessionID);
  119. },
  120. child: Container(
  121. padding: const EdgeInsets.all(10),
  122. child: const Center(
  123. child: Text(
  124. "Lost device?",
  125. style: TextStyle(
  126. decoration: TextDecoration.underline,
  127. fontSize: 12,
  128. ),
  129. ),
  130. ),
  131. ),
  132. ),
  133. ],
  134. );
  135. }
  136. Future<void> _verifyTwoFactorCode(String code) async {
  137. await UserService.instance.verifyTwoFactor(context, widget.sessionID, code);
  138. }
  139. }