diff --git a/src/app/Flash.jsx b/src/app/Flash.jsx index 33e66bc..05d191d 100644 --- a/src/app/Flash.jsx +++ b/src/app/Flash.jsx @@ -105,6 +105,10 @@ const errors = { description: 'Your system does not meet the requirements to flash your device. Make sure to use a browser which ' + 'supports WebUSB and is up to date.', }, + [Error.STORAGE_SPACE]: { + description: 'Your system does not have enough space available to download the system image. Your browser may ' + + 'be restricting the available space if you are in a private, incognito or guest session.', + }, } if (isLinux) { @@ -206,6 +210,7 @@ export default function Flash() { // Handle user clicking the start button const handleStart = () => qdlManager.current?.start() + const canStart = step === Step.READY && !error // Handle retry on error const handleRetry = () => window.location.reload() @@ -222,6 +227,8 @@ export default function Flash() { if (progress >= 0) { title += ` (${(progress * 100).toFixed(0)}%)` } + } else if (error === Error.STORAGE_SPACE) { + title = message } else { title = status } @@ -237,8 +244,8 @@ export default function Flash() {
({ quota: 10 * (1024 ** 3) })), getDirectory: () => ({ getFileHandle: () => ({ createWritable: vi.fn().mockImplementation(() => ({ diff --git a/src/utils/qdl.js b/src/utils/qdl.js index a151f67..509bd4b 100644 --- a/src/utils/qdl.js +++ b/src/utils/qdl.js @@ -25,6 +25,7 @@ export const Error = { FLASH_FAILED: 6, ERASE_FAILED: 7, REQUIREMENTS_NOT_MET: 8, + STORAGE_SPACE: 9, } /** @@ -170,7 +171,12 @@ export class QdlManager { this.setStep(Step.READY) } catch (err) { console.error('[QDL] Initialization error', err) - this.setError(Error.UNKNOWN) + if (err.startsWith('Not enough storage')) { + this.setError(Error.STORAGE_SPACE) + this.setMessage(err) + } else { + this.setError(Error.UNKNOWN) + } } } diff --git a/src/workers/image.worker.js b/src/workers/image.worker.js index a9b1d82..bfb4df1 100644 --- a/src/workers/image.worker.js +++ b/src/workers/image.worker.js @@ -39,6 +39,8 @@ async function readChunks(reader, total, { onChunk, onProgress = undefined }) { } } +const MIN_QUOTA_MB = 5250 + /** @type {FileSystemDirectoryHandle} */ let root @@ -48,15 +50,17 @@ let root const imageWorker = { async init() { - if (root) { - console.warn('[ImageWorker] Already initialized') - return + if (!root) { + root = await navigator.storage.getDirectory() + await root.remove({ recursive: true }) + console.info('[ImageWorker] Initialized') } - // TODO: check storage quota and report error if insufficient - root = await navigator.storage.getDirectory() - await root.remove({ recursive: true }) - console.info('[ImageWorker] Initialized') + const estimate = await navigator.storage.estimate() + const quotaMB = (estimate.quota || 0) / (1024 ** 2) + if (quotaMB < MIN_QUOTA_MB) { + throw `Not enough storage: ${quotaMB.toFixed(0)}MB free, need ${MIN_QUOTA_MB.toFixed(0)}MB` + } }, /**