Fixes for Settings Page

This commit is contained in:
Arseni
2025-12-22 21:09:58 +03:00
parent 41abf723e6
commit 47ada0691c
25 changed files with 1126 additions and 270 deletions

View File

@@ -0,0 +1,68 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:pshared/provider/account.dart';
import 'package:pweb/pages/settings/profile/account/password/form/form.dart';
import 'package:pweb/providers/password_form.dart';
import 'package:pweb/generated/i18n/app_localizations.dart';
class AccountPasswordContent extends StatelessWidget {
const AccountPasswordContent({
required this.title,
required this.successText,
required this.errorText,
required this.oldPasswordLabel,
required this.newPasswordLabel,
required this.confirmPasswordLabel,
required this.savePassword,
required this.loc,
});
final String title;
final String successText;
final String errorText;
final String oldPasswordLabel;
final String newPasswordLabel;
final String confirmPasswordLabel;
final String savePassword;
final AppLocalizations loc;
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Consumer2<AccountProvider, PasswordFormProvider>(
builder: (context, accountProvider, formProvider, _) {
final isBusy = accountProvider.isLoading || formProvider.isSaving;
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
TextButton.icon(
onPressed: isBusy ? null : formProvider.toggleExpanded,
icon: Icon(Icons.lock_outline, color: theme.colorScheme.primary),
label: Text(title, style: theme.textTheme.bodyMedium),
),
if (formProvider.isExpanded)
PasswordForm(
formProvider: formProvider,
accountProvider: accountProvider,
isBusy: accountProvider.isLoading,
oldPasswordLabel: oldPasswordLabel,
newPasswordLabel: newPasswordLabel,
confirmPasswordLabel: confirmPasswordLabel,
savePassword: savePassword,
successText: successText,
errorText: errorText,
loc: loc,
),
],
);
},
);
}
}

View File

@@ -0,0 +1,32 @@
import 'package:flutter/material.dart';
class PasswordErrorText extends StatelessWidget {
const PasswordErrorText({
super.key,
required this.errorText,
required this.gapSmall,
});
final String errorText;
final double gapSmall;
@override
Widget build(BuildContext context) {
if (errorText.isEmpty) return const SizedBox.shrink();
final theme = Theme.of(context);
return Column(
children: [
SizedBox(height: gapSmall),
Text(
errorText,
style: theme.textTheme.bodySmall?.copyWith(
color: theme.colorScheme.error,
),
),
],
);
}
}

View File

@@ -0,0 +1,101 @@
import 'package:flutter/material.dart';
import 'package:pshared/provider/account.dart';
import 'package:pshared/widgets/password/fields.dart';
import 'package:pshared/utils/snackbar.dart';
import 'package:pweb/providers/password_form.dart';
import 'package:pweb/pages/settings/profile/account/password/form/error_text.dart';
import 'package:pweb/pages/settings/profile/account/password/form/submit_button.dart';
import 'package:pweb/utils/error/snackbar.dart';
import 'package:pweb/generated/i18n/app_localizations.dart';
class PasswordForm extends StatelessWidget {
const PasswordForm({
super.key,
required this.formProvider,
required this.accountProvider,
required this.isBusy,
required this.oldPasswordLabel,
required this.newPasswordLabel,
required this.confirmPasswordLabel,
required this.savePassword,
required this.successText,
required this.errorText,
required this.loc,
});
static const double _fieldWidth = 320;
static const double _gapMedium = 12;
static const double _gapSmall = 8;
final PasswordFormProvider formProvider;
final AccountProvider accountProvider;
final bool isBusy;
final String oldPasswordLabel;
final String newPasswordLabel;
final String confirmPasswordLabel;
final String savePassword;
final String successText;
final String errorText;
final AppLocalizations loc;
@override
Widget build(BuildContext context) {
final isFormBusy = isBusy || formProvider.isSaving;
return Column(
children: [
const SizedBox(height: _gapMedium),
Form(
key: formProvider.formKey,
child: Column(
children: [
PasswordFields(
oldPasswordController: formProvider.oldPasswordController,
newPasswordController: formProvider.newPasswordController,
confirmPasswordController: formProvider.confirmPasswordController,
oldPasswordLabel: oldPasswordLabel,
newPasswordLabel: newPasswordLabel,
confirmPasswordLabel: confirmPasswordLabel,
missingPasswordError: loc.errorPasswordMissing,
passwordsDoNotMatchError: loc.passwordsDoNotMatch,
fieldWidth: _fieldWidth,
gapSmall: _gapSmall,
isEnabled: !isFormBusy,
),
const SizedBox(height: _gapMedium),
PasswordSubmitButton(
isBusy: isFormBusy,
label: savePassword,
onSubmit: () async {
try {
await formProvider.submit(
accountProvider: accountProvider,
errorText: errorText,
);
if (!context.mounted) return;
notifyUser(context, successText);
} catch (e) {
if (!context.mounted) return;
await postNotifyUserOfErrorX(
context: context,
errorSituation: errorText,
exception: e,
);
}
},
),
PasswordErrorText(
errorText: formProvider.errorText,
gapSmall: _gapSmall,
),
],
),
),
],
);
}
}

View File

@@ -0,0 +1,24 @@
import 'package:flutter/material.dart';
class PasswordSubmitButton extends StatelessWidget {
const PasswordSubmitButton({
super.key,
required this.isBusy,
required this.onSubmit,
required this.label,
});
final bool isBusy;
final VoidCallback onSubmit;
final String label;
@override
Widget build(BuildContext context) {
return ElevatedButton.icon(
onPressed: isBusy ? null : onSubmit,
icon: const Icon(Icons.save_outlined),
label: Text(label),
);
}
}

View File

@@ -0,0 +1,49 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:pweb/pages/settings/profile/account/password/content.dart';
import 'package:pweb/providers/password_form.dart';
import 'package:pweb/generated/i18n/app_localizations.dart';
class AccountPassword extends StatelessWidget {
final String title;
final String successText;
final String errorText;
final String oldPasswordLabel;
final String newPasswordLabel;
final String confirmPasswordLabel;
final String savePassword;
const AccountPassword({
super.key,
required this.title,
required this.successText,
required this.errorText,
required this.oldPasswordLabel,
required this.newPasswordLabel,
required this.confirmPasswordLabel,
required this.savePassword,
});
@override
Widget build(BuildContext context) {
final loc = AppLocalizations.of(context)!;
return ChangeNotifierProvider(
create: (_) => PasswordFormProvider(),
child: AccountPasswordContent(
title: title,
successText: successText,
errorText: errorText,
oldPasswordLabel: oldPasswordLabel,
newPasswordLabel: newPasswordLabel,
confirmPasswordLabel: confirmPasswordLabel,
savePassword: savePassword,
loc: loc,
),
);
}
}

View File

@@ -0,0 +1,36 @@
import 'package:flutter/material.dart';
class PasswordToggleButton extends StatelessWidget {
const PasswordToggleButton({
super.key,
required this.title,
required this.isExpanded,
required this.isBusy,
required this.onToggle,
});
final String title;
final bool isExpanded;
final bool isBusy;
final VoidCallback onToggle;
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final iconColor = theme.colorScheme.primary;
return TextButton.icon(
onPressed: isBusy
? null
: () {
onToggle();
},
icon: Icon(
isExpanded ? Icons.lock_open : Icons.lock_outline,
color: iconColor,
),
label: Text(title, style: theme.textTheme.bodyMedium),
);
}
}