import 'package:flutter/material.dart'; import 'package:outbag_app/backend/crypto.dart'; import 'package:outbag_app/backend/request.dart'; import 'package:outbag_app/backend/user.dart'; import 'package:outbag_app/tools/fetch_wrapper.dart'; import 'package:outbag_app/tools/snackbar.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:provider/provider.dart'; class ChangePasswordDialog extends StatefulWidget { const ChangePasswordDialog({super.key}); @override State createState() => _ChangePasswordDialogState(); } class _ChangePasswordDialogState extends State { final TextEditingController _ctrOldPassword = TextEditingController(); final TextEditingController _ctrNewPassword = TextEditingController(); final TextEditingController _ctrNewPasswordRepeat = TextEditingController(); @override Widget build(BuildContext context) { return AlertDialog( title: Text(AppLocalizations.of(context)!.changeThemeTitle), icon: const Icon(Icons.password), content: SingleChildScrollView( child: Column( children: [ Padding( padding: const EdgeInsets.all(8), child: TextField( controller: _ctrOldPassword, keyboardType: TextInputType.visiblePassword, obscureText: true, decoration: InputDecoration( prefixIcon: const Icon(Icons.lock), labelText: AppLocalizations.of(context)!.inputOldPasswordLabel, hintText: AppLocalizations.of(context)!.inputOldPasswordHint, helperText: AppLocalizations.of(context)!.inputOldPasswordHelp, border: const OutlineInputBorder(), ), ), ), Padding( padding: const EdgeInsets.all(8), child: TextField( controller: _ctrNewPassword, keyboardType: TextInputType.visiblePassword, obscureText: true, decoration: InputDecoration( prefixIcon: const Icon(Icons.lock), labelText: AppLocalizations.of(context)!.inputNewPasswordLabel, hintText: AppLocalizations.of(context)!.inputNewPasswordHint, helperText: AppLocalizations.of(context)!.inputNewPasswordHelp, border: const OutlineInputBorder(), ), ), ), Padding( padding: const EdgeInsets.all(8), child: TextField( controller: _ctrNewPasswordRepeat, keyboardType: TextInputType.visiblePassword, obscureText: true, decoration: InputDecoration( prefixIcon: const Icon(Icons.lock), labelText: AppLocalizations.of(context)!.inputNewPasswordRepeatLabel, hintText: AppLocalizations.of(context)!.inputNewPasswordRepeatHint, helperText: AppLocalizations.of(context)!.inputNewPasswordRepeatHelp, border: const OutlineInputBorder(), ), ), ), ], )), actions: [ TextButton( onPressed: () { // close popup Navigator.of(context).pop(); }, child: Text(AppLocalizations.of(context)!.cancel), ), FilledButton( onPressed: () async { final scaffMgr = ScaffoldMessenger.of(context); final nav = Navigator.of(context); final user = context.read(); final trans = AppLocalizations.of(context); // validate password if (_ctrNewPassword.text.length < 6) { // password has to be at least 6 characters long showSimpleSnackbar(scaffMgr, text: trans!.errorPasswordLength, action: trans.dismiss); _ctrNewPasswordRepeat.clear(); return; } if (_ctrNewPassword.text != _ctrNewPasswordRepeat.text) { // new passwords do not match showSimpleSnackbar(scaffMgr, text: trans!.errorPasswordsDoNotMatch, action: trans.dismiss); _ctrNewPasswordRepeat.clear(); return; } if (hashPassword(_ctrOldPassword.text) != user.password) { // current password wrong showSimpleSnackbar(scaffMgr, text: trans!.errorOldPasswordWrong, action: trans.dismiss); _ctrOldPassword.clear(); return; } final password = hashPassword(_ctrNewPassword.text); // send request doNetworkRequest(scaffMgr, req: () => postWithCreadentials( path: 'changePassword', target: user.server, body: {'accountKey': password}, credentials: user), onOK: (_) async { // update local user struct final updatedUser = User( username: user.username, password: password, server: user.server); await updatedUser.toDisk(); }, after: () { // close popup nav.pop(); }); }, child: Text(AppLocalizations.of(context)!.changeThemeTitle), ) ], ); } }