Open vusters opened 1 year ago
@vusters Can I have something like this below with an Overlay? I just used similar to the ErrorScreen widget.
Here, there's one problem onError is called in every situation (for ex: assets not found). Is it okay? Also, the user needs to reload the view after fixing the issue, we couldn't find whether the user fixed the issue or not. So they need to refresh the whole app (like hot restart)
FlutterError.onError = (details) {
print('onError else called');
debugPrint(details.exception.toString());
final state = errorKey.currentState;
if (state != null && !state.isOverlay) {
state.createErrorOverlay(FlutterErrorDetails(exception: details));
}
};
// async error
PlatformDispatcher.instance.onError = (error, stack) {
debugPrint("Async Error: " + error.toString());
final state = errorKey.currentState;
if (state != null && !state.isOverlay) {
state.createErrorOverlay(FlutterErrorDetails(exception: error));
}
return true;
};
class AppHandler extends StatefulWidget {
const AppHandler({super.key, required this.child});
final Widget child;
@override
State<AppHandler> createState() => AppHandlerState();
}
class AppHandlerState extends State<AppHandler> {
OverlayEntry? overlayEntry;
bool isOverlay = false;
void createErrorOverlay(FlutterErrorDetails? errorDetails) {
// Remove the existing OverlayEntry.
removeErrorOverlay();
if (errorDetails == null) {
removeErrorOverlay();
return;
}
assert(overlayEntry == null);
List<Widget> children = [];
// main error and graphics
children.add(Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(Utils.randomize(["Oh Snap", "Uh Oh ..", "Foo Bar"]),
style: const TextStyle(
fontSize: 28,
color: Color(0xFFF7535A),
fontWeight: FontWeight.w500)),
const Image(
image: AssetImage("assets/images/error.png", package: 'ensemble'),
width: 200),
const SizedBox(height: 16),
// Text(
// widget.errorText +
// (widget.recovery != null ? '\n${widget.recovery}' : ''),
// textAlign: TextAlign.center,
// style: const TextStyle(fontSize: 16, height: 1.4),
// ),
],
));
// add detail
if (kDebugMode) {
children.add(Column(children: [
const SizedBox(height: 30),
const Text('DETAILS',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600)),
const SizedBox(height: 10),
Text(errorDetails.exception.toString(),
textAlign: TextAlign.start,
style: const TextStyle(fontSize: 14, color: Colors.black87))
]));
}
overlayEntry = OverlayEntry(
// Create a new OverlayEntry.
builder: (BuildContext context) {
// Align is used to position the highlight overlay
// relative to the NavigationBar destination.
return Scaffold(
body: SafeArea(
child: SingleChildScrollView(
padding: const EdgeInsets.only(left: 40, right: 40, top: 40),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: children),
),
),
);
},
);
// Add the OverlayEntry to the Overlay.
isOverlay = true;
Future.delayed(const Duration(milliseconds: 100), () {
Overlay.of(context, debugRequiredFor: widget).insert(overlayEntry!);
});
}
void removeErrorOverlay() {
isOverlay = false;
overlayEntry?.remove();
overlayEntry = null;
}
@override
void initState() {
super.initState();
WidgetsBinding.instance
.addPostFrameCallback((_) => createErrorOverlay(null));
}
@override
void dispose() {
// Make sure to remove OverlayEntry when the widget is disposed.
removeErrorOverlay();
super.dispose();
}
@override
Widget build(BuildContext context) {
return widget.child;
}
}
Looking at main.dart, we handle errors on the widget tree (case 1), but simply prints out the error for (2), and (3).
We should display same ErrorScreen for #2 and #3.