forked from github-such-software/hash-wallet
Compare commits
4 Commits
2867836992
...
771938e545
| Author | SHA1 | Date | |
|---|---|---|---|
| 771938e545 | |||
|
|
0b9c67f0e5 | ||
|
|
4c09950e0b | ||
|
|
3faa89d49d |
@@ -16,8 +16,8 @@ import 'package:device_info_plus/device_info_plus.dart';
|
|||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_mailer/flutter_mailer.dart';
|
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
class ExceptionHandler {
|
class ExceptionHandler {
|
||||||
static bool _hasError = false;
|
static bool _hasError = false;
|
||||||
@@ -70,39 +70,60 @@ class ExceptionHandler {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hash Wallet: the original Cake implementation used flutter_mailer to
|
||||||
|
// hand the error.txt to the OS mail client. That plugin has no Linux
|
||||||
|
// implementation (throws MissingPluginException) and on other platforms
|
||||||
|
// many users have no mail client configured, so very few reports ever
|
||||||
|
// reached anyone. Instead, we open a prefilled GitHub issue. Users
|
||||||
|
// without a GH account get nothing useful, but the trade-off beats
|
||||||
|
// pretending the mail flow works.
|
||||||
|
//
|
||||||
|
// GitHub's "new issue" URL caps the body at ~8KB before truncating, so
|
||||||
|
// we send the tail of error.txt (most recent exception is usually most
|
||||||
|
// relevant) and prepend a hint to attach the full file.
|
||||||
|
static const _issueUrl =
|
||||||
|
'https://github.com/Such-Software/hash-wallet/issues/new';
|
||||||
|
static const _maxBodyChars = 6500;
|
||||||
|
|
||||||
static void _sendExceptionFile() async {
|
static void _sendExceptionFile() async {
|
||||||
try {
|
try {
|
||||||
if (_file == null) {
|
if (_file == null) {
|
||||||
final appDocDir = await getAppDir();
|
final appDocDir = await getAppDir();
|
||||||
|
|
||||||
_file = File('${appDocDir.path}/error.txt');
|
_file = File('${appDocDir.path}/error.txt');
|
||||||
}
|
}
|
||||||
|
|
||||||
await _addDeviceInfo(_file!);
|
await _addDeviceInfo(_file!);
|
||||||
|
|
||||||
// Check if a mail client is available
|
final fullBody = await _file!.readAsString();
|
||||||
final bool canSend = await FlutterMailer.canSendMail();
|
final trimmed = fullBody.length > _maxBodyChars
|
||||||
|
? '...(truncated, full log at ${_file!.path})\n\n${fullBody.substring(fullBody.length - _maxBodyChars)}'
|
||||||
|
: fullBody;
|
||||||
|
|
||||||
if (Platform.isIOS && !canSend) {
|
final body = '''
|
||||||
printV('Mail app is not available');
|
<!-- Thanks for reporting. The trace below was captured automatically.
|
||||||
|
Please add a short description of what you were doing when the error
|
||||||
|
appeared (e.g. "creating wallet", "restoring from seed", "sending Tx"). -->
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
$trimmed
|
||||||
|
''';
|
||||||
|
|
||||||
|
final uri = Uri.https('github.com', '/Such-Software/hash-wallet/issues/new', {
|
||||||
|
'title': 'App error report',
|
||||||
|
'labels': 'bug,from-app',
|
||||||
|
'body': body,
|
||||||
|
});
|
||||||
|
|
||||||
|
final launched = await launchUrl(uri, mode: LaunchMode.externalApplication);
|
||||||
|
if (!launched) {
|
||||||
|
printV('Could not open GitHub issue URL: $uri');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final MailOptions mailOptions = MailOptions(
|
// Clear the file now that the user has been handed the trace.
|
||||||
subject: 'Mobile App Issue',
|
await _file!.writeAsString('', mode: FileMode.write);
|
||||||
recipients: ['support@such.software'],
|
|
||||||
attachments: [_file!.path],
|
|
||||||
);
|
|
||||||
|
|
||||||
final result = await FlutterMailer.send(mailOptions);
|
|
||||||
|
|
||||||
// Clear file content if the error was sent or saved.
|
|
||||||
// On android we can't know if it was sent or saved
|
|
||||||
if (result.name == MailerResponse.sent.name ||
|
|
||||||
result.name == MailerResponse.saved.name ||
|
|
||||||
result.name == MailerResponse.android.name) {
|
|
||||||
_file!.writeAsString("", mode: FileMode.write);
|
|
||||||
}
|
|
||||||
} catch (e, s) {
|
} catch (e, s) {
|
||||||
_saveException(e.toString(), s);
|
_saveException(e.toString(), s);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,7 +58,9 @@ abstract class MoneroAccountListViewModelBase with Store {
|
|||||||
|
|
||||||
@computed
|
@computed
|
||||||
AccountListItem get selected {
|
AccountListItem get selected {
|
||||||
final currentId = monero!.getCurrentAccount(_wallet).id;
|
final currentId = _wallet.type == WalletType.wownero
|
||||||
|
? wownero!.getCurrentAccount(_wallet).id
|
||||||
|
: monero!.getCurrentAccount(_wallet).id;
|
||||||
return accounts.firstWhere((item) => item.id == currentId);
|
return accounts.firstWhere((item) => item.id == currentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -75,10 +75,6 @@ dependencies:
|
|||||||
url: https://github.com/MrCyjaneK/device_display_brightness.git
|
url: https://github.com/MrCyjaneK/device_display_brightness.git
|
||||||
ref: 4cac18c446ce686f3d75b1565badbd7da439bbd9
|
ref: 4cac18c446ce686f3d75b1565badbd7da439bbd9
|
||||||
wakelock_plus: ^1.2.5
|
wakelock_plus: ^1.2.5
|
||||||
flutter_mailer:
|
|
||||||
git:
|
|
||||||
url: https://github.com/taljacobson/flutter_mailer
|
|
||||||
ref: 9c4ed111a9151a2bbfb9afe2c18a37599c6f84f3
|
|
||||||
device_info_plus: ^9.1.0
|
device_info_plus: ^9.1.0
|
||||||
base32: 2.1.3
|
base32: 2.1.3
|
||||||
in_app_review: ^2.0.6
|
in_app_review: ^2.0.6
|
||||||
|
|||||||
Reference in New Issue
Block a user