Show popup on un-caught exceptions to send errors via email
OmarHatem committed
Jan 6, 2023 at 19:42 UTC
e904c0a7b751cee11031dd953ddf035df2d7f872
3 files changed
+40
-114
lib/main.dart
+39
-26
@@ -9,7 +9,6 @@ import 'package:cake_wallet/buy/order.dart';
9
import 'package:cake_wallet/entities/preferences_key.dart';
10
import 'package:cake_wallet/ionia/ionia_category.dart';
11
import 'package:cake_wallet/ionia/ionia_merchant.dart';
12
-import 'package:cake_wallet/src/screens/failure_page.dart';
12
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
13
import 'package:cake_wallet/store/yat/yat_store.dart';
14
import 'package:cake_wallet/themes/theme_list.dart';
@@ -17,6 +16,7 @@ import 'package:cake_wallet/utils/show_pop_up.dart';
16
import 'package:flutter/foundation.dart';
17
import 'package:flutter/material.dart';
18
import 'package:flutter/services.dart';
19
+import 'package:flutter_mailer/flutter_mailer.dart';
20
import 'package:hive/hive.dart';
21
import 'package:cake_wallet/di.dart';
22
import 'package:path_provider/path_provider.dart';
@@ -57,31 +57,14 @@ Future<void> main() async {
57
WidgetsFlutterBinding.ensureInitialized();
58
59
FlutterError.onError = (errorDetails) {
60
- print("@@@@@@@@@@@@@@@@@ in on error");
61
- print(errorDetails.exception.toString());
60
_onError(errorDetails);
63
- _saveException(errorDetails.exception.toString(), errorDetails.stack);
64
- };
65
-
66
- ErrorWidget.builder = (errorDetails) {
67
- print("@@@@@@@@@@@@@@@@@ in widget error");
68
- // TODO: uncomment
69
- // if (kDebugMode) {
70
- // return ErrorWidget(errorDetails.exception);
71
- // }
72
-
73
- return FailurePage(
74
- error: errorDetails.exception.toString(),
75
- stackTrace: errorDetails.stack,
76
- );
61
};
62
63
/// A callback that is invoked when an unhandled error occurs in the root
64
/// isolate.
65
PlatformDispatcher.instance.onError = (error, stack) {
82
- print("@@@@@@@@@@@@@@@");
83
- print("PlatformDispatcher.instance.onError");
84
- _saveException(error.toString(), stack);
66
+ _onError(FlutterErrorDetails(exception: error, stack: stack));
67
+
68
return true;
69
};
70
@@ -187,12 +170,42 @@ void _saveException(String? error, StackTrace? stackTrace) async {
170
}
171
};
172
190
- await file.writeAsString(jsonEncode(exception), mode: FileMode.append);
173
+ String separator = "\n\n==========================================================" +
174
+ "\n==========================================================\n\n";
175
+
176
+ await file.writeAsString(
177
+ jsonEncode(exception) + separator,
178
+ mode: FileMode.append,
179
+ );
180
}
181
193
-void _onError(FlutterErrorDetails details) {
194
- print("#############");
195
- print(details.exception.toString());
182
+void _sendExceptionFile() async {
183
+ final appDocDir = await getApplicationDocumentsDirectory();
184
+
185
+ final file = File('${appDocDir.path}/error.txt');
186
+
187
+ print(file.readAsStringSync());
188
+
189
+ final MailOptions mailOptions = MailOptions(
190
+ subject: 'Mobile App Issue',
191
+ recipients: ['support@cakewallet.com'],
192
+ attachments: [file.path],
193
+ );
194
+
195
+ final result = await FlutterMailer.send(mailOptions);
196
+
197
+ // clear file content if the error was sent or saved
198
+ // on android we can't know if it was sent or saved
199
+ if (result.name == MailerResponse.sent.name ||
200
+ result.name == MailerResponse.saved.name ||
201
+ result.name == MailerResponse.android.name) {
202
+ file.writeAsString("", mode: FileMode.write);
203
+ }
204
+}
205
+
206
+void _onError(FlutterErrorDetails errorDetails) {
207
+ _saveException(errorDetails.exception.toString(), errorDetails.stack);
208
+
209
WidgetsBinding.instance.addPostFrameCallback(
210
(timeStamp) {
211
showPopUp<void>(
@@ -204,12 +217,12 @@ void _onError(FlutterErrorDetails details) {
217
alertContent: "Oops, we got some error.\n\nPlease send crash report to our support team to make the application better.",
218
rightButtonText: S.of(context).send,
219
leftButtonText: "Don't send",
207
- actionRightButton: () async {
220
+ actionRightButton: () {
221
Navigator.of(context).pop();
222
+ _sendExceptionFile();
223
},
224
actionLeftButton: () {
225
Navigator.of(context).pop();
212
- _saveException(details.exception.toString(), details.stack);
226
},
227
);
228
},
lib/src/screens/failure_page.dart
deleted
-87
@@ -1,87 +0,0 @@
1
-import 'dart:io';
2
-
3
-import 'package:cake_wallet/generated/i18n.dart';
4
-import 'package:cake_wallet/src/widgets/primary_button.dart';
5
-import 'package:flutter/material.dart';
6
-import 'package:flutter_mailer/flutter_mailer.dart';
7
-import 'package:path_provider/path_provider.dart';
8
-
9
-class FailurePage extends StatelessWidget {
10
- final String? error;
11
- final StackTrace? stackTrace;
12
-
13
- FailurePage({Key? key, this.error, this.stackTrace});
14
-
15
- @override
16
- Widget build(BuildContext context) {
17
- final theme = Theme.of(context);
18
- return Scaffold(
19
- backgroundColor: Colors.grey.shade400,
20
- body: Center(
21
- child: Padding(
22
- padding: EdgeInsets.symmetric(
23
- horizontal: MediaQuery.of(context).size.width * 0.2),
24
- child: Column(
25
- mainAxisSize: MainAxisSize.min,
26
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
27
- children: [
28
- Icon(
29
- Icons.warning,
30
- color: theme.errorColor,
31
- size: 50,
32
- ),
33
- Padding(
34
- padding: const EdgeInsets.symmetric(vertical: 20),
35
- child: Text(
36
- "Oops, we got some error.",
37
- style: theme.textTheme.headline1?.copyWith(fontSize: 20),
38
- ),
39
- ),
40
- Text(
41
- "Please send crash report to our support team to make the application better.",
42
- textAlign: TextAlign.center,
43
- style: theme.textTheme.headline1?.copyWith(fontSize: 16),
44
- ),
45
- Padding(
46
- padding: const EdgeInsets.symmetric(vertical: 20),
47
- child: PrimaryButton(
48
- onPressed: _sendExceptionFile,
49
- text: S.of(context).send,
50
- textColor: Colors.white,
51
- color: theme.accentTextTheme.bodyText1!.color!,
52
- ),
53
- ),
54
- PrimaryButton(
55
- onPressed: () {
56
- },
57
- text: "Don't Send",
58
- color: Theme.of(context).accentTextTheme.caption!.color!,
59
- textColor:
60
- Theme.of(context).primaryTextTheme.headline6!.color!,
61
- ),
62
- ],
63
- ),
64
- ),
65
- ),
66
- );
67
- }
68
-
69
- void _sendExceptionFile() async {
70
- final appDocDir = await getApplicationDocumentsDirectory();
71
-
72
- final file = File('${appDocDir.path}/error.txt');
73
-
74
- print(file.readAsStringSync());
75
-
76
- final MailOptions mailOptions = MailOptions(
77
- subject: 'Mobile App Issue',
78
- recipients: ['support@cakewallet.com'],
79
- attachments: [file.path],
80
- );
81
-
82
- await FlutterMailer.send(mailOptions);
83
-
84
- // clear file content
85
- // file.writeAsString("", mode: FileMode.write);
86
- }
87
-}
pubspec_base.yaml
+1
-1
@@ -61,7 +61,7 @@ dependencies:
61
permission_handler: ^10.0.0
62
device_display_brightness: ^0.0.6
63
platform_device_id: ^1.0.1
64
- flutter_mailer: ^2.0.1
64
+ flutter_mailer: ^2.0.2
65
cake_backup:
66
git:
67
url: https://github.com/cake-tech/cake_backup.git