Initial version
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
|
||||
/// Persistent protocol log for field debugging without a USB cable.
|
||||
///
|
||||
/// Every line is kept in a bounded in-memory ring (viewable in-app) and, once
|
||||
/// [init] has run, appended to a file that can be pulled with adb:
|
||||
///
|
||||
/// adb pull /sdcard/Android/data/dev.teamhydra.openscooter/files/openscooter.log
|
||||
///
|
||||
/// Before [init], or in tests, only the in-memory ring is used.
|
||||
/// The PIN is never written here; callers mask it first.
|
||||
class ProtocolLog extends ChangeNotifier {
|
||||
ProtocolLog._();
|
||||
static final ProtocolLog instance = ProtocolLog._();
|
||||
|
||||
static const maxLines = 2000;
|
||||
|
||||
final List<String> _lines = <String>[];
|
||||
File? _file;
|
||||
IOSink? _sink;
|
||||
|
||||
List<String> get lines => List.unmodifiable(_lines);
|
||||
String? get path => _file?.path;
|
||||
|
||||
Future<void> init() async {
|
||||
if (_file != null) return;
|
||||
try {
|
||||
Directory? dir;
|
||||
if (Platform.isAndroid) dir = await getExternalStorageDirectory();
|
||||
dir ??= await getApplicationDocumentsDirectory();
|
||||
_file = File('${dir.path}/openscooter.log');
|
||||
_sink = _file!.openWrite(mode: FileMode.append);
|
||||
log('LOG', 'opened ${_file!.path}');
|
||||
} catch (e) {
|
||||
debugPrint('ProtocolLog: could not open log file: $e');
|
||||
}
|
||||
}
|
||||
|
||||
void log(String tag, String message) {
|
||||
final line = '${DateTime.now().toIso8601String()} [$tag] $message';
|
||||
if (kDebugMode) debugPrint(line);
|
||||
_lines.add(line);
|
||||
if (_lines.length > maxLines) _lines.removeRange(0, _lines.length - maxLines);
|
||||
_sink?.writeln(line);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> clear() async {
|
||||
_lines.clear();
|
||||
await _sink?.flush();
|
||||
await _sink?.close();
|
||||
_sink = null;
|
||||
final f = _file;
|
||||
if (f != null) {
|
||||
try {
|
||||
await f.writeAsString('');
|
||||
} catch (_) {}
|
||||
_sink = f.openWrite(mode: FileMode.append);
|
||||
}
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> flush() async => _sink?.flush();
|
||||
}
|
||||
Reference in New Issue
Block a user