From c93d722d3f217eaffbbc23966293d92e0ee11004 Mon Sep 17 00:00:00 2001 From: Fabian Freund Date: Sun, 29 Jun 2025 21:00:43 +0200 Subject: [PATCH] improve error logging --- app/lib/core/logger.dart | 14 +++++++- .../screens/general_settings.dart | 32 +++++++++++++++++++ app/lib/main.dart | 9 ++++++ app/lib/utils/ui_helper.dart | 6 ++++ 4 files changed, 60 insertions(+), 1 deletion(-) diff --git a/app/lib/core/logger.dart b/app/lib/core/logger.dart index 55058ea0..b2201889 100644 --- a/app/lib/core/logger.dart +++ b/app/lib/core/logger.dart @@ -1,3 +1,15 @@ import 'package:logger/logger.dart'; -final logger = Logger(); +class _DebugLogFilter extends LogFilter { + @override + bool shouldLog(LogEvent event) { + //Log all events + return true; + } +} + +final loggerMemory = MemoryOutput( + bufferSize: 255, + secondOutput: ConsoleOutput(), +); +final logger = Logger(filter: _DebugLogFilter(), output: loggerMemory); diff --git a/app/lib/features/settings/presentation/screens/general_settings.dart b/app/lib/features/settings/presentation/screens/general_settings.dart index dc76f6aa..6eef664f 100644 --- a/app/lib/features/settings/presentation/screens/general_settings.dart +++ b/app/lib/features/settings/presentation/screens/general_settings.dart @@ -1,9 +1,11 @@ import 'package:fading_scroll/fading_scroll.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_material_design_icons/flutter_material_design_icons.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:nullability/nullability.dart'; +import 'package:weblibre/core/logger.dart'; import 'package:weblibre/features/search/domain/entities/abstract/i_search_suggestion_provider.dart'; import 'package:weblibre/features/settings/presentation/controllers/save_settings.dart'; import 'package:weblibre/features/settings/presentation/widgets/bang_icon.dart'; @@ -13,6 +15,7 @@ import 'package:weblibre/features/user/data/models/general_settings.dart'; import 'package:weblibre/features/user/domain/providers.dart'; import 'package:weblibre/features/user/domain/repositories/cache.dart'; import 'package:weblibre/features/user/domain/repositories/general_settings.dart'; +import 'package:weblibre/utils/ui_helper.dart'; class GeneralSettingsScreen extends HookConsumerWidget { const GeneralSettingsScreen({super.key}); @@ -260,6 +263,35 @@ class GeneralSettingsScreen extends HookConsumerWidget { ); }, ), + CustomListTile( + title: 'Error Logs', + subtitle: 'Copy logs for issue reporting', + prefix: Padding( + padding: const EdgeInsets.only(right: 16.0), + child: Icon( + Icons.bug_report, + size: 24, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + suffix: FilledButton.icon( + onPressed: () async { + await Clipboard.setData( + ClipboardData( + text: loggerMemory.buffer + .map((e) => e.lines.join('\n')) + .join('\n\n'), + ), + ); + + if (context.mounted) { + showInfoMessage(context, 'Logs copied'); + } + }, + icon: const Icon(Icons.copy), + label: const Text('Copy'), + ), + ), ], ); }, diff --git a/app/lib/main.dart b/app/lib/main.dart index 87bbbe55..123324e5 100644 --- a/app/lib/main.dart +++ b/app/lib/main.dart @@ -21,6 +21,15 @@ import 'package:weblibre/presentation/main_app.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); + FlutterError.onError = (e) { + logger.e(e.toString(), error: e.exception, stackTrace: e.stack); + }; + + PlatformDispatcher.instance.onError = (error, stack) { + logger.e('Unhandled Error', error: error, stackTrace: stack); + return true; + }; + if (kDebugMode) { final serviceProtocolInfo = await Service.getInfo(); logger.d('VM: ${serviceProtocolInfo.serverUri}'); diff --git a/app/lib/utils/ui_helper.dart b/app/lib/utils/ui_helper.dart index 1a411426..ef338d3f 100644 --- a/app/lib/utils/ui_helper.dart +++ b/app/lib/utils/ui_helper.dart @@ -15,6 +15,12 @@ void showErrorMessage(BuildContext context, String message) { ScaffoldMessenger.of(context).showSnackBar(snackBar); } +void showInfoMessage(BuildContext context, String message) { + final snackBar = SnackBar(content: Text(message)); + + ScaffoldMessenger.of(context).showSnackBar(snackBar); +} + void showTabBackButtonMessage( BuildContext context, int tabCount,