import_accounts.dart 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. import 'package:flutter/material.dart';
  2. import 'package:barcode_scan2/barcode_scan2.dart';
  3. import 'package:pb_authenticator_totp/otpauth_migration.dart';
  4. import 'package:pb_authenticator_totp/totp_item.dart';
  5. import 'package:provider/provider.dart';
  6. import '../state/app_state.dart';
  7. import '../l10n/app_localizations.dart';
  8. class ImportAccountsPage extends StatefulWidget {
  9. const ImportAccountsPage({super.key});
  10. @override
  11. State<ImportAccountsPage> createState() => _ImportAccountsPageState();
  12. }
  13. class _ImportAccountsPageState extends State<ImportAccountsPage> {
  14. bool _importing = false;
  15. String? _resultMessage;
  16. Future<void> _scanAndImport() async {
  17. setState(() {
  18. _importing = true;
  19. _resultMessage = null;
  20. });
  21. try {
  22. final scanResult = await BarcodeScanner.scan();
  23. final uri = scanResult.rawContent;
  24. if (uri.isEmpty) {
  25. setState(() {
  26. _importing = false;
  27. _resultMessage = AppLocalizations.of(context)?.errIncorrectFormat ?? 'Scanned code is of incorrect format';
  28. });
  29. return;
  30. }
  31. final uris = OtpAuthMigration().decode(uri);
  32. if (uris.isEmpty) {
  33. setState(() {
  34. _importing = false;
  35. _resultMessage = AppLocalizations.of(context)?.errIncorrectFormat ?? 'Scanned code is of incorrect format';
  36. });
  37. return;
  38. }
  39. final items = uris.map((u) => TotpItem.fromUri(u)).toList();
  40. final state = Provider.of<AppState>(context, listen: false);
  41. for (final item in items) {
  42. await state.addItem(item);
  43. }
  44. setState(() {
  45. _importing = false;
  46. _resultMessage = AppLocalizations.of(context)?.importSuccess ?? 'Accounts imported successfully!';
  47. });
  48. } catch (e) {
  49. setState(() {
  50. _importing = false;
  51. _resultMessage = AppLocalizations.of(context)?.errUnknown ?? 'Unknown error';
  52. });
  53. }
  54. }
  55. @override
  56. Widget build(BuildContext context) {
  57. return Scaffold(
  58. appBar: AppBar(title: Text(AppLocalizations.of(context)?.importAccounts ?? 'Import accounts')),
  59. body: Center(
  60. child: _importing
  61. ? const CircularProgressIndicator()
  62. : Column(
  63. mainAxisAlignment: MainAxisAlignment.center,
  64. children: [
  65. Icon(Icons.qr_code_2, size: 64, color: Colors.blue),
  66. const SizedBox(height: 16),
  67. Padding(
  68. padding: const EdgeInsets.symmetric(horizontal: 24.0),
  69. child: Text(
  70. AppLocalizations.of(context)?.importDescription ??
  71. 'Import your accounts from Google Authenticator or PB Authenticator by scanning a QR code.',
  72. textAlign: TextAlign.center,
  73. style: Theme.of(context).textTheme.bodyMedium,
  74. ),
  75. ),
  76. const SizedBox(height: 32),
  77. ElevatedButton.icon(
  78. icon: const Icon(Icons.qr_code_scanner),
  79. label: Text(AppLocalizations.of(context)?.importAccounts ?? 'Import accounts'),
  80. onPressed: _scanAndImport,
  81. ),
  82. if (_resultMessage != null) ...[
  83. const SizedBox(height: 24),
  84. Text(_resultMessage!, textAlign: TextAlign.center),
  85. ]
  86. ],
  87. ),
  88. ),
  89. );
  90. }
  91. }