Send error file via email
OmarHatem committed
Nov 25, 2022 at 18:59 UTC
7b99e409a9e0c9a4eba92698557923e1b251eecb
3 files changed
+135
-20
lib/main.dart
+47
-20
@@ -5,9 +5,12 @@ import 'dart:isolate';
5
import 'package:cake_wallet/bitcoin/bitcoin.dart';
6
import 'package:cake_wallet/entities/language_service.dart';
7
import 'package:cake_wallet/buy/order.dart';
8
+import 'package:cake_wallet/entities/preferences_key.dart';
9
import 'package:cake_wallet/ionia/ionia_category.dart';
10
import 'package:cake_wallet/ionia/ionia_merchant.dart';
11
+import 'package:cake_wallet/src/screens/failure_page.dart';
12
import 'package:cake_wallet/store/yat/yat_store.dart';
13
+import 'package:cake_wallet/themes/theme_list.dart';
14
import 'package:flutter/foundation.dart';
15
import 'package:flutter/material.dart';
16
import 'package:flutter/services.dart';
@@ -50,24 +53,28 @@ Future<void> main() async {
53
WidgetsFlutterBinding.ensureInitialized();
54
55
FlutterError.onError = (errorDetails) {
56
+ print("@@@@@@@@@@@@@@@");
57
+ print("FlutterError.onError");
58
+ print(errorDetails);
59
_saveException(errorDetails.exception.toString(), errorDetails.stack);
60
};
61
62
+ ErrorWidget.builder = (errorDetails) {
63
+ return FailurePage(
64
+ error: errorDetails.exception.toString(),
65
+ stackTrace: errorDetails.stack,
66
+ );
67
+ };
68
+
69
+ /// A callback that is invoked when an unhandled error occurs in the root
70
+ /// isolate.
71
PlatformDispatcher.instance.onError = (error, stack) {
72
+ print("@@@@@@@@@@@@@@@");
73
+ print("PlatformDispatcher.instance.onError");
74
_saveException(error.toString(), stack);
75
return true;
76
};
77
61
- Isolate.current.addErrorListener(RawReceivePort((pair) async {
62
- final errorAndStacktrace = pair as List<String?>;
63
- _saveException(
64
- errorAndStacktrace.first,
65
- errorAndStacktrace.last == null
66
- ? null
67
- : StackTrace.fromString(errorAndStacktrace.last!),
68
- );
69
- }).sendPort);
70
-
78
final appDir = await getApplicationDocumentsDirectory();
79
await Hive.close();
80
Hive.init(appDir.path);
@@ -153,29 +160,49 @@ Future<void> main() async {
160
secureStorage: secureStorage,
161
initialMigrationVersion: 17);
162
runApp(App());
156
- }, (error, stackTrace) {
163
+ }, (error, stackTrace) async {
164
_saveException(error.toString(), stackTrace);
158
- runApp(MaterialApp(
165
+ final sharedPreferences = await SharedPreferences.getInstance();
166
+ final theme = ThemeList.deserialize(
167
+ raw: sharedPreferences.getInt(PreferencesKey.currentTheme) ?? 0);
168
+
169
+ final savedLanguageCode =
170
+ sharedPreferences.getString(PreferencesKey.currentLanguageCode) ??
171
+ await LanguageService.localeDetection();
172
+ runApp(
173
+ MaterialApp(
174
debugShowCheckedModeBanner: true,
175
+ theme: theme.themeData,
176
+ localizationsDelegates: [
177
+ S.delegate,
178
+ GlobalCupertinoLocalizations.delegate,
179
+ GlobalMaterialLocalizations.delegate,
180
+ GlobalWidgetsLocalizations.delegate,
181
+ ],
182
+ supportedLocales: S.delegate.supportedLocales,
183
+ locale: Locale(savedLanguageCode),
184
home: Scaffold(
161
- body: Container(
162
- margin:
163
- EdgeInsets.only(top: 50, left: 20, right: 20, bottom: 20),
164
- child: Text(
165
- 'Error:\n${error.toString()}\nStacktrace: $stackTrace',
166
- style: TextStyle(fontSize: 22),
167
- )))));
185
+ body: FailurePage(
186
+ error: error.toString(),
187
+ stackTrace: stackTrace,
188
+ ),
189
+ ),
190
+ ),
191
+ );
192
});
193
}
194
195
void _saveException(String? error, StackTrace? stackTrace) async {
172
- final file = File('/error.txt');
196
+ final appDocDir = await getApplicationDocumentsDirectory();
197
+
198
+ final file = File('${appDocDir.path}/error.txt');
199
final exception = {
200
"${DateTime.now()}": {
201
"error": error,
202
"stackTrace": stackTrace.toString(),
203
}
204
};
205
+
206
await file.writeAsString(jsonEncode(exception), mode: FileMode.append);
207
}
208
lib/src/screens/failure_page.dart
new
+87
@@ -0,0 +1,87 @@
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
@@ -61,6 +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
65
cake_backup:
66
git:
67
url: https://github.com/cake-tech/cake_backup.git