import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../../core/localization/app_localizations.dart'; import '../../../core/theme/app_theme.dart'; import '../../../shared/services/toast_service.dart'; import '../services/usb_detection_service.dart'; /// U盘导入面板 /// /// 在设置页右侧主区域渲染 U盘检测与导入操作。 class UsbImportPanel extends ConsumerStatefulWidget { const UsbImportPanel({super.key}); @override ConsumerState createState() => _UsbImportPanelState(); } class _UsbImportPanelState extends ConsumerState { bool _detecting = false; Future _detect() async { if (_detecting) return; setState(() => _detecting = true); final l10n = AppLocalizations.of(context); final connected = await UsbDetectionService.instance.detectUsb(); if (!mounted) return; setState(() => _detecting = false); if (connected) { ToastService.showInfo(context, l10n?.detectingUsb ?? '正在检测U盘...'); } else { ToastService.showWarning(context, l10n?.usbNotDetected ?? '未检测到U盘'); } } @override Widget build(BuildContext context) { final l10n = AppLocalizations.of(context); final state = ref.watch(_usbStateProvider); final connected = state.maybeWhen( data: (s) => s.isConnected, orElse: () => UsbDetectionService.instance.isConnected, ); final path = state.maybeWhen( data: (s) => s.path, orElse: () => UsbDetectionService.instance.usbPath, ); return ListView( padding: EdgeInsets.zero, children: [ Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(8), border: Border.all(color: AppTheme.borderSubtle), ), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Row( children: [ Icon( connected ? Icons.usb : Icons.usb_off, color: connected ? AppTheme.primaryColor : AppTheme.warningColor, size: 28, ), const SizedBox(width: 12), Expanded( child: Text( connected ? (l10n?.usbConnected ?? 'U盘已连接') : (l10n?.usbNotDetected ?? '未检测到U盘'), style: TextStyle( color: AppTheme.textPrimary, fontSize: 16, fontWeight: FontWeight.w600, ), ), ), ], ), const SizedBox(height: 12), Text( connected ? '${l10n?.mountPath ?? '挂载路径'}: ${path ?? "?"}' : (l10n?.insertUsb ?? '请插入U盘后重试'), style: TextStyle( color: AppTheme.textSecondary, fontSize: 13), ), const SizedBox(height: 20), Row( mainAxisAlignment: MainAxisAlignment.end, children: [ OutlinedButton.icon( onPressed: _detecting ? null : _detect, icon: _detecting ? const SizedBox( width: 14, height: 14, child: CircularProgressIndicator(strokeWidth: 2), ) : const Icon(Icons.refresh, size: 18), label: Text(l10n?.reDetect ?? '重新检测'), ), const SizedBox(width: 12), ElevatedButton.icon( onPressed: connected ? () => _import(path) : null, icon: const Icon(Icons.download, size: 18), label: Text(l10n?.importProgram ?? '导入程序'), ), ], ), ], ), ), const SizedBox(height: 16), Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(8), border: Border.all(color: AppTheme.borderSubtle), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( l10n?.usageInstructions ?? '使用说明', style: TextStyle( color: AppTheme.textPrimary, fontSize: 14, fontWeight: FontWeight.w600, ), ), const SizedBox(height: 8), _bullet(l10n?.usbUsageStep1 ?? '将程序文件 (.json) 放入 U盘根目录的 programs 文件夹'), _bullet(l10n?.usbUsageStep2 ?? '插入 U盘后点击"重新检测"'), _bullet(l10n?.usbUsageStep3 ?? '检测成功后点击"导入程序"加载程序列表'), ], ), ), ], ); } void _import(String? path) { final l10n = AppLocalizations.of(context); if (path == null) { ToastService.showWarning(context, l10n?.usbPathInvalid ?? 'U盘路径无效'); return; } ToastService.showInfo(context, l10n?.importingPrograms ?? '正在导入程序...'); // TODO: 接入 program_import_service 实现真正的导入流程 } Widget _bullet(String text) { return Padding( padding: const EdgeInsets.symmetric(vertical: 4), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: const EdgeInsets.only(top: 6, right: 8), child: Container( width: 4, height: 4, decoration: BoxDecoration( color: AppTheme.primaryColor, shape: BoxShape.circle, ), ), ), Expanded( child: Text( text, style: TextStyle( color: AppTheme.textSecondary, fontSize: 13, height: 1.5, ), ), ), ], ), ); } } /// 监听 USB 状态变化的 Riverpod StreamProvider final _usbStateProvider = StreamProvider((ref) { return UsbDetectionService.instance.stateStream; });