import "package:ente_auth/l10n/l10n.dart"; import 'package:ente_auth/models/code.dart'; import 'package:ente_auth/utils/dialog_util.dart'; import 'package:ente_auth/utils/totp_util.dart'; import "package:flutter/material.dart"; class SetupEnterSecretKeyPage extends StatefulWidget { final Code? code; SetupEnterSecretKeyPage({this.code, Key? key}) : super(key: key); @override State createState() => _SetupEnterSecretKeyPageState(); } class _SetupEnterSecretKeyPageState extends State { late TextEditingController _issuerController; late TextEditingController _accountController; late TextEditingController _secretController; late bool _secretKeyObscured; @override void initState() { _issuerController = TextEditingController( text: widget.code != null ? safeDecode(widget.code!.issuer).trim() : null, ); _accountController = TextEditingController( text: widget.code != null ? safeDecode(widget.code!.account).trim() : null, ); _secretController = TextEditingController( text: widget.code != null ? widget.code!.secret : null, ); _secretKeyObscured = widget.code != null; super.initState(); } @override Widget build(BuildContext context) { final l10n = context.l10n; return Scaffold( appBar: AppBar( title: Text(l10n.importAccountPageTitle), ), body: SafeArea( child: Center( child: Padding( padding: const EdgeInsets.symmetric(vertical: 40.0, horizontal: 40), child: Column( children: [ TextFormField( // The validator receives the text that the user has entered. validator: (value) { if (value == null || value.isEmpty) { return "Please enter some text"; } return null; }, decoration: InputDecoration( hintText: l10n.codeIssuerHint, ), controller: _issuerController, autofocus: true, ), const SizedBox( height: 20, ), TextFormField( // The validator receives the text that the user has entered. validator: (value) { if (value == null || value.isEmpty) { return "Please enter some text"; } return null; }, decoration: InputDecoration( hintText: l10n.codeSecretKeyHint, suffixIcon: IconButton( onPressed: () { setState(() { _secretKeyObscured = !_secretKeyObscured; }); }, icon: _secretKeyObscured ? const Icon(Icons.visibility_off_rounded) : const Icon(Icons.visibility_rounded), ), ), obscureText: _secretKeyObscured, controller: _secretController, ), const SizedBox( height: 20, ), TextFormField( // The validator receives the text that the user has entered. validator: (value) { if (value == null || value.isEmpty) { return "Please enter some text"; } return null; }, decoration: InputDecoration( hintText: l10n.codeAccountHint, ), controller: _accountController, ), const SizedBox( height: 40, ), SizedBox( width: 400, child: OutlinedButton( onPressed: () { if ((_accountController.text.trim().isEmpty && _issuerController.text.trim().isEmpty) || _secretController.text.trim().isEmpty) { String message; if (_secretController.text.trim().isEmpty) { message = context.l10n.secretCanNotBeEmpty; } else { message = context.l10n.bothIssuerAndAccountCanNotBeEmpty; } _showIncorrectDetailsDialog(context, message: message); return; } try { final account = _accountController.text.trim(); final issuer = _issuerController.text.trim(); final secret = _secretController.text.trim().replaceAll(' ', ''); final Code newCode = widget.code == null ? Code.fromAccountAndSecret( account, issuer, secret, ) : widget.code!.copyWith( account: account, issuer: issuer, secret: secret, ); // Verify the validity of the code getOTP(newCode); Navigator.of(context).pop(newCode); } catch (e) { _showIncorrectDetailsDialog(context); } }, child: Padding( padding: const EdgeInsets.symmetric( horizontal: 16.0, vertical: 4, ), child: Text(l10n.saveAction), ), ), ) ], ), ), ), ), ); } void _showIncorrectDetailsDialog( BuildContext context, { String? message, }) { showErrorDialog( context, context.l10n.incorrectDetails, message ?? context.l10n.pleaseVerifyDetails, ); } }