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:io';
import 'dart:typed_data';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter_file_dialog/flutter_file_dialog.dart';
import 'package:logging/logging.dart';
import 'package:path_provider/path_provider.dart';
import 'package:provider/provider.dart';
import '../controls/padding.dart';
@ -10,7 +15,12 @@ import '../controls/standard_appbar.dart';
import '../services/log_service.dart';
import '../services/setting_service.dart';
import '../utils/clipboard_utils.dart';
import '../utils/dateutils.dart';
import '../utils/json_printer.dart';
import '../utils/logrecord_extensions.dart';
import '../utils/snackbar_builder.dart';
final _logger = Logger('LogViewerScreen');
class LogViewerScreen extends StatefulWidget {
const LogViewerScreen({super.key});
@ -24,6 +34,49 @@ class _LogViewerScreenState extends State<LogViewerScreen> {
var filterByText = false;
var filterByModule = false;
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
Widget build(BuildContext context) {
@ -32,23 +85,28 @@ class _LogViewerScreenState extends State<LogViewerScreen> {
final events = logService.events;
return Scaffold(
appBar: StandardAppBar.build(context, 'Log Viewer'),
body: Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: ResponsiveMaxWidth(
child: Column(
children: [
buildLogPanel(settings),
buildModuleFilter(settings, events),
buildTextSearchPanel(),
const VerticalPadding(),
buildLogList(settings.logLevel, events),
],
),
appBar: StandardAppBar.build(context, 'Log Viewer'),
body: Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: ResponsiveMaxWidth(
child: Column(
children: [
buildLogPanel(settings),
buildModuleFilter(settings, events),
buildTextSearchPanel(),
const VerticalPadding(),
buildLogList(settings.logLevel, events),
],
),
),
));
),
),
floatingActionButton: FloatingActionButton.small(
onPressed: () => _writeEventsLog(events),
child: const Icon(Icons.save),
),
);
}
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
? null
: DropdownButton<String>(
@ -105,6 +163,7 @@ class _LogViewerScreenState extends State<LogViewerScreen> {
},
),
title: TextField(
enabled: filterByText,
onChanged: (value) {
setState(() {
filterText = value.toLowerCase();

Wyświetl plik

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