mirror of
https://github.com/szimek/sharedrop.git
synced 2026-06-13 21:03:07 +08:00
Merge branch 'filesystem_api'
This commit is contained in:
commit
356ef34b06
@ -43,6 +43,7 @@
|
||||
<script src="//netdna.bootstrapcdn.com/bootstrap/3.0.3/js/bootstrap.min.js"></script>
|
||||
|
||||
<!-- build:js(app) /scripts/vendor.js -->
|
||||
<script src="/scripts/vendor/filer.min.js"></script>
|
||||
<script src="/scripts/vendor/peer.js"></script>
|
||||
<script src="/scripts/vendor/socket.io/socket.io.js"></script>
|
||||
<script src="/scripts/vendor/ba-tiny-pubsub.js"></script>
|
||||
@ -51,7 +52,9 @@
|
||||
<!-- build:js({.tmp,app}) /scripts/app.js -->
|
||||
<script src="/scripts/app.js"></script>
|
||||
<script src="/scripts/app/lib/room.js"></script>
|
||||
<script src="/scripts/app/lib/file.js"></script>
|
||||
<script src="/scripts/app/lib/webrtc.js"></script>
|
||||
<script src="/scripts/initializer.js"></script>
|
||||
<script src="/scripts/app/components/confirm_popover_component.js"></script>
|
||||
<script src="/scripts/app/controllers/application_controller.js"></script>
|
||||
<script src="/scripts/app/controllers/index_controller.js"></script>
|
||||
|
||||
@ -155,23 +155,12 @@ FileDrop.IndexController = Ember.ArrayController.extend({
|
||||
console.log('Peer:\t Received file', data);
|
||||
|
||||
var connection = data.connection,
|
||||
peer = this.findBy('peer.id', connection.peer),
|
||||
blob = data.blob,
|
||||
info = peer.get('transfer.info'),
|
||||
dataUrl;
|
||||
peer = this.findBy('peer.id', connection.peer);
|
||||
|
||||
// Stop listening for 'receiving' progress now that we have a file
|
||||
peer.get('peer.connection').removeAllListeners('receiving_progress');
|
||||
peer.set('transfer.receiving_progress', 0);
|
||||
peer.set('transfer.info', null);
|
||||
|
||||
// Save received file
|
||||
dataUrl = window.URL.createObjectURL(blob);
|
||||
var a = document.createElement('a');
|
||||
a.setAttribute('download', info.name);
|
||||
a.setAttribute('href', dataUrl);
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
},
|
||||
|
||||
// Based on http://net.ipcalf.com/
|
||||
|
||||
183
app/scripts/app/lib/file.js
Normal file
183
app/scripts/app/lib/file.js
Normal file
@ -0,0 +1,183 @@
|
||||
window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
|
||||
window.URL = window.URL || window.webkitURL;
|
||||
|
||||
FileDrop.File = function (options) {
|
||||
var self = this;
|
||||
|
||||
this.name = options.name;
|
||||
this.size = options.size;
|
||||
this.type = options.type;
|
||||
|
||||
this._reset();
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
window.requestFileSystem(
|
||||
window.TEMPORARY,
|
||||
options.size,
|
||||
function (filesystem) {
|
||||
self.filesystem = filesystem;
|
||||
resolve(self);
|
||||
},
|
||||
function (error) {
|
||||
self.errorHandler(error);
|
||||
reject(error);
|
||||
}
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
FileDrop.File.removeAll = function () {
|
||||
return new Promise(function (resolve, reject) {
|
||||
var filer = new Filer();
|
||||
|
||||
filer.init({persistent: false}, function () {
|
||||
filer.ls('/', function (entries) {
|
||||
function rm(entry) {
|
||||
if (entry) {
|
||||
filer.rm(entry, function () {
|
||||
rm(entries.pop());
|
||||
});
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
|
||||
rm(entries.pop());
|
||||
});
|
||||
}, function (error) {
|
||||
console.log(error);
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
FileDrop.File.prototype.append = function (data) {
|
||||
var self = this,
|
||||
options = {
|
||||
create: this.create
|
||||
};
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
self.filesystem.root.getFile(self.name, options, function (fileEntry) {
|
||||
if (self.create) {
|
||||
self.fileEntry = fileEntry;
|
||||
self.create = false;
|
||||
}
|
||||
|
||||
fileEntry.createWriter(function (writer) {
|
||||
var blob = new Blob(data, {type: self.type});
|
||||
|
||||
// console.log('File: Appending ' + blob.size + ' bytes at ' + self.seek);
|
||||
|
||||
writer.onwriteend = function () {
|
||||
self.seek += blob.size;
|
||||
resolve(fileEntry);
|
||||
};
|
||||
|
||||
writer.onerror = function (error) {
|
||||
self.errorHandler(error);
|
||||
reject(error);
|
||||
};
|
||||
|
||||
writer.seek(self.seek);
|
||||
writer.write(blob);
|
||||
}, function (error) {
|
||||
self.errorHandler(error);
|
||||
reject(error);
|
||||
});
|
||||
}, function (error) {
|
||||
self.errorHandler(error);
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
FileDrop.File.prototype.save = function () {
|
||||
var self = this;
|
||||
|
||||
console.log('File: Saving file: ', this.fileEntry);
|
||||
|
||||
var a = document.createElement('a');
|
||||
a.download = this.name;
|
||||
|
||||
if (this._isWebKit()) {
|
||||
a.href = this.fileEntry.toURL();
|
||||
finish(a);
|
||||
} else {
|
||||
this.fileEntry.file(function (file) {
|
||||
a.href = window.URL.createObjectURL(file);
|
||||
finish(a);
|
||||
});
|
||||
}
|
||||
|
||||
function finish(a) {
|
||||
document.body.appendChild(a);
|
||||
a.addEventListener('click', function () {
|
||||
// Remove file entry from filesystem.
|
||||
setTimeout(function () {
|
||||
self.remove().then(self._reset);
|
||||
}, 1); // Hack, but otherwise browser doesn't save the file at all.
|
||||
|
||||
a.parentNode.removeChild(a);
|
||||
});
|
||||
a.click();
|
||||
}
|
||||
};
|
||||
|
||||
FileDrop.File.prototype.errorHandler = function (error) {
|
||||
var msg;
|
||||
|
||||
switch (error.code) {
|
||||
case FileError.QUOTA_EXCEEDED_ERR:
|
||||
msg = 'QUOTA_EXCEEDED_ERR';
|
||||
break;
|
||||
case FileError.NOT_FOUND_ERR:
|
||||
msg = 'NOT_FOUND_ERR';
|
||||
break;
|
||||
case FileError.SECURITY_ERR:
|
||||
msg = 'SECURITY_ERR';
|
||||
break;
|
||||
case FileError.INVALID_MODIFICATION_ERR:
|
||||
msg = 'INVALID_MODIFICATION_ERR';
|
||||
break;
|
||||
case FileError.INVALID_STATE_ERR:
|
||||
msg = 'INVALID_STATE_ERR';
|
||||
break;
|
||||
default:
|
||||
msg = 'Unknown Error';
|
||||
break;
|
||||
}
|
||||
|
||||
console.error('File error: ' + msg);
|
||||
};
|
||||
|
||||
FileDrop.File.prototype.remove = function () {
|
||||
var self = this;
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
self.filesystem.root.getFile(self.name, {create: false}, function (fileEntry) {
|
||||
fileEntry.remove(function () {
|
||||
console.debug('File: Removed file: ' + self.name);
|
||||
resolve(fileEntry);
|
||||
}, function (error) {
|
||||
self.errorHandler(error);
|
||||
reject(error);
|
||||
});
|
||||
}, function (error) {
|
||||
self.errorHandler(error);
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
FileDrop.File.prototype._reset = function () {
|
||||
this.create = true;
|
||||
this.filesystem = null;
|
||||
this.fileEntry = null;
|
||||
this.seek = 0;
|
||||
};
|
||||
|
||||
FileDrop.File.prototype._isWebKit = function () {
|
||||
return !!window.webkitRequestFileSystem;
|
||||
};
|
||||
|
||||
@ -1,6 +1,3 @@
|
||||
window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
|
||||
window.URL = window.URL || window.webkitURL;
|
||||
|
||||
// TODO: provide TURN server config
|
||||
// once it's possible to create rooms with custom names.
|
||||
FileDrop.WebRTC = function (options) {
|
||||
@ -35,11 +32,10 @@ FileDrop.WebRTC = function (options) {
|
||||
// Listen for incoming connections
|
||||
this.conn.on('connection', this._onConnection.bind(this));
|
||||
|
||||
this.conn.on('close', function (error) {
|
||||
this.conn.on('close', function () {
|
||||
console.log('Peer:\t Connected to server closed.');
|
||||
});
|
||||
|
||||
|
||||
this.conn.on('error', function (error) {
|
||||
console.log('Peer:\t Error while connecting to server: ', error);
|
||||
});
|
||||
@ -52,7 +48,7 @@ FileDrop.WebRTC = function (options) {
|
||||
};
|
||||
};
|
||||
|
||||
FileDrop.WebRTC.CHUNKS_PER_ACK = 32;
|
||||
FileDrop.WebRTC.CHUNKS_PER_ACK = 64;
|
||||
|
||||
FileDrop.WebRTC.prototype.connect = function (id) {
|
||||
var connection = this.conn.connect(id, {
|
||||
@ -94,32 +90,38 @@ FileDrop.WebRTC.prototype._onConnection = function (connection) {
|
||||
};
|
||||
|
||||
FileDrop.WebRTC.prototype._onBinaryData = function (data, connection) {
|
||||
var incoming = this.files.incoming[connection.peer],
|
||||
var self = this,
|
||||
incoming = this.files.incoming[connection.peer],
|
||||
block = incoming.block,
|
||||
info = incoming.info,
|
||||
receivedChunkNum = incoming.receivedChunkNum,
|
||||
chunksPerAck = FileDrop.WebRTC.CHUNKS_PER_ACK,
|
||||
cache = incoming.cache,
|
||||
receivedChunkNum, nextChunkNum, blob;
|
||||
|
||||
cache.push(data);
|
||||
|
||||
receivedChunkNum = cache.length - 1;
|
||||
nextChunkNum = receivedChunkNum + 1;
|
||||
nextChunkNum, lastChunkInFile, lastChunkInBlock;
|
||||
|
||||
connection.emit('receiving_progress', receivedChunkNum / (info.chunksTotal - 1));
|
||||
console.log('Got chunk no ' + (receivedChunkNum + 1) + ' out of ' + info.chunksTotal);
|
||||
// console.log('Got chunk no ' + (receivedChunkNum + 1) + ' out of ' + info.chunksTotal);
|
||||
|
||||
if (receivedChunkNum === info.chunksTotal - 1) {
|
||||
// If all chunks were transmitted, create a blob
|
||||
blob = new Blob(cache, {type : info.type});
|
||||
block.push(data);
|
||||
|
||||
$.publish('file.p2p.peer', {
|
||||
blob: blob,
|
||||
connection: connection
|
||||
nextChunkNum = incoming.receivedChunkNum = receivedChunkNum + 1;
|
||||
lastChunkInFile = receivedChunkNum === info.chunksTotal - 1;
|
||||
lastChunkInBlock = receivedChunkNum > 0 && ((receivedChunkNum + 1) % chunksPerAck) === 0;
|
||||
|
||||
if (lastChunkInFile || lastChunkInBlock) {
|
||||
this.file.append(block).then(function () {
|
||||
if (lastChunkInFile) {
|
||||
self.file.save();
|
||||
|
||||
$.publish('file.p2p.peer', {
|
||||
blob: self.file,
|
||||
connection: connection
|
||||
});
|
||||
} else {
|
||||
// console.log('Requesting block starting at: ' + (nextChunkNum));
|
||||
incoming.block = [];
|
||||
self._requestFileBlock(connection, nextChunkNum);
|
||||
}
|
||||
});
|
||||
} else if (receivedChunkNum > 0 && (receivedChunkNum + 1) % chunksPerAck === 0) {
|
||||
// If all chunks in a block were transmitted, request a new block
|
||||
console.log('Requesting block starting at: ' + (receivedChunkNum + 1));
|
||||
this._requestFileBlock(connection, receivedChunkNum + 1);
|
||||
}
|
||||
};
|
||||
|
||||
@ -161,7 +163,7 @@ FileDrop.WebRTC.prototype._onJSONData = function (data, connection) {
|
||||
case 'block_request':
|
||||
var file = this.files.outgoing[connection.peer].file;
|
||||
|
||||
console.log('Peer:\t Block request: ', data.payload);
|
||||
// console.log('Peer:\t Block request: ', data.payload);
|
||||
|
||||
this._sendBlock(connection, file, data.payload);
|
||||
break;
|
||||
@ -190,25 +192,31 @@ FileDrop.WebRTC.prototype.sendFileInfo = function (connection, info) {
|
||||
};
|
||||
|
||||
FileDrop.WebRTC.prototype.sendFileResponse = function (connection, response) {
|
||||
var message = {
|
||||
type: 'response',
|
||||
payload: response
|
||||
};
|
||||
var self = this,
|
||||
message = {
|
||||
type: 'response',
|
||||
payload: response
|
||||
};
|
||||
|
||||
// If recipient rejected the file, delete stored file info
|
||||
if (!response) {
|
||||
if (response) {
|
||||
// If recipient accepted the file, request required space to store the file on HTML5 filesystem
|
||||
var incoming = this.files.incoming[connection.peer],
|
||||
info = incoming.info;
|
||||
|
||||
new FileDrop.File({name: info.name, size: info.size, type: info.type})
|
||||
.then(function (file) {
|
||||
self.file = file;
|
||||
|
||||
incoming.block = [];
|
||||
incoming.receivedChunkNum = 0;
|
||||
|
||||
connection.send(JSON.stringify(message));
|
||||
});
|
||||
} else {
|
||||
// Otherwise, delete stored file info
|
||||
delete this.files.incoming[connection.peer];
|
||||
connection.send(JSON.stringify(message));
|
||||
}
|
||||
|
||||
connection.send(JSON.stringify(message));
|
||||
};
|
||||
|
||||
FileDrop.WebRTC.prototype._requestFileBlock = function (connection, chunkNum) {
|
||||
var message = {
|
||||
type: 'block_request',
|
||||
payload: chunkNum
|
||||
};
|
||||
connection.send(JSON.stringify(message));
|
||||
};
|
||||
|
||||
FileDrop.WebRTC.prototype.sendFile = function (connection, file) {
|
||||
@ -222,6 +230,14 @@ FileDrop.WebRTC.prototype.sendFile = function (connection, file) {
|
||||
this._sendBlock(connection, file, 0);
|
||||
};
|
||||
|
||||
FileDrop.WebRTC.prototype._requestFileBlock = function (connection, chunkNum) {
|
||||
var message = {
|
||||
type: 'block_request',
|
||||
payload: chunkNum
|
||||
};
|
||||
connection.send(JSON.stringify(message));
|
||||
};
|
||||
|
||||
// FIXME: Figure out why 64th chunk is sent twice
|
||||
FileDrop.WebRTC.prototype._sendBlock = function (connection, file, beginChunkNum) {
|
||||
var info = this.files.outgoing[connection.peer].info,
|
||||
@ -231,7 +247,7 @@ FileDrop.WebRTC.prototype._sendBlock = function (connection, file, beginChunkNum
|
||||
endChunkNum = beginChunkNum + chunksToSend - 1,
|
||||
chunkNum;
|
||||
|
||||
console.log('Send block: start: ' + beginChunkNum + ' end: ' + endChunkNum);
|
||||
// console.log('Send block: start: ' + beginChunkNum + ' end: ' + endChunkNum);
|
||||
|
||||
for (chunkNum = beginChunkNum; chunkNum < endChunkNum + 1; chunkNum++) {
|
||||
this._sendChunk(connection, file, chunkNum);
|
||||
@ -255,7 +271,7 @@ FileDrop.WebRTC.prototype._sendChunk = function (connection, file, chunkNum) {
|
||||
connection.send(event.target.result);
|
||||
|
||||
connection.emit('sending_progress', chunkNum / (info.chunksTotal - 1));
|
||||
console.log('Sent chunk no ' + (chunkNum + 1) + ' out of ' + info.chunksTotal);
|
||||
// console.log('Sent chunk no ' + (chunkNum + 1) + ' out of ' + info.chunksTotal);
|
||||
}
|
||||
};
|
||||
reader.readAsArrayBuffer(blob);
|
||||
|
||||
6
app/scripts/initializer.js
Normal file
6
app/scripts/initializer.js
Normal file
@ -0,0 +1,6 @@
|
||||
// Clear HTML5 filesystem on page load
|
||||
FileDrop.deferReadiness();
|
||||
FileDrop.File.removeAll().then(function () {
|
||||
console.log("Cleared HTML5 filesystem");
|
||||
FileDrop.advanceReadiness();
|
||||
});
|
||||
16
app/scripts/vendor/filer.min.js
vendored
Normal file
16
app/scripts/vendor/filer.min.js
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
var self=this;self.URL=self.URL||self.webkitURL;self.requestFileSystem=self.requestFileSystem||self.webkitRequestFileSystem;self.resolveLocalFileSystemURL=self.resolveLocalFileSystemURL||self.webkitResolveLocalFileSystemURL;navigator.temporaryStorage=navigator.temporaryStorage||navigator.webkitTemporaryStorage;navigator.persistentStorage=navigator.persistentStorage||navigator.webkitPersistentStorage;self.BlobBuilder=self.BlobBuilder||self.MozBlobBuilder||self.WebKitBlobBuilder;
|
||||
if(void 0===self.FileError){var FileError=function(){};FileError.prototype.prototype=Error.prototype}
|
||||
var Util={toArray:function(a){return Array.prototype.slice.call(a||[],0)},strToDataURL:function(a,b,c){return(void 0!=c?c:1)?"data:"+b+";base64,"+self.btoa(a):"data:"+b+","+a},strToObjectURL:function(a,b){for(var c=new Uint8Array(a.length),e=0;e<c.length;++e)c[e]=a.charCodeAt(e);c=new Blob([c],b?{type:b}:{});return self.URL.createObjectURL(c)},fileToObjectURL:function(a){return self.URL.createObjectURL(a)},fileToArrayBuffer:function(a,b,c){var e=new FileReader;e.onload=function(a){b(a.target.result)};
|
||||
e.onerror=function(a){c&&c(a)};e.readAsArrayBuffer(a)},dataURLToBlob:function(a){if(-1==a.indexOf(";base64,")){var b=a.split(","),a=b[0].split(":")[1],b=b[1];return new Blob([b],{type:a})}for(var b=a.split(";base64,"),a=b[0].split(":")[1],b=window.atob(b[1]),c=b.length,e=new Uint8Array(c),i=0;i<c;++i)e[i]=b.charCodeAt(i);return new Blob([e],{type:a})},arrayBufferToBlob:function(a,b){var c=new Uint8Array(a);return new Blob([c],b?{type:b}:{})},arrayBufferToBinaryString:function(a,b,c){var e=new FileReader;
|
||||
e.onload=function(a){b(a.target.result)};e.onerror=function(a){c&&c(a)};a=new Uint8Array(a);e.readAsBinaryString(new Blob([a]))},arrayToBinaryString:function(a){if("object"!=typeof a)return null;for(var b=a.length,c=Array(b);b--;)c[b]=String.fromCharCode(a[b]);return c.join("")},getFileExtension:function(a){var b=a.lastIndexOf(".");return-1!=b?a.substring(b):""}},MyFileError=function(a){this.prototype=FileError.prototype;this.code=a.code;this.name=a.name};FileError.BROWSER_NOT_SUPPORTED=1E3;
|
||||
FileError.prototype.__defineGetter__("name",function(){for(var a=Object.keys(FileError),b=0,c;c=a[b];++b)if(FileError[c]==this.code)return c;return"Unknown Error"});
|
||||
var Filer=new function(){function a(d){if(b=d||null)c=b.root,e=!0}var b=null,c=null,e=!1,i=function(d){return 0==d.indexOf("filesystem:")},k=function(d){i(d)||(d="/"==d[0]?b.root.toURL()+d.substring(1):0==d.indexOf("./")||0==d.indexOf("../")?"../"==d&&c!=b.root?c.toURL()+"/"+d:c.toURL()+d:c.toURL()+"/"+d);return d},j=function(d,a){var b=arguments[1],f=arguments[2],c=function(d){if(d.code==FileError.NOT_FOUND_ERR){if(f)throw Error('"'+b+'" or "'+f+'" does not exist.');throw Error('"'+b+'" does not exist.');
|
||||
}throw Error("Problem getting Entry for one or more paths.");},l=k(b);if(3==arguments.length){var e=k(f);self.resolveLocalFileSystemURL(l,function(a){self.resolveLocalFileSystemURL(e,function(b){d(a,b)},c)},c)}else self.resolveLocalFileSystemURL(l,d,c)},o=function(d,a,c,f,h,l){if(!b)throw Error("Filesystem has not been initialized.");if(typeof d!=typeof a)throw Error("These method arguments are not supported.");var e=c||null,m=void 0!=l?l:!1;(d.isFile||a.isDirectory)&&a.isDirectory?m?d.moveTo(a,e,
|
||||
f,h):d.copyTo(a,e,f,h):j(function(d,a){if(a.isDirectory)m?d.moveTo(a,e,f,h):d.copyTo(a,e,f,h);else{var b=Error('Oops! "'+a.name+" is not a directory!");if(h)h(b);else throw b;}},d,a)};a.DEFAULT_FS_SIZE=1048576;a.version="0.4.3";a.prototype={get fs(){return b},get isOpen(){return e},get cwd(){return c}};a.prototype.pathToFilesystemURL=function(d){return k(d)};a.prototype.init=function(d,a,g){if(!self.requestFileSystem)throw new MyFileError({code:FileError.BROWSER_NOT_SUPPORTED,name:"BROWSER_NOT_SUPPORTED"});
|
||||
var d=d?d:{},f=d.size||1048576;this.type=self.TEMPORARY;if("persistent"in d&&d.persistent)this.type=self.PERSISTENT;var h=function(d){this.size=f;b=d;c=b.root;e=!0;a&&a(d)};this.type==self.PERSISTENT&&navigator.persistentStorage?navigator.persistentStorage.requestQuota(f,function(d){self.requestFileSystem(this.type,d,h.bind(this),g)}.bind(this),g):self.requestFileSystem(this.type,f,h.bind(this),g)};a.prototype.ls=function(d,a,g){if(!b)throw Error("Filesystem has not been initialized.");var f=function(d){c=
|
||||
d;var b=[],f=c.createReader(),e=function(){f.readEntries(function(d){d.length?(b=b.concat(Util.toArray(d)),e()):(b.sort(function(d,a){return d.name<a.name?-1:a.name<d.name?1:0}),a(b))},g)};e()};d.isDirectory?f(d):i(d)?j(f,d):c.getDirectory(d,{},f,g)};a.prototype.mkdir=function(d,a,g,f){if(!b)throw Error("Filesystem has not been initialized.");var h=null!=a?a:!1,e=d.split("/"),n=function(a,b){if("."==b[0]||""==b[0])b=b.slice(1);a.getDirectory(b[0],{create:!0,exclusive:h},function(a){if(a.isDirectory)b.length&&
|
||||
1!=e.length?n(a,b.slice(1)):g&&g(a);else if(a=Error(d+" is not a directory"),f)f(a);else throw a;},function(a){if(a.code==FileError.INVALID_MODIFICATION_ERR)if(a.message="'"+d+"' already exists",f)f(a);else throw a;})};n(c,e)};a.prototype.open=function(a,c,e){if(!b)throw Error("Filesystem has not been initialized.");a.isFile?a.file(c,e):j(function(a){a.file(c,e)},k(a))};a.prototype.create=function(a,e,g,f){if(!b)throw Error("Filesystem has not been initialized.");c.getFile(a,{create:!0,exclusive:null!=
|
||||
e?e:!0},g,function(b){if(b.code==FileError.INVALID_MODIFICATION_ERR)b.message="'"+a+"' already exists";if(f)f(b);else throw b;})};a.prototype.mv=function(a,b,c,f,e){o.bind(this,a,b,c,f,e,!0)()};a.prototype.rm=function(a,c,e){if(!b)throw Error("Filesystem has not been initialized.");var f=function(a){a.isFile?a.remove(c,e):a.isDirectory&&a.removeRecursively(c,e)};a.isFile||a.isDirectory?f(a):j(f,a)};a.prototype.cd=function(a,e,g){if(!b)throw Error("Filesystem has not been initialized.");a.isDirectory?
|
||||
(c=a,e&&e(c)):(a=k(a),j(function(a){if(a.isDirectory)c=a,e&&e(c);else if(a=Error("Path was not a directory."),g)g(a);else throw a;},a))};a.prototype.cp=function(a,b,c,e,h){o.bind(this,a,b,c,e,h)()};a.prototype.write=function(a,e,g,f){if(!b)throw Error("Filesystem has not been initialized.");var h=function(a){a.createWriter(function(b){b.onerror=f;if(e.append)b.onwriteend=function(){g&&g(a,this)},b.seek(b.length);else{var d=!1;b.onwriteend=function(){d?g&&g(a,this):(d=!0,this.truncate(this.position))}}if(e.data.__proto__==
|
||||
ArrayBuffer.prototype)e.data=new Uint8Array(e.data);var c=new Blob([e.data],e.type?{type:e.type}:{});b.write(c)},f)};a.isFile?h(a):i(a)?j(h,a):c.getFile(a,{create:!0,exclusive:!1},h,f)};a.prototype.df=function(a,b){var c=function(b,c){a(b,c-b,c)};if(!navigator.temporaryStorage.queryUsageAndQuota||!navigator.persistentStorage.queryUsageAndQuota)throw Error("Not implemented.");self.TEMPORARY==this.type?navigator.temporaryStorage.queryUsageAndQuota(c,b):self.PERSISTENT==this.type&&navigator.persistentStorage.queryUsageAndQuota(c,
|
||||
b)};return a};
|
||||
16
app/scripts/vendor/idb.filesystem.min.js
vendored
Normal file
16
app/scripts/vendor/idb.filesystem.min.js
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
(function(f){function m(a){var c=a.code,b=a.name;Object.defineProperty(this,"code",{set:function(a){c=a},get:function(){return c}});Object.defineProperty(this,"name",{set:function(a){b=a},get:function(){return b}})}function q(a,c){var b=c;c[0]!=g&&(b=a,b=a!=g?b+(g+c):b+c);for(var b=b.split(g),d=0;d<b.length;++d)".."==b[d]&&(b[d-1]="",b[d]="");b=b.filter(function(a){return a}).join(g);b[0]!=g&&(b=g+b);b=b.replace(/\.\//g,g);b=b.replace(/\/\//g,g);b=b.replace(/\/\./g,g);b[b.length-1]==g&&b!=g&&(b=b.substring(0,
|
||||
b.length-1));return b}function r(a){var c=null;this.size=a.size||0;this.name=a.name||"";this.type=a.type||"";this.lastModifiedDate=a.lastModifiedDate||null;Object.defineProperty(this,"blob_",{enumerable:!0,get:function(){return c},set:function(a){c=a;this.size=c.size;this.name=c.name;this.type=c.type;this.lastModifiedDate=c.lastModifiedDate}.bind(this)})}function x(a){if(!a)throw Error("Expected fileEntry argument to write.");var c=0,b=a.file_?a.file_.blob_:null;Object.defineProperty(this,"position",
|
||||
{get:function(){return c}});Object.defineProperty(this,"length",{get:function(){return b?b.size:0}});this.seek=function(a){c=a;if(c>this.length)c=this.length;0>c&&(c+=this.length);0>c&&(c=0)};this.truncate=function(a){b=b?a<this.length?b.slice(0,a):new Blob([b,new Uint8Array(a-this.length)],{type:b.type}):new Blob([]);c=0;this.write(b)};this.write=function(d){if(!d)throw Error("Expected blob argument to write.");if(this.onwritestart)this.onwritestart();if(b){var e=b.slice(0,c),g=b.slice(c+d.size),
|
||||
f=c-e.size;0>f&&(f=0);b=new Blob([e,new Uint8Array(f),d,g],{type:b.type})}else b=new Blob([d],{type:d.type});a.file_.blob_=b;a.file_.lastModifiedDate=d.lastModifiedDate||null;h.put(a,function(){c+=d.size;if(this.onwriteend)this.onwriteend()}.bind(this),this.onerror)}}function y(a){var c=!1;this.readEntries=function(b,d){if(!b)throw Error("Expected successCallback argument.");c?b([]):h.getAllEntries(a.fullPath,function(a){c=!0;b(a)},d)}}function s(a,c){this.modificationTime_=a||null;this.size_=c||
|
||||
0}function o(){}function j(a){this.file_=null;Object.defineProperty(this,"isFile",{enumerable:!0,get:function(){return!0}});Object.defineProperty(this,"isDirectory",{enumerable:!0,get:function(){return!1}});if(a)this.file_=a.file_,this.name=a.name,this.fullPath=a.fullPath,this.filesystem=a.filesystem}function i(a){Object.defineProperty(this,"isFile",{enumerable:!0,get:function(){return!1}});Object.defineProperty(this,"isDirectory",{enumerable:!0,get:function(){return!0}});if(a)this.name=a.name,this.fullPath=
|
||||
a.fullPath,this.filesystem=a.filesystem}function z(a){t=a==f.TEMPORARY?"Temporary":"Persistent";this.name=(location.protocol+location.host).replace(/:/g,"_")+":"+t;this.root=new i;this.root.fullPath=g;this.root.filesystem=this;this.root.name=""}function k(a){switch(a.target.errorCode){case 12:console.log("Error - Attempt to open db with a lower version than the current one.");break;default:console.log("errorCode: "+a.target.errorCode)}console.log(a,a.code,a.message)}if(!f.requestFileSystem&&!f.webkitRequestFileSystem){var u=
|
||||
f.indexedDB||f.mozIndexedDB||f.msIndexedDB;if(u){f.TEMPORARY=0;f.PERSISTENT=1;if(void 0===f.FileError)window.FileError=function(){},FileError.prototype.prototype=Error.prototype;FileError.INVALID_MODIFICATION_ERR=9;FileError.NOT_FOUND_ERR=1;m.prototype=FileError.prototype;m.prototype.toString=Error.prototype.toString;var l=new m({code:FileError.INVALID_MODIFICATION_ERR,name:"INVALID_MODIFICATION_ERR"}),p=new m({code:1E3,name:"Not implemented"}),w=new m({code:FileError.NOT_FOUND_ERR,name:"Not found"}),
|
||||
n=null,t="temporary",h={db:null},g="/",v=String.fromCharCode(g.charCodeAt(0)+1);r.prototype.constructor=r;s.prototype={get modificationTime(){return this.modificationTime_},get size(){return this.size_}};o.prototype={name:null,fullPath:null,filesystem:null,copyTo:function(){throw p;},getMetadata:function(a,c){if(!a)throw Error("Expected successCallback argument.");try{this.isFile?a(new s(this.file_.lastModifiedDate,this.file_.size)):c(new m({code:1001,name:"getMetadata() not implemented for DirectoryEntry"}))}catch(b){c&&
|
||||
c(b)}},getParent:function(){throw p;},moveTo:function(){throw p;},remove:function(a,c){if(!a)throw Error("Expected successCallback argument.");h["delete"](this.fullPath,function(){a()},c)},toURL:function(){return"filesystem:"+(location.protocol+"//"+location.host)+g+t.toLowerCase()+this.fullPath}};j.prototype=new o;j.prototype.constructor=j;j.prototype.createWriter=function(a){a(new x(this))};j.prototype.file=function(a,c){if(!a)throw Error("Expected successCallback argument.");if(null==this.file_)if(c)c(w);
|
||||
else throw w;else{var b=null==this.file_.blob_?this.file_:this.file_.blob_;b.lastModifiedDate=this.file_.lastModifiedDate;a(b)}};i.prototype=new o;i.prototype.constructor=i;i.prototype.createReader=function(){return new y(this)};i.prototype.getDirectory=function(a,c,b,d){a=q(this.fullPath,a);h.get(a,function(e){c||(c={});!0===c.create&&!0===c.exclusive&&e?d&&d(l):!0===c.create&&!e?(e=new i,e.name=a.split(g).pop(),e.fullPath=a,e.filesystem=n,h.put(e,b,d)):!0===c.create&&e?e.isDirectory?b(new i(e)):
|
||||
d&&d(l):(!c.create||!1===c.create)&&!e?a==g?(e=new i,e.name="",e.fullPath=g,e.filesystem=n,b(e)):d&&d(l):(!c.create||!1===c.create)&&e&&e.isFile?d&&d(l):b(new i(e))},d)};i.prototype.getFile=function(a,c,b,d){a=q(this.fullPath,a);h.get(a,function(e){c||(c={});!0===c.create&&!0===c.exclusive&&e?d&&d(l):!0===c.create&&!e?(e=new j,e.name=a.split(g).pop(),e.fullPath=a,e.filesystem=n,e.file_=new r({size:0,name:e.name,lastModifiedDate:new Date}),h.put(e,b,d)):!0===c.create&&e?e.isFile?b(new j(e)):d&&d(l):
|
||||
(!c.create||!1===c.create)&&!e?d&&d(l):(!c.create||!1===c.create)&&e&&e.isDirectory?d&&d(l):b(new j(e))},d)};i.prototype.removeRecursively=function(a,c){if(!a)throw Error("Expected successCallback argument.");this.remove(a,c)};h.open=function(a,c,b){var d=this,a=u.open(a.replace(":","_"));a.onerror=b||k;a.onupgradeneeded=function(a){d.db=a.target.result;d.db.onerror=k;d.db.objectStoreNames.contains("entries")||d.db.createObjectStore("entries")};a.onsuccess=function(a){d.db=a.target.result;d.db.onerror=
|
||||
k;c(a)};a.onblocked=b||k};h.close=function(){this.db.close();this.db=null};h.drop=function(a,c){if(this.db){var b=u.deleteDatabase(this.db.name);b.onsuccess=function(b){a(b)};b.onerror=c||k;h.close()}};h.get=function(a,c,b){if(this.db){var d=this.db.transaction(["entries"],"readonly"),a=IDBKeyRange.bound(a,a+v,!1,!0),e=d.objectStore("entries").get(a);d.onabort=b||k;d.oncomplete=function(){c(e.result)}}};h.getAllEntries=function(a,c,b){if(this.db){var d=[],e=null;a!=g&&(e=IDBKeyRange.bound(a+g,a+v,
|
||||
!1,!0));var f=this.db.transaction(["entries"],"readonly");f.onabort=b||k;f.oncomplete=function(){d=d.filter(function(b){var c=b.fullPath.split(g).length,d=a.split(g).length;if(a==g&&c<d+1||a!=g&&c==d+1)return b});c(d)};f.objectStore("entries").openCursor(e).onsuccess=function(a){if(a=a.target.result){var b=a.value;d.push(b.isFile?new j(b):new i(b));a["continue"]()}}}};h["delete"]=function(a,c,b){if(this.db){var d=this.db.transaction(["entries"],"readwrite");d.oncomplete=c;d.onabort=b||k;a=IDBKeyRange.bound(a,
|
||||
a+v,!1,!0);d.objectStore("entries")["delete"](a)}};h.put=function(a,c,b){if(this.db){var d=this.db.transaction(["entries"],"readwrite");d.onabort=b||k;d.oncomplete=function(){c(a)};d.objectStore("entries").put(a,a.fullPath)}};f.addEventListener("beforeunload",function(){h.db.close()},!1);f.requestFileSystem=function(a,c,b,d){a!=f.TEMPORARY&&a!=f.PERSISTENT&&d?d(l):(n=new z(a,c),h.open(n.name,function(){b(n)},d))};f.resolveLocalFileSystemURL=function(a,c,b){b&&b(p)};if(f===window&&f.RUNNING_TESTS)f.Entry=
|
||||
o,f.FileEntry=j,f.DirectoryEntry=i,f.resolveToFullPath_=q,f.Metadata=s}}})(self);
|
||||
Loading…
Reference in New Issue
Block a user