2016-01-16 11:29:08 -07:00
|
|
|
define(['cryptojs-md5'], function () {
|
|
|
|
|
2016-03-04 20:39:49 -07:00
|
|
|
function loadImage(elem, url) {
|
2016-01-16 11:29:08 -07:00
|
|
|
|
|
|
|
if (elem.tagName !== "IMG") {
|
|
|
|
|
2016-04-23 20:04:04 -07:00
|
|
|
elem.style.backgroundImage = "url('" + url + "')";
|
|
|
|
return Promise.resolve(elem);
|
2016-01-16 11:29:08 -07:00
|
|
|
|
|
|
|
} else {
|
|
|
|
elem.setAttribute("src", url);
|
2016-03-04 20:39:49 -07:00
|
|
|
return Promise.resolve(elem);
|
2016-01-16 11:29:08 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Request Quota (only for File System API)
|
|
|
|
var requestedBytes = 1024 * 1024 * 1500;
|
|
|
|
var imageCacheDirectoryEntry;
|
|
|
|
var imageCacheFolder = 'images';
|
|
|
|
|
|
|
|
function createDir(rootDirEntry, folders, callback, errorCallback) {
|
|
|
|
// Throw out './' or '/' and move on to prevent something like '/foo/.//bar'.
|
|
|
|
if (folders[0] == '.' || folders[0] == '') {
|
|
|
|
folders = folders.slice(1);
|
|
|
|
}
|
|
|
|
rootDirEntry.getDirectory(folders[0], { create: true }, function (dirEntry) {
|
|
|
|
// Recursively add the new subfolder (if we still have another to create).
|
|
|
|
if (folders.length > 1) {
|
|
|
|
createDir(dirEntry, folders.slice(1), callback, errorCallback);
|
|
|
|
} else {
|
|
|
|
callback(dirEntry);
|
|
|
|
}
|
|
|
|
}, errorCallback);
|
|
|
|
}
|
|
|
|
|
|
|
|
navigator.webkitPersistentStorage.requestQuota(
|
|
|
|
requestedBytes, function (grantedBytes) {
|
|
|
|
|
|
|
|
var requestMethod = window.webkitRequestFileSystem || window.requestFileSystem;
|
|
|
|
|
|
|
|
requestMethod(PERSISTENT, grantedBytes, function (fs) {
|
|
|
|
|
|
|
|
fileSystem = fs;
|
|
|
|
|
|
|
|
createDir(fileSystem.root, imageCacheFolder.split('/'), function (dirEntry) {
|
|
|
|
|
|
|
|
imageCacheDirectoryEntry = dirEntry;
|
|
|
|
|
2016-04-03 12:16:39 -07:00
|
|
|
// TODO: find a better time to schedule this
|
|
|
|
setTimeout(cleanCache, 60000);
|
2016-01-16 11:29:08 -07:00
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
2016-04-03 12:16:39 -07:00
|
|
|
function toArray(list) {
|
|
|
|
return Array.prototype.slice.call(list || [], 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
function cleanCache() {
|
|
|
|
|
|
|
|
var dirReader = imageCacheDirectoryEntry.createReader();
|
|
|
|
var entries = [];
|
|
|
|
|
|
|
|
var onReadFail = function () {
|
|
|
|
console.log('dirReader.readEntries failed');
|
|
|
|
};
|
|
|
|
|
|
|
|
// Keep calling readEntries() until no more results are returned.
|
|
|
|
var readEntries = function () {
|
|
|
|
dirReader.readEntries(function (results) {
|
|
|
|
if (!results.length) {
|
|
|
|
entries.forEach(cleanFile);
|
|
|
|
} else {
|
|
|
|
entries = entries.concat(toArray(results));
|
|
|
|
readEntries();
|
|
|
|
}
|
|
|
|
}, onReadFail);
|
|
|
|
};
|
|
|
|
|
|
|
|
// Start reading the directory.
|
|
|
|
readEntries();
|
|
|
|
}
|
|
|
|
|
|
|
|
function cleanFile(fileEntry) {
|
|
|
|
if (!fileEntry.isFile) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
fileEntry.file(function (file) {
|
2016-04-04 12:55:39 -07:00
|
|
|
|
2016-04-04 22:49:30 -07:00
|
|
|
getLastModified(file, fileEntry).then(function (lastModifiedDate) {
|
2016-04-04 12:55:39 -07:00
|
|
|
|
2016-04-04 22:49:30 -07:00
|
|
|
var elapsed = new Date().getTime() - lastModifiedDate;
|
|
|
|
// 40 days
|
|
|
|
var maxElapsed = 3456000000;
|
|
|
|
if (elapsed >= maxElapsed) {
|
2016-04-03 12:16:39 -07:00
|
|
|
|
2016-04-04 22:49:30 -07:00
|
|
|
var fullPath = fileEntry.fullPath;
|
|
|
|
console.log('deleting file: ' + fullPath);
|
2016-04-03 12:16:39 -07:00
|
|
|
|
2016-04-04 22:49:30 -07:00
|
|
|
fileEntry.remove(function () {
|
|
|
|
console.log('File deleted: ' + fullPath);
|
|
|
|
}, function () {
|
|
|
|
console.log('Failed to delete file: ' + fullPath);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function getLastModified(file, fileEntry) {
|
|
|
|
|
|
|
|
var lastModifiedDate = file.lastModified || file.lastModifiedDate || file.modificationTime;
|
|
|
|
if (lastModifiedDate) {
|
|
|
|
if (lastModifiedDate.getTime) {
|
|
|
|
lastModifiedDate = lastModifiedDate.getTime();
|
2016-04-03 12:16:39 -07:00
|
|
|
}
|
2016-04-04 22:49:30 -07:00
|
|
|
return Promise.resolve(lastModifiedDate);
|
|
|
|
}
|
|
|
|
|
|
|
|
return new Promise(function (resolve, reject) {
|
|
|
|
|
|
|
|
fileEntry.getMetadata(function (metadata) {
|
|
|
|
var lastModifiedDate = metadata.lastModified || metadata.lastModifiedDate || metadata.modificationTime;
|
|
|
|
if (lastModifiedDate) {
|
|
|
|
if (lastModifiedDate.getTime) {
|
|
|
|
lastModifiedDate = lastModifiedDate.getTime();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
resolve(lastModifiedDate);
|
|
|
|
});
|
2016-04-03 12:16:39 -07:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2016-01-16 11:29:08 -07:00
|
|
|
function getCacheKey(url) {
|
|
|
|
|
|
|
|
// Try to strip off the domain to share the cache between local and remote connections
|
|
|
|
var index = url.indexOf('://');
|
|
|
|
|
|
|
|
if (index != -1) {
|
|
|
|
url = url.substring(index + 3);
|
|
|
|
|
|
|
|
index = url.indexOf('/');
|
|
|
|
|
|
|
|
if (index != -1) {
|
|
|
|
url = url.substring(index + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return CryptoJS.MD5(url).toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
function downloadToFile(url, dir, filename, callback, errorCallback) {
|
|
|
|
|
|
|
|
console.log('Downloading ' + url);
|
|
|
|
|
|
|
|
var xhr = new XMLHttpRequest();
|
|
|
|
xhr.open('GET', url, true);
|
|
|
|
xhr.responseType = "arraybuffer";
|
|
|
|
|
|
|
|
xhr.onload = function (e) {
|
|
|
|
if (this.status == 200) {
|
|
|
|
writeData(dir, filename, this.getResponseHeader('Content-Type'), this.response, callback, errorCallback);
|
|
|
|
} else {
|
|
|
|
errorCallback();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
xhr.send();
|
|
|
|
}
|
|
|
|
|
|
|
|
function writeData(dir, filename, fileType, data, callback, errorCallback) {
|
|
|
|
|
|
|
|
dir.getFile(filename, { create: true }, function (fileEntry) {
|
|
|
|
|
|
|
|
// Create a FileWriter object for our FileEntry (log.txt).
|
|
|
|
fileEntry.createWriter(function (fileWriter) {
|
|
|
|
|
|
|
|
fileWriter.onwriteend = function (e) {
|
|
|
|
callback(fileEntry);
|
|
|
|
};
|
|
|
|
|
|
|
|
fileWriter.onerror = errorCallback;
|
|
|
|
|
|
|
|
// Create a new Blob and write it to log.txt.
|
|
|
|
var blob = new Blob([data], { type: fileType });
|
|
|
|
|
|
|
|
fileWriter.write(blob);
|
|
|
|
|
|
|
|
}, errorCallback);
|
|
|
|
|
|
|
|
}, errorCallback);
|
|
|
|
}
|
|
|
|
|
|
|
|
function getImageUrl(originalUrl) {
|
|
|
|
|
|
|
|
return new Promise(function (resolve, reject) {
|
|
|
|
|
|
|
|
if (originalUrl.indexOf('tag=') != -1) {
|
|
|
|
originalUrl += "&accept=webp";
|
|
|
|
}
|
|
|
|
|
|
|
|
var key = getCacheKey(originalUrl);
|
|
|
|
|
|
|
|
var fileEntryCallback = function (fileEntry) {
|
|
|
|
resolve(fileEntry.toURL());
|
|
|
|
};
|
|
|
|
|
|
|
|
var errorCallback = function (e) {
|
|
|
|
console.log('Imagestore error: ' + e.name);
|
|
|
|
reject();
|
|
|
|
};
|
|
|
|
|
|
|
|
if (!fileSystem || !imageCacheDirectoryEntry) {
|
|
|
|
errorCallback('');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
var path = '/' + imageCacheFolder + "/" + key;
|
|
|
|
|
|
|
|
fileSystem.root.getFile(path, { create: false }, fileEntryCallback, function () {
|
|
|
|
|
|
|
|
downloadToFile(originalUrl, imageCacheDirectoryEntry, key, fileEntryCallback, errorCallback);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
var fileSystem;
|
|
|
|
|
|
|
|
return {
|
|
|
|
loadImage: function (elem, url) {
|
|
|
|
|
|
|
|
return getImageUrl(url).then(function (localUrl) {
|
|
|
|
|
2016-03-04 20:39:49 -07:00
|
|
|
return loadImage(elem, localUrl);
|
2016-01-16 11:29:08 -07:00
|
|
|
|
|
|
|
}, function () {
|
2016-03-04 20:39:49 -07:00
|
|
|
return loadImage(elem, url);
|
2016-01-16 11:29:08 -07:00
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
});
|