refactor: extract download progress label formatting

- Extract _formatDownloadProgressLabel() for cleaner code
- Show received/total size when bytesTotal is available
- Estimate total size from progress when only bytesReceived is known
- Add text overflow handling with ellipsis
This commit is contained in:
zarzet
2026-05-15 01:00:20 +07:00
parent 012dcdc2dd
commit 8b7cecc1c5
3 changed files with 85 additions and 46 deletions
+18 -2
View File
@@ -244,7 +244,7 @@ func (r *extensionRuntime) fileDownload(call goja.FunctionCall) goja.Value {
}
contentLength := resp.ContentLength
shouldTrackItemBytes := activeItemID != "" && onProgress == nil
shouldTrackItemBytes := activeItemID != ""
if shouldTrackItemBytes && contentLength > 0 {
SetItemBytesTotal(activeItemID, contentLength)
}
@@ -301,6 +301,14 @@ func (r *extensionRuntime) fileDownload(call goja.FunctionCall) goja.Value {
}
}
if shouldTrackItemBytes {
if contentLength > 0 {
SetItemProgress(activeItemID, float64(written)/float64(contentLength), written, contentLength)
} else if written > 0 {
SetItemBytesReceived(activeItemID, written)
}
}
GoLog("[Extension:%s] Downloaded %d bytes to %s\n", r.extensionID, written, fullPath)
return r.vm.ToValue(map[string]interface{}{
@@ -383,7 +391,7 @@ func (r *extensionRuntime) fileDownloadChunked(client *http.Client, urlStr, full
SetItemDownloading(activeItemID)
}
shouldTrackItemBytes := activeItemID != "" && onProgress == nil
shouldTrackItemBytes := activeItemID != ""
if shouldTrackItemBytes && totalSize > 0 {
SetItemBytesTotal(activeItemID, totalSize)
}
@@ -526,6 +534,14 @@ func (r *extensionRuntime) fileDownloadChunked(client *http.Client, urlStr, full
}
}
if shouldTrackItemBytes {
if totalSize > 0 {
SetItemProgress(activeItemID, float64(totalWritten)/float64(totalSize), totalWritten, totalSize)
} else if totalWritten > 0 {
SetItemBytesReceived(activeItemID, totalWritten)
}
}
GoLog("[Extension:%s] Chunked download complete: %d bytes to %s\n", r.extensionID, totalWritten, fullPath)
return r.vm.ToValue(map[string]interface{}{
+1 -1
View File
@@ -2340,7 +2340,7 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
);
} else {
_log.d(
'Progress [$itemId]: ${(percentage * 100).toStringAsFixed(1)}% (DASH segments/unknown size) @ ${speedMBps.toStringAsFixed(2)} MB/s',
'Progress [$itemId]: ${(percentage * 100).toStringAsFixed(1)}% (stream/unknown size) @ ${speedMBps.toStringAsFixed(2)} MB/s',
);
}
}
+66 -43
View File
@@ -42,6 +42,49 @@ import 'package:spotiflac_android/widgets/animation_utils.dart';
part 'queue_tab_helpers.dart';
part 'queue_tab_widgets.dart';
String _formatDownloadSizeMB(num bytes) {
return '${(bytes / (1024 * 1024)).toStringAsFixed(1)} MB';
}
String _formatDownloadProgressLabel(BuildContext context, DownloadItem item) {
final progress = item.progress.clamp(0.0, 1.0);
final speedSuffix = item.speedMBps > 0
? '${item.speedMBps.toStringAsFixed(1)} MB/s'
: '';
if (item.bytesTotal > 0) {
final received = item.bytesReceived > 0
? item.bytesReceived
: item.bytesTotal * progress;
final percent = (progress * 100).toStringAsFixed(0);
return '${_formatDownloadSizeMB(received)} / ${_formatDownloadSizeMB(item.bytesTotal)}$percent%$speedSuffix';
}
if (item.bytesReceived > 0) {
final canEstimateTotal = progress > 0.01 && progress < 0.995;
if (canEstimateTotal) {
final estimatedTotal = item.bytesReceived / progress;
if (estimatedTotal > item.bytesReceived) {
return '${_formatDownloadSizeMB(item.bytesReceived)} / ~${_formatDownloadSizeMB(estimatedTotal)}$speedSuffix';
}
}
return '${_formatDownloadSizeMB(item.bytesReceived)}$speedSuffix';
}
if (progress > 0) {
final percent = (progress * 100).toStringAsFixed(0);
return '$percent%$speedSuffix';
}
if (item.speedMBps > 0) {
return context.l10n.queueDownloadSpeedStatus(
item.speedMBps.toStringAsFixed(1),
);
}
return context.l10n.queueDownloadStarting;
}
class QueueTab extends ConsumerStatefulWidget {
final PageController? parentPageController;
final int parentPageIndex;
@@ -5591,51 +5634,31 @@ class _QueueTabState extends ConsumerState<QueueTab> {
?.copyWith(color: colorScheme.onSurfaceVariant),
),
if (item.status == DownloadStatus.downloading) ...[
const SizedBox(height: 8),
Row(
children: [
Expanded(
child: ClipRRect(
borderRadius: BorderRadius.circular(4),
child: LinearProgressIndicator(
value: item.progress > 0
? item.progress
: null,
backgroundColor:
colorScheme.surfaceContainerHighest,
const SizedBox(height: 6),
Align(
alignment: Alignment.centerRight,
child: Text(
_formatDownloadProgressLabel(context, item),
maxLines: 1,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.right,
style: Theme.of(context).textTheme.labelSmall
?.copyWith(
color: colorScheme.primary,
minHeight: 6,
fontWeight: FontWeight.bold,
),
),
),
const SizedBox(width: 8),
Text(
item.bytesTotal > 0
? '${(item.progress * 100).toStringAsFixed(0)}%'
: (item.bytesReceived > 0
? '${(item.bytesReceived / (1024 * 1024)).toStringAsFixed(1)} MB${item.speedMBps > 0 ? '${item.speedMBps.toStringAsFixed(1)} MB/s' : ''}'
: (item.progress > 0
? (item.speedMBps > 0
? '${(item.progress * 100).toStringAsFixed(0)}% • ${item.speedMBps.toStringAsFixed(1)} MB/s'
: '${(item.progress * 100).toStringAsFixed(0)}%')
: (item.speedMBps > 0
? context.l10n
.queueDownloadSpeedStatus(
item.speedMBps
.toStringAsFixed(
1,
),
)
: context
.l10n
.queueDownloadStarting))),
style: Theme.of(context).textTheme.labelSmall
?.copyWith(
color: colorScheme.primary,
fontWeight: FontWeight.bold,
),
),
],
),
),
const SizedBox(height: 3),
ClipRRect(
borderRadius: BorderRadius.circular(4),
child: LinearProgressIndicator(
value: item.progress > 0 ? item.progress : null,
backgroundColor:
colorScheme.surfaceContainerHighest,
color: colorScheme.primary,
minHeight: 6,
),
),
],
if (item.status == DownloadStatus.failed) ...[