yx_app_upgrade_flutter/lib/widgets/download_progress_dialog.dart

179 lines
5.4 KiB
Dart

import 'package:flutter/material.dart';
import '../app_upgrade_plugin.dart';
import '../core/upgrade_utils.dart';
/// 下载进度对话框
class DownloadProgressDialog extends StatefulWidget {
final String downloadUrl;
final Color? primaryColor;
const DownloadProgressDialog({super.key, required this.downloadUrl, this.primaryColor});
/// 显示下载进度对话框
static Future<String?> show(BuildContext context, {required String downloadUrl, Color? primaryColor}) {
return showDialog<String?>(
context: context,
barrierDismissible: false,
builder: (context) => DownloadProgressDialog(downloadUrl: downloadUrl, primaryColor: primaryColor),
);
}
@override
State<DownloadProgressDialog> createState() => _DownloadProgressDialogState();
}
class _DownloadProgressDialogState extends State<DownloadProgressDialog> {
final AppUpgradePlugin _plugin = AppUpgradePlugin();
double _progress = 0.0;
String _progressText = '准备下载...';
int _received = 0;
int _total = 0;
bool _isDownloading = false;
String? _errorMessage;
@override
void initState() {
super.initState();
_startDownload();
}
@override
Widget build(BuildContext context) {
final primaryColor = widget.primaryColor ?? Theme.of(context).primaryColor;
return WillPopScope(
onWillPop: () async => false,
child: Dialog(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
child: Padding(
padding: const EdgeInsets.all(24),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// 图标
Icon(
_errorMessage != null ? Icons.error_outline : Icons.download_rounded,
size: 48,
color: _errorMessage != null ? Colors.red : primaryColor,
),
const SizedBox(height: 16),
// 标题
Text(
_errorMessage != null ? '下载失败' : '正在下载更新',
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
const SizedBox(height: 16),
if (_errorMessage != null) ...[
// 错误信息
Text(
_errorMessage!,
style: TextStyle(fontSize: 14, color: Colors.grey[600]),
textAlign: TextAlign.center,
),
const SizedBox(height: 16),
// 按钮
Row(
children: [
Expanded(
child: TextButton(
onPressed: () {
Navigator.of(context).pop(null);
},
child: const Text('取消'),
),
),
const SizedBox(width: 16),
Expanded(
child: ElevatedButton(
onPressed: () {
setState(() {
_errorMessage = null;
_progress = 0.0;
_progressText = '准备下载...';
});
_startDownload();
},
style: ElevatedButton.styleFrom(backgroundColor: primaryColor),
child: const Text('重试'),
),
),
],
),
] else ...[
// 进度条
LinearProgressIndicator(
value: _isDownloading ? _progress : null,
backgroundColor: Colors.grey[300],
valueColor: AlwaysStoppedAnimation<Color>(primaryColor),
),
const SizedBox(height: 12),
// 进度文本
Text(_progressText, style: TextStyle(fontSize: 14, color: Colors.grey[600])),
const SizedBox(height: 8),
// 文件大小信息
if (_total > 0)
Text(
'${formatBytes(_received)} / ${formatBytes(_total)}',
style: TextStyle(fontSize: 12, color: Colors.grey[500]),
),
],
],
),
),
),
);
}
Future<void> _startDownload() async {
setState(() {
_isDownloading = true;
_errorMessage = null;
});
try {
final filePath = await _plugin.downloadApk(
widget.downloadUrl,
onProgress: (progress) {
setState(() {
_progress = progress.progress;
_received = progress.received;
_total = progress.total;
_progressText = '下载中 ${progress.percentage}%';
});
},
);
if (filePath != null) {
setState(() {
_progressText = '下载完成';
});
// 延迟一下让用户看到完成状态
await Future.delayed(const Duration(milliseconds: 500));
// 返回文件路径
if (mounted) {
Navigator.of(context).pop(filePath);
}
} else {
setState(() {
_errorMessage = '下载失败,请检查网络连接';
_isDownloading = false;
});
}
} catch (e) {
setState(() {
_errorMessage = '下载出错:${e.toString()}';
_isDownloading = false;
});
}
}
}