Don't dump all the debug info to the error reporting

This commit is contained in:
Roland Geider
2025-10-08 14:42:58 +02:00
parent 4b9afa5c98
commit 8199205b02
3 changed files with 61 additions and 61 deletions

View File

@@ -101,7 +101,8 @@ void showGeneralErrorDialog(dynamic error, StackTrace? stackTrace, {BuildContext
if (error is TimeoutException) { if (error is TimeoutException) {
issueTitle = 'Network Timeout'; issueTitle = 'Network Timeout';
issueErrorMessage = 'The connection to the server timed out. Please check your ' issueErrorMessage =
'The connection to the server timed out. Please check your '
'internet connection and try again.'; 'internet connection and try again.';
} else if (error is FlutterErrorDetails) { } else if (error is FlutterErrorDetails) {
issueTitle = 'Application Error'; issueTitle = 'Application Error';
@@ -116,7 +117,7 @@ void showGeneralErrorDialog(dynamic error, StackTrace? stackTrace, {BuildContext
} }
final String fullStackTrace = stackTrace?.toString() ?? 'No stack trace available.'; final String fullStackTrace = stackTrace?.toString() ?? 'No stack trace available.';
final applicationLogs = InMemoryLogStore().formattedLogs; final applicationLogs = InMemoryLogStore().getFormattedLogs();
showDialog( showDialog(
context: dialogContext, context: dialogContext,
@@ -127,15 +128,9 @@ void showGeneralErrorDialog(dynamic error, StackTrace? stackTrace, {BuildContext
spacing: 8, spacing: 8,
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Icon( Icon(icon, color: Theme.of(context).colorScheme.error),
icon,
color: Theme.of(context).colorScheme.error,
),
Expanded( Expanded(
child: Text( child: Text(errorTitle, style: TextStyle(color: Theme.of(context).colorScheme.error)),
errorTitle,
style: TextStyle(color: Theme.of(context).colorScheme.error),
),
), ),
], ],
), ),
@@ -150,10 +145,7 @@ void showGeneralErrorDialog(dynamic error, StackTrace? stackTrace, {BuildContext
tilePadding: EdgeInsets.zero, tilePadding: EdgeInsets.zero,
title: Text(i18n.errorViewDetails), title: Text(i18n.errorViewDetails),
children: [ children: [
Text( Text(issueErrorMessage, style: const TextStyle(fontWeight: FontWeight.bold)),
issueErrorMessage,
style: const TextStyle(fontWeight: FontWeight.bold),
),
Container( Container(
alignment: Alignment.topLeft, alignment: Alignment.topLeft,
padding: const EdgeInsets.symmetric(vertical: 8.0), padding: const EdgeInsets.symmetric(vertical: 8.0),
@@ -166,15 +158,13 @@ void showGeneralErrorDialog(dynamic error, StackTrace? stackTrace, {BuildContext
), ),
), ),
CopyToClipboardButton( CopyToClipboardButton(
text: 'Error Title: $issueTitle\n' text:
'Error Title: $issueTitle\n'
'Error Message: $issueErrorMessage\n\n' 'Error Message: $issueErrorMessage\n\n'
'Stack Trace:\n$fullStackTrace', 'Stack Trace:\n$fullStackTrace',
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
Text( Text(i18n.applicationLogs, style: const TextStyle(fontWeight: FontWeight.bold)),
i18n.applicationLogs,
style: const TextStyle(fontWeight: FontWeight.bold),
),
Container( Container(
alignment: Alignment.topLeft, alignment: Alignment.topLeft,
padding: const EdgeInsets.symmetric(vertical: 8.0), padding: const EdgeInsets.symmetric(vertical: 8.0),
@@ -182,10 +172,12 @@ void showGeneralErrorDialog(dynamic error, StackTrace? stackTrace, {BuildContext
child: SingleChildScrollView( child: SingleChildScrollView(
child: Column( child: Column(
children: [ children: [
...applicationLogs.map((entry) => Text( ...applicationLogs.map(
entry, (entry) => Text(
style: TextStyle(fontSize: 12.0, color: Colors.grey[700]), entry,
)) style: TextStyle(fontSize: 12.0, color: Colors.grey[700]),
),
),
], ],
), ),
), ),
@@ -215,7 +207,8 @@ void showGeneralErrorDialog(dynamic error, StackTrace? stackTrace, {BuildContext
'App logs (last ${applicationLogs.length} entries):\n' 'App logs (last ${applicationLogs.length} entries):\n'
'```\n$logText\n```', '```\n$logText\n```',
); );
final githubIssueUrl = '$GITHUB_ISSUES_BUG_URL' final githubIssueUrl =
'$GITHUB_ISSUES_BUG_URL'
'&title=$issueTitle' '&title=$issueTitle'
'&description=$description'; '&description=$description';
final Uri reportUri = Uri.parse(githubIssueUrl); final Uri reportUri = Uri.parse(githubIssueUrl);
@@ -226,9 +219,9 @@ void showGeneralErrorDialog(dynamic error, StackTrace? stackTrace, {BuildContext
if (kDebugMode) { if (kDebugMode) {
logger.warning('Error launching URL: $e'); logger.warning('Error launching URL: $e');
} }
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(
SnackBar(content: Text('Error opening issue tracker: $e')), context,
); ).showSnackBar(SnackBar(content: Text('Error opening issue tracker: $e')));
} }
}, },
), ),
@@ -248,10 +241,7 @@ class CopyToClipboardButton extends StatelessWidget {
final logger = Logger('CopyToClipboardButton'); final logger = Logger('CopyToClipboardButton');
final String text; final String text;
CopyToClipboardButton({ CopyToClipboardButton({required this.text, super.key});
required this.text,
super.key,
});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@@ -265,21 +255,23 @@ class CopyToClipboardButton extends StatelessWidget {
tapTargetSize: MaterialTapTargetSize.shrinkWrap, tapTargetSize: MaterialTapTargetSize.shrinkWrap,
), ),
onPressed: () { onPressed: () {
Clipboard.setData(ClipboardData(text: text)).then((_) { Clipboard.setData(ClipboardData(text: text))
if (context.mounted) { .then((_) {
ScaffoldMessenger.of(context).showSnackBar( if (context.mounted) {
const SnackBar(content: Text('Details copied to clipboard!')), ScaffoldMessenger.of(
); context,
} ).showSnackBar(const SnackBar(content: Text('Details copied to clipboard!')));
}).catchError((copyError) { }
logger.warning('Error copying to clipboard: $copyError'); })
.catchError((copyError) {
logger.warning('Error copying to clipboard: $copyError');
if (context.mounted) { if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(
const SnackBar(content: Text('Could not copy details.')), context,
); ).showSnackBar(const SnackBar(content: Text('Could not copy details.')));
} }
}); });
}, },
); );
} }
@@ -290,9 +282,7 @@ void showDeleteDialog(BuildContext context, String confirmDeleteName, Log log) a
context: context, context: context,
builder: (BuildContext contextDialog) { builder: (BuildContext contextDialog) {
return AlertDialog( return AlertDialog(
content: Text( content: Text(AppLocalizations.of(context).confirmDelete(confirmDeleteName)),
AppLocalizations.of(context).confirmDelete(confirmDeleteName),
),
actions: [ actions: [
TextButton( TextButton(
key: const ValueKey('cancel-button'), key: const ValueKey('cancel-button'),
@@ -387,7 +377,10 @@ List<Widget> formatApiErrors(List<ApiError> errors, {Color? color}) {
for (final error in errors) { for (final error in errors) {
errorList.add( errorList.add(
Text(error.key, style: TextStyle(fontWeight: FontWeight.bold, color: textColor)), Text(
error.key,
style: TextStyle(fontWeight: FontWeight.bold, color: textColor),
),
); );
print(error.errorMessages); print(error.errorMessages);
@@ -408,7 +401,10 @@ List<Widget> formatTextErrors(List<String> errors, {String? title, Color? color}
if (title != null) { if (title != null) {
errorList.add( errorList.add(
Text(title, style: TextStyle(fontWeight: FontWeight.bold, color: textColor)), Text(
title,
style: TextStyle(fontWeight: FontWeight.bold, color: textColor),
),
); );
} }
@@ -458,11 +454,7 @@ class GeneralErrorsWidget extends StatelessWidget {
child: Column( child: Column(
children: [ children: [
Icon(Icons.error_outline, color: Theme.of(context).colorScheme.error), Icon(Icons.error_outline, color: Theme.of(context).colorScheme.error),
...formatTextErrors( ...formatTextErrors(widgets, title: title, color: Theme.of(context).colorScheme.error),
widgets,
title: title,
color: Theme.of(context).colorScheme.error,
),
], ],
), ),
), ),

View File

@@ -41,10 +41,16 @@ class InMemoryLogStore {
List<LogRecord> get logs => List.unmodifiable(_logs); List<LogRecord> get logs => List.unmodifiable(_logs);
List<String> get formattedLogs => _logs List<String> getFormattedLogs({Level? minLevel}) {
.map((log) => final level = minLevel ?? Logger.root.level;
'${log.time.toIso8601String()} ${log.level.name} [${log.loggerName}] ${log.message}') return _logs
.toList(); .where((log) => log.level >= level)
.map(
(log) =>
'${log.time.toIso8601String()} ${log.level.name} [${log.loggerName}] ${log.message}',
)
.toList();
}
void clear() => _logs.clear(); void clear() => _logs.clear();
} }

View File

@@ -36,10 +36,12 @@ void main() {
}); });
test('correctly adds LogRecords', () { test('correctly adds LogRecords', () {
logStore.add(LogRecord(Level.FINE, 'this is fine!!!', 'testLogger'));
logStore.add(LogRecord(Level.INFO, 'this is a test', 'testLogger')); logStore.add(LogRecord(Level.INFO, 'this is a test', 'testLogger'));
expect(logStore.logs.length, 1); expect(logStore.logs.length, 2);
expect(logStore.formattedLogs.length, 1); expect(logStore.getFormattedLogs(minLevel: Level.INFO).length, 1);
expect(logStore.getFormattedLogs(minLevel: Level.FINE).length, 2);
}); });
test('total number of logs is limited', () { test('total number of logs is limited', () {