123 lines
3.4 KiB
Dart
123 lines
3.4 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
import '../proto/messages.pb.dart';
|
|
import 'app_scope.dart';
|
|
import 'log_list_view.dart';
|
|
|
|
class FullLogTab extends StatefulWidget {
|
|
const FullLogTab({super.key});
|
|
|
|
@override
|
|
State<FullLogTab> createState() => _FullLogTabState();
|
|
}
|
|
|
|
class _FullLogTabState extends State<FullLogTab> {
|
|
Set<int> _visible = {1, 2, 3, 4, 5};
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final scope = AppScope.of(context);
|
|
return Padding(
|
|
padding: const EdgeInsets.all(8),
|
|
child: Container(
|
|
decoration: BoxDecoration(
|
|
border: Border.all(
|
|
color: Theme.of(context).colorScheme.outlineVariant,
|
|
),
|
|
borderRadius: BorderRadius.circular(6),
|
|
),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
children: [
|
|
_FilterRow(
|
|
visible: _visible,
|
|
onToggle: (s) => setState(() {
|
|
if (_visible.contains(s)) {
|
|
_visible.remove(s);
|
|
} else {
|
|
_visible.add(s);
|
|
}
|
|
}),
|
|
onExport: () => _exportLog(context),
|
|
),
|
|
const Divider(height: 1),
|
|
Expanded(
|
|
child: LogListView(
|
|
session: scope.session,
|
|
filter: (e) => _visible.contains(
|
|
e.hasSeverity() ? e.severity.value : 0,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Future<void> _exportLog(BuildContext context) async {
|
|
final scope = AppScope.of(context);
|
|
final messenger = ScaffoldMessenger.of(context);
|
|
try {
|
|
final result =
|
|
await scope.exporter.exportLog(buffer: scope.session.logs);
|
|
messenger.showSnackBar(
|
|
SnackBar(content: Text('Exported to ${result.path}')),
|
|
);
|
|
} catch (e) {
|
|
messenger.showSnackBar(
|
|
SnackBar(content: Text('Export failed: $e')),
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
class _FilterRow extends StatelessWidget {
|
|
const _FilterRow({
|
|
required this.visible,
|
|
required this.onToggle,
|
|
required this.onExport,
|
|
});
|
|
|
|
final Set<int> visible;
|
|
final void Function(int) onToggle;
|
|
final VoidCallback onExport;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
Widget chip(int sev, String label, Color color) {
|
|
final on = visible.contains(sev);
|
|
return Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 3),
|
|
child: FilterChip(
|
|
label: Text(label, style: const TextStyle(fontSize: 11)),
|
|
selected: on,
|
|
onSelected: (_) => onToggle(sev),
|
|
selectedColor: color.withValues(alpha: 0.2),
|
|
checkmarkColor: color,
|
|
),
|
|
);
|
|
}
|
|
|
|
return Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 6),
|
|
child: Row(
|
|
children: [
|
|
const Text('Filter:', style: TextStyle(fontSize: 11)),
|
|
const SizedBox(width: 6),
|
|
chip(1, 'DEBUG', Colors.grey),
|
|
chip(2, 'INFO', Colors.blueGrey),
|
|
chip(3, 'WARN', Colors.amber.shade800),
|
|
chip(4, 'ERROR', Colors.red.shade800),
|
|
chip(5, 'FATAL', Colors.red.shade900),
|
|
const Spacer(),
|
|
OutlinedButton.icon(
|
|
onPressed: onExport,
|
|
icon: const Icon(Icons.download, size: 16),
|
|
label: const Text('Export log'),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
} |