Files
smart-serow/pi/ui/lib/widgets/debug_console.dart

82 lines
1.8 KiB
Dart
Raw Normal View History

2026-01-26 22:22:33 +09:00
import 'dart:async';
import 'package:flutter/material.dart';
import '../theme/app_theme.dart';
2026-01-27 00:03:01 +09:00
/// Generic debug console that displays streaming log messages.
///
/// Can be wired to any message source via [messageStream] and [initialMessages].
/// Example sources: WebSocketService.debugStream, ArduinoService logs, etc.
2026-01-26 22:22:33 +09:00
class DebugConsole extends StatefulWidget {
2026-01-27 00:03:01 +09:00
/// Stream of new messages to display
final Stream<String> messageStream;
/// Initial messages to populate (e.g., from a buffer)
final List<String> initialMessages;
2026-01-26 22:22:33 +09:00
/// Maximum lines to display
final int maxLines;
const DebugConsole({
super.key,
2026-01-27 00:03:01 +09:00
required this.messageStream,
this.initialMessages = const [],
2026-01-26 22:22:33 +09:00
this.maxLines = 8,
});
@override
State<DebugConsole> createState() => _DebugConsoleState();
}
class _DebugConsoleState extends State<DebugConsole> {
final List<String> _messages = [];
2026-01-27 00:03:01 +09:00
StreamSubscription<String>? _sub;
2026-01-26 22:22:33 +09:00
@override
void initState() {
super.initState();
// Initialize with existing buffer
2026-01-27 00:03:01 +09:00
_messages.addAll(widget.initialMessages);
2026-01-26 22:22:33 +09:00
_trimMessages();
// Subscribe to new messages
2026-01-27 00:03:01 +09:00
_sub = widget.messageStream.listen((msg) {
2026-01-26 22:22:33 +09:00
setState(() {
_messages.add(msg);
_trimMessages();
});
});
}
void _trimMessages() {
while (_messages.length > widget.maxLines) {
_messages.removeAt(0);
}
}
@override
void dispose() {
2026-01-27 00:03:01 +09:00
_sub?.cancel();
2026-01-26 22:22:33 +09:00
super.dispose();
}
@override
Widget build(BuildContext context) {
final theme = AppTheme.of(context);
return Container(
padding: const EdgeInsets.all(4),
child: Text(
_messages.isEmpty ? '(no messages)' : _messages.join('\n'),
style: TextStyle(
fontFamily: 'monospace',
fontSize: 34,
color: theme.foreground,
height: 1.2,
),
),
);
}
}