import 'package:flutter/material.dart'; import '../services/ble_service.dart'; class DataPacketCard extends StatelessWidget { final DataPacket packet; const DataPacketCard({super.key, required this.packet}); @override Widget build(BuildContext context) { final timeStr = '${packet.timestamp.hour.toString().padLeft(2, '0')}:' '${packet.timestamp.minute.toString().padLeft(2, '0')}:' '${packet.timestamp.second.toString().padLeft(2, '0')}'; return Card( margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), child: ExpansionTile( leading: CircleAvatar( backgroundColor: Theme.of(context).primaryColor, child: Text( '#${packet.packetNumber}', style: const TextStyle(color: Colors.white, fontSize: 12), ), ), title: Text( packet.hexString, style: const TextStyle(fontFamily: 'monospace', fontSize: 14), ), subtitle: Text('$timeStr • ${packet.data.length} bytes'), children: [ Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildSection('Hex', packet.hexString), const SizedBox(height: 8), // 'timbang' style: bytes shown in decimal (matching Python output) _buildSection('timbang', packet.bytesString), const SizedBox(height: 16), if (packet.value32BitUnsigned != null) ...[ _buildValueRow( '32-bit Unsigned (BE)', packet.value32BitUnsigned.toString(), ), _buildValueRow( '32-bit Signed (BE)', packet.value32BitSigned.toString(), ), if (packet.value32BitUnsigned! > 0) ...[ _buildValueRow( 'As Float (÷100)', (packet.value32BitUnsigned! / 100.0).toStringAsFixed(2), ), _buildValueRow( 'As Float (÷1000)', (packet.value32BitUnsigned! / 1000.0).toStringAsFixed(3), ), ], ], if (packet.value16BitUnsigned != null) ...[ const SizedBox(height: 8), _buildValueRow( '16-bit Unsigned (BE)', packet.value16BitUnsigned.toString(), ), _buildValueRow( '16-bit Signed (BE)', packet.value16BitSigned.toString(), ), ], if (packet.asciiString != null) ...[ const SizedBox(height: 8), _buildSection('ASCII', packet.asciiString!), ], ], ), ), ], ), ); } Widget _buildSection(String label, String value) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( label, style: const TextStyle( fontWeight: FontWeight.bold, fontSize: 12, color: Colors.grey, ), ), const SizedBox(height: 4), SelectableText( value, style: const TextStyle(fontFamily: 'monospace', fontSize: 14), ), ], ); } Widget _buildValueRow(String label, String value) { return Padding( padding: const EdgeInsets.symmetric(vertical: 2), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( label, style: const TextStyle(fontSize: 12, color: Colors.grey), ), Text( value, style: const TextStyle( fontFamily: 'monospace', fontWeight: FontWeight.bold, ), ), ], ), ); } }