316 lines
7.9 KiB
JavaScript
316 lines
7.9 KiB
JavaScript
/*global define*/
|
||
define(
|
||
[ 'config', 'util/browser', 'util/addpublishers', 'lib/md5', 'lib/localforage.nopromises', 'models/localisationmodel' ],
|
||
function ( config, browser, addPublishers, md5, localforage, LocalisationModel ) {
|
||
// the StorageModel takes care of loading and saving data to localStorage.
|
||
// It stores the used glitch values as well as the imgur address if the
|
||
// image was shared.
|
||
// It generares a UID for each image to avoid having to save the
|
||
// same image multiple times.
|
||
// If an image was updated (shared/deleted), it updates the corresponding
|
||
// object in localstorage
|
||
function StorageModel () {
|
||
if ( ! ( this instanceof StorageModel ) ) {
|
||
return new StorageModel();
|
||
}
|
||
|
||
var self = this;
|
||
var isFirstVisit = false;
|
||
var visitCount = 0;
|
||
var entries = { };
|
||
var useLocalForage = browser.test( 'localforage' ) && localforage;
|
||
var worker;
|
||
|
||
var publisherNames = [
|
||
'update', 'save', 'loaditem',
|
||
'removeall', 'removelocaldata', 'removeimgurdata',
|
||
'visits', 'firstvisit', 'error', 'statusmessage'
|
||
];
|
||
|
||
var publishers = addPublishers( self, publisherNames );
|
||
|
||
var storageKey = config.keys.storage;
|
||
|
||
if (
|
||
useLocalForage &&
|
||
browser.test( 'webworker' ) &&
|
||
browser.test( 'browserdb' ) &&
|
||
! browser.test( 'safari' )
|
||
) {
|
||
worker = new Worker( config.workers.storage );
|
||
worker.addEventListener( 'message', workerResponded, false );
|
||
sendMessageToWorker( 'setStorageKey', storageKey );
|
||
}
|
||
|
||
function add ( item ) {
|
||
if ( useLocalForage && item ) {
|
||
if ( worker ) {
|
||
sendMessageToWorker( 'add', item );
|
||
} else {
|
||
var uid = createUID( item );
|
||
|
||
if (
|
||
entries[uid] &&
|
||
entries[uid].deleteHash === item.deleteHash &&
|
||
entries[uid].publicUrl === item.publicUrl &&
|
||
entries[uid].imgurID === item.imgurID
|
||
) {
|
||
publishers.statusmessage.dispatch( 'file.message.before' );
|
||
} else {
|
||
item.timestamp = Date.now();
|
||
entries[uid] = item;
|
||
|
||
save( function () {
|
||
publishers.statusmessage.dispatch( 'file.message.save' );
|
||
} );
|
||
}
|
||
}
|
||
}
|
||
|
||
return self;
|
||
}
|
||
|
||
function removeCompletely ( uid ) {
|
||
if ( useLocalForage && uid ) {
|
||
if ( worker ) {
|
||
sendMessageToWorker( 'removeCompletely', uid );
|
||
} else {
|
||
if (
|
||
entries[uid] &&
|
||
(
|
||
entries[uid].deleteHash ||
|
||
entries[uid].publicUrl ||
|
||
entries[uid].imgurID ||
|
||
entries[uid].values ||
|
||
entries[uid].src
|
||
)
|
||
) {
|
||
console && console.log( 'cant delete storage item because theres still some data left', entries[uid] );
|
||
} else {
|
||
publishers.removeall.dispatch( entries[uid] );
|
||
delete entries[uid];
|
||
|
||
save( function () {
|
||
publishers.statusmessage.dispatch( 'file.message.del' );
|
||
} );
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
function removeLocalData ( uid ) {
|
||
if ( useLocalForage && uid ) {
|
||
if ( worker ) {
|
||
sendMessageToWorker( 'removeLocalData', uid );
|
||
} else {
|
||
if ( entries[uid] ) {
|
||
if ( entries[uid].src ) {
|
||
delete entries[uid].src;
|
||
|
||
publishers.removelocaldata.dispatch( entries[uid] );
|
||
}
|
||
|
||
if ( entries[uid].values ) {
|
||
delete entries[uid].values;
|
||
}
|
||
|
||
if ( ! ( entries[uid].deleteHash || entries[uid].publicUrl || entries[uid].imgurID ) ) {
|
||
removeCompletely( uid );
|
||
}
|
||
|
||
save();
|
||
}
|
||
}
|
||
}
|
||
|
||
return self;
|
||
}
|
||
|
||
function removeImgurData ( uid ) {
|
||
if ( useLocalForage && uid ) {
|
||
if ( worker ) {
|
||
sendMessageToWorker( 'removeImgurData', uid );
|
||
} else {
|
||
if ( entries[uid] ) {
|
||
if ( entries[uid].deleteHash ) {
|
||
publishers.removeimgurdata.dispatch( entries[uid] );
|
||
delete entries[uid].deleteHash;
|
||
}
|
||
|
||
if ( entries[uid].publicUrl ) {
|
||
delete entries[uid].publicUrl;
|
||
}
|
||
|
||
if ( entries[uid].imgurID ) {
|
||
delete entries[uid].imgurID;
|
||
}
|
||
|
||
if ( ! ( entries[uid].src || entries[uid].values ) ) {
|
||
removeCompletely( uid );
|
||
}
|
||
|
||
save();
|
||
}
|
||
}
|
||
}
|
||
|
||
return self;
|
||
}
|
||
|
||
function load ( callback ) {
|
||
if ( useLocalForage ) {
|
||
if ( worker ) {
|
||
sendMessageToWorker( 'load' );
|
||
} else {
|
||
localforage.getItem( storageKey, function ( err, loadedData ) {
|
||
if ( err ) {
|
||
publishers.error.dispatch( 'file.error.load' );
|
||
console && console.log( 'localforage error', err );
|
||
} else {
|
||
entries = loadedData && loadedData.entries ? loadedData.entries : { };
|
||
publishers.update.dispatch( entries );
|
||
|
||
visitCount = ( loadedData && loadedData.visitCount ) ? loadedData.visitCount : 1;
|
||
isFirstVisit = ( loadedData && loadedData.lastVisit ) ? false : true;
|
||
|
||
if ( isFirstVisit ) {
|
||
publishers.firstvisit.dispatch();
|
||
}
|
||
|
||
save();
|
||
|
||
if ( visitCount ) {
|
||
publishers.visits.dispatch( visitCount );
|
||
}
|
||
|
||
if ( typeof callback === 'function' ) {
|
||
callback();
|
||
}
|
||
}
|
||
} );
|
||
}
|
||
}
|
||
|
||
return self;
|
||
}
|
||
|
||
function save ( callback ) {
|
||
if ( useLocalForage ) {
|
||
if ( worker ) {
|
||
sendMessageToWorker( 'save' );
|
||
} else {
|
||
localforage.setItem( storageKey, {
|
||
entries: entries,
|
||
lastVisit: Date.now(),
|
||
visitCount: visitCount + 1
|
||
}, function ( err, savedData ) {
|
||
if ( err ) {
|
||
publishers.error.dispatch( 'file.error.save' );
|
||
console && console.log( 'localforage error', err );
|
||
} else {
|
||
if ( savedData ) {
|
||
entries = savedData.entries;
|
||
publishers.update.dispatch( entries );
|
||
publishers.save.dispatch();
|
||
|
||
if ( typeof callback === 'function' ) {
|
||
callback();
|
||
}
|
||
} else {
|
||
console && console.log( 'no data was saved', savedData );
|
||
}
|
||
}
|
||
} );
|
||
}
|
||
}
|
||
|
||
return self;
|
||
}
|
||
|
||
function loadItem ( uid ) {
|
||
if ( useLocalForage ) {
|
||
if ( worker ) {
|
||
sendMessageToWorker( 'loadItem', uid );
|
||
} else {
|
||
if ( entries[uid] ) {
|
||
publishers.loaditem.dispatch( uid, entries[uid] );
|
||
}
|
||
}
|
||
}
|
||
|
||
return self;
|
||
}
|
||
|
||
function workerResponded ( event ) {
|
||
if ( event && event.data ) {
|
||
publisherNames.forEach( function ( type ) {
|
||
if ( typeof event.data[type] !== 'undefined' ) {
|
||
if ( type === 'loaditem' ) {
|
||
publishers[type].dispatch( event.data[type].uid, event.data[type].entries );
|
||
} else {
|
||
if ( publishers[type] === type ) {
|
||
// if message is empty, the worker sends the type as data.
|
||
publishers[type].dispatch()
|
||
} else {
|
||
publishers[type].dispatch( event.data[type] )
|
||
}
|
||
}
|
||
}
|
||
} );
|
||
}
|
||
}
|
||
|
||
function sendMessageToWorker ( type, data ) {
|
||
if ( typeof type === 'string' ) {
|
||
if ( typeof data === 'undefined' ) {
|
||
data = type;
|
||
}
|
||
|
||
var message = { };
|
||
message[type] = data;
|
||
worker.postMessage( message );
|
||
}
|
||
}
|
||
|
||
function createUID ( item ) {
|
||
var inputStr = 'N' + item.name + 'S' + item.src + 'L' + item.thumbnail.length || 0 + 'V';
|
||
|
||
for ( var key in item.values ) {
|
||
inputStr += key.substr( 0, 2 );
|
||
inputStr += item.values[key];
|
||
}
|
||
|
||
return md5( inputStr );
|
||
}
|
||
|
||
function getLatestUID () {
|
||
var latestUid;
|
||
var latestTimestamp;
|
||
var timestamp;
|
||
|
||
for ( var uid in entries ) {
|
||
timestamp = entries[uid].timestamp;
|
||
|
||
if ( timestamp ) {
|
||
if ( ! latestUid || timestamp > latestTimestamp ) {
|
||
latestUid = uid;
|
||
latestTimestamp = timestamp;
|
||
}
|
||
}
|
||
}
|
||
|
||
return latestUid;
|
||
}
|
||
|
||
self.add = add;
|
||
self.removeImgurData = removeImgurData;
|
||
self.removeLocalData = removeLocalData;
|
||
self.load = load;
|
||
self.loadItem = loadItem;
|
||
self.removeImgurData = removeImgurData;
|
||
self.getLatestUID = getLatestUID;
|
||
}
|
||
|
||
return StorageModel;
|
||
}
|
||
); |