Add ability to save entire event log to a json file

main
Hank Grabowski 2023-11-27 14:52:16 -06:00
rodzic 2a9a409946
commit 346571b52e
2 zmienionych plików z 81 dodań i 16 usunięć

Wyświetl plik

@ -1,7 +1,12 @@
import 'dart:convert'; import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_file_dialog/flutter_file_dialog.dart';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
import 'package:path_provider/path_provider.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../controls/padding.dart'; import '../controls/padding.dart';
@ -10,7 +15,12 @@ import '../controls/standard_appbar.dart';
import '../services/log_service.dart'; import '../services/log_service.dart';
import '../services/setting_service.dart'; import '../services/setting_service.dart';
import '../utils/clipboard_utils.dart'; import '../utils/clipboard_utils.dart';
import '../utils/dateutils.dart';
import '../utils/json_printer.dart';
import '../utils/logrecord_extensions.dart'; import '../utils/logrecord_extensions.dart';
import '../utils/snackbar_builder.dart';
final _logger = Logger('LogViewerScreen');
class LogViewerScreen extends StatefulWidget { class LogViewerScreen extends StatefulWidget {
const LogViewerScreen({super.key}); const LogViewerScreen({super.key});
@ -24,6 +34,49 @@ class _LogViewerScreenState extends State<LogViewerScreen> {
var filterByText = false; var filterByText = false;
var filterByModule = false; var filterByModule = false;
var filterModuleName = ''; var filterModuleName = '';
var attemptingWrite = false;
Future<void> _writeEventsLog(List<LogRecord> events) async {
if (attemptingWrite) {
return;
}
attemptingWrite = true;
try {
final json =
PrettyJsonEncoder().convert(events.map((e) => e.toJson()).toList());
final filename = 'EventsLog_${DateTime.now().toFileNameString()}.json';
if (Platform.isAndroid || Platform.isIOS) {
final params = SaveFileDialogParams(
data: Uint8List.fromList(json.codeUnits),
fileName: filename,
);
await FlutterFileDialog.saveFile(params: params);
if (mounted) {
buildSnackbar(context, 'Wrote Events Log to: $filename');
}
} else {
final appsDir = await getApplicationDocumentsDirectory();
final location = await FilePicker.platform.saveFile(
dialogTitle: 'Save Events Log',
fileName: filename,
initialDirectory: appsDir.path,
);
if (location != null) {
await File(location).writeAsString(json);
if (mounted) {
buildSnackbar(context, 'Wrote Events Log to: $location');
}
}
}
} catch (e) {
_logger.severe('Error attempting to write out log: $e');
if (mounted) {
buildSnackbar(context, 'Error attempting to write out log: $e');
}
}
attemptingWrite = false;
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -32,23 +85,28 @@ class _LogViewerScreenState extends State<LogViewerScreen> {
final events = logService.events; final events = logService.events;
return Scaffold( return Scaffold(
appBar: StandardAppBar.build(context, 'Log Viewer'), appBar: StandardAppBar.build(context, 'Log Viewer'),
body: Center( body: Center(
child: Padding( child: Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: ResponsiveMaxWidth( child: ResponsiveMaxWidth(
child: Column( child: Column(
children: [ children: [
buildLogPanel(settings), buildLogPanel(settings),
buildModuleFilter(settings, events), buildModuleFilter(settings, events),
buildTextSearchPanel(), buildTextSearchPanel(),
const VerticalPadding(), const VerticalPadding(),
buildLogList(settings.logLevel, events), buildLogList(settings.logLevel, events),
], ],
),
), ),
), ),
)); ),
),
floatingActionButton: FloatingActionButton.small(
onPressed: () => _writeEventsLog(events),
child: const Icon(Icons.save),
),
);
} }
Widget buildLogPanel(SettingsService settings) { Widget buildLogPanel(SettingsService settings) {
@ -78,7 +136,7 @@ class _LogViewerScreenState extends State<LogViewerScreen> {
}); });
}, },
), ),
title: const Text('Filter by module:'), title: filterByModule ? null : const Text('Filter by module'),
trailing: !filterByModule trailing: !filterByModule
? null ? null
: DropdownButton<String>( : DropdownButton<String>(
@ -105,6 +163,7 @@ class _LogViewerScreenState extends State<LogViewerScreen> {
}, },
), ),
title: TextField( title: TextField(
enabled: filterByText,
onChanged: (value) { onChanged: (value) {
setState(() { setState(() {
filterText = value.toLowerCase(); filterText = value.toLowerCase();

Wyświetl plik

@ -58,3 +58,9 @@ class ElapsedDateUtils {
return 'seconds ago'; return 'seconds ago';
} }
} }
const _separator = '_';
extension DateTimeExtensions on DateTime {
String toFileNameString() => '$year$month$day$_separator$hour$minute$second';
}