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