feat: enhance error boundary widget with improved error handling and UI updates

- Added a method to ignore specific errors related to RenderFlex overflow.
- Refactored the error display layout to use a centered scrollable view.
- Improved visual presentation with a gradient background for the error icon and updated button styles for retry functionality.
This commit is contained in:
cogwheel0
2025-10-26 23:15:44 +05:30
parent c37151bba5
commit dded22f1ec
2 changed files with 102 additions and 34 deletions

View File

@@ -31,7 +31,19 @@ class _ErrorBoundaryState extends ConsumerState<ErrorBoundary> {
bool _hasError = false; bool _hasError = false;
void Function(FlutterErrorDetails details)? _previousOnError; void Function(FlutterErrorDetails details)? _previousOnError;
bool _shouldIgnoreError(Object error) {
// Ignore RenderFlex overflow errors (layout issues)
final errorString = error.toString();
return errorString.contains('RenderFlex') ||
errorString.contains('overflow') && errorString.contains('pixels');
}
void _scheduleHandleError(Object error, StackTrace? stack) { void _scheduleHandleError(Object error, StackTrace? stack) {
// Skip errors that should be ignored
if (_shouldIgnoreError(error)) {
return;
}
// Defer to next frame to avoid setState during build exceptions // Defer to next frame to avoid setState during build exceptions
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
if (mounted) { if (mounted) {
@@ -119,39 +131,93 @@ class _ErrorBoundaryState extends ConsumerState<ErrorBoundary> {
child: Scaffold( child: Scaffold(
backgroundColor: context.conduitTheme.surfaceBackground, backgroundColor: context.conduitTheme.surfaceBackground,
body: SafeArea( body: SafeArea(
child: Padding( child: Center(
padding: const EdgeInsets.all(16.0), child: SingleChildScrollView(
padding: const EdgeInsets.symmetric(
horizontal: Spacing.pagePadding,
vertical: Spacing.lg,
),
child: Container(
constraints: const BoxConstraints(maxWidth: 480),
decoration: BoxDecoration(
color: context.conduitTheme.cardBackground,
borderRadius: BorderRadius.circular(
context.conduitTheme.radiusLg,
),
border: Border.all(
color: context.conduitTheme.cardBorder,
width: BorderWidth.regular,
),
boxShadow: context.conduitTheme.cardShadows,
),
padding: const EdgeInsets.all(Spacing.xl),
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.min,
children: [ children: [
Icon( // Error icon with gradient background
Icons.error_outline, Container(
size: 64, width: 80,
height: 80,
decoration: BoxDecoration(
color: context.conduitTheme.errorBackground,
shape: BoxShape.circle,
),
child: Icon(
Icons.error_outline_rounded,
size: 40,
color: context.conduitTheme.error, color: context.conduitTheme.error,
), ),
const SizedBox(height: 16), ),
const SizedBox(height: Spacing.lg),
// Error title
Text( Text(
AppLocalizations.of(context)?.errorMessage ?? AppLocalizations.of(context)?.errorMessage ??
'An unexpected error occurred', 'Something went wrong',
style: Theme.of(context).textTheme.headlineSmall?.copyWith( style: context.conduitTheme.headingSmall,
color: context.conduitTheme.textPrimary, textAlign: TextAlign.center,
), ),
), const SizedBox(height: Spacing.sm),
const SizedBox(height: 8),
// Error description
Text( Text(
enhancedErrorService.getUserMessage(_error!), enhancedErrorService.getUserMessage(_error!),
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: Theme.of(context).textTheme.bodyMedium?.copyWith( style: context.conduitTheme.bodySmall?.copyWith(
color: context.conduitTheme.textSecondary, color: context.conduitTheme.textSecondary,
), ),
), ),
if (widget.allowRetry) ...[ if (widget.allowRetry) ...[
const SizedBox(height: 24), const SizedBox(height: Spacing.xl),
FilledButton.icon(
// Retry button
SizedBox(
width: double.infinity,
child: FilledButton.icon(
onPressed: _retry, onPressed: _retry,
icon: const Icon(Icons.refresh), icon: const Icon(Icons.refresh_rounded),
style: FilledButton.styleFrom(
backgroundColor: context.conduitTheme.buttonPrimary,
foregroundColor: context.conduitTheme.buttonPrimaryText,
padding: const EdgeInsets.symmetric(
horizontal: Spacing.lg,
vertical: Spacing.md,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(
context.conduitTheme.radiusMd,
),
),
elevation: 0,
),
label: Text( label: Text(
AppLocalizations.of(context)?.retry ?? 'Retry', AppLocalizations.of(context)?.retry ?? 'Try Again',
style: context.conduitTheme.bodySmall?.copyWith(
fontWeight: FontWeight.w600,
color: context.conduitTheme.buttonPrimaryText,
),
),
), ),
), ),
], ],
@@ -160,6 +226,8 @@ class _ErrorBoundaryState extends ConsumerState<ErrorBoundary> {
), ),
), ),
), ),
),
),
); );
} }

Submodule openwebui-src updated: 43a2881074...7a83e7dfa3