Send error file via email

This commit is contained in:
OmarHatem 2022-11-25 18:59:47 +02:00
parent 34746c31c8
commit 7b99e409a9
3 changed files with 135 additions and 20 deletions

View file

@ -5,9 +5,12 @@ import 'dart:isolate';
import 'package:cake_wallet/bitcoin/bitcoin.dart';
import 'package:cake_wallet/entities/language_service.dart';
import 'package:cake_wallet/buy/order.dart';
import 'package:cake_wallet/entities/preferences_key.dart';
import 'package:cake_wallet/ionia/ionia_category.dart';
import 'package:cake_wallet/ionia/ionia_merchant.dart';
import 'package:cake_wallet/src/screens/failure_page.dart';
import 'package:cake_wallet/store/yat/yat_store.dart';
import 'package:cake_wallet/themes/theme_list.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
@ -50,24 +53,28 @@ Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
FlutterError.onError = (errorDetails) {
print("@@@@@@@@@@@@@@@");
print("FlutterError.onError");
print(errorDetails);
_saveException(errorDetails.exception.toString(), errorDetails.stack);
};
ErrorWidget.builder = (errorDetails) {
return FailurePage(
error: errorDetails.exception.toString(),
stackTrace: errorDetails.stack,
);
};
/// A callback that is invoked when an unhandled error occurs in the root
/// isolate.
PlatformDispatcher.instance.onError = (error, stack) {
print("@@@@@@@@@@@@@@@");
print("PlatformDispatcher.instance.onError");
_saveException(error.toString(), stack);
return true;
};
Isolate.current.addErrorListener(RawReceivePort((pair) async {
final errorAndStacktrace = pair as List<String?>;
_saveException(
errorAndStacktrace.first,
errorAndStacktrace.last == null
? null
: StackTrace.fromString(errorAndStacktrace.last!),
);
}).sendPort);
final appDir = await getApplicationDocumentsDirectory();
await Hive.close();
Hive.init(appDir.path);
@ -153,29 +160,49 @@ Future<void> main() async {
secureStorage: secureStorage,
initialMigrationVersion: 17);
runApp(App());
}, (error, stackTrace) {
}, (error, stackTrace) async {
_saveException(error.toString(), stackTrace);
runApp(MaterialApp(
final sharedPreferences = await SharedPreferences.getInstance();
final theme = ThemeList.deserialize(
raw: sharedPreferences.getInt(PreferencesKey.currentTheme) ?? 0);
final savedLanguageCode =
sharedPreferences.getString(PreferencesKey.currentLanguageCode) ??
await LanguageService.localeDetection();
runApp(
MaterialApp(
debugShowCheckedModeBanner: true,
theme: theme.themeData,
localizationsDelegates: [
S.delegate,
GlobalCupertinoLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: S.delegate.supportedLocales,
locale: Locale(savedLanguageCode),
home: Scaffold(
body: Container(
margin:
EdgeInsets.only(top: 50, left: 20, right: 20, bottom: 20),
child: Text(
'Error:\n${error.toString()}\nStacktrace: $stackTrace',
style: TextStyle(fontSize: 22),
)))));
body: FailurePage(
error: error.toString(),
stackTrace: stackTrace,
),
),
),
);
});
}
void _saveException(String? error, StackTrace? stackTrace) async {
final file = File('/error.txt');
final appDocDir = await getApplicationDocumentsDirectory();
final file = File('${appDocDir.path}/error.txt');
final exception = {
"${DateTime.now()}": {
"error": error,
"stackTrace": stackTrace.toString(),
}
};
await file.writeAsString(jsonEncode(exception), mode: FileMode.append);
}

View file

@ -0,0 +1,87 @@
import 'dart:io';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/src/widgets/primary_button.dart';
import 'package:flutter/material.dart';
import 'package:flutter_mailer/flutter_mailer.dart';
import 'package:path_provider/path_provider.dart';
class FailurePage extends StatelessWidget {
final String? error;
final StackTrace? stackTrace;
FailurePage({Key? key, this.error, this.stackTrace});
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Scaffold(
backgroundColor: Colors.grey.shade400,
body: Center(
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: MediaQuery.of(context).size.width * 0.2),
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Icon(
Icons.warning,
color: theme.errorColor,
size: 50,
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 20),
child: Text(
"Oops, we got some error.",
style: theme.textTheme.headline1?.copyWith(fontSize: 20),
),
),
Text(
"Please send crash report to our support team to make the application better.",
textAlign: TextAlign.center,
style: theme.textTheme.headline1?.copyWith(fontSize: 16),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 20),
child: PrimaryButton(
onPressed: _sendExceptionFile,
text: S.of(context).send,
textColor: Colors.white,
color: theme.accentTextTheme.bodyText1!.color!,
),
),
PrimaryButton(
onPressed: () {
},
text: "Don't Send",
color: Theme.of(context).accentTextTheme.caption!.color!,
textColor:
Theme.of(context).primaryTextTheme.headline6!.color!,
),
],
),
),
),
);
}
void _sendExceptionFile() async {
final appDocDir = await getApplicationDocumentsDirectory();
final file = File('${appDocDir.path}/error.txt');
print(file.readAsStringSync());
final MailOptions mailOptions = MailOptions(
subject: 'Mobile App Issue',
recipients: ['support@cakewallet.com'],
attachments: [file.path],
);
await FlutterMailer.send(mailOptions);
// clear file content
// file.writeAsString("", mode: FileMode.write);
}
}

View file

@ -61,6 +61,7 @@ dependencies:
permission_handler: ^10.0.0
device_display_brightness: ^0.0.6
platform_device_id: ^1.0.1
flutter_mailer: ^2.0.1
cake_backup:
git:
url: https://github.com/cake-tech/cake_backup.git