import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import '/data/models/user_Info.dart'; import '../controllers/my_devices_controller.dart'; enum _MyDeviceCategory { unknown(0), classicHeadset(1), bleHeadset(2), voiceRecorder(4), smartEye(5); const _MyDeviceCategory(this.value); final int value; static _MyDeviceCategory fromValue(int value) => _MyDeviceCategory.values.firstWhere( (c) => c.value == value, orElse: () => _MyDeviceCategory.unknown, ); String get displayName { switch (this) { case _MyDeviceCategory.unknown: return 'deviceTypeUnknown'.tr; case _MyDeviceCategory.classicHeadset: return 'deviceTypeClassicBluetoothHeadset'.tr; case _MyDeviceCategory.bleHeadset: return 'deviceTypeBleBluetoothHeadset'.tr; case _MyDeviceCategory.voiceRecorder: return 'deviceTypeSmartVoiceRecorder'.tr; case _MyDeviceCategory.smartEye: return 'deviceTypeSmartEye'.tr; } } IconData get icon { switch (this) { case _MyDeviceCategory.classicHeadset: case _MyDeviceCategory.bleHeadset: return Icons.headphones; case _MyDeviceCategory.voiceRecorder: return Icons.mic; case _MyDeviceCategory.smartEye: return Icons.visibility; default: return Icons.device_unknown; } } } class MyDevicesView extends GetView { const MyDevicesView({super.key}); @override Widget build(BuildContext context) { final isDark = Theme.of(context).brightness == Brightness.dark; final bg = isDark ? const Color(0xFF0A0A0F) : const Color(0xFFF5F6FA); final topBg = isDark ? const Color(0xFF0F1018) : const Color(0xFFF0F1F6); return Scaffold( backgroundColor: bg, body: Column( children: [ _buildTopArea(context, isDark, bg), Expanded(child: _buildDevicesList(isDark, topBg)), _buildAddDeviceButton(isDark), ], ), ); } Widget _buildTopArea(BuildContext context, bool isDark, Color bg) { return Container( padding: EdgeInsets.only( top: MediaQuery.of(context).padding.top + 8.h, left: 20.w, right: 20.w, bottom: 20.h, ), decoration: BoxDecoration(color: bg), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ GestureDetector( onTap: () => Get.back(), child: Container( width: 40.w, height: 40.w, decoration: BoxDecoration( shape: BoxShape.circle, color: isDark ? Colors.white.withValues(alpha: 0.06) : Colors.black.withValues(alpha: 0.04), ), child: Icon( Icons.arrow_back_ios_new, size: 18.sp, color: isDark ? Colors.white : const Color(0xFF222222), ), ), ), SizedBox(width: 16.w), Expanded( child: Text( 'deviceManagement'.tr, style: TextStyle( fontSize: 24.sp, fontWeight: FontWeight.w800, color: isDark ? Colors.white : const Color(0xFF111111), letterSpacing: -0.5, ), ), ), Obx(() => controller.isLoading.value ? SizedBox( width: 18.w, height: 18.w, child: const CircularProgressIndicator(strokeWidth: 2), ) : IconButton( onPressed: controller.loadDevices, icon: Icon( Icons.refresh, size: 20.sp, color: isDark ? Colors.white70 : Colors.black54, ), )), ], ), SizedBox(height: 16.h), Obx(() { final total = controller.devicesByType.values .fold(0, (sum, list) => sum + list.length); final connected = controller.devicesByType.values .expand((list) => list) .where(controller.isConnected) .length; return Row( children: [ _buildSummaryCard( number: '$total', label: 'boundDevices'.tr, isActive: true, isDark: isDark), SizedBox(width: 12.w), _buildSummaryCard( number: '$connected', label: 'currentConnection'.tr, isActive: false, isDark: isDark), ], ); }), ], ), ); } Widget _buildSummaryCard({ required String number, required String label, required bool isActive, required bool isDark, }) { final activeGradient = isDark ? [ const Color(0xFF6366F1).withValues(alpha: 0.15), const Color(0xFF8B5CF6).withValues(alpha: 0.1), ] : [const Color(0xFFEEF2FF), const Color(0xFFF5F3FF)]; return Expanded( child: Container( padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 14.h), decoration: BoxDecoration( borderRadius: BorderRadius.circular(16.r), gradient: isActive ? LinearGradient(colors: activeGradient) : null, color: isActive ? null : (isDark ? Colors.white.withValues(alpha: 0.04) : Colors.white), border: Border.all( color: isActive ? const Color(0xFF6366F1).withValues(alpha: 0.18) : (isDark ? Colors.white.withValues(alpha: 0.06) : Colors.black.withValues(alpha: 0.04)), ), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( number, style: TextStyle( fontSize: 22.sp, fontWeight: FontWeight.w700, color: isActive ? (isDark ? const Color(0xFFA5B4FC) : const Color(0xFF6366F1)) : (isDark ? Colors.white : const Color(0xFF222222)), ), ), SizedBox(height: 2.h), Text( label, style: TextStyle( fontSize: 11.sp, fontWeight: FontWeight.w500, color: isDark ? Colors.white.withValues(alpha: 0.5) : const Color(0xFF999999), ), ), ], ), ), ); } Widget _buildDevicesList(bool isDark, Color topBg) { return Obx(() { final groups = controller.devicesByType; if (groups.isEmpty) { return _buildEmptyState(isDark); } return ListView( padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 16.h), children: groups.entries.map((entry) { final category = _MyDeviceCategory.fromValue(entry.key); final list = entry.value; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: EdgeInsets.only(left: 8.w, bottom: 10.h), child: Text( category.displayName.toUpperCase(), style: TextStyle( fontSize: 12.sp, fontWeight: FontWeight.w600, color: isDark ? Colors.white.withValues(alpha: 0.25) : const Color(0xFFAAAAAA), letterSpacing: 1.2, ), ), ), ...list.map((d) => _buildDeviceCard(d, category, isDark)), SizedBox(height: 14.h), ], ); }).toList(), ); }); } Widget _buildEmptyState(bool isDark) { return Center( child: Padding( padding: EdgeInsets.symmetric(horizontal: 32.w), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.devices_other, size: 72.sp, color: isDark ? Colors.white54 : Colors.grey[400], ), SizedBox(height: 16.h), Text( 'noDevicesBound'.tr, style: TextStyle( fontSize: 16.sp, color: isDark ? Colors.white70 : Colors.grey[700], ), ), SizedBox(height: 8.h), Text( 'pleaseBindDeviceFirst'.tr, textAlign: TextAlign.center, style: TextStyle( fontSize: 13.sp, color: isDark ? Colors.white54 : Colors.grey[500], ), ), ], ), ), ); } Widget _buildDeviceCard( UserDevice device, _MyDeviceCategory category, bool isDark) { final connected = controller.isConnected(device); const connectedColor = Color(0xFF22C55E); return Container( margin: EdgeInsets.only(bottom: 10.h), padding: EdgeInsets.all(18.w), decoration: BoxDecoration( borderRadius: BorderRadius.circular(18.r), color: isDark ? (connected ? connectedColor.withValues(alpha: 0.04) : Colors.white.withValues(alpha: 0.03)) : Colors.white, border: Border.all( color: connected ? connectedColor.withValues(alpha: 0.25) : (isDark ? Colors.white.withValues(alpha: 0.05) : Colors.black.withValues(alpha: 0.04)), ), boxShadow: isDark ? null : [ BoxShadow( color: Colors.black.withValues(alpha: 0.03), blurRadius: 10, offset: const Offset(0, 2), ), ], ), child: Column( children: [ Row( children: [ Container( width: 44.w, height: 44.w, decoration: BoxDecoration( borderRadius: BorderRadius.circular(12.r), gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: connected ? [connectedColor, const Color(0xFF16A34A)] : [const Color(0xFF6366F1), const Color(0xFF8B5CF6)], ), ), child: Icon( category.icon, color: Colors.white, size: 22.sp, ), ), SizedBox(width: 14.w), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Flexible( child: Text( device.devicename.isNotEmpty ? device.devicename : 'deviceTypeUnknown'.tr, maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w700, color: isDark ? Colors.white : const Color(0xFF1A1A2E), ), ), ), if (connected) ...[ SizedBox(width: 8.w), Container( padding: EdgeInsets.symmetric( horizontal: 8.w, vertical: 3.h), decoration: BoxDecoration( borderRadius: BorderRadius.circular(6.r), color: connectedColor.withValues(alpha: 0.12), ), child: Text( 'connected'.tr, style: TextStyle( fontSize: 10.sp, fontWeight: FontWeight.w600, color: connectedColor, ), ), ), ], ], ), SizedBox(height: 3.h), Text( device.devicemac.isNotEmpty ? device.devicemac : 'noMacAddress'.tr, style: TextStyle( fontSize: 11.sp, fontWeight: FontWeight.w500, color: isDark ? Colors.white.withValues(alpha: 0.3) : const Color(0xFF999999), fontFamily: 'Menlo', letterSpacing: 0.5, ), ), ], ), ), GestureDetector( onTap: () => _showUnbindDialog(device, isDark), child: Container( padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 7.h), decoration: BoxDecoration( borderRadius: BorderRadius.circular(10.r), border: Border.all( color: isDark ? Colors.white.withValues(alpha: 0.08) : Colors.black.withValues(alpha: 0.08), ), ), child: Text( 'unbind'.tr, style: TextStyle( fontSize: 12.sp, fontWeight: FontWeight.w600, color: isDark ? Colors.white.withValues(alpha: 0.4) : const Color(0xFF999999), ), ), ), ), ], ), if (device.license.isNotEmpty || device.cmei.isNotEmpty) ...[ SizedBox(height: 14.h), Container( padding: EdgeInsets.all(12.w), decoration: BoxDecoration( borderRadius: BorderRadius.circular(12.r), color: isDark ? Colors.white.withValues(alpha: 0.03) : const Color(0xFFF7F7FA), ), child: Column( children: [ if (device.license.isNotEmpty) _buildFieldRow( label: 'licenseCode'.tr, value: device.license, isDark: isDark), if (device.license.isNotEmpty && device.cmei.isNotEmpty) SizedBox(height: 8.h), if (device.cmei.isNotEmpty) _buildFieldRow( label: 'CMEI', value: device.cmei, isDark: isDark), ], ), ), ], ], ), ); } Widget _buildFieldRow({ required String label, required String value, required bool isDark, }) { return Row( children: [ SizedBox( width: 50.w, child: Text( label, style: TextStyle( fontSize: 10.sp, fontWeight: FontWeight.w600, color: isDark ? Colors.white.withValues(alpha: 0.25) : const Color(0xFFBBBBBB), letterSpacing: 0.5, ), ), ), SizedBox(width: 8.w), Expanded( child: Text( value, style: TextStyle( fontSize: 11.sp, fontWeight: FontWeight.w500, color: isDark ? Colors.white.withValues(alpha: 0.5) : const Color(0xFF666666), fontFamily: 'Menlo', letterSpacing: 0.3, ), overflow: TextOverflow.ellipsis, ), ), ], ); } Widget _buildAddDeviceButton(bool isDark) { return Padding( padding: EdgeInsets.fromLTRB(20.w, 8.h, 20.w, 20.h), child: SizedBox( width: double.infinity, height: 48.h, child: ElevatedButton.icon( onPressed: controller.goToScan, icon: Icon(Icons.add, size: 18.sp), label: Text( 'addDevice'.tr, style: TextStyle(fontSize: 14.sp, fontWeight: FontWeight.w600), ), style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF0066CC), foregroundColor: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(14.r), ), elevation: 0, ), ), ), ); } void _showUnbindDialog(UserDevice device, bool isDark) { Get.dialog( AlertDialog( backgroundColor: isDark ? const Color(0xFF1C1C1E) : Colors.white, title: Text( 'confirmUnbind'.tr, style: TextStyle(color: isDark ? Colors.white : Colors.black87), ), content: Text( 'confirmUnbindMessage' .tr .replaceAll('{deviceName}', device.devicename), style: TextStyle(color: isDark ? Colors.white70 : Colors.black54), ), actions: [ TextButton( onPressed: () => Get.back(), child: Text( 'cancel'.tr, style: TextStyle( color: isDark ? Colors.white70 : Colors.grey[600]), ), ), TextButton( onPressed: () { Get.back(); controller.unbindDevice(device); }, child: Text( 'confirmUnbindAction'.tr, style: const TextStyle(color: Colors.red), ), ), ], ), ); } }