actions-test/lib/screens/settings/dialogs/password.dart
Jakob Meier 8fffafde47
Added translations using l10n
Translations are provided in *.arb* format.
Some keys have descriptions
(indicated by leading @-symbol).
Descriptions should not be copied into the translation itself.

Currently only English is supported (app_en.arb),
but German is planned.

Apparently weblate merged .arb support at some time,
so it would be nice to enable community translations at some point.
2023-03-29 15:14:27 +02:00

146 lines
5.4 KiB
Dart

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<StatefulWidget> createState() => _ChangePasswordDialogState();
}
class _ChangePasswordDialogState extends State<ChangePasswordDialog> {
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<User>();
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),
)
],
);
}
}