- Implemented RawFrameDebugScreen for displaying ECU frame data and diagnostics. - Created DtcScreen to show active Diagnostic Trouble Codes (DTCs) with detailed descriptions. - Added DtcRow widget for individual DTC representation. - Introduced GraphScreen for visualizing sensor data over time with customizable time windows. - Developed SensorListScreen to display available sensors and their current values. - Enhanced SettingsScreen with options for Bluetooth connection, ECU protocol selection, polling interval, and theme settings. - Added AppColors and AppTheme for consistent theming across the application. - Implemented BtStatusChip to show Bluetooth connection status in the app bar. - Created RecordFab for starting and stopping data recording sessions.
91 lines
3.2 KiB
Dart
91 lines
3.2 KiB
Dart
import 'package:flutter/material.dart';
|
||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||
import '../../../core/datalog/datalog_player.dart';
|
||
import '../../../core/providers/datalog_provider.dart';
|
||
|
||
class DatalogPlaybackBar extends ConsumerWidget {
|
||
final PlaybackState state;
|
||
const DatalogPlaybackBar({super.key, required this.state});
|
||
|
||
@override
|
||
Widget build(BuildContext context, WidgetRef ref) {
|
||
final notifier = ref.read(playbackProvider.notifier);
|
||
final isPlaying = state.status == PlaybackStatus.playing;
|
||
|
||
return Container(
|
||
color: const Color(0xFF1A1A1A),
|
||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
||
child: Column(
|
||
mainAxisSize: MainAxisSize.min,
|
||
children: [
|
||
// Progress slider
|
||
SliderTheme(
|
||
data: SliderTheme.of(context).copyWith(
|
||
trackHeight: 3,
|
||
thumbShape:
|
||
const RoundSliderThumbShape(enabledThumbRadius: 6),
|
||
overlayShape:
|
||
const RoundSliderOverlayShape(overlayRadius: 12),
|
||
),
|
||
child: Slider(
|
||
value: state.progress,
|
||
onChanged: (v) =>
|
||
notifier.seek((v * state.total).round()),
|
||
),
|
||
),
|
||
// Controls row
|
||
Row(
|
||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||
children: [
|
||
// Frame counter
|
||
Text(
|
||
'${state.position} / ${state.total}',
|
||
style:
|
||
const TextStyle(color: Colors.grey, fontSize: 11),
|
||
),
|
||
// Play / Pause / Stop
|
||
Row(
|
||
children: [
|
||
IconButton(
|
||
icon: Icon(
|
||
isPlaying ? Icons.pause : Icons.play_arrow,
|
||
size: 22,
|
||
),
|
||
onPressed: isPlaying ? notifier.pause : notifier.play,
|
||
padding: const EdgeInsets.all(4),
|
||
constraints: const BoxConstraints(),
|
||
),
|
||
const SizedBox(width: 8),
|
||
IconButton(
|
||
icon: const Icon(Icons.stop, size: 22),
|
||
onPressed: () async => notifier.stop(),
|
||
padding: const EdgeInsets.all(4),
|
||
constraints: const BoxConstraints(),
|
||
),
|
||
],
|
||
),
|
||
// Speed selector
|
||
DropdownButton<double>(
|
||
value: state.speed,
|
||
isDense: true,
|
||
underline: const SizedBox(),
|
||
style: const TextStyle(
|
||
color: Colors.white70, fontSize: 12),
|
||
items: const [
|
||
DropdownMenuItem(value: 0.5, child: Text('0.5×')),
|
||
DropdownMenuItem(value: 1.0, child: Text('1×')),
|
||
DropdownMenuItem(value: 2.0, child: Text('2×')),
|
||
DropdownMenuItem(value: 5.0, child: Text('5×')),
|
||
],
|
||
onChanged: (v) {
|
||
if (v != null) notifier.setSpeed(v);
|
||
},
|
||
),
|
||
],
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
}
|