Skip to content

Commit c2e74d6

Browse files
committed
fix progress throttling
only do it on total progress
1 parent 3cd20a1 commit c2e74d6

File tree

3 files changed

+88
-81
lines changed

3 files changed

+88
-81
lines changed

packages/@uppy/core/src/Uppy.test.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1187,7 +1187,7 @@ describe('src/Core', () => {
11871187
core.addUploader((fileIDs) => {
11881188
fileIDs.forEach((fileID) => {
11891189
const file = core.getFile(fileID)
1190-
if (/bar/.test(file.name)) {
1190+
if (file.name != null && /bar/.test(file.name)) {
11911191
// @ts-ignore
11921192
core.emit(
11931193
'upload-error',
@@ -1701,6 +1701,9 @@ describe('src/Core', () => {
17011701

17021702
const fileId = Object.keys(core.getState().files)[0]
17031703
const file = core.getFile(fileId)
1704+
1705+
core.emit('upload-start', [core.getFile(fileId)])
1706+
17041707
// @ts-ignore
17051708
core.emit('upload-progress', file, {
17061709
bytesUploaded: 12345,
@@ -1711,7 +1714,7 @@ describe('src/Core', () => {
17111714
bytesUploaded: 12345,
17121715
bytesTotal: 17175,
17131716
uploadComplete: false,
1714-
uploadStarted: null,
1717+
uploadStarted: expect.any(Number),
17151718
})
17161719

17171720
// @ts-ignore
@@ -1720,14 +1723,12 @@ describe('src/Core', () => {
17201723
bytesTotal: 17175,
17211724
})
17221725

1723-
core.calculateProgress.flush()
1724-
17251726
expect(core.getFile(fileId).progress).toEqual({
17261727
percentage: 100,
17271728
bytesUploaded: 17175,
17281729
bytesTotal: 17175,
17291730
uploadComplete: false,
1730-
uploadStarted: null,
1731+
uploadStarted: expect.any(Number),
17311732
})
17321733
})
17331734

@@ -1897,7 +1898,6 @@ describe('src/Core', () => {
18971898

18981899
// @ts-ignore
18991900
core[Symbol.for('uppy test: updateTotalProgress')]()
1900-
core.calculateProgress.flush()
19011901

19021902
expect(core.getState().totalProgress).toEqual(66)
19031903
})
@@ -1942,7 +1942,6 @@ describe('src/Core', () => {
19421942

19431943
// @ts-ignore
19441944
core[Symbol.for('uppy test: updateTotalProgress')]()
1945-
core.calculateProgress.flush()
19461945

19471946
expect(core.getState().totalProgress).toEqual(66)
19481947
expect(core.getState().allowNewUpload).toEqual(true)

packages/@uppy/core/src/Uppy.ts

Lines changed: 81 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1270,7 +1270,7 @@ export class Uppy<
12701270
}
12711271

12721272
this.setState(stateUpdate)
1273-
this.#updateTotalProgress()
1273+
this.#updateTotalProgressThrottled()
12741274

12751275
const removedFileIDs = Object.keys(removedFiles)
12761276
removedFileIDs.forEach((fileID) => {
@@ -1416,121 +1416,133 @@ export class Uppy<
14161416
})
14171417
}
14181418

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+
}
14371430

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+
}
14441437

1438+
const newProgress = {
1439+
bytesTotal: progress.bytesTotal,
14451440
// 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) {
14481452
this.setFileState(file.id, {
14491453
progress: {
14501454
...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,
14571457
},
14581458
})
1459+
} else {
1460+
this.setFileState(file.id, {
1461+
progress: {
1462+
...fileInState.progress,
1463+
...newProgress,
1464+
},
1465+
})
1466+
}
14591467

1460-
this.#updateTotalProgress()
1461-
},
1462-
500,
1463-
{ leading: true, trailing: true },
1464-
)
1468+
this.#updateTotalProgressThrottled()
1469+
}
14651470

14661471
#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+
14681476
this.emit('progress', totalProgress)
14691477
this.setState({ totalProgress })
14701478
}
14711479

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+
14721493
// eslint-disable-next-line class-methods-use-this, @typescript-eslint/explicit-module-boundary-types
14731494
private [Symbol.for('uppy test: updateTotalProgress')]() {
14741495
return this.#updateTotalProgress()
14751496
}
14761497

14771498
#calculateTotalProgress() {
14781499
// 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
14801501
const files = this.getFiles()
14811502

1482-
const inProgress = files.filter((file) => {
1503+
const filesInProgress = files.filter((file) => {
14831504
return (
14841505
file.progress.uploadStarted ||
14851506
file.progress.preprocess ||
14861507
file.progress.postprocess
14871508
)
14881509
})
14891510

1490-
if (inProgress.length === 0) {
1511+
if (filesInProgress.length === 0) {
14911512
return 0
14921513
}
14931514

1494-
const sizedFiles = inProgress.filter(
1515+
const sizedFiles = filesInProgress.filter(
14951516
(file) => file.progress.bytesTotal != null,
14961517
)
1497-
const unsizedFiles = inProgress.filter(
1518+
const unsizedFiles = filesInProgress.filter(
14981519
(file) => file.progress.bytesTotal == null,
14991520
)
15001521

15011522
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
15081529
}
15091530

1510-
let totalSize = sizedFiles.reduce((acc, file) => {
1531+
let totalFilesSize = sizedFiles.reduce((acc, file) => {
15111532
return (acc + (file.progress.bytesTotal ?? 0)) as number
15121533
}, 0)
1513-
const averageSize = totalSize / sizedFiles.length
1514-
totalSize += averageSize * unsizedFiles.length
1534+
const averageSize = totalFilesSize / sizedFiles.length
1535+
totalFilesSize += averageSize * unsizedFiles.length
15151536

1516-
let uploadedSize = 0
1537+
let totalUploadedSize = 0
15171538
sizedFiles.forEach((file) => {
1518-
uploadedSize += file.progress.bytesUploaded as number
1539+
totalUploadedSize += file.progress.bytesUploaded || 0
15191540
})
15201541
unsizedFiles.forEach((file) => {
1521-
uploadedSize += (averageSize * (file.progress.percentage || 0)) / 100
1542+
totalUploadedSize += averageSize * ((file.progress.percentage ?? 0) / 100)
15221543
})
15231544

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
15341546
}
15351547

15361548
/**
@@ -1629,7 +1641,7 @@ export class Uppy<
16291641

16301642
this.on('upload-start', onUploadStarted)
16311643

1632-
this.on('upload-progress', this.calculateProgress)
1644+
this.on('upload-progress', this.#handleUploadProgress)
16331645

16341646
this.on('upload-success', (file, uploadResp) => {
16351647
if (file == null || !this.getFile(file.id)) {
@@ -1666,7 +1678,7 @@ export class Uppy<
16661678
})
16671679
}
16681680

1669-
this.#updateTotalProgress()
1681+
this.#updateTotalProgressThrottled()
16701682
})
16711683

16721684
this.on('preprocess-progress', (file, progress) => {
@@ -1736,7 +1748,7 @@ export class Uppy<
17361748

17371749
this.on('restored', () => {
17381750
// Files may have changed--ensure progress is still accurate.
1739-
this.#updateTotalProgress()
1751+
this.#updateTotalProgressThrottled()
17401752
})
17411753

17421754
// @ts-expect-error should fix itself when dashboard it typed (also this doesn't belong here)

packages/@uppy/utils/src/emitSocketProgress.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import throttle from 'lodash/throttle.js'
21
import type { Uppy } from '@uppy/core'
32
import type { UppyFile } from './UppyFile.ts'
43

@@ -22,7 +21,4 @@ function emitSocketProgress(
2221
}
2322
}
2423

25-
export default throttle(emitSocketProgress, 300, {
26-
leading: true,
27-
trailing: true,
28-
})
24+
export default emitSocketProgress

0 commit comments

Comments
 (0)