feat: show extraction progress (#1217)

This commit is contained in:
Matteo Pietro Dazzi authored and GitHub committed 2025-12-31 09:25:21 +08:00
1 parent dbe37befa3
commit b0e133b554
27 files changed
+2591 -40

No files matched your search

+16
View File
@@ -8,6 +8,18 @@ enum Status { ready, running, pause, wait, error, done }
enum Protocol { http, bt }
// ExtractStatus enum matching Go backend
enum ExtractStatus {
@JsonValue('')
none,
@JsonValue('extracting')
extracting,
@JsonValue('done')
done,
@JsonValue('error')
error
}
@JsonSerializable(explicitToJson: true)
class Task {
String id;
@@ -43,6 +55,8 @@ class Progress {
int downloaded;
int uploadSpeed;
int uploaded;
ExtractStatus extractStatus;
int extractProgress;
Progress({
required this.used,
@@ -50,6 +64,8 @@ class Progress {
required this.downloaded,
required this.uploadSpeed,
required this.uploaded,
this.extractStatus = ExtractStatus.none,
this.extractProgress = 0,
});
factory Progress.fromJson(Map<String, dynamic> json) =>
+13
View File
@@ -53,12 +53,23 @@ const _$ProtocolEnumMap = {
Protocol.bt: 'bt',
};
const _$ExtractStatusEnumMap = {
ExtractStatus.none: '',
ExtractStatus.extracting: 'extracting',
ExtractStatus.done: 'done',
ExtractStatus.error: 'error',
};
Progress _$ProgressFromJson(Map<String, dynamic> json) => Progress(
used: (json['used'] as num).toInt(),
speed: (json['speed'] as num).toInt(),
downloaded: (json['downloaded'] as num).toInt(),
uploadSpeed: (json['uploadSpeed'] as num).toInt(),
uploaded: (json['uploaded'] as num).toInt(),
extractStatus: $enumDecodeNullable(
_$ExtractStatusEnumMap, json['extractStatus']) ??
ExtractStatus.none,
extractProgress: (json['extractProgress'] as num?)?.toInt() ?? 0,
);
Map<String, dynamic> _$ProgressToJson(Progress instance) => <String, dynamic>{
@@ -67,4 +78,6 @@ Map<String, dynamic> _$ProgressToJson(Progress instance) => <String, dynamic>{
'downloaded': instance.downloaded,
'uploadSpeed': instance.uploadSpeed,
'uploaded': instance.uploaded,
'extractStatus': _$ExtractStatusEnumMap[instance.extractStatus]!,
'extractProgress': instance.extractProgress,
};
@@ -187,6 +187,19 @@ class BuildTaskListView extends GetView {
return totalSize <= 0 ? 0 : task.progress.downloaded / totalSize;
}
String getExtractionStatusText() {
switch (task.progress.extractStatus) {
case ExtractStatus.extracting:
return '${'extracting'.tr} ${task.progress.extractProgress}%';
case ExtractStatus.done:
return 'extractDone'.tr;
case ExtractStatus.error:
return 'extractError'.tr;
default:
return '';
}
}
String getProgressText() {
if (isDone()) {
return Util.fmtByte(task.meta.res!.size);
@@ -317,6 +330,56 @@ class BuildTaskListView extends GetView {
: LinearProgressIndicator(
value: getProgress(),
),
// Extraction status row
if (task.progress.extractStatus != ExtractStatus.none)
Builder(builder: (context) {
final isExtracting =
task.progress.extractStatus == ExtractStatus.extracting;
final isExtractDone =
task.progress.extractStatus == ExtractStatus.done;
final statusColor = isExtracting
? Get.theme.colorScheme.primary
: (isExtractDone ? Colors.green : Colors.red);
return Column(
children: [
Row(
children: [
Expanded(
child: Row(
children: [
Icon(
isExtracting
? Icons.unarchive
: (isExtractDone
? Icons.check_circle
: Icons.error),
size: 16,
color: statusColor,
),
const SizedBox(width: 4),
Text(
getExtractionStatusText(),
style: Get.textTheme.bodySmall?.copyWith(
color: statusColor,
),
),
],
).padding(left: 18),
),
],
).padding(top: 4, bottom: isExtracting ? 0 : 8),
// Extraction progress bar
if (isExtracting)
LinearProgressIndicator(
value: task.progress.extractProgress / 100.0,
backgroundColor:
Get.theme.colorScheme.surfaceContainerHighest,
valueColor: AlwaysStoppedAnimation<Color>(
Get.theme.colorScheme.secondary),
),
],
);
}),
],
),
)).padding(horizontal: 14, top: 8),
+3
View File
@@ -121,6 +121,9 @@ const deDE = {
'archivePassword': 'Archiv-Passwort',
'archivePasswordHint': 'Leer lassen, wenn nicht passwortgeschützt',
'deleteAfterExtract': 'Archiv nach Entpacken löschen',
'extracting': 'Wird entpackt',
'extractDone': 'Entpacken abgeschlossen',
'extractError': 'Entpacken fehlgeschlagen',
'name': 'Name',
'size': 'Größe',
'unknown': 'Unbekannt',
+3
View File
@@ -129,6 +129,9 @@ const enUS = {
'archivePassword': 'Archive Password',
'archivePasswordHint': 'Leave empty if not password protected',
'deleteAfterExtract': 'Delete Archive After Extraction',
'extracting': 'Extracting',
'extractDone': 'Extraction completed',
'extractError': 'Extraction failed',
'name': 'Name',
'size': 'Size',
'unknown': 'Unknown',
+3
View File
@@ -113,6 +113,9 @@ const esES = {
'archivePassword': 'Contraseña del archivo',
'archivePasswordHint': 'Dejar vacío si no tiene contraseña',
'deleteAfterExtract': 'Eliminar archivo después de extraer',
'extracting': 'Extrayendo',
'extractDone': 'Extracción completada',
'extractError': 'Error en la extracción',
'insertPlaceholder': 'Insertar marcador de posición',
'placeholderYear': 'Año actual',
'placeholderMonth': 'Mes actual (01-12)',
+3
View File
@@ -68,6 +68,9 @@ const faIR = {
'archivePassword': 'رمز عبور بایگانی',
'archivePasswordHint': 'اگر رمز ندارد خالی بگذارید',
'deleteAfterExtract': 'حذف آرشیو پس از استخراج',
'extracting': 'در حال استخراج',
'extractDone': 'استخراج کامل شد',
'extractError': 'استخراج ناموفق بود',
'insertPlaceholder': 'درج نگهدارنده',
'placeholderYear': 'سال جاری',
'placeholderMonth': 'ماه جاری (01-12)',
+3
View File
@@ -105,6 +105,9 @@ const frFR = {
'archivePassword': 'Mot de passe de l\'archive',
'archivePasswordHint': 'Laisser vide si non protégé par mot de passe',
'deleteAfterExtract': "Supprimer l'archive après extraction",
'extracting': 'Extraction en cours',
'extractDone': 'Extraction terminée',
'extractError': 'Échec de l\'extraction',
'insertPlaceholder': 'Insérer un espace réservé',
'placeholderYear': 'Année en cours',
'placeholderMonth': 'Mois en cours (01-12)',
+3
View File
@@ -121,6 +121,9 @@ const huHU = {
'archivePassword': 'Archívum jelszó',
'archivePasswordHint': 'Hagyja üresen, ha nincs jelszóval védve',
'deleteAfterExtract': 'Archívum törlése kicsomagolás után',
'extracting': 'Kicsomagolás',
'extractDone': 'Kicsomagolás befejezve',
'extractError': 'Kicsomagolás sikertelen',
'name': 'Név',
'size': 'Méret',
'unknown': 'Ismeretlen',
+3
View File
@@ -115,6 +115,9 @@ const idID = {
'archivePassword': 'Kata Sandi Arsip',
'archivePasswordHint': 'Kosongkan jika tidak dilindungi kata sandi',
'deleteAfterExtract': 'Hapus arsip setelah ekstraksi',
'extracting': 'Mengekstrak',
'extractDone': 'Ekstraksi selesai',
'extractError': 'Ekstraksi gagal',
'insertPlaceholder': 'Sisipkan placeholder',
'placeholderYear': 'Tahun saat ini',
'placeholderMonth': 'Bulan saat ini (01-12)',
+3
View File
@@ -103,6 +103,9 @@ const itIT = {
'archivePassword': 'Password archivio',
'archivePasswordHint': 'Lasciare vuoto se non protetto da password',
'deleteAfterExtract': "Elimina l'archivio dopo l'estrazione",
'extracting': 'Estrazione in corso',
'extractDone': 'Estrazione completata',
'extractError': 'Estrazione fallita',
'insertPlaceholder': 'Inserisci segnaposto',
'placeholderYear': 'Anno corrente',
'placeholderMonth': 'Mese corrente (01-12)',
+3
View File
@@ -69,6 +69,9 @@ const jaJP = {
'archivePassword': 'アーカイブパスワード',
'archivePasswordHint': 'パスワードなしの場合は空のままにしてください',
'deleteAfterExtract': '展開後にアーカイブを削除',
'extracting': '展開中',
'extractDone': '展開完了',
'extractError': '展開失敗',
'insertPlaceholder': 'プレースホルダーを挿入',
'placeholderYear': '現在の年',
'placeholderMonth': '現在の月 (01-12)',
+3
View File
@@ -101,6 +101,9 @@ const plPL = {
'archivePassword': 'Hasło archiwum',
'archivePasswordHint': 'Pozostaw puste, jeśli nie ma hasła',
'deleteAfterExtract': 'Usuń archiwum po rozpakowaniu',
'extracting': 'Rozpakowywanie',
'extractDone': 'Rozpakowywanie zakończone',
'extractError': 'Rozpakowywanie nie powiodło się',
'insertPlaceholder': 'Wstaw placeholder',
'placeholderYear': 'Bieżący rok',
'placeholderMonth': 'Bieżący miesiąc (01-12)',
+3
View File
@@ -118,6 +118,9 @@ const ptBR = {
'archivePassword': 'Senha do arquivo',
'archivePasswordHint': 'Deixar vazio se não estiver protegido por senha',
'deleteAfterExtract': 'Excluir arquivo após extração',
'extracting': 'Extraindo',
'extractDone': 'Extração concluída',
'extractError': 'Falha na extração',
'name': 'Nome',
'size': 'Tamanho',
'unknown': 'Desconhecido',
+3
View File
@@ -118,6 +118,9 @@ const ruRU = {
'archivePassword': 'Пароль архива',
'archivePasswordHint': 'Оставить пустым, если архив не защищён паролем',
'deleteAfterExtract': 'Удалить архив после распаковки',
'extracting': 'Распаковка',
'extractDone': 'Распаковка завершена',
'extractError': 'Ошибка распаковки',
'name': 'Название',
'size': 'Размер',
'unknown': 'Неизвестно',
+3
View File
@@ -103,6 +103,9 @@ const taTA = {
'archivePassword': 'காப்பக கடவுச்சொல்',
'archivePasswordHint': 'கடவுச்சொல் இல்லையென்றால் காலியாக விடவும்',
'deleteAfterExtract': 'பிரித்தெடுத்த பிறகு காப்பகத்தை நீக்கு',
'extracting': 'பிரித்தெடுக்கிறது',
'extractDone': 'பிரித்தெடுத்தல் முடிந்தது',
'extractError': 'பிரித்தெடுத்தல் தோல்வியடைந்தது',
'insertPlaceholder': 'இடங்காட்டி செருக',
'placeholderYear': 'தற்போதைய ஆண்டு',
'placeholderMonth': 'தற்போதைய மாதம் (01-12)',
+3
View File
@@ -119,6 +119,9 @@ const trTR = {
'archivePassword': 'Arşiv şifresi',
'archivePasswordHint': 'Şifre yoksa boş bırakın',
'deleteAfterExtract': 'Çıkarmadan sonra arşivi sil',
'extracting': 'Çıkarılıyor',
'extractDone': 'Çıkarma tamamlandı',
'extractError': 'Çıkarma başarısız',
'name': 'Ad',
'size': 'Boyut',
'unknown': 'Bilinmeyen',
+3
View File
@@ -118,6 +118,9 @@ const ukUA = {
'archivePassword': 'Пароль архіву',
'archivePasswordHint': 'Залишити порожнім, якщо архів не захищений паролем',
'deleteAfterExtract': 'Видалити архів після розпакування',
'extracting': 'Розпакування',
'extractDone': 'Розпакування завершено',
'extractError': 'Помилка розпакування',
'name': 'Назва',
'size': 'Розмір',
'unknown': 'Невідомо',
+3
View File
@@ -96,6 +96,9 @@ const viVN = {
'archivePassword': 'Mật khẩu tập tin nén',
'archivePasswordHint': 'Để trống nếu không có mật khẩu',
'deleteAfterExtract': 'Xóa tập tin nén sau khi giải nén',
'extracting': 'Đang giải nén',
'extractDone': 'Giải nén hoàn tất',
'extractError': 'Giải nén thất bại',
'insertPlaceholder': 'Chèn placeholder',
'placeholderYear': 'Năm hiện tại',
'placeholderMonth': 'Tháng hiện tại (01-12)',
+3
View File
@@ -127,6 +127,9 @@ const zhCN = {
'archivePassword': '压缩包密码',
'archivePasswordHint': '如无密码请留空',
'deleteAfterExtract': '解压后删除压缩包',
'extracting': '正在解压',
'extractDone': '解压完成',
'extractError': '解压失败',
'name': '名称',
'size': '大小',
'unknown': '未知',
+3
View File
@@ -115,6 +115,9 @@ const zhTW = {
'archivePassword': '壓縮包密碼',
'archivePasswordHint': '如無密碼請留空',
'deleteAfterExtract': '解壓後刪除壓縮檔',
'extracting': '正在解壓',
'extractDone': '解壓完成',
'extractError': '解壓失敗',
'name': '名稱',
'size': '大小',
'unknown': '未知',