From f86a379f9341b572ed03127e69345ac1ebc1370d Mon Sep 17 00:00:00 2001 From: Locon213 <167447571+Locon213@users.noreply.github.com> Date: Wed, 14 Jan 2026 04:47:45 +0300 Subject: [PATCH] feat(ui): add download percentage and ETA display (#1238) --- .../lib/app/views/buid_task_list_view.dart | 68 +++++++++++++++++-- ui/flutter/lib/i18n/langs/fr_fr.dart | 3 +- 2 files changed, 66 insertions(+), 5 deletions(-) diff --git a/ui/flutter/lib/app/views/buid_task_list_view.dart b/ui/flutter/lib/app/views/buid_task_list_view.dart index 7e0bbe7c..3b98a95c 100644 --- a/ui/flutter/lib/app/views/buid_task_list_view.dart +++ b/ui/flutter/lib/app/views/buid_task_list_view.dart @@ -214,6 +214,43 @@ class BuildTaskListView extends GetView { (total > 0 ? " / ${Util.fmtByte(total)}" : ""); } + // Get percentage text, e.g. " (50.5%)" + String getPercentText() { + final total = task.meta.res?.size ?? 0; + if (total <= 0 || isDone()) return ""; + double p = getProgress(); + return "(${(p * 100).toStringAsFixed(1)}%)"; + } + + // Get ETA text, e.g. "00:05:30" + String getEtaText() { + if (isDone()) return ""; + + final total = task.meta.res?.size ?? 0; + final downloaded = task.progress.downloaded; + final speed = task.progress.speed; + + // If speed is 0 or file is downloaded, don't show time + if (total <= 0 || speed <= 0 || downloaded >= total) { + return ""; + } + + final remainingBytes = total - downloaded; + final remainingSeconds = remainingBytes ~/ speed; + + // If time is too long (e.g. > 1 day), return > 1d + if (remainingSeconds > 86400) return "> 1d"; + + Duration duration = Duration(seconds: remainingSeconds); + String twoDigits(int n) => n.toString().padLeft(2, "0"); + + if (duration.inHours > 0) { + return "${twoDigits(duration.inHours)}:${twoDigits(duration.inMinutes.remainder(60))}:${twoDigits(duration.inSeconds.remainder(60))}"; + } else { + return "${twoDigits(duration.inMinutes.remainder(60))}:${twoDigits(duration.inSeconds.remainder(60))}"; + } + } + final taskController = Get.find(); final taskListController = taskController.tabIndex.value == 0 ? Get.find() @@ -308,18 +345,41 @@ class BuildTaskListView extends GetView { )), Row( children: [ + // Left side: Progress text + Percentage Expanded( flex: 1, - child: Text( - getProgressText(), - style: Get.textTheme.bodyLarge - ?.copyWith(color: Get.theme.disabledColor), + child: Row( + children: [ + Text( + getProgressText(), + style: Get.textTheme.bodyLarge + ?.copyWith(color: Get.theme.disabledColor), + ), + const SizedBox(width: 8), + Text( + getPercentText(), + style: Get.textTheme.bodyLarge + ?.copyWith(color: Get.theme.disabledColor), + ), + ], ).padding(left: 18)), + // Right side: ETA + Speed + Actions Expanded( flex: 1, child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ + Text( + getEtaText(), + style: Get.textTheme.titleSmall, + ), + Text( + " | ", + style: Get.textTheme.titleSmall?.copyWith( + color: Get.theme.disabledColor, + fontWeight: FontWeight.w300, + ), + ).padding(horizontal: 4), Text("${Util.fmtByte(task.progress.speed)} / s", style: Get.textTheme.titleSmall), ...buildActions() diff --git a/ui/flutter/lib/i18n/langs/fr_fr.dart b/ui/flutter/lib/i18n/langs/fr_fr.dart index 266e5df8..7bcca821 100644 --- a/ui/flutter/lib/i18n/langs/fr_fr.dart +++ b/ui/flutter/lib/i18n/langs/fr_fr.dart @@ -38,7 +38,8 @@ const frFR = { 'useServerCtime': 'Utiliser l\'heure du serveur pour la création de fichier', 'maxRunning': 'Tâches en cours maximum', - 'autoStartTasks': 'Démarrer automatiquement les tâches incomplètes au lancement', + 'autoStartTasks': + 'Démarrer automatiquement les tâches incomplètes au lancement', 'items': '@count éléments', 'subscribeTracker': 'S\'abonner au tracker', 'subscribeFail':