uppy
Version:
Almost as cute as a Puppy :dog:
206 lines (166 loc) • 7.92 kB
JavaScript
;
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var Plugin = require('../Plugin');
var ServiceWorkerStore = require('./ServiceWorkerStore');
var IndexedDBStore = require('./IndexedDBStore'
/**
* Restore Files plugin — restores selected files and resumes uploads
* after a closed tab or a browser crash!
*
* Uses localStorage, IndexedDB and ServiceWorker to do its magic, read more:
* https://uppy.io/blog/2017/07/golden-retriever/
*/
);module.exports = function (_Plugin) {
_inherits(RestoreFiles, _Plugin);
function RestoreFiles(core, opts) {
_classCallCheck(this, RestoreFiles);
var _this = _possibleConstructorReturn(this, _Plugin.call(this, core, opts));
_this.type = 'debugger';
_this.id = 'RestoreFiles';
_this.title = 'Restore Files';
var defaultOptions = {
serviceWorker: false
};
_this.opts = _extends({}, defaultOptions, opts);
_this.ServiceWorkerStore = null;
if (_this.opts.serviceWorker) {
_this.ServiceWorkerStore = new ServiceWorkerStore(core, { storeName: core.getID() });
}
_this.IndexedDBStore = new IndexedDBStore(core, _extends({}, opts.indexedDB || {}, { storeName: core.getID() }));
_this.saveFilesStateToLocalStorage = _this.saveFilesStateToLocalStorage.bind(_this);
_this.loadFilesStateFromLocalStorage = _this.loadFilesStateFromLocalStorage.bind(_this);
_this.loadFileBlobsFromServiceWorker = _this.loadFileBlobsFromServiceWorker.bind(_this);
_this.loadFileBlobsFromIndexedDB = _this.loadFileBlobsFromIndexedDB.bind(_this);
_this.onBlobsLoaded = _this.onBlobsLoaded.bind(_this);
return _this;
}
RestoreFiles.prototype.loadFilesStateFromLocalStorage = function loadFilesStateFromLocalStorage() {
var savedState = localStorage.getItem('uppyState:' + this.core.opts.id);
if (savedState) {
this.core.log('Recovered some state from Local Storage');
this.core.setState(JSON.parse(savedState));
}
};
RestoreFiles.prototype.saveFilesStateToLocalStorage = function saveFilesStateToLocalStorage() {
var files = JSON.stringify({
currentUploads: this.core.state.currentUploads,
files: this.core.state.files
});
localStorage.setItem('uppyState:' + this.core.opts.id, files);
};
RestoreFiles.prototype.loadFileBlobsFromServiceWorker = function loadFileBlobsFromServiceWorker() {
var _this2 = this;
this.ServiceWorkerStore.list().then(function (blobs) {
var numberOfFilesRecovered = Object.keys(blobs).length;
var numberOfFilesTryingToRecover = Object.keys(_this2.core.state.files).length;
if (numberOfFilesRecovered === numberOfFilesTryingToRecover) {
_this2.core.log('Successfully recovered ' + numberOfFilesRecovered + ' blobs from Service Worker!');
_this2.core.info('Successfully recovered ' + numberOfFilesRecovered + ' files', 'success', 3000);
_this2.onBlobsLoaded(blobs);
} else {
_this2.core.log('Failed to recover blobs from Service Worker, trying IndexedDB now...');
_this2.loadFileBlobsFromIndexedDB();
}
});
};
RestoreFiles.prototype.loadFileBlobsFromIndexedDB = function loadFileBlobsFromIndexedDB() {
var _this3 = this;
this.IndexedDBStore.list().then(function (blobs) {
var numberOfFilesRecovered = Object.keys(blobs).length;
if (numberOfFilesRecovered > 0) {
_this3.core.log('Successfully recovered ' + numberOfFilesRecovered + ' blobs from Indexed DB!');
_this3.core.info('Successfully recovered ' + numberOfFilesRecovered + ' files', 'success', 3000);
return _this3.onBlobsLoaded(blobs);
}
_this3.core.log('Couldn’t recover anything from IndexedDB :(');
});
};
RestoreFiles.prototype.onBlobsLoaded = function onBlobsLoaded(blobs) {
var _this4 = this;
var obsoleteBlobs = [];
var updatedFiles = _extends({}, this.core.state.files);
Object.keys(blobs).forEach(function (fileID) {
var originalFile = _this4.core.getFile(fileID);
if (!originalFile) {
obsoleteBlobs.push(fileID);
return;
}
var cachedData = blobs[fileID];
var updatedFileData = {
data: cachedData,
isRestored: true
};
var updatedFile = _extends({}, originalFile, updatedFileData);
updatedFiles[fileID] = updatedFile;
_this4.core.generatePreview(updatedFile);
});
this.core.setState({
files: updatedFiles
});
this.core.emit('core:restored');
if (obsoleteBlobs.length) {
this.deleteBlobs(obsoleteBlobs).then(function () {
_this4.core.log('RestoreFiles: cleaned up ' + obsoleteBlobs.length + ' old files');
});
}
};
RestoreFiles.prototype.deleteBlobs = function deleteBlobs(fileIDs) {
var _this5 = this;
var promises = [];
fileIDs.forEach(function (id) {
if (_this5.ServiceWorkerStore) {
promises.push(_this5.ServiceWorkerStore.delete(id));
}
if (_this5.IndexedDBStore) {
promises.push(_this5.IndexedDBStore.delete(id));
}
});
return Promise.all(promises);
};
RestoreFiles.prototype.install = function install() {
var _this6 = this;
this.loadFilesStateFromLocalStorage();
if (Object.keys(this.core.state.files).length > 0) {
if (this.ServiceWorkerStore) {
this.core.log('Attempting to load files from Service Worker...');
this.loadFileBlobsFromServiceWorker();
} else {
this.core.log('Attempting to load files from Indexed DB...');
this.loadFileBlobsFromIndexedDB();
}
}
this.core.on('core:file-added', function (file) {
if (file.isRemote) return;
if (_this6.ServiceWorkerStore) {
_this6.ServiceWorkerStore.put(file).catch(function (err) {
_this6.core.log('Could not store file', 'error');
_this6.core.log(err);
});
}
_this6.IndexedDBStore.put(file).catch(function (err) {
_this6.core.log('Could not store file', 'error');
_this6.core.log(err);
});
});
this.core.on('core:file-removed', function (fileID) {
if (_this6.ServiceWorkerStore) _this6.ServiceWorkerStore.delete(fileID);
_this6.IndexedDBStore.delete(fileID);
});
this.core.on('core:state-update', this.saveFilesStateToLocalStorage);
this.core.on('core:restored', function () {
// start all uploads again when file blobs are restored
var _core$getState = _this6.core.getState(),
currentUploads = _core$getState.currentUploads;
if (currentUploads) {
Object.keys(currentUploads).forEach(function (uploadId) {
_this6.core.restore(uploadId, currentUploads[uploadId]);
});
}
});
};
return RestoreFiles;
}(Plugin);
//# sourceMappingURL=index.js.map