thedesk/app/node_modules/electron-dl/index.js
2019-09-12 23:38:13 +09:00

148 lines
3.8 KiB
JavaScript

'use strict';
const path = require('path');
const {app, BrowserWindow, shell, dialog} = require('electron');
const unusedFilename = require('unused-filename');
const pupa = require('pupa');
const extName = require('ext-name');
function getFilenameFromMime(name, mime) {
const exts = extName.mime(mime);
if (exts.length !== 1) {
return name;
}
return `${name}.${exts[0].ext}`;
}
function registerListener(session, options, cb = () => {}) {
const downloadItems = new Set();
let receivedBytes = 0;
let completedBytes = 0;
let totalBytes = 0;
const activeDownloadItems = () => downloadItems.size;
const progressDownloadItems = () => receivedBytes / totalBytes;
options = Object.assign({
showBadge: true
}, options);
const listener = (e, item, webContents) => {
downloadItems.add(item);
totalBytes += item.getTotalBytes();
let hostWebContents = webContents;
if (webContents.getType() === 'webview') {
({hostWebContents} = webContents);
}
const win = BrowserWindow.fromWebContents(hostWebContents);
const dir = options.directory || app.getPath('downloads');
let filePath;
if (options.filename) {
filePath = path.join(dir, options.filename);
} else {
const filename = item.getFilename();
const name = path.extname(filename) ? filename : getFilenameFromMime(filename, item.getMimeType());
filePath = unusedFilename.sync(path.join(dir, name));
}
const errorMessage = options.errorMessage || 'The download of {filename} was interrupted';
const errorTitle = options.errorTitle || 'Download Error';
if (!options.saveAs) {
item.setSavePath(filePath);
}
if (typeof options.onStarted === 'function') {
options.onStarted(item);
}
item.on('updated', () => {
receivedBytes = [...downloadItems].reduce((receivedBytes, item) => {
receivedBytes += item.getReceivedBytes();
return receivedBytes;
}, completedBytes);
if (options.showBadge && ['darwin', 'linux'].includes(process.platform)) {
app.setBadgeCount(activeDownloadItems());
}
if (!win.isDestroyed()) {
win.setProgressBar(progressDownloadItems());
}
if (typeof options.onProgress === 'function') {
options.onProgress(progressDownloadItems());
}
});
item.on('done', (event, state) => {
completedBytes += item.getTotalBytes();
downloadItems.delete(item);
if (options.showBadge && ['darwin', 'linux'].includes(process.platform)) {
app.setBadgeCount(activeDownloadItems());
}
if (!win.isDestroyed() && !activeDownloadItems()) {
win.setProgressBar(-1);
receivedBytes = 0;
completedBytes = 0;
totalBytes = 0;
}
if (options.unregisterWhenDone) {
session.removeListener('will-download', listener);
}
if (state === 'cancelled') {
if (typeof options.onCancel === 'function') {
options.onCancel(item);
}
} else if (state === 'interrupted') {
const message = pupa(errorMessage, {filename: item.getFilename()});
dialog.showErrorBox(errorTitle, message);
cb(new Error(message));
} else if (state === 'completed') {
if (process.platform === 'darwin') {
app.dock.downloadFinished(filePath);
}
if (options.openFolderWhenDone) {
shell.showItemInFolder(path.join(dir, item.getFilename()));
}
cb(null, item);
}
});
};
session.on('will-download', listener);
}
module.exports = (options = {}) => {
app.on('session-created', session => {
registerListener(session, options);
});
};
// TODO: Remove this for the next major release
module.exports.default = module.exports;
module.exports.download = (win, url, options) => new Promise((resolve, reject) => {
options = Object.assign({}, options, {unregisterWhenDone: true});
registerListener(win.webContents.session, options, (err, item) => {
if (err) {
reject(err);
} else {
resolve(item);
}
});
win.webContents.downloadURL(url);
});