import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../models/device.dart'; import '../models/user_info.dart'; import '../services/authentication_manager.dart'; import '../services/brandmeister_client.dart'; import '../widgets/user_header.dart'; import 'device_detail_view.dart'; class DevicesView extends StatefulWidget { const DevicesView({super.key}); @override State createState() => _DevicesViewState(); } class _DevicesViewState extends State { List _devices = []; bool _isLoadingDevices = false; String? _errorMessage; @override void initState() { super.initState(); _loadDevices(); } Future _loadDevices() async { setState(() { _isLoadingDevices = true; _errorMessage = null; }); try { final authManager = context.read(); final devices = await authManager.getDevices(); setState(() { _devices = devices; _isLoadingDevices = false; }); } on BrandmeisterError catch (e) { setState(() { _errorMessage = e.message; _isLoadingDevices = false; }); } catch (e) { setState(() { _errorMessage = e.toString(); _isLoadingDevices = false; }); } } @override Widget build(BuildContext context) { final authManager = context.watch(); final userInfo = authManager.userInfo; return Scaffold( appBar: AppBar( title: const Text('Devices'), ), body: RefreshIndicator( onRefresh: _loadDevices, child: _buildBody(userInfo), ), ); } Widget _buildBody(UserInfo? userInfo) { if (_isLoadingDevices && _devices.isEmpty) { return const Center( child: CircularProgressIndicator(), ); } if (_errorMessage != null) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.error_outline, size: 64, color: Colors.red[300], ), const SizedBox(height: 16), Text( 'Error', style: Theme.of(context).textTheme.titleLarge, ), const SizedBox(height: 8), Padding( padding: const EdgeInsets.symmetric(horizontal: 32), child: Text( _errorMessage!, textAlign: TextAlign.center, style: TextStyle(color: Colors.grey[600]), ), ), const SizedBox(height: 24), ElevatedButton.icon( onPressed: _loadDevices, icon: const Icon(Icons.refresh), label: const Text('Retry'), ), ], ), ); } if (_devices.isEmpty) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.devices_other, size: 64, color: Colors.grey[400], ), const SizedBox(height: 16), Text( 'No devices found', style: Theme.of(context).textTheme.titleLarge, ), const SizedBox(height: 8), Text( 'You don\'t have any devices registered', style: TextStyle(color: Colors.grey[600]), ), ], ), ); } return ListView( children: [ UserHeader( userInfo: userInfo, radioId: _devices.isNotEmpty ? _devices.first.id.toString() : null, ), const Divider(), ..._devices.map((device) => _DeviceRow( device: device, baseRadioId: _devices.isNotEmpty ? _devices.first.id : null, onTap: () { Navigator.push( context, MaterialPageRoute( builder: (context) => DeviceDetailView(device: device), ), ); }, )), ], ); } } class _DeviceRow extends StatelessWidget { final Device device; final int? baseRadioId; final VoidCallback onTap; const _DeviceRow({ required this.device, required this.onTap, this.baseRadioId, }); String? get _deviceExtension { if (baseRadioId == null) return null; final baseStr = baseRadioId.toString(); final idStr = device.id.toString(); // Check if device ID starts with the base radio ID if (idStr.startsWith(baseStr)) { final extension = idStr.substring(baseStr.length); return extension.isNotEmpty ? extension : '0'; } return null; } @override Widget build(BuildContext context) { final extension = _deviceExtension; final showExtension = extension != null && extension != '0'; return ListTile( leading: CircleAvatar( backgroundColor: Theme.of(context).colorScheme.primaryContainer, child: showExtension ? Text( extension, style: TextStyle( fontWeight: FontWeight.bold, color: Theme.of(context).colorScheme.onPrimaryContainer, ), ) : Icon( Icons.settings_input_antenna, color: Theme.of(context).colorScheme.onPrimaryContainer, ), ), title: Text(device.callsign ?? 'Unknown'), subtitle: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('ID: ${device.id}'), if (device.name != null) Text(device.name!), Text(device.displayLocation), ], ), isThreeLine: true, trailing: const Icon(Icons.chevron_right), onTap: onTap, ); } }