mirror of
https://github.com/lifegpc/eh_downloader_flutter.git
synced 2026-07-05 04:22:23 +08:00
Add eta support
This commit is contained in:
@@ -78,8 +78,8 @@ class TaskDownloadSingleProgress {
|
||||
final DateTime started;
|
||||
final int downloaded;
|
||||
final double speed;
|
||||
@JsonKey(name: 'last_updated')
|
||||
final int lastUpdated;
|
||||
@JsonKey(name: 'last_updated', fromJson: _fromJson, toJson: _toJson)
|
||||
final DateTime lastUpdated;
|
||||
static DateTime _fromJson(int d) =>
|
||||
DateTime.fromMillisecondsSinceEpoch(d, isUtc: true);
|
||||
static int _toJson(DateTime d) => d.millisecondsSinceEpoch;
|
||||
|
||||
@@ -45,7 +45,8 @@ TaskDownloadSingleProgress _$TaskDownloadSingleProgressFromJson(
|
||||
(json['started'] as num).toInt()),
|
||||
downloaded: (json['downloaded'] as num).toInt(),
|
||||
speed: (json['speed'] as num).toDouble(),
|
||||
lastUpdated: (json['last_updated'] as num).toInt(),
|
||||
lastUpdated: TaskDownloadSingleProgress._fromJson(
|
||||
(json['last_updated'] as num).toInt()),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$TaskDownloadSingleProgressToJson(
|
||||
@@ -61,7 +62,7 @@ Map<String, dynamic> _$TaskDownloadSingleProgressToJson(
|
||||
'started': TaskDownloadSingleProgress._toJson(instance.started),
|
||||
'downloaded': instance.downloaded,
|
||||
'speed': instance.speed,
|
||||
'last_updated': instance.lastUpdated,
|
||||
'last_updated': TaskDownloadSingleProgress._toJson(instance.lastUpdated),
|
||||
};
|
||||
|
||||
TaskDownloadProgess _$TaskDownloadProgessFromJson(Map<String, dynamic> json) =>
|
||||
|
||||
@@ -94,6 +94,7 @@ class _TaskView extends State<TaskView> {
|
||||
onTap: () {
|
||||
context.push("/dialog/task/${widget.task.base.id}");
|
||||
},
|
||||
behavior: HitTestBehavior.opaque,
|
||||
child: Column(children: [
|
||||
_buildText(context),
|
||||
LinearPercentIndicator(
|
||||
|
||||
@@ -4,6 +4,7 @@ import 'package:go_router/go_router.dart';
|
||||
import 'package:percent_indicator/linear_percent_indicator.dart';
|
||||
import '../api/task.dart';
|
||||
import '../globals.dart';
|
||||
import '../utils/duration.dart';
|
||||
import '../utils/filesize.dart';
|
||||
|
||||
class _KeyValue extends StatelessWidget {
|
||||
@@ -151,7 +152,8 @@ class _TaskPage extends State<TaskPage> {
|
||||
_KeyValue(i18n.totalPages, p.totalPage.toString(), fontSize: 16),
|
||||
_KeyValue(i18n.downloadedSize2, getFileSize(p.downloadedBytes),
|
||||
fontSize: 16),
|
||||
_KeyValue(i18n.speed, "${getFileSize((speed * 1000).toInt())}/s", fontSize: 16),
|
||||
_KeyValue(i18n.speed, "${getFileSize((speed * 1000).toInt())}/s",
|
||||
fontSize: 16),
|
||||
]);
|
||||
}
|
||||
int now = 0;
|
||||
@@ -199,12 +201,21 @@ class _TaskPage extends State<TaskPage> {
|
||||
}
|
||||
final p = task.progress as TaskDownloadProgess;
|
||||
if (p.details.isEmpty) return SliverToBoxAdapter(child: Container());
|
||||
final i18n = AppLocalizations.of(context)!;
|
||||
return SliverList.builder(
|
||||
itemCount: p.details.length,
|
||||
itemBuilder: (context, index) {
|
||||
final d = p.details[index];
|
||||
final percent = d.total == 0 ? 0.0 : d.downloaded / d.total;
|
||||
final percentText = "${(percent * 100).toStringAsFixed(2)}%";
|
||||
final avgSpeed = d.started.millisecondsSinceEpoch == 0
|
||||
? 0.0
|
||||
: d.downloaded /
|
||||
(d.lastUpdated.millisecondsSinceEpoch -
|
||||
d.started.millisecondsSinceEpoch);
|
||||
final eta = d.total == 0
|
||||
? double.infinity
|
||||
: (d.total - d.downloaded) / avgSpeed;
|
||||
return Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||
SelectableText("${d.name}(${d.width}x${d.height})"),
|
||||
LinearPercentIndicator(
|
||||
@@ -223,7 +234,8 @@ class _TaskPage extends State<TaskPage> {
|
||||
Expanded(
|
||||
child: Text(
|
||||
"${getFileSize(d.downloaded)}/${getFileSize(d.total)}")),
|
||||
Text("${getFileSize((d.speed * 1000).toInt())}/s"),
|
||||
Text(
|
||||
"${getFileSize((d.speed * 1000).toInt())}/s${i18n.comma}${fmtDuration(context, eta)}"),
|
||||
]),
|
||||
]);
|
||||
},
|
||||
|
||||
@@ -181,5 +181,13 @@
|
||||
},
|
||||
"comma": ", ",
|
||||
"downloadedSize2": "Downloaded size",
|
||||
"speed": "Speed"
|
||||
"speed": "Speed",
|
||||
"days": "{num} days",
|
||||
"@days": {
|
||||
"placeholders": {
|
||||
"num": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,5 +181,13 @@
|
||||
},
|
||||
"comma": ",",
|
||||
"downloadedSize2": "已下载大小",
|
||||
"speed": "速度"
|
||||
"speed": "速度",
|
||||
"days": "{num} 天",
|
||||
"@days": {
|
||||
"placeholders": {
|
||||
"num": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
21
lib/utils/duration.dart
Normal file
21
lib/utils/duration.dart
Normal file
@@ -0,0 +1,21 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
|
||||
String fmtDuration(BuildContext context, double ms) {
|
||||
if (ms.isInfinite) {
|
||||
return "∞";
|
||||
}
|
||||
final dur = ms.toInt() ~/ 1000;
|
||||
String re = "";
|
||||
if (dur >= 86400) {
|
||||
final i18n = AppLocalizations.of(context)!;
|
||||
re += "${i18n.days(dur ~/ 86400)} ";
|
||||
}
|
||||
if (dur >= 3600) {
|
||||
re += "${(dur ~/ 3600).toString().padLeft(2, '0')}:";
|
||||
}
|
||||
final min = (dur ~/ 60).toString().padLeft(2, '0');
|
||||
final secs = (dur % 60).toString().padLeft(2, '0');
|
||||
re += "$min:$secs";
|
||||
return re;
|
||||
}
|
||||
Reference in New Issue
Block a user