kopia lustrzana https://gitlab.com/mysocialportal/relatica
Add ability to save entire event log to a json file
rodzic
2a9a409946
commit
346571b52e
|
@ -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();
|
||||||
|
|
|
@ -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';
|
||||||
|
}
|
||||||
|
|
Ładowanie…
Reference in New Issue