Email Confirmation and refactor for snackbar

This commit is contained in:
Arseni
2026-01-27 14:42:52 +03:00
parent e5cd0c9433
commit be1d678c42
28 changed files with 958 additions and 173 deletions

View File

@@ -4,50 +4,56 @@ import 'package:flutter/material.dart';
import 'package:pweb/utils/error_handler.dart';
import 'package:pweb/utils/snackbar.dart';
import 'package:pweb/widgets/error/content.dart';
import 'package:pweb/widgets/error/content.dart';
import 'package:pweb/generated/i18n/app_localizations.dart';
ScaffoldFeatureController<SnackBar, SnackBarClosedReason> notifyUserOfErrorX({
required ScaffoldMessengerState scaffoldMessenger,
Future<void> notifyUserOfErrorX({
required BuildContext context,
required String errorSituation,
required Object exception,
required AppLocalizations appLocalizations,
int delaySeconds = 3,
}) {
// A. Localized user-friendly error message
final String localizedError = ErrorHandler.handleErrorLocs(appLocalizations, exception);
}) async {
if (!context.mounted) return;
final localizedError = ErrorHandler.handleErrorLocs(appLocalizations, exception);
final technicalDetails = exception.toString();
final scaffoldMessenger = ScaffoldMessenger.maybeOf(context);
// B. Technical details for advanced reference
final String technicalDetails = exception.toString();
if (scaffoldMessenger != null) {
final snackBar = _buildMainErrorSnackBar(
errorSituation: errorSituation,
localizedError: localizedError,
technicalDetails: technicalDetails,
loc: appLocalizations,
scaffoldMessenger: scaffoldMessenger,
delaySeconds: delaySeconds,
);
scaffoldMessenger.showSnackBar(snackBar);
return;
}
// C. Build the snack bar
final snackBar = _buildMainErrorSnackBar(
errorSituation: errorSituation,
localizedError: localizedError,
technicalDetails: technicalDetails,
loc: appLocalizations,
scaffoldMessenger: scaffoldMessenger,
delaySeconds: delaySeconds,
await _showErrorDialog(
context,
title: errorSituation,
message: localizedError,
);
// D. Show it
return scaffoldMessenger.showSnackBar(snackBar);
}
ScaffoldFeatureController<SnackBar, SnackBarClosedReason> notifyUserOfError({
Future<void> notifyUserOfError({
required BuildContext context,
required String errorSituation,
required Object exception,
int delaySeconds = 3,
}) => notifyUserOfErrorX(
scaffoldMessenger: ScaffoldMessenger.of(context),
errorSituation: errorSituation,
exception: exception,
appLocalizations: AppLocalizations.of(context)!,
delaySeconds: delaySeconds,
);
}) =>
notifyUserOfErrorX(
context: context,
errorSituation: errorSituation,
exception: exception,
appLocalizations: AppLocalizations.of(context)!,
delaySeconds: delaySeconds,
);
Future<T?> executeActionWithNotification<T>({
required BuildContext context,
@@ -56,19 +62,17 @@ Future<T?> executeActionWithNotification<T>({
String? successMessage,
int delaySeconds = 3,
}) async {
final scaffoldMessenger = ScaffoldMessenger.of(context);
final localizations = AppLocalizations.of(context)!;
try {
final res = await action();
if (successMessage != null) {
notifyUserX(scaffoldMessenger, successMessage, delaySeconds: delaySeconds);
await notifyUser(context, successMessage, delaySeconds: delaySeconds);
}
return res;
} catch (e) {
// Report the error using your existing notifier.
notifyUserOfErrorX(
scaffoldMessenger: scaffoldMessenger,
await notifyUserOfErrorX(
context: context,
errorSituation: errorMessage,
exception: e,
appLocalizations: localizations,
@@ -78,43 +82,48 @@ Future<T?> executeActionWithNotification<T>({
return null;
}
Future<ScaffoldFeatureController<SnackBar, SnackBarClosedReason>> postNotifyUserOfError({
required ScaffoldMessengerState scaffoldMessenger,
Future<void> postNotifyUserOfError({
required BuildContext context,
required String errorSituation,
required Object exception,
required AppLocalizations appLocalizations,
int delaySeconds = 3,
}) {
final completer = Completer<void>();
final completer = Completer<ScaffoldFeatureController<SnackBar, SnackBarClosedReason>>();
WidgetsBinding.instance.addPostFrameCallback((_) => completer.complete(notifyUserOfErrorX(
scaffoldMessenger: scaffoldMessenger,
WidgetsBinding.instance.addPostFrameCallback((_) async {
if (!context.mounted) {
completer.complete();
return;
}
await notifyUserOfErrorX(
context: context,
errorSituation: errorSituation,
exception: exception,
appLocalizations: appLocalizations,
delaySeconds: delaySeconds,
)),
);
);
completer.complete();
});
return completer.future;
}
Future<ScaffoldFeatureController<SnackBar, SnackBarClosedReason>> postNotifyUserOfErrorX({
Future<void> postNotifyUserOfErrorX({
required BuildContext context,
required String errorSituation,
required Object exception,
int delaySeconds = 3,
}) => postNotifyUserOfError(
scaffoldMessenger: ScaffoldMessenger.of(context),
errorSituation: errorSituation,
exception: exception,
appLocalizations: AppLocalizations.of(context)!,
delaySeconds: delaySeconds,
);
}) =>
postNotifyUserOfError(
context: context,
errorSituation: errorSituation,
exception: exception,
appLocalizations: AppLocalizations.of(context)!,
delaySeconds: delaySeconds,
);
/// 2) A helper function that returns the main SnackBar widget
SnackBar _buildMainErrorSnackBar({
required String errorSituation,
required String localizedError,
@@ -122,17 +131,42 @@ SnackBar _buildMainErrorSnackBar({
required AppLocalizations loc,
required ScaffoldMessengerState scaffoldMessenger,
int delaySeconds = 3,
}) => SnackBar(
duration: Duration(seconds: delaySeconds),
content: ErrorSnackBarContent(
situation: errorSituation,
localizedError: localizedError,
),
action: SnackBarAction(
label: loc.showDetailsAction,
onPressed: () => scaffoldMessenger.showSnackBar(SnackBar(
content: Text(technicalDetails),
duration: const Duration(seconds: 6),
)),
),
);
}) =>
SnackBar(
duration: Duration(seconds: delaySeconds),
content: ErrorSnackBarContent(
situation: errorSituation,
localizedError: localizedError,
),
action: SnackBarAction(
label: loc.showDetailsAction,
onPressed: () => scaffoldMessenger.showSnackBar(
SnackBar(
content: Text(technicalDetails),
duration: const Duration(seconds: 6),
),
),
),
);
Future<void> _showErrorDialog(
BuildContext context, {
required String title,
required String message,
}) async {
if (!context.mounted) return;
final loc = AppLocalizations.of(context)!;
await showDialog<void>(
context: context,
builder: (dialogContext) => AlertDialog(
title: Text(title),
content: Text(message),
actions: [
TextButton(
onPressed: () => Navigator.of(dialogContext).pop(),
child: Text(loc.ok),
),
],
),
);
}