import 'package:file_sizes/file_sizes.dart'; import 'package:intl/intl.dart'; import 'package:starcitizen_doctor/base/ui.dart'; import 'package:starcitizen_doctor/base/ui_model.dart'; import 'downloads_ui_model.dart'; class DownloadsUI extends BaseUI { final DateFormat formatter = DateFormat('yyyy-MM-dd HH:mm:ss'); @override Widget? buildBody(BuildContext context, DownloadsUIModel model) { return makeDefaultPage(context, model, content: Column( children: [ const SizedBox(height: 12), Row( mainAxisAlignment: MainAxisAlignment.end, children: [ for (final item in , String>{ if (model.tasks.isNotEmpty) const MapEntry("pause_all", FluentIcons.pause): "暂停全部" else const MapEntry("resume_all", FluentIcons.download): "恢复全部", const MapEntry("cancel_all", FluentIcons.cancel): "取消全部", }.entries) Padding( padding: const EdgeInsets.only(left: 6, right: 6), child: Button( child: Padding( padding: const EdgeInsets.all(4), child: Row( children: [ Icon(item.key.value), const SizedBox(width: 6), Text(item.value), ], ), ), onPressed: () => model.onTapButton(item.key.key)), ), const SizedBox(width: 12), ], ), Expanded( child: ListView.builder( itemBuilder: (BuildContext context, int index) { final (task, type, isFirstType) = model.getTaskAndType(index); final nt = model.getTaskTypeAndName(task); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ if (isFirstType) Column( children: [ Container( padding: EdgeInsets.only( left: 24, right: 24, top: index == 0 ? 0 : 12, bottom: 12), margin: const EdgeInsets.only(top: 6, bottom: 6), child: Row( children: [ Expanded( child: Text( "${model.listHeaderStatusMap[type]}", style: const TextStyle( fontSize: 24, fontWeight: FontWeight.bold), )), ], ), ), ], ), Container( padding: const EdgeInsets.only( left: 12, right: 12, top: 12, bottom: 12), margin: const EdgeInsets.only( left: 12, right: 12, top: 6, bottom: 6), decoration: BoxDecoration( color: FluentTheme.of(context).cardColor.withOpacity(.03), borderRadius: BorderRadius.circular(7), ), child: Row( children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( nt.value, style: const TextStyle( fontSize: 18, fontWeight: FontWeight.bold), ), const SizedBox(height: 6), Row( children: [ Text( "总大小:${FileSize.getSize(task.totalLength ?? 0)}", style: const TextStyle(fontSize: 14), ), const SizedBox(width: 12), if (nt.key == "torrent" && task.verifiedLength != null && task.verifiedLength != 0) Text( "校验中...(${FileSize.getSize(task.verifiedLength)})", style: const TextStyle(fontSize: 14), ) else if (task.status == "active") Text( "下载中... (${((task.completedLength ?? 0) / (task.totalLength ?? 1)).toStringAsFixed(4)}%)") else Text( "状态:${model.statusMap[task.status]}", style: const TextStyle(fontSize: 14), ), const SizedBox(width: 24), if (task.status == "active" && task.verifiedLength == null) Text( "ETA: ${formatter.format(DateTime.now().add(Duration(seconds: model.getETA(task))))}"), ], ), ], ), const Spacer(), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "已上传:${FileSize.getSize(task.uploadLength)}"), Text( "已下载:${FileSize.getSize(task.completedLength)}"), ], ), const SizedBox(width: 18), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text("↑:${FileSize.getSize(task.uploadSpeed)}/s"), Text( "↓:${FileSize.getSize(task.downloadSpeed)}/s"), ], ), const SizedBox(width: 32), if (type != "stopped") DropDownButton( closeAfterClick: false, title: const Padding( padding: EdgeInsets.all(3), child: Text('选项'), ), items: [ if (task.status == "paused") MenuFlyoutItem( leading: const Icon(FluentIcons.download), text: const Text('继续下载'), onPressed: () => model.resumeTask(task.gid)) else if (task.status == "active") MenuFlyoutItem( leading: const Icon(FluentIcons.pause), text: const Text('暂停下载'), onPressed: () => model.pauseTask(task.gid)), const MenuFlyoutSeparator(), MenuFlyoutItem( leading: const Icon( FluentIcons.chrome_close, size: 14, ), text: const Text('取消下载'), onPressed: () => model.cancelTask(task.gid)), MenuFlyoutItem( leading: const Icon( FluentIcons.folder_open, size: 14, ), text: const Text('打开文件夹'), onPressed: () => model.openFolder(task)), ], ), const SizedBox(width: 12), ], ), ), ], ); }, itemCount: model.getTasksLen(), )) ], )); } @override String getUITitle(BuildContext context, DownloadsUIModel model) => "下载管理"; }