client-share-web/0.2.3/scripts/accounts.js

216 строки
6.1 KiB
JavaScript

/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Raindrop.
*
* The Initial Developer of the Original Code is
* Mozilla Messaging, Inc..
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* */
/*jslint indent: 2 */
/*global require: false, define: false, window: false, location: true,
localStorage: false, opener: false, setTimeout: false */
'use strict';
define([ 'storage', 'dispatch', 'rdapi'],
function (storage, dispatch, rdapi) {
var store = storage(), impl,
changeTypes = {
//localStorage is the most robust, since the change in localStorage
//can be listened to across windows.
'localStorage': {
accounts: function (ok, error) {
var accountCache = store.accountCache,
lastCheck = store.lastAccountCheck || 0,
currentTime = (new Date()).getTime(),
fetch = false;
if (!accountCache || (currentTime - lastCheck) > 3000) {
fetch = true;
}
//Set up accountCache as a real object.
if (accountCache) {
accountCache = JSON.parse(accountCache);
} else {
accountCache = [];
}
//Call ok callback with current knowledge. If there is a change in the
//account info, then the fetch will trigger changed event later.
if (ok) {
ok(accountCache);
}
if (fetch) {
impl.fetch(null, error);
}
},
fetch: function (ok, error) {
rdapi('account/get', {
success: function (json) {
if (json.error) {
json = [];
}
store.lastAccountCheck = (new Date()).getTime();
if (ok) {
ok(json);
}
//Check for changes, and if so, then trigger accounts changed.
var accountCache = store.accountCache, same;
accountCache = accountCache ? JSON.parse(accountCache) : [];
same = json.length === accountCache.length;
if (same) {
same = !json.some(function (account, i) {
return account.identifier !== accountCache[i].identifier;
});
}
if (!same) {
store.accountCache = JSON.stringify(json);
impl.changed();
}
},
error: error || function () {}
});
},
changed: function () {
store.accountChanged = (new Date()).getTime();
//Force the onchange events to occur. Sometimes the storage
//events do not fire?
if (opener && !opener.closed) {
dispatch.pub('accountsChanged', null, opener);
}
dispatch.pub('accountsChanged');
},
onChange: function (action) {
//Listen to storage changes, and if a the accountChanged key
//changes, refresh.
var lastValue = store.accountChanged;
window.addEventListener('storage', function (evt) {
//Only refresh if the accounts were changed.
if (store.accountChanged !== lastValue) {
action();
}
}, false);
//Also use direct notification in case storage events fail.
dispatch.sub('accountsChanged', action);
}
},
//Some extensions mess with localStorage, so in that case, fall back to
//using dispatching.
'memory': {
accounts: function (ok, error) {
impl.fetch(ok, error);
},
fetch: function (ok, error) {
rdapi('account/get', {
success: function (json) {
if (json.error) {
json = [];
}
if (ok) {
ok(json);
}
},
error: error || function () {}
});
},
changed: function () {
//Use dispatching. Dispatch to current window, but also to an opener
//if available.
store.accountChanged = (new Date()).getTime();
if (opener) {
dispatch.pub('accountsChanged', null, opener);
}
dispatch.pub('accountsChanged');
},
onChange: function (action) {
dispatch.sub('accountsChanged', action);
}
}
};
impl = changeTypes[storage.type];
/**
* Gets the accounts. Can use a cached value.
* @param {Function} ok function to receive the account info.
* @param {Function} error function to call if an error.
*/
function accounts(ok, error) {
return impl.accounts(ok, error);
}
/**
* Gets the accounts. Forces a call to the server.
* @param {Function} ok function to receive the account info.
* @param {Function} error function to call if an error.
*/
accounts.fetch = function (ok, error) {
impl.fetch(ok, error);
};
/**
* Clears the account data. Use this when it is known that the server
* info is no longer valid/expired.
*/
accounts.clear = function () {
delete store.accountCache;
};
/**
* Called when the cache of accounts has changed.
*/
accounts.changed = function () {
return impl.changed();
};
/**
* Default action is to just reload.
*/
function defaultAction() {
location.reload();
}
/**
* Called to set up the action when accounts change.
* Call it with no args to get the default behavior, page reload.
*/
accounts.onChange = function (action) {
return impl.onChange(action || defaultAction);
};
return accounts;
});