fix: Fix downloads silently failing on Android

This commit is contained in:
Aman Harwara
2025-01-31 22:48:39 +05:30
parent 27aa7139cb
commit 42aedcdf84
2 changed files with 35 additions and 15 deletions

View File

@@ -21,17 +21,30 @@ export class StreamingFileSaver {
return window.showSaveFilePicker != undefined return window.showSaveFilePicker != undefined
} }
/** This function must be called in response to a user interaction, otherwise, it will be rejected by the browser. */ /**
async selectFileToSaveTo(handle?: FileSystemFileHandle): Promise<void> { * This function must be called in response to a user interaction, otherwise, it will be rejected by the browser.
* @returns Whether file was successfully selected or not.
*/
async selectFileToSaveTo(handle?: FileSystemFileHandle): Promise<boolean> {
this.log('Showing save file picker') this.log('Showing save file picker')
const downloadHandle = handle try {
? handle const downloadHandle = handle
: await window.showSaveFilePicker({ ? handle
suggestedName: this.name, : await window.showSaveFilePicker({
}) suggestedName: this.name,
})
this.writableStream = await downloadHandle.createWritable() if (!downloadHandle) {
return false
}
this.writableStream = await downloadHandle.createWritable()
return true
} catch {
return false
}
} }
async pushBytes(bytes: Uint8Array): Promise<void> { async pushBytes(bytes: Uint8Array): Promise<void> {

View File

@@ -313,15 +313,18 @@ export class FilesController extends AbstractViewController<FilesControllerEvent
} }
try { try {
const saver = this.shouldUseStreamingAPI ? new StreamingFileSaver(file.name) : new ClassicFileSaver() let saver = this.shouldUseStreamingAPI ? new StreamingFileSaver(file.name) : new ClassicFileSaver()
let didSelectFileToStreamTo = false
const isUsingStreamingSaver = saver instanceof StreamingFileSaver if (isUsingStreamingSaver(saver)) {
if (isUsingStreamingSaver) {
const fileHandle = directoryHandle const fileHandle = directoryHandle
? await directoryHandle.getFileHandle(file.name, { create: true }) ? await directoryHandle.getFileHandle(file.name, { create: true })
: undefined : undefined
await saver.selectFileToSaveTo(fileHandle) didSelectFileToStreamTo = await saver.selectFileToSaveTo(fileHandle)
}
if (isUsingStreamingSaver(saver) && !didSelectFileToStreamTo) {
saver = new ClassicFileSaver()
} }
if (this.mobileDevice && canShowProgressNotification) { if (this.mobileDevice && canShowProgressNotification) {
@@ -345,7 +348,7 @@ export class FilesController extends AbstractViewController<FilesControllerEvent
let lastProgress: FileDownloadProgress | undefined let lastProgress: FileDownloadProgress | undefined
const result = await this.files.downloadFile(file, async (decryptedBytes, progress) => { const result = await this.files.downloadFile(file, async (decryptedBytes, progress) => {
if (isUsingStreamingSaver) { if (isUsingStreamingSaver(saver)) {
await saver.pushBytes(decryptedBytes) await saver.pushBytes(decryptedBytes)
} else { } else {
decryptedBytesArray.push(decryptedBytes) decryptedBytesArray.push(decryptedBytes)
@@ -378,7 +381,7 @@ export class FilesController extends AbstractViewController<FilesControllerEvent
throw new Error(result.text) throw new Error(result.text)
} }
if (isUsingStreamingSaver) { if (isUsingStreamingSaver(saver)) {
await saver.finish() await saver.finish()
} else { } else {
const finalBytes = concatenateUint8Arrays(decryptedBytesArray) const finalBytes = concatenateUint8Arrays(decryptedBytesArray)
@@ -850,3 +853,7 @@ export class FilesController extends AbstractViewController<FilesControllerEvent
}) })
} }
} }
function isUsingStreamingSaver(saver: StreamingFileSaver | ClassicFileSaver): saver is StreamingFileSaver {
return saver instanceof StreamingFileSaver
}