@@ -1270,7 +1270,7 @@ export class Uppy<
1270
1270
}
1271
1271
1272
1272
this . setState ( stateUpdate )
1273
- this . #updateTotalProgress ( )
1273
+ this . #updateTotalProgressThrottled ( )
1274
1274
1275
1275
const removedFileIDs = Object . keys ( removedFiles )
1276
1276
removedFileIDs . forEach ( ( fileID ) => {
@@ -1416,121 +1416,133 @@ export class Uppy<
1416
1416
} )
1417
1417
}
1418
1418
1419
- // ___Why throttle at 500ms?
1420
- // - We must throttle at >250ms for superfocus in Dashboard to work well
1421
- // (because animation takes 0.25s, and we want to wait for all animations to be over before refocusing).
1422
- // [Practical Check]: if thottle is at 100ms, then if you are uploading a file,
1423
- // and click 'ADD MORE FILES', - focus won't activate in Firefox.
1424
- // - We must throttle at around >500ms to avoid performance lags.
1425
- // [Practical Check] Firefox, try to upload a big file for a prolonged period of time. Laptop will start to heat up.
1426
- // todo when uploading multiple files, this will cause problems because they share the same throttle,
1427
- // meaning some files might never get their progress reported (eaten up by progress events from other files)
1428
- calculateProgress = throttle (
1429
- ( file , data ) => {
1430
- const fileInState = this . getFile ( file ?. id )
1431
- if ( file == null || ! fileInState ) {
1432
- this . log (
1433
- `Not setting progress for a file that has been removed: ${ file ?. id } ` ,
1434
- )
1435
- return
1436
- }
1419
+ #handleUploadProgress = (
1420
+ file : UppyFile < M , B > | undefined ,
1421
+ progress : FileProgressStarted ,
1422
+ ) => {
1423
+ const fileInState = file ? this . getFile ( file . id ) : undefined
1424
+ if ( file == null || ! fileInState ) {
1425
+ this . log (
1426
+ `Not setting progress for a file that has been removed: ${ file ?. id } ` ,
1427
+ )
1428
+ return
1429
+ }
1437
1430
1438
- if ( fileInState . progress . percentage === 100 ) {
1439
- this . log (
1440
- `Not setting progress for a file that has been already uploaded: ${ file . id } ` ,
1441
- )
1442
- return
1443
- }
1431
+ if ( fileInState . progress . percentage === 100 ) {
1432
+ this . log (
1433
+ `Not setting progress for a file that has been already uploaded: ${ file . id } ` ,
1434
+ )
1435
+ return
1436
+ }
1444
1437
1438
+ const newProgress = {
1439
+ bytesTotal : progress . bytesTotal ,
1445
1440
// bytesTotal may be null or zero; in that case we can't divide by it
1446
- const canHavePercentage =
1447
- Number . isFinite ( data . bytesTotal ) && data . bytesTotal > 0
1441
+ percentage :
1442
+ (
1443
+ progress . bytesTotal != null &&
1444
+ Number . isFinite ( progress . bytesTotal ) &&
1445
+ progress . bytesTotal > 0
1446
+ ) ?
1447
+ Math . round ( ( progress . bytesUploaded / progress . bytesTotal ) * 100 )
1448
+ : 0 ,
1449
+ }
1450
+
1451
+ if ( fileInState . progress . uploadStarted != null ) {
1448
1452
this . setFileState ( file . id , {
1449
1453
progress : {
1450
1454
...fileInState . progress ,
1451
- bytesUploaded : data . bytesUploaded ,
1452
- bytesTotal : data . bytesTotal ,
1453
- percentage :
1454
- canHavePercentage ?
1455
- Math . round ( ( data . bytesUploaded / data . bytesTotal ) * 100 )
1456
- : 0 ,
1455
+ bytesUploaded : progress . bytesUploaded ,
1456
+ ...newProgress ,
1457
1457
} ,
1458
1458
} )
1459
+ } else {
1460
+ this . setFileState ( file . id , {
1461
+ progress : {
1462
+ ...fileInState . progress ,
1463
+ ...newProgress ,
1464
+ } ,
1465
+ } )
1466
+ }
1459
1467
1460
- this . #updateTotalProgress( )
1461
- } ,
1462
- 500 ,
1463
- { leading : true , trailing : true } ,
1464
- )
1468
+ this . #updateTotalProgressThrottled( )
1469
+ }
1465
1470
1466
1471
#updateTotalProgress( ) {
1467
- const totalProgress = this . #calculateTotalProgress( )
1472
+ let totalProgress = Math . round ( this . #calculateTotalProgress( ) * 100 )
1473
+ if ( totalProgress > 100 ) totalProgress = 100
1474
+ else if ( totalProgress < 0 ) totalProgress = 0
1475
+
1468
1476
this . emit ( 'progress' , totalProgress )
1469
1477
this . setState ( { totalProgress } )
1470
1478
}
1471
1479
1480
+ // ___Why throttle at 500ms?
1481
+ // - We must throttle at >250ms for superfocus in Dashboard to work well
1482
+ // (because animation takes 0.25s, and we want to wait for all animations to be over before refocusing).
1483
+ // [Practical Check]: if thottle is at 100ms, then if you are uploading a file,
1484
+ // and click 'ADD MORE FILES', - focus won't activate in Firefox.
1485
+ // - We must throttle at around >500ms to avoid performance lags.
1486
+ // [Practical Check] Firefox, try to upload a big file for a prolonged period of time. Laptop will start to heat up.
1487
+ #updateTotalProgressThrottled = throttle (
1488
+ ( ) => this . #updateTotalProgress( ) ,
1489
+ 500 ,
1490
+ { leading : true , trailing : true } ,
1491
+ )
1492
+
1472
1493
// eslint-disable-next-line class-methods-use-this, @typescript-eslint/explicit-module-boundary-types
1473
1494
private [ Symbol . for ( 'uppy test: updateTotalProgress' ) ] ( ) {
1474
1495
return this . #updateTotalProgress( )
1475
1496
}
1476
1497
1477
1498
#calculateTotalProgress( ) {
1478
1499
// calculate total progress, using the number of files currently uploading,
1479
- // multiplied by 100 and the summ of individual progress of each file
1500
+ // between 0 and 1 and sum of individual progress of each file
1480
1501
const files = this . getFiles ( )
1481
1502
1482
- const inProgress = files . filter ( ( file ) => {
1503
+ const filesInProgress = files . filter ( ( file ) => {
1483
1504
return (
1484
1505
file . progress . uploadStarted ||
1485
1506
file . progress . preprocess ||
1486
1507
file . progress . postprocess
1487
1508
)
1488
1509
} )
1489
1510
1490
- if ( inProgress . length === 0 ) {
1511
+ if ( filesInProgress . length === 0 ) {
1491
1512
return 0
1492
1513
}
1493
1514
1494
- const sizedFiles = inProgress . filter (
1515
+ const sizedFiles = filesInProgress . filter (
1495
1516
( file ) => file . progress . bytesTotal != null ,
1496
1517
)
1497
- const unsizedFiles = inProgress . filter (
1518
+ const unsizedFiles = filesInProgress . filter (
1498
1519
( file ) => file . progress . bytesTotal == null ,
1499
1520
)
1500
1521
1501
1522
if ( sizedFiles . length === 0 ) {
1502
- const progressMax = inProgress . length * 100
1503
- const currentProgress = unsizedFiles . reduce ( ( acc , file ) => {
1504
- return acc + ( file . progress . percentage as number )
1505
- } , 0 )
1506
- const totalProgress = Math . round ( ( currentProgress / progressMax ) * 100 )
1507
- return totalProgress
1523
+ const totalUnsizedProgress = unsizedFiles . reduce (
1524
+ ( acc , file ) => acc + ( file . progress . percentage ?? 0 ) / 100 ,
1525
+ 0 ,
1526
+ )
1527
+
1528
+ return totalUnsizedProgress / unsizedFiles . length
1508
1529
}
1509
1530
1510
- let totalSize = sizedFiles . reduce ( ( acc , file ) => {
1531
+ let totalFilesSize = sizedFiles . reduce ( ( acc , file ) => {
1511
1532
return ( acc + ( file . progress . bytesTotal ?? 0 ) ) as number
1512
1533
} , 0 )
1513
- const averageSize = totalSize / sizedFiles . length
1514
- totalSize += averageSize * unsizedFiles . length
1534
+ const averageSize = totalFilesSize / sizedFiles . length
1535
+ totalFilesSize += averageSize * unsizedFiles . length
1515
1536
1516
- let uploadedSize = 0
1537
+ let totalUploadedSize = 0
1517
1538
sizedFiles . forEach ( ( file ) => {
1518
- uploadedSize += file . progress . bytesUploaded as number
1539
+ totalUploadedSize += file . progress . bytesUploaded || 0
1519
1540
} )
1520
1541
unsizedFiles . forEach ( ( file ) => {
1521
- uploadedSize += ( averageSize * ( file . progress . percentage || 0 ) ) / 100
1542
+ totalUploadedSize += averageSize * ( ( file . progress . percentage ?? 0 ) / 100 )
1522
1543
} )
1523
1544
1524
- let totalProgress =
1525
- totalSize === 0 ? 0 : Math . round ( ( uploadedSize / totalSize ) * 100 )
1526
-
1527
- // hot fix, because:
1528
- // uploadedSize ended up larger than totalSize, resulting in 1325% total
1529
- if ( totalProgress > 100 ) {
1530
- totalProgress = 100
1531
- }
1532
-
1533
- return totalProgress
1545
+ return totalFilesSize === 0 ? 0 : totalUploadedSize / totalFilesSize
1534
1546
}
1535
1547
1536
1548
/**
@@ -1629,7 +1641,7 @@ export class Uppy<
1629
1641
1630
1642
this . on ( 'upload-start' , onUploadStarted )
1631
1643
1632
- this . on ( 'upload-progress' , this . calculateProgress )
1644
+ this . on ( 'upload-progress' , this . #handleUploadProgress )
1633
1645
1634
1646
this . on ( 'upload-success' , ( file , uploadResp ) => {
1635
1647
if ( file == null || ! this . getFile ( file . id ) ) {
@@ -1666,7 +1678,7 @@ export class Uppy<
1666
1678
} )
1667
1679
}
1668
1680
1669
- this . #updateTotalProgress ( )
1681
+ this . #updateTotalProgressThrottled ( )
1670
1682
} )
1671
1683
1672
1684
this . on ( 'preprocess-progress' , ( file , progress ) => {
@@ -1736,7 +1748,7 @@ export class Uppy<
1736
1748
1737
1749
this . on ( 'restored' , ( ) => {
1738
1750
// Files may have changed--ensure progress is still accurate.
1739
- this . #updateTotalProgress ( )
1751
+ this . #updateTotalProgressThrottled ( )
1740
1752
} )
1741
1753
1742
1754
// @ts -expect-error should fix itself when dashboard it typed (also this doesn't belong here)
0 commit comments