Initial version

This commit is contained in:
2026-09-21 18:03:21 -04:00
commit e8e7dc4a81
83 changed files with 7177 additions and 0 deletions
+67
View File
@@ -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();
}