|
|
|
@ -89,33 +89,17 @@ class OtaUpgradeView extends GetView<OtaUpgradeController> { |
|
|
|
), |
|
|
|
body: SingleChildScrollView( |
|
|
|
child: Padding( |
|
|
|
padding: EdgeInsets.all(20), |
|
|
|
padding: EdgeInsets.symmetric(horizontal: 20.w, vertical: 16.h), |
|
|
|
child: Column( |
|
|
|
mainAxisSize: MainAxisSize.min, |
|
|
|
children: [ |
|
|
|
// 设备信息卡片 |
|
|
|
Card( |
|
|
|
elevation: 2, |
|
|
|
shape: RoundedRectangleBorder( |
|
|
|
borderRadius: BorderRadius.circular(16), |
|
|
|
), |
|
|
|
color: isDarkMode ? Colors.grey[900] : Colors.white, |
|
|
|
child: Padding( |
|
|
|
padding: EdgeInsets.all(20), |
|
|
|
child: Column( |
|
|
|
children: [ |
|
|
|
_buildDeviceIcon(isDarkMode), |
|
|
|
SizedBox(height: 20), |
|
|
|
_buildVersionInfo(isDarkMode), |
|
|
|
], |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
SizedBox(height: 20), |
|
|
|
// 设备信息卡片 - 优化后的版本 |
|
|
|
_buildDeviceCard(isDarkMode), |
|
|
|
SizedBox(height: 24.h), |
|
|
|
|
|
|
|
// 更新说明 |
|
|
|
_buildUpdateNotes(isDarkMode), |
|
|
|
SizedBox(height: 20), |
|
|
|
// 更新说明 - 当有可用更新时显示 |
|
|
|
//_buildUpdateNotes(isDarkMode), |
|
|
|
SizedBox(height: 16.h), |
|
|
|
|
|
|
|
// 状态显示区域 |
|
|
|
Obx(() { |
|
|
|
@ -135,257 +119,696 @@ class OtaUpgradeView extends GetView<OtaUpgradeController> { |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
// 设备信息卡片 |
|
|
|
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(24.w), |
|
|
|
child: Column( |
|
|
|
children: [ |
|
|
|
// 设备图标区域 |
|
|
|
_buildDeviceIcon(isDarkMode), |
|
|
|
SizedBox(height: 24.h), |
|
|
|
// 版本信息区域 |
|
|
|
_buildVersionInfo(isDarkMode), |
|
|
|
], |
|
|
|
), |
|
|
|
), |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
// 设备图标 |
|
|
|
Widget _buildDeviceIcon(bool isDarkMode) => Image.asset( |
|
|
|
Widget _buildDeviceIcon(bool isDarkMode) { |
|
|
|
return Container( |
|
|
|
padding: EdgeInsets.all(20.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: Image.asset( |
|
|
|
isDarkMode |
|
|
|
? 'assets/images/headphone_dark.png' |
|
|
|
: 'assets/images/headphone_light.png', |
|
|
|
height: 180.h, |
|
|
|
height: 120.h, |
|
|
|
fit: BoxFit.contain, |
|
|
|
); |
|
|
|
), |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
Widget _buildVersionInfo(bool isDarkMode) => Column( |
|
|
|
mainAxisAlignment: MainAxisAlignment.start, |
|
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
|
// 版本信息显示 |
|
|
|
Widget _buildVersionInfo(bool isDarkMode) { |
|
|
|
return Column( |
|
|
|
children: [ |
|
|
|
// 当前版本信息 |
|
|
|
_buildVersionInfoRow( |
|
|
|
label: '当前固件版本'.tr, |
|
|
|
version: controller.currentVersion, |
|
|
|
isDarkMode: isDarkMode, |
|
|
|
isLatest: false, |
|
|
|
), |
|
|
|
SizedBox(height: 16.h), |
|
|
|
// 最新版本信息 |
|
|
|
_buildVersionInfoRow( |
|
|
|
label: '最新固件版本'.tr, |
|
|
|
version: controller.latestVersion, |
|
|
|
isDarkMode: isDarkMode, |
|
|
|
isLatest: true, |
|
|
|
), |
|
|
|
// 版本状态指示器 |
|
|
|
SizedBox(height: 20.h), |
|
|
|
_buildVersionStatusIndicator(isDarkMode), |
|
|
|
], |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
// 版本信息行组件 |
|
|
|
Widget _buildVersionInfoRow({ |
|
|
|
required String label, |
|
|
|
required RxString version, |
|
|
|
required bool isDarkMode, |
|
|
|
required bool isLatest, |
|
|
|
}) { |
|
|
|
return Container( |
|
|
|
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 12.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: [ |
|
|
|
Row( |
|
|
|
crossAxisAlignment: CrossAxisAlignment.center, // 改为center对齐 |
|
|
|
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: [ |
|
|
|
Text('当前固件版本:'.tr, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 18, |
|
|
|
color: isDarkMode ? Colors.grey[300] : Colors.black)), |
|
|
|
SizedBox(width: 8), // 改为width |
|
|
|
Obx(() => Text('V ${controller.currentVersion}', |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 24, |
|
|
|
fontWeight: FontWeight.normal, |
|
|
|
color: isDarkMode ? Colors.blue[300] : Colors.blue))), |
|
|
|
Icon( |
|
|
|
Icons.update, |
|
|
|
size: 16.sp, |
|
|
|
color: Colors.orange, |
|
|
|
), |
|
|
|
SizedBox(width: 6.w), |
|
|
|
Text( |
|
|
|
'发现新版本', |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 12.sp, |
|
|
|
fontWeight: FontWeight.w500, |
|
|
|
color: Colors.orange, |
|
|
|
), |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
SizedBox(height: 8), // 改为height |
|
|
|
Row( |
|
|
|
crossAxisAlignment: CrossAxisAlignment.center, // 改为center对齐 |
|
|
|
); |
|
|
|
} 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: [ |
|
|
|
Text('最新固件版本:'.tr, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 18, |
|
|
|
color: isDarkMode ? Colors.grey[300] : Colors.black)), |
|
|
|
SizedBox(width: 8), // 改为width |
|
|
|
Obx(() => Text('V ${controller.latestVersion}', |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 24, |
|
|
|
fontWeight: FontWeight.normal, |
|
|
|
color: isDarkMode ? Colors.blue[300] : Colors.blue))), |
|
|
|
Icon( |
|
|
|
Icons.check_circle, |
|
|
|
size: 16.sp, |
|
|
|
color: Colors.green, |
|
|
|
), |
|
|
|
SizedBox(width: 6.w), |
|
|
|
Text( |
|
|
|
'已是最新版本', |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 12.sp, |
|
|
|
fontWeight: FontWeight.w500, |
|
|
|
color: Colors.green, |
|
|
|
), |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
], |
|
|
|
); |
|
|
|
); |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
// 添加固件更新说明 |
|
|
|
Widget _buildUpdateNotes(bool isDarkMode) => |
|
|
|
Obx(() => controller.isUpdateAvailable.value |
|
|
|
? Card( |
|
|
|
elevation: 2, |
|
|
|
shape: RoundedRectangleBorder( |
|
|
|
borderRadius: BorderRadius.circular(16), |
|
|
|
// 固件更新说明 |
|
|
|
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), |
|
|
|
], |
|
|
|
), |
|
|
|
color: isDarkMode ? Colors.grey[900] : Colors.white, |
|
|
|
child: Padding( |
|
|
|
padding: EdgeInsets.all(16), |
|
|
|
child: Column( |
|
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
|
children: [ |
|
|
|
Row( |
|
|
|
children: [ |
|
|
|
Icon( |
|
|
|
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, |
|
|
|
size: 20, |
|
|
|
color: isDarkMode ? Colors.amber[300] : Colors.amber[700], |
|
|
|
size: 18.sp, |
|
|
|
), |
|
|
|
SizedBox(width: 8), |
|
|
|
Text( |
|
|
|
'更新内容'.tr, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 18, |
|
|
|
fontWeight: FontWeight.bold, |
|
|
|
color: isDarkMode ? Colors.white : Colors.black, |
|
|
|
), |
|
|
|
), |
|
|
|
SizedBox(width: 12.w), |
|
|
|
Text( |
|
|
|
'更新内容'.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), |
|
|
|
), |
|
|
|
Divider(), |
|
|
|
SizedBox(height: 8), |
|
|
|
// 这里可以从controller中获取更新说明,如果有的话 |
|
|
|
Text( |
|
|
|
child: Text( |
|
|
|
controller.updatedescription.value, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 14, |
|
|
|
color: isDarkMode ? Colors.grey[300] : Colors.grey[800], |
|
|
|
fontSize: 14.sp, |
|
|
|
height: 1.5, |
|
|
|
color: isDarkMode ? Colors.grey[300] : Colors.grey[700], |
|
|
|
), |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
) |
|
|
|
: SizedBox.shrink()); |
|
|
|
), |
|
|
|
) |
|
|
|
: const SizedBox.shrink()); |
|
|
|
} |
|
|
|
|
|
|
|
Widget _buildLoadingIndicator(bool isDarkMode) => Column( |
|
|
|
// 加载指示器 |
|
|
|
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: [ |
|
|
|
CircularProgressIndicator( |
|
|
|
valueColor: AlwaysStoppedAnimation( |
|
|
|
isDarkMode ? Colors.blue[300] : Colors.blue), |
|
|
|
// 自定义加载动画 |
|
|
|
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( |
|
|
|
'正在获取设备信息...', |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 16.sp, |
|
|
|
fontWeight: FontWeight.w500, |
|
|
|
color: isDarkMode ? Colors.grey[300] : Colors.grey[700], |
|
|
|
), |
|
|
|
), |
|
|
|
SizedBox(height: 8.h), |
|
|
|
Text( |
|
|
|
'请保持设备连接', |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 12.sp, |
|
|
|
color: isDarkMode ? Colors.grey[500] : Colors.grey[500], |
|
|
|
), |
|
|
|
), |
|
|
|
SizedBox(height: 20), |
|
|
|
Text('正在获取设备信息...', |
|
|
|
style: |
|
|
|
TextStyle(color: isDarkMode ? Colors.grey[300] : Colors.grey)) |
|
|
|
], |
|
|
|
); |
|
|
|
), |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
Widget _buildErrorInfo(bool isDarkMode) => Container( |
|
|
|
padding: EdgeInsets.all(16), |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: |
|
|
|
isDarkMode ? Colors.red[900]!.withOpacity(0.2) : Colors.red[50], |
|
|
|
borderRadius: BorderRadius.circular(12), |
|
|
|
border: Border.all( |
|
|
|
color: isDarkMode ? Colors.red[700]! : Colors.red[200]!, |
|
|
|
width: 1, |
|
|
|
), |
|
|
|
// 错误信息显示 |
|
|
|
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), |
|
|
|
], |
|
|
|
), |
|
|
|
child: Column( |
|
|
|
children: [ |
|
|
|
Icon(Icons.error_outline, color: Colors.red, size: 40), |
|
|
|
SizedBox(height: 10), |
|
|
|
Text(controller.errorMessage.value, |
|
|
|
textAlign: TextAlign.center, |
|
|
|
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( |
|
|
|
'连接失败', |
|
|
|
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( |
|
|
|
'重试连接'.tr, |
|
|
|
style: TextStyle( |
|
|
|
color: isDarkMode ? Colors.red[300] : Colors.red, |
|
|
|
fontSize: 16)), |
|
|
|
SizedBox(height: 20), |
|
|
|
ElevatedButton.icon( |
|
|
|
icon: Icon(Icons.refresh), |
|
|
|
label: Text('重试连接'.tr), |
|
|
|
fontSize: 16.sp, |
|
|
|
fontWeight: FontWeight.w500, |
|
|
|
), |
|
|
|
), |
|
|
|
style: ElevatedButton.styleFrom( |
|
|
|
backgroundColor: isDarkMode ? Colors.blue[700] : Colors.blue, |
|
|
|
backgroundColor: isDarkMode ? const Color(0xFF0066CC) : Colors.blue, |
|
|
|
foregroundColor: Colors.white, |
|
|
|
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10), |
|
|
|
padding: EdgeInsets.symmetric(vertical: 14.h), |
|
|
|
shape: RoundedRectangleBorder( |
|
|
|
borderRadius: BorderRadius.circular(16.r), |
|
|
|
), |
|
|
|
elevation: 0, |
|
|
|
), |
|
|
|
onPressed: controller.retryConnection, |
|
|
|
) |
|
|
|
], |
|
|
|
), |
|
|
|
); |
|
|
|
), |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
// 更新按钮 |
|
|
|
Widget _buildUpdateButton(bool isDarkMode) { |
|
|
|
return controller.isUpgrade.value |
|
|
|
? _buildProgressIndicator(isDarkMode) |
|
|
|
: Container( |
|
|
|
width: double.infinity, |
|
|
|
padding: EdgeInsets.symmetric(vertical: 10), |
|
|
|
child: Column( |
|
|
|
children: [ |
|
|
|
ElevatedButton.icon( |
|
|
|
icon: Icon( |
|
|
|
controller.isUpdateAvailable.value |
|
|
|
? Icons.system_update |
|
|
|
: Icons.check_circle, |
|
|
|
return Obx(() { |
|
|
|
if (controller.isUpgrade.value) { |
|
|
|
return _buildProgressIndicator(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 ? '立即更新' : '已是最新版本', |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 16.sp, |
|
|
|
fontWeight: FontWeight.w600, |
|
|
|
), |
|
|
|
label: Text( |
|
|
|
controller.isUpdateAvailable.value ? '立即更新' : '已是最新版本', |
|
|
|
style: TextStyle(fontSize: 16), |
|
|
|
), |
|
|
|
style: ElevatedButton.styleFrom( |
|
|
|
backgroundColor: Colors.transparent, |
|
|
|
foregroundColor: Colors.white, |
|
|
|
shadowColor: Colors.transparent, |
|
|
|
shape: RoundedRectangleBorder( |
|
|
|
borderRadius: BorderRadius.circular(16.r), |
|
|
|
), |
|
|
|
style: ElevatedButton.styleFrom( |
|
|
|
backgroundColor: controller.isUpdateAvailable.value |
|
|
|
? (isDarkMode ? Colors.blue[700] : Colors.blue) |
|
|
|
: (isDarkMode ? Colors.grey[800] : Colors.grey), |
|
|
|
foregroundColor: Colors.white, |
|
|
|
padding: EdgeInsets.symmetric(horizontal: 40, vertical: 15), |
|
|
|
shape: RoundedRectangleBorder( |
|
|
|
borderRadius: BorderRadius.circular(30), |
|
|
|
), |
|
|
|
minimumSize: Size(240, 50), |
|
|
|
), |
|
|
|
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, |
|
|
|
), |
|
|
|
onPressed: controller.isUpdateAvailable.value |
|
|
|
? controller.startUpdate |
|
|
|
: null, |
|
|
|
), |
|
|
|
if (controller.isUpdateAvailable.value) ...[ |
|
|
|
SizedBox(height: 8), |
|
|
|
Text( |
|
|
|
'取出双耳机,并保证电量均为30%以上的状态'.tr, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 14, |
|
|
|
color: isDarkMode ? Colors.grey[400] : Colors.grey[600], |
|
|
|
child: Row( |
|
|
|
children: [ |
|
|
|
Icon( |
|
|
|
Icons.info_outline, |
|
|
|
color: Colors.orange, |
|
|
|
size: 20.sp, |
|
|
|
), |
|
|
|
), |
|
|
|
], |
|
|
|
], |
|
|
|
), |
|
|
|
); |
|
|
|
SizedBox(width: 12.w), |
|
|
|
Expanded( |
|
|
|
child: Text( |
|
|
|
'取出双耳机,并保证电量均为30%以上的状态'.tr, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 13.sp, |
|
|
|
color: isDarkMode ? Colors.orange[200] : Colors.orange[800], |
|
|
|
height: 1.3, |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
), |
|
|
|
], |
|
|
|
], |
|
|
|
), |
|
|
|
); |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
// 进度指示器 |
|
|
|
Widget _buildProgressIndicator(bool isDarkMode) { |
|
|
|
return Obx(() { |
|
|
|
final progress = controller.progress.value; |
|
|
|
final type = controller.type.value; |
|
|
|
// // 处理升级失败状态:弹出 snackbar 并显示错误提示 |
|
|
|
// if (type == OtaUpgradeController.UPGRADE_FAILED || |
|
|
|
// type == OtaUpgradeController.CONNECTION_DISCONNECTION) { |
|
|
|
// // 使用延迟确保在 build 完成后执行 |
|
|
|
// Future.delayed(Duration.zero, () { |
|
|
|
// Get.snackbar('升级失败', '重新连接设备后重试'); |
|
|
|
// }); |
|
|
|
|
|
|
|
// return Container( |
|
|
|
// width: double.infinity, |
|
|
|
// padding: const EdgeInsets.symmetric(vertical: 10), |
|
|
|
// child: Text( |
|
|
|
// '升级失败,请重新连接设备', |
|
|
|
// style: TextStyle( |
|
|
|
// fontSize: 18, |
|
|
|
// fontWeight: FontWeight.bold, |
|
|
|
// color: Colors.red[700], |
|
|
|
// ), |
|
|
|
// ), |
|
|
|
// ); |
|
|
|
// } |
|
|
|
final statusMessage = controller.getStatusMessage(type); |
|
|
|
|
|
|
|
// 正常升级状态 |
|
|
|
return Container( |
|
|
|
width: double.infinity, |
|
|
|
padding: const EdgeInsets.symmetric(vertical: 10), |
|
|
|
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: [ |
|
|
|
Text( |
|
|
|
controller.getStatusMessage(type), |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 18, |
|
|
|
fontWeight: FontWeight.bold, |
|
|
|
color: isDarkMode ? Colors.blue[300] : Colors.blue[700], |
|
|
|
), |
|
|
|
// 状态图标和文字 |
|
|
|
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], |
|
|
|
), |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
const SizedBox(height: 16), |
|
|
|
LinearProgressIndicator( |
|
|
|
value: progress / 100.0, // 转换为 0.0-1.0 |
|
|
|
backgroundColor: isDarkMode ? Colors.grey[800] : Colors.grey[200], |
|
|
|
valueColor: AlwaysStoppedAnimation<Color>( |
|
|
|
isDarkMode ? Colors.blue[300]! : Colors.blue, |
|
|
|
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), |
|
|
|
), |
|
|
|
), |
|
|
|
const SizedBox(height: 8), |
|
|
|
Text( |
|
|
|
'${progress.toStringAsFixed(1)}%', |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 16, |
|
|
|
fontWeight: FontWeight.bold, |
|
|
|
color: isDarkMode ? Colors.blue[300] : Colors.blue[700], |
|
|
|
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( |
|
|
|
'请勿断开连接', |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 12.sp, |
|
|
|
color: isDarkMode ? Colors.grey[400] : Colors.grey[600], |
|
|
|
), |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
); |
|
|
|
|