You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1145 lines
37 KiB

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../controllers/ota_upgrade_controller.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import '../../../data/services/ble_manager.dart';
class OtaUpgradeView extends GetView<OtaUpgradeController> {
const OtaUpgradeView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final isDarkMode = Theme.of(context).brightness == Brightness.dark;
return WillPopScope(
onWillPop: () async {
if (controller.isUpgrade.value) {
// 显示确认弹窗
await Get.dialog(
AlertDialog(
title: Text('tip'.tr), // 提示
content:
Text('upgradeExitConfirm'.tr), // 当前正在升级,退出将中断升级进程,确定要退出吗?
actions: [
TextButton(
onPressed: () => Get.back(), // 关闭弹窗
child: Text('cancel'.tr), // 取消
),
TextButton(
onPressed: () {
controller.stopUpgrading();
Get.back(); // 关闭弹窗
Get.back(); // 返回上一页
},
child: Text('confirm'.tr), // 确定
),
],
),
);
return false; // 阻止默认返回
}
return true; // 允许返回
},
child: Scaffold(
backgroundColor: isDarkMode ? Colors.black : Colors.grey[100],
appBar: AppBar(
automaticallyImplyLeading: false,
centerTitle: true,
elevation: 0,
backgroundColor: isDarkMode ? Colors.black : Colors.white,
leading: IconButton(
icon: Icon(
Icons.arrow_back_ios,
size: 20.sp,
color: isDarkMode ? Colors.white : Colors.black,
),
onPressed: () {
if (controller.isUpgrade.value) {
// 显示确认弹窗
Get.dialog(
AlertDialog(
title: Text('tip'.tr), // 提示
content: Text(
'upgradeExitConfirm'.tr), // 当前正在升级,退出将中断升级进程,确定要退出吗?
actions: [
TextButton(
onPressed: () => Get.back(), // 关闭弹窗
child: Text('cancel'.tr), // 取消
),
TextButton(
onPressed: () {
controller.stopUpgrading();
Get.back(); // 关闭弹窗
Get.back(); // 返回上一页
},
child: Text('confirm'.tr), // 确定
),
],
),
);
} else {
Get.back(); // 正常返回
}
},
),
title: Text(
'firmwareUpgrade'.tr, //固件升级
style: TextStyle(
fontSize: 20.sp,
color: isDarkMode ? Colors.white : Colors.black,
),
),
),
body: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 20.w, vertical: 12.h),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// 设备信息卡片 - 优化后的版本
_buildDeviceCard(isDarkMode),
SizedBox(height: 16.h),
// 更新说明 - 当有可用更新时显示
//_buildUpdateNotes(isDarkMode),
// 状态显示区域
Obx(() {
if (controller.isFetchingDeviceInfo.value) {
return _buildLoadingIndicator(isDarkMode);
}
if (controller.errorMessage.value.isNotEmpty) {
return _buildErrorInfo(isDarkMode);
}
return _buildUpdateButton(isDarkMode);
}),
],
),
),
),
),
);
}
// 设备信息卡片
Widget _buildDeviceCard(bool isDarkMode) {
return Container(
width: double.infinity,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: isDarkMode
? [
const Color(0xFF1A1A1A).withValues(alpha: 0.9),
const Color(0xFF2A2A2A).withValues(alpha: 0.9),
]
: [
const Color(0xFFF8FAFF),
const Color(0xFFE3F2FD),
],
),
borderRadius: BorderRadius.circular(20.r),
boxShadow: [
BoxShadow(
color: isDarkMode
? Colors.black.withValues(alpha: 0.3)
: Colors.black.withValues(alpha: 0.08),
blurRadius: 20,
offset: const Offset(0, 8),
spreadRadius: 0,
),
],
),
child: Padding(
padding: EdgeInsets.all(20.w),
child: Column(
children: [
// 设备图标区域
_buildDeviceIcon(isDarkMode),
SizedBox(height: 16.h),
// 设备详细信息区域
_buildDeviceDetailInfo(isDarkMode),
SizedBox(height: 16.h),
// 版本信息区域
_buildVersionInfo(isDarkMode),
],
),
),
);
}
// 设备图标
Widget _buildDeviceIcon(bool isDarkMode) {
return Container(
padding: EdgeInsets.all(16.w),
decoration: BoxDecoration(
color: isDarkMode
? Colors.white.withValues(alpha: 0.05)
: Colors.white.withValues(alpha: 0.7),
borderRadius: BorderRadius.circular(16.r),
border: Border.all(
color: isDarkMode
? Colors.white.withValues(alpha: 0.1)
: Colors.blue.withValues(alpha: 0.1),
width: 1,
),
),
child: GetBuilder<OtaUpgradeController>(
builder: (controller) {
final imagePath = controller.lastConnectedDeviceImage;
if (imagePath == null || imagePath.isEmpty) {
return Image.asset(
isDarkMode
? 'assets/images/headphone_new3.png'
: 'assets/images/headphone_new4.png',
height: 100.h,
fit: BoxFit.contain,
);
}
// 网络图片
return Image.network(
imagePath,
height: 100.h,
fit: BoxFit.contain,
loadingBuilder: (context, child, loadingProgress) {
if (loadingProgress == null) return child;
return SizedBox(
height: 100.h,
child: Center(
child: CircularProgressIndicator(
value: loadingProgress.expectedTotalBytes != null
? loadingProgress.cumulativeBytesLoaded /
loadingProgress.expectedTotalBytes!
: null,
strokeWidth: 2,
color: isDarkMode ? Colors.white : Colors.blue,
),
),
);
},
errorBuilder: (context, error, stackTrace) {
// 网络图片加载失败时使用默认图片
return Image.asset(
isDarkMode
? 'assets/images/headphone_new3.png'
: 'assets/images/headphone_new4.png',
height: 100.h,
fit: BoxFit.contain,
);
},
);
},
),
);
}
// 设备详细信息显示
Widget _buildDeviceDetailInfo(bool isDarkMode) {
return Obx(() {
final deviceInfo = Get.find<BleManager>().deviceInfo.value;
return Container(
padding: EdgeInsets.all(14.w),
decoration: BoxDecoration(
color: isDarkMode
? Colors.white.withValues(alpha: 0.03)
: Colors.white.withValues(alpha: 0.8),
borderRadius: BorderRadius.circular(12.r),
border: Border.all(
color: isDarkMode
? Colors.white.withValues(alpha: 0.08)
: Colors.grey.withValues(alpha: 0.2),
width: 1,
),
),
child: Column(
children: [
// 设备型号信息
_buildDeviceInfoRow(
icon: Icons.headset,
label: 'deviceModel'.tr, // 设备型号
value: deviceInfo?.name ?? 'unknownDevice'.tr, // 未知设备
isDarkMode: isDarkMode,
),
// SizedBox(height: 10.h),
// // 电量信息区域
// Row(
// children: [
// // 左耳电量
// Expanded(
// child: _buildBatteryInfo(
// label: '左耳电量',
// batteryLevel: deviceInfo?.leftEarBattery ?? 0,
// isCharging: deviceInfo?.leftEarCharging ?? false,
// isDarkMode: isDarkMode,
// icon: Icons.headset,
// ),
// ),
// SizedBox(width: 10.w),
// // 右耳电量
// Expanded(
// child: _buildBatteryInfo(
// label: '右耳电量',
// batteryLevel: deviceInfo?.rightEarBattery ?? 0,
// isCharging: deviceInfo?.rightEarCharging ?? false,
// isDarkMode: isDarkMode,
// icon: Icons.headset,
// ),
// ),
// ],
// ),
],
),
);
});
}
// 设备信息行组件
Widget _buildDeviceInfoRow({
required IconData icon,
required String label,
required String value,
required bool isDarkMode,
}) {
return Row(
children: [
Container(
padding: EdgeInsets.all(6.w),
decoration: BoxDecoration(
color: isDarkMode
? Colors.blue.withValues(alpha: 0.1)
: Colors.blue.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(6.r),
),
child: Icon(
icon,
size: 16.sp,
color: isDarkMode ? Colors.blue[300] : Colors.blue[600],
),
),
SizedBox(width: 12.w),
Text(
label,
style: TextStyle(
fontSize: 14.sp,
color: isDarkMode ? Colors.grey[300] : Colors.grey[700],
fontWeight: FontWeight.w500,
),
),
const Spacer(),
Text(
value,
style: TextStyle(
fontSize: 14.sp,
fontWeight: FontWeight.w600,
color: isDarkMode ? Colors.white : Colors.black87,
),
),
],
);
}
// 电池信息组件
Widget _buildBatteryInfo({
required String label,
required int batteryLevel,
required bool isCharging,
required bool isDarkMode,
required IconData icon,
}) {
Color batteryColor;
if (batteryLevel > 60) {
batteryColor = Colors.green;
} else if (batteryLevel > 30) {
batteryColor = Colors.orange;
} else {
batteryColor = Colors.red;
}
return Container(
padding: EdgeInsets.all(10.w),
decoration: BoxDecoration(
color: isDarkMode
? batteryColor.withValues(alpha: 0.1)
: batteryColor.withValues(alpha: 0.05),
borderRadius: BorderRadius.circular(8.r),
border: Border.all(
color: batteryColor.withValues(alpha: 0.3),
width: 1,
),
),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
isCharging ? Icons.battery_charging_full : Icons.battery_std,
size: 16.sp,
color: batteryColor,
),
SizedBox(width: 4.w),
Text(
label,
style: TextStyle(
fontSize: 12.sp,
color: isDarkMode ? Colors.grey[300] : Colors.grey[700],
fontWeight: FontWeight.w500,
),
),
],
),
SizedBox(height: 4.h),
Text(
'${batteryLevel}%',
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.bold,
color: batteryColor,
),
),
if (isCharging) ...[
SizedBox(height: 1.h),
Text(
'charging'.tr, // 充电中
style: TextStyle(
fontSize: 10.sp,
color: batteryColor,
fontWeight: FontWeight.w500,
),
),
],
],
),
);
}
// 版本信息显示
Widget _buildVersionInfo(bool isDarkMode) {
return Column(
children: [
// 当前版本信息
_buildVersionInfoRow(
label: 'currentFirmwareVersion'.tr, //当前固件版本
version: controller.currentVersion,
isDarkMode: isDarkMode,
isLatest: false,
),
SizedBox(height: 8.h),
// 最新版本信息
_buildVersionInfoRow(
label: 'latestFirmwareVersion'.tr, //最新固件版本
version: controller.latestVersion,
isDarkMode: isDarkMode,
isLatest: true,
),
// 版本状态指示器
SizedBox(height: 14.h),
if (controller.isBleConnected.value)
_buildVersionStatusIndicator(isDarkMode),
],
);
}
// 版本信息行组件
Widget _buildVersionInfoRow({
required String label,
required RxString version,
required bool isDarkMode,
required bool isLatest,
}) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 14.w, vertical: 10.h),
decoration: BoxDecoration(
color: isDarkMode
? Colors.white.withValues(alpha: 0.03)
: Colors.white.withValues(alpha: 0.8),
borderRadius: BorderRadius.circular(12.r),
border: Border.all(
color: isDarkMode
? Colors.white.withValues(alpha: 0.08)
: Colors.grey.withValues(alpha: 0.2),
width: 1,
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
label,
style: TextStyle(
fontSize: 14.sp,
color: isDarkMode ? Colors.grey[300] : Colors.grey[700],
fontWeight: FontWeight.w500,
),
),
Obx(() => Row(
children: [
if (isLatest && controller.isUpdateAvailable.value) ...[
Container(
padding:
EdgeInsets.symmetric(horizontal: 6.w, vertical: 2.h),
decoration: BoxDecoration(
color: Colors.orange.withValues(alpha: 0.2),
borderRadius: BorderRadius.circular(8.r),
),
child: Text(
'NEW',
style: TextStyle(
fontSize: 10.sp,
fontWeight: FontWeight.bold,
color: Colors.orange,
),
),
),
SizedBox(width: 8.w),
],
Text(
'V ${version.value}',
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w600,
color: isDarkMode
? (isLatest ? Colors.green[300] : Colors.blue[300])
: (isLatest ? Colors.green[600] : Colors.blue[600]),
),
),
],
)),
],
),
);
}
// 版本状态指示器
Widget _buildVersionStatusIndicator(bool isDarkMode) {
return Obx(() {
if (controller.isUpdateAvailable.value) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 8.h),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Colors.orange.withValues(alpha: 0.1),
Colors.red.withValues(alpha: 0.1),
],
),
borderRadius: BorderRadius.circular(20.r),
border: Border.all(
color: Colors.orange.withValues(alpha: 0.3),
width: 1,
),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.update,
size: 16.sp,
color: Colors.orange,
),
SizedBox(width: 6.w),
Text(
'ota_newVersionFound'.tr, // 发现新版本
style: TextStyle(
fontSize: 12.sp,
fontWeight: FontWeight.w500,
color: Colors.orange,
),
),
],
),
);
} else {
return Container(
padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 8.h),
decoration: BoxDecoration(
color: Colors.green.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(20.r),
border: Border.all(
color: Colors.green.withValues(alpha: 0.3),
width: 1,
),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.check_circle,
size: 16.sp,
color: Colors.green,
),
SizedBox(width: 6.w),
Text(
'latestVersion'.tr, // 已是最新版本
style: TextStyle(
fontSize: 12.sp,
fontWeight: FontWeight.w500,
color: Colors.green,
),
),
],
),
);
}
});
}
// 固件更新说明
Widget _buildUpdateNotes(bool isDarkMode) {
return Obx(() => controller.isUpdateAvailable.value &&
controller.updatedescription.value.isNotEmpty
? Container(
width: double.infinity,
margin: EdgeInsets.only(bottom: 8.h),
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: isDarkMode
? [
Colors.amber[900]!.withValues(alpha: 0.1),
Colors.orange[900]!.withValues(alpha: 0.05),
]
: [
Colors.amber[50]!,
Colors.orange[100]!.withValues(alpha: 0.3),
],
),
borderRadius: BorderRadius.circular(16.r),
border: Border.all(
color: isDarkMode
? Colors.amber[700]!.withValues(alpha: 0.3)
: Colors.amber[200]!.withValues(alpha: 0.5),
width: 1,
),
),
child: Padding(
padding: EdgeInsets.all(20.w),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Container(
padding: EdgeInsets.all(8.w),
decoration: BoxDecoration(
color: Colors.amber.withValues(alpha: 0.2),
borderRadius: BorderRadius.circular(8.r),
),
child: Icon(
Icons.new_releases,
color: isDarkMode
? Colors.amber[300]
: Colors.amber[700],
size: 18.sp,
),
),
SizedBox(width: 12.w),
Text(
'updateContent'.tr, //更新内容
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w600,
color: isDarkMode
? Colors.amber[200]
: Colors.amber[800],
),
),
],
),
SizedBox(height: 16.h),
Container(
width: double.infinity,
padding: EdgeInsets.all(16.w),
decoration: BoxDecoration(
color: isDarkMode
? Colors.white.withValues(alpha: 0.03)
: Colors.white.withValues(alpha: 0.7),
borderRadius: BorderRadius.circular(12.r),
),
child: Text(
controller.updatedescription.value,
style: TextStyle(
fontSize: 14.sp,
height: 1.5,
color: isDarkMode ? Colors.grey[300] : Colors.grey[700],
),
),
),
],
),
),
)
: const SizedBox.shrink());
}
// 加载指示器
Widget _buildLoadingIndicator(bool isDarkMode) {
return Container(
padding: EdgeInsets.all(32.w),
decoration: BoxDecoration(
color: isDarkMode
? Colors.white.withValues(alpha: 0.03)
: Colors.white.withValues(alpha: 0.8),
borderRadius: BorderRadius.circular(20.r),
border: Border.all(
color: isDarkMode
? Colors.white.withValues(alpha: 0.08)
: Colors.grey.withValues(alpha: 0.2),
width: 1,
),
),
child: Column(
children: [
// 自定义加载动画
SizedBox(
width: 50.w,
height: 50.w,
child: CircularProgressIndicator(
strokeWidth: 3,
valueColor: AlwaysStoppedAnimation(
isDarkMode ? const Color(0xFF0066CC) : Colors.blue,
),
backgroundColor: isDarkMode
? Colors.white.withValues(alpha: 0.1)
: Colors.grey.withValues(alpha: 0.2),
),
),
SizedBox(height: 24.h),
Text(
'gettingDeviceInfo'.tr, // 正在获取设备信息...
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w500,
color: isDarkMode ? Colors.grey[300] : Colors.grey[700],
),
),
SizedBox(height: 8.h),
Text(
'keepDeviceConnected'.tr, // 请保持设备连接
style: TextStyle(
fontSize: 12.sp,
color: isDarkMode ? Colors.grey[500] : Colors.grey[500],
),
),
],
),
);
}
// 错误信息显示
Widget _buildErrorInfo(bool isDarkMode) {
return Container(
padding: EdgeInsets.all(24.w),
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: isDarkMode
? [
Colors.red[900]!.withValues(alpha: 0.15),
Colors.red[800]!.withValues(alpha: 0.1),
]
: [
Colors.red[50]!,
Colors.red[100]!.withValues(alpha: 0.3),
],
),
borderRadius: BorderRadius.circular(20.r),
border: Border.all(
color: isDarkMode
? Colors.red[700]!.withValues(alpha: 0.3)
: Colors.red[200]!.withValues(alpha: 0.5),
width: 1,
),
),
child: Column(
children: [
// 错误图标
Container(
padding: EdgeInsets.all(16.w),
decoration: BoxDecoration(
color: Colors.red.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(50.r),
),
child: Icon(
Icons.error_outline,
color: Colors.red,
size: 32.sp,
),
),
SizedBox(height: 16.h),
// 错误标题
Text(
'connectionFailed'.tr, // 连接失败
style: TextStyle(
fontSize: 18.sp,
fontWeight: FontWeight.w600,
color: isDarkMode ? Colors.red[300] : Colors.red[700],
),
),
SizedBox(height: 8.h),
// 错误信息
Text(
controller.errorMessage.value,
textAlign: TextAlign.center,
style: TextStyle(
color: isDarkMode ? Colors.red[200] : Colors.red[600],
fontSize: 14.sp,
height: 1.4,
),
),
SizedBox(height: 24.h),
// 重试按钮
SizedBox(
width: double.infinity,
child: ElevatedButton.icon(
icon: Icon(Icons.refresh, size: 18.sp),
label: Text(
'retryConnection'.tr, //重试连接
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w500,
),
),
style: ElevatedButton.styleFrom(
backgroundColor:
isDarkMode ? const Color(0xFF0066CC) : Colors.blue,
foregroundColor: Colors.white,
padding: EdgeInsets.symmetric(vertical: 14.h),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16.r),
),
elevation: 0,
),
onPressed: controller.retryConnection,
),
),
],
),
);
}
// 更新按钮
Widget _buildUpdateButton(bool isDarkMode) {
return Obx(() {
if (controller.isUpgrade.value) {
return _buildProgressIndicator(isDarkMode);
}
// 显示详细状态提示
if (controller.showDetailedStatus.value) {
return _buildDetailedStatusIndicator(isDarkMode);
}
return SizedBox(
width: double.infinity,
child: Column(
children: [
// 主要更新按钮
Container(
width: double.infinity,
height: 56.h,
decoration: BoxDecoration(
gradient: controller.isUpdateAvailable.value
? LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: isDarkMode
? [const Color(0xFF0066CC), const Color(0xFF0052A3)]
: [Colors.blue, Colors.blue[700]!],
)
: null,
color: !controller.isUpdateAvailable.value
? (isDarkMode ? Colors.grey[800] : Colors.grey[300])
: null,
borderRadius: BorderRadius.circular(16.r),
boxShadow: controller.isUpdateAvailable.value
? [
BoxShadow(
color: Colors.blue.withValues(alpha: 0.3),
blurRadius: 12,
offset: const Offset(0, 4),
),
]
: null,
),
child: ElevatedButton.icon(
icon: Icon(
controller.isUpdateAvailable.value
? Icons.system_update
: Icons.check_circle,
size: 20.sp,
),
label: Text(
controller.isUpdateAvailable.value
? 'ota_updateNow'.tr
: controller.isBleConnected.value
? 'latestVersion'.tr // 立即更新 : 已是最新版本
: 'unconnected'.tr,
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w600,
),
),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.transparent,
foregroundColor: Colors.white,
shadowColor: Colors.transparent,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16.r),
),
),
onPressed: controller.isUpdateAvailable.value
? controller.startUpdate
: null,
),
),
// 更新提示信息
if (controller.isUpdateAvailable.value) ...[
SizedBox(height: 16.h),
Container(
padding: EdgeInsets.all(16.w),
decoration: BoxDecoration(
color: isDarkMode
? Colors.orange.withValues(alpha: 0.1)
: Colors.orange[50],
borderRadius: BorderRadius.circular(12.r),
border: Border.all(
color: Colors.orange.withValues(alpha: 0.3),
width: 1,
),
),
child: Row(
children: [
Icon(
Icons.info_outline,
color: Colors.orange,
size: 20.sp,
),
SizedBox(width: 12.w),
Expanded(
child: Text(
'removeEarbudsEnsureBattery'.tr, //取出双耳机,并保证电量均为30%以上的状态
style: TextStyle(
fontSize: 13.sp,
color: isDarkMode
? Colors.orange[200]
: Colors.orange[800],
height: 1.3,
),
),
),
],
),
),
],
],
),
);
});
}
// 详细状态指示器
Widget _buildDetailedStatusIndicator(bool isDarkMode) {
return Obx(() {
return Container(
width: double.infinity,
padding: EdgeInsets.all(24.w),
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: isDarkMode
? [
const Color(0xFF1A1A1A).withValues(alpha: 0.9),
const Color(0xFF2A2A2A).withValues(alpha: 0.9),
]
: [
const Color(0xFFF8FAFF),
const Color(0xFFE3F2FD),
],
),
borderRadius: BorderRadius.circular(20.r),
boxShadow: [
BoxShadow(
color: isDarkMode
? Colors.black.withValues(alpha: 0.3)
: Colors.black.withValues(alpha: 0.08),
blurRadius: 20,
offset: const Offset(0, 8),
),
],
),
child: Column(
children: [
// 状态图标和文字
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
padding: EdgeInsets.all(8.w),
decoration: BoxDecoration(
color: Colors.blue.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(8.r),
),
child: SizedBox(
width: 20.sp,
height: 20.sp,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(
isDarkMode ? const Color(0xFF0066CC) : Colors.blue,
),
),
),
),
SizedBox(width: 12.w),
Expanded(
child: Text(
controller.detailedStatus.value,
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w500,
color: isDarkMode ? Colors.blue[300] : Colors.blue[700],
),
),
),
],
),
SizedBox(height: 16.h),
// 提示信息
Text(
'keepConnectedDontClose'.tr, // 请保持设备连接,不要关闭应用
style: TextStyle(
fontSize: 12.sp,
color: isDarkMode ? Colors.grey[400] : Colors.grey[600],
),
),
],
),
);
});
}
// 进度指示器
Widget _buildProgressIndicator(bool isDarkMode) {
return Obx(() {
final progress = controller.progress.value;
final type = controller.type.value;
final statusMessage = controller.getStatusMessage(type);
return Container(
width: double.infinity,
padding: EdgeInsets.all(24.w),
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: isDarkMode
? [
const Color(0xFF1A1A1A).withValues(alpha: 0.9),
const Color(0xFF2A2A2A).withValues(alpha: 0.9),
]
: [
const Color(0xFFF8FAFF),
const Color(0xFFE3F2FD),
],
),
borderRadius: BorderRadius.circular(20.r),
boxShadow: [
BoxShadow(
color: isDarkMode
? Colors.black.withValues(alpha: 0.3)
: Colors.black.withValues(alpha: 0.08),
blurRadius: 20,
offset: const Offset(0, 8),
),
],
),
child: Column(
children: [
// 状态图标和文字
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
padding: EdgeInsets.all(8.w),
decoration: BoxDecoration(
color: Colors.blue.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(8.r),
),
child: Icon(
Icons.system_update,
color: isDarkMode ? const Color(0xFF0066CC) : Colors.blue,
size: 20.sp,
),
),
SizedBox(width: 12.w),
Text(
statusMessage,
style: TextStyle(
fontSize: 18.sp,
fontWeight: FontWeight.w600,
color: isDarkMode ? Colors.blue[300] : Colors.blue[700],
),
),
],
),
SizedBox(height: 24.h),
// 进度条容器
Container(
height: 8.h,
decoration: BoxDecoration(
color: isDarkMode
? Colors.white.withValues(alpha: 0.1)
: Colors.grey[200],
borderRadius: BorderRadius.circular(4.r),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(4.r),
child: LinearProgressIndicator(
value: progress / 100.0,
backgroundColor: Colors.transparent,
valueColor: AlwaysStoppedAnimation<Color>(
isDarkMode ? const Color(0xFF0066CC) : Colors.blue,
),
),
),
),
SizedBox(height: 16.h),
// 进度百分比和详细信息
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'${progress.toStringAsFixed(1)}%',
style: TextStyle(
fontSize: 24.sp,
fontWeight: FontWeight.bold,
color: isDarkMode ? Colors.blue[300] : Colors.blue[700],
),
),
Text(
'doNotDisconnect'.tr, // 请勿断开连接
style: TextStyle(
fontSize: 12.sp,
color: isDarkMode ? Colors.grey[400] : Colors.grey[600],
),
),
],
),
],
),
);
});
}
}