-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'Expensify:main' into 41906-fix
- Loading branch information
Showing
235 changed files
with
3,299 additions
and
1,992 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
import type {BrowserWindow} from 'electron'; | ||
import {app} from 'electron'; | ||
import * as path from 'path'; | ||
import createQueue from '@libs/Queue/Queue'; | ||
import CONST from '@src/CONST'; | ||
import ELECTRON_EVENTS from './ELECTRON_EVENTS'; | ||
import type Options from './electronDownloadManagerType'; | ||
|
||
type DownloadItem = { | ||
// The window where the download will be initiated | ||
win: BrowserWindow; | ||
|
||
// The URL of the file to be downloaded | ||
url: string; | ||
|
||
// The options for the download, such as save path, file name, etc. | ||
options: Options; | ||
}; | ||
|
||
/** | ||
* Returns the filename with extension based on the given name and MIME type. | ||
* @param name - The name of the file. | ||
* @param mime - The MIME type of the file. | ||
* @returns The filename with extension. | ||
*/ | ||
const getFilenameFromMime = (name: string, mime: string): string => { | ||
const extensions = mime.split('/').pop(); | ||
return `${name}.${extensions}`; | ||
}; | ||
|
||
const createDownloadQueue = () => { | ||
const downloadItemProcessor = (item: DownloadItem): Promise<void> => | ||
new Promise((resolve, reject) => { | ||
let downloadTimeout: NodeJS.Timeout; | ||
let downloadListener: (event: Electron.Event, electronDownloadItem: Electron.DownloadItem) => void; | ||
|
||
const timeoutFunction = () => { | ||
item.win.webContents.session.removeListener('will-download', downloadListener); | ||
resolve(); | ||
}; | ||
|
||
const listenerFunction = (event: Electron.Event, electronDownloadItem: Electron.DownloadItem) => { | ||
clearTimeout(downloadTimeout); | ||
|
||
const options = item.options; | ||
const cleanup = () => item.win.webContents.session.removeListener('will-download', listenerFunction); | ||
const errorMessage = `The download of ${electronDownloadItem.getFilename()} was interrupted`; | ||
|
||
if (options.directory && !path.isAbsolute(options.directory)) { | ||
throw new Error('The `directory` option must be an absolute path'); | ||
} | ||
|
||
const directory = options.directory ?? app.getPath('downloads'); | ||
|
||
let filePath: string; | ||
if (options.filename) { | ||
filePath = path.join(directory, options.filename); | ||
} else { | ||
const filename = electronDownloadItem.getFilename(); | ||
const name = path.extname(filename) ? filename : getFilenameFromMime(filename, electronDownloadItem.getMimeType()); | ||
|
||
filePath = options.overwrite ? path.join(directory, name) : path.join(directory, name); | ||
} | ||
|
||
if (options.saveAs) { | ||
electronDownloadItem.setSaveDialogOptions({defaultPath: filePath, ...options.dialogOptions}); | ||
} else { | ||
electronDownloadItem.setSavePath(filePath); | ||
} | ||
|
||
electronDownloadItem.on('updated', (_, state) => { | ||
if (state !== 'interrupted') { | ||
return; | ||
} | ||
|
||
item.win.webContents.send(ELECTRON_EVENTS.DOWNLOAD_CANCELED, {url: item.url}); | ||
cleanup(); | ||
reject(new Error(errorMessage)); | ||
electronDownloadItem.cancel(); | ||
}); | ||
|
||
electronDownloadItem.on('done', (_, state) => { | ||
cleanup(); | ||
if (state === 'cancelled') { | ||
item.win.webContents.send(ELECTRON_EVENTS.DOWNLOAD_CANCELED, {url: item.url}); | ||
resolve(); | ||
} else if (state === 'interrupted') { | ||
item.win.webContents.send(ELECTRON_EVENTS.DOWNLOAD_FAILED, {url: item.url}); | ||
reject(new Error(errorMessage)); | ||
} else if (state === 'completed') { | ||
if (process.platform === 'darwin') { | ||
const savePath = electronDownloadItem.getSavePath(); | ||
app.dock.downloadFinished(savePath); | ||
} | ||
item.win.webContents.send(ELECTRON_EVENTS.DOWNLOAD_COMPLETED, {url: item.url}); | ||
resolve(); | ||
} | ||
}); | ||
}; | ||
|
||
downloadTimeout = setTimeout(timeoutFunction, CONST.DOWNLOADS_TIMEOUT); | ||
downloadListener = listenerFunction; | ||
|
||
item.win.webContents.downloadURL(item.url); | ||
item.win.webContents.session.on('will-download', downloadListener); | ||
}); | ||
|
||
const queue = createQueue<DownloadItem>(downloadItemProcessor); | ||
|
||
const enqueueDownloadItem = (item: DownloadItem): void => { | ||
queue.enqueue(item); | ||
}; | ||
return {enqueueDownloadItem, dequeueDownloadItem: queue.dequeue}; | ||
}; | ||
|
||
export default createDownloadQueue; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import type {SaveDialogOptions} from 'electron'; | ||
|
||
type Options = { | ||
/** | ||
Show a `Save As…` dialog instead of downloading immediately. | ||
Note: Only use this option when strictly necessary. Downloading directly without a prompt is a much better user experience. | ||
@default false | ||
*/ | ||
readonly saveAs?: boolean; | ||
|
||
/** | ||
The directory to save the file in. | ||
Must be an absolute path. | ||
Default: [User's downloads directory](https://electronjs.org/docs/api/app/#appgetpathname) | ||
*/ | ||
readonly directory?: string; | ||
|
||
/** | ||
Name of the saved file. | ||
This option only makes sense for `electronDownloadManager.download()`. | ||
Default: [`downloadItem.getFilename()`](https://electronjs.org/docs/api/download-item/#downloaditemgetfilename) | ||
*/ | ||
readonly filename?: string; | ||
|
||
/** | ||
Allow downloaded files to overwrite files with the same name in the directory they are saved to. | ||
The default behavior is to append a number to the filename. | ||
@default false | ||
*/ | ||
readonly overwrite?: boolean; | ||
|
||
/** | ||
Customize the save dialog. | ||
If `defaultPath` is not explicity defined, a default value is assigned based on the file path. | ||
@default {} | ||
*/ | ||
readonly dialogOptions?: SaveDialogOptions; | ||
}; | ||
|
||
export default Options; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Oops, something went wrong.