fox-send/app/fileManager.js

282 lines
7.4 KiB
JavaScript
Raw Normal View History

2018-08-03 19:24:41 +00:00
/* global MAXFILESIZE */
import FileSender from './fileSender';
import FileReceiver from './fileReceiver';
2018-07-31 18:09:18 +00:00
import { copyToClipboard, delay, openLinksInNewTab, percent } from './utils';
import * as metrics from './metrics';
2018-07-31 18:09:18 +00:00
import { hasPassword } from './api';
import Archive from './archive';
2018-08-03 19:24:41 +00:00
import { bytes } from './utils';
export default function(state, emitter) {
let lastRender = 0;
2017-09-13 19:01:55 +00:00
let updateTitle = false;
function render() {
emitter.emit('render');
}
async function checkFiles() {
2018-02-27 01:50:58 +00:00
const files = state.storage.files.slice();
let rerender = false;
for (const file of files) {
2018-01-23 02:11:48 +00:00
const oldLimit = file.dlimit;
const oldTotal = file.dtotal;
2018-01-24 18:23:13 +00:00
await file.updateDownloadCount();
if (file.dtotal === file.dlimit) {
state.storage.remove(file.id);
rerender = true;
2018-01-24 18:23:13 +00:00
} else if (oldLimit !== file.dlimit || oldTotal !== file.dtotal) {
2018-01-23 02:11:48 +00:00
rerender = true;
}
}
if (rerender) {
render();
}
}
2017-09-13 19:01:55 +00:00
function updateProgress() {
if (updateTitle) {
emitter.emit('DOMTitleChange', percent(state.transfer.progressRatio));
}
render();
}
emitter.on('DOMContentLoaded', () => {
document.addEventListener('blur', () => (updateTitle = true));
document.addEventListener('focus', () => {
updateTitle = false;
emitter.emit('DOMTitleChange', 'Firefox Send');
});
checkFiles();
});
2018-06-25 21:01:08 +00:00
emitter.on('navigate', checkFiles);
emitter.on('render', () => {
lastRender = Date.now();
});
2017-11-30 21:41:09 +00:00
emitter.on('changeLimit', async ({ file, value }) => {
2018-01-24 18:23:13 +00:00
await file.changeLimit(value);
state.storage.writeFile(file);
2017-11-30 21:41:09 +00:00
metrics.changedDownloadLimit(file);
});
2018-08-03 19:24:41 +00:00
emitter.on('removeUpload', async ({ index }) => {
state.archive.remove(index);
render();
2018-07-31 18:09:18 +00:00
});
emitter.on('delete', async ({ file, location }) => {
try {
metrics.deletedUpload({
size: file.size,
time: file.time,
speed: file.speed,
type: file.type,
ttl: file.expiresAt - Date.now(),
location
});
state.storage.remove(file.id);
2018-01-24 18:23:13 +00:00
await file.del();
} catch (e) {
state.raven.captureException(e);
}
});
emitter.on('cancel', () => {
state.transfer.cancel();
});
2018-07-31 18:09:18 +00:00
emitter.on('addFiles', async ({ files }) => {
2018-08-03 19:24:41 +00:00
if (state.archive) {
if (!state.archive.addFiles(files)) {
// eslint-disable-next-line no-alert
alert(state.translate('fileTooBig', { size: bytes(MAXFILESIZE) }));
return;
}
} else {
const archive = new Archive(files);
if (!archive.checkSize()) {
// eslint-disable-next-line no-alert
alert(state.translate('fileTooBig', { size: bytes(MAXFILESIZE) }));
return;
}
state.archive = archive;
2018-07-31 18:09:18 +00:00
}
render();
});
2018-08-03 19:24:41 +00:00
emitter.on('upload', async ({ type, dlCount, password }) => {
if (!state.archive) return;
const size = state.archive.size;
const sender = new FileSender(state.archive);
2017-09-13 19:01:55 +00:00
sender.on('progress', updateProgress);
sender.on('encrypting', render);
2018-07-31 18:09:18 +00:00
sender.on('complete', render);
state.transfer = sender;
state.uploading = true;
render();
2018-01-24 18:23:13 +00:00
const links = openLinksInNewTab();
await delay(200);
try {
metrics.startedUpload({ size, type });
2018-07-31 18:09:18 +00:00
2018-01-31 19:12:36 +00:00
const ownedFile = await sender.upload();
2018-02-02 18:15:17 +00:00
ownedFile.type = type;
2018-01-24 18:23:13 +00:00
state.storage.totalUploads += 1;
metrics.completedUpload(ownedFile);
state.storage.addFile(ownedFile);
2018-07-31 18:09:18 +00:00
if (password) {
emitter.emit('password', { password, file: ownedFile });
}
emitter.emit('changeLimit', { file: ownedFile, value: dlCount });
2018-03-06 00:29:09 +00:00
const cancelBtn = document.getElementById('cancel-upload');
if (cancelBtn) {
cancelBtn.hidden = 'hidden';
}
if (document.querySelector('.page')) {
await delay(1000);
}
2018-01-24 18:23:13 +00:00
emitter.emit('pushState', `/share/${ownedFile.id}`);
} catch (err) {
if (err.message === '0') {
//cancelled. do nothing
metrics.cancelledUpload({ size, type });
render();
} else {
// eslint-disable-next-line no-console
console.error(err);
state.raven.captureException(err);
metrics.stoppedUpload({ size, type, err });
emitter.emit('pushState', '/error');
}
} finally {
openLinksInNewTab(links, false);
2018-07-31 18:09:18 +00:00
state.files = [];
state.password = '';
state.uploading = false;
state.transfer = null;
}
});
2018-01-24 18:23:13 +00:00
emitter.on('password', async ({ password, file }) => {
try {
2018-02-16 20:56:53 +00:00
state.settingPassword = true;
render();
2018-01-24 18:23:13 +00:00
await file.setPassword(password);
state.storage.writeFile(file);
metrics.addedPassword({ size: file.size });
2018-02-16 20:56:53 +00:00
await delay(1000);
2018-01-24 18:23:13 +00:00
} catch (err) {
2018-03-02 05:36:45 +00:00
// eslint-disable-next-line no-console
2018-01-24 18:23:13 +00:00
console.error(err);
2018-02-21 20:35:52 +00:00
state.passwordSetError = err;
} finally {
state.settingPassword = false;
}
render();
});
2018-07-31 18:09:18 +00:00
emitter.on('getPasswordExist', async ({ id }) => {
try {
state.fileInfo = await hasPassword(id);
render();
} catch (e) {
if (e.message === '404') {
return emitter.emit('pushState', '/404');
}
}
});
2018-01-24 18:23:13 +00:00
emitter.on('getMetadata', async () => {
const file = state.fileInfo;
2018-07-06 22:49:50 +00:00
2018-01-24 18:23:13 +00:00
const receiver = new FileReceiver(file);
try {
2018-01-24 18:23:13 +00:00
await receiver.getMetadata();
state.transfer = receiver;
} catch (e) {
if (e.message === '401') {
file.password = null;
2018-01-24 18:23:13 +00:00
if (!file.requiresPassword) {
return emitter.emit('pushState', '/404');
}
}
}
2018-07-05 19:40:49 +00:00
render();
});
emitter.on('download', async file => {
state.transfer.on('progress', updateProgress);
state.transfer.on('decrypting', render);
2018-07-31 18:09:18 +00:00
state.transfer.on('complete', render);
const links = openLinksInNewTab();
const size = file.size;
try {
const start = Date.now();
metrics.startedDownload({ size: file.size, ttl: file.ttl });
2018-07-31 18:29:26 +00:00
const dl = state.transfer.download({
stream: state.capabilities.streamDownload
});
render();
await dl;
const time = Date.now() - start;
const speed = size / (time / 1000);
if (document.querySelector('.page')) {
await delay(1000);
}
state.storage.totalDownloads += 1;
2018-02-05 02:30:33 +00:00
state.transfer.reset();
metrics.completedDownload({ size, time, speed });
} catch (err) {
2018-01-24 18:23:13 +00:00
if (err.message === '0') {
// download cancelled
state.transfer.reset();
render();
} else {
// eslint-disable-next-line no-console
console.error(err);
state.transfer = null;
const location = err.message === '404' ? '/404' : '/error';
if (location === '/error') {
state.raven.captureException(err);
metrics.stoppedDownload({ size, err });
}
emitter.emit('pushState', location);
}
} finally {
openLinksInNewTab(links, false);
}
});
emitter.on('copy', ({ url, location }) => {
copyToClipboard(url);
metrics.copiedLink({ location });
});
2018-01-24 18:23:13 +00:00
setInterval(() => {
// poll for updates of the download counts
// TODO something for the share page: || state.route === '/share/:id'
if (state.route === '/') {
checkFiles();
}
}, 2 * 60 * 1000);
setInterval(() => {
// poll for rerendering the file list countdown timers
if (
state.route === '/' &&
state.storage.files.length > 0 &&
Date.now() - lastRender > 30000
) {
render();
}
}, 60000);
}