import 'package:flutter/material.dart'; import 'package:flutter_sdk/starcloud_flutter_sdk.dart'; import 'package:starcloud/entity/star_cloud_lock_list.dart' as scl; import '../l10n.dart'; import '../global.dart'; import '../widgets/common_widgets.dart'; class DeviceScanTab extends StatefulWidget { const DeviceScanTab({super.key}); @override State createState() => _DeviceScanTabState(); } class _DeviceScanTabState extends State { bool _scanning = false; bool _pairing = false; List _devices = []; final List _log = []; void _log_(String msg) { final ts = DateTime.now().toIso8601String().substring(11, 19); setState(() => _log.add('[$ts] $msg')); } Future _scan() async { if (!sdkCloudAccountReady.value) { _log_(S.isEn ? 'Set an SDK cloud account before scanning and pairing a lock.' : '请先在“登录”页创建或设置 SDK 星云账户,再扫描绑定锁。'); return; } setState(() { _scanning = true; _devices = []; }); _log_(S.isEn ? 'Scan start (10s)...' : '开始扫描(10 秒超时)...'); try { await StarCloudClient.instance.device.scanDeviceList( timeout: 10, onScan: (results) { setState(() => _devices = results); }); _log_(S.isEn ? 'Done. Found ${_devices.length}' : '扫描完成,发现 ${_devices.length} 个设备'); } catch (e) { _log_('${S.isEn ? "Failed" : "失败"}: $e'); } finally { setState(() => _scanning = false); } } Future _pair(int idx) async { if (!sdkCloudAccountReady.value) { _log_( S.isEn ? 'Please set an SDK cloud account first.' : '请先设置 SDK 星云账户。'); return; } setState(() => _pairing = true); _log_(S.isEn ? 'Pairing...' : '正在配对...'); try { final lock = await StarCloudClient.instance.device .pairDevice(scanResult: _devices[idx]); // 更新 ValueNotifier 的值 wifiConfiguredLockId.value = null; pairedLockId.value = lock.lockId; pairedLock.value = lock; _log_('${S.isEn ? "Success" : "成功"}! ID: ${lock.lockId}'); } catch (e) { _log_('${S.isEn ? "Failed" : "失败"}: $e'); } finally { setState(() => _pairing = false); } } @override Widget build(BuildContext context) { return ValueListenableBuilder( valueListenable: S.langNotifier, builder: (context, isEn, _) { return Column( children: [ Padding( padding: const EdgeInsets.all(12), child: Row( children: [ Expanded( child: ElevatedButton.icon( onPressed: _scanning ? null : _scan, icon: _scanning ? const SizedBox( width: 16, height: 16, child: CircularProgressIndicator(strokeWidth: 2)) : const Icon(Icons.bluetooth_searching), label: Text(_scanning ? S.btnScanning : S.btnScan), ), ), const SizedBox(width: 8), ElevatedButton( onPressed: _scanning ? () => StarCloudClient.instance.device .stopScan() .then((_) => setState(() => _scanning = false)) : null, child: Text(S.btnStop)), ], ), ), // 使用 ValueListenableBuilder 监听配对状态 ValueListenableBuilder( valueListenable: pairedLockId, builder: (context, id, _) { if (id == null) return const SizedBox.shrink(); return Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4), alignment: Alignment.centerLeft, child: Chip( label: Text('${S.pairedStatus}: #$id'), backgroundColor: Colors.green.shade50, onDeleted: () { wifiConfiguredLockId.value = null; pairedLockId.value = null; pairedLock.value = null; }, ), ); }, ), Expanded( child: ValueListenableBuilder( valueListenable: pairedLock, builder: (context, paired, _) { if (_devices.isEmpty) { return Center( child: Text( S.scanHint, style: const TextStyle(color: Colors.grey), ), ); } return ListView.separated( padding: const EdgeInsets.symmetric(horizontal: 12), itemCount: _devices.length, separatorBuilder: (_, __) => const Divider(height: 1), itemBuilder: (context, i) { final device = _devices[i] as StarCloudScanResult; final isPaired = _isPairedDevice(device, paired); return ListTile( title: Text(device.advName.isNotEmpty ? device.advName : (S.isEn ? 'Unknown' : '未知设备')), subtitle: Text('MAC: ${device.id}'), trailing: ElevatedButton( onPressed: _pairing || isPaired ? null : () => _pair(i), child: Text(isPaired ? S.pairedStatus : S.btnPair), ), ); }, ); }, ), ), LogArea(log: _log), ], ); }, ); } bool _isPairedDevice( StarCloudScanResult device, scl.StarCloudLock? paired, ) { if (paired == null) return false; return paired.mac == device.id || paired.bluetooth.bluetoothDeviceName == device.advName; } }