Merge pull request #509 from Xelio/patch-plugin-sync-5

Bug fix: Plugin Sync
This commit is contained in:
Jon Atkins 2013-08-25 10:30:27 -07:00
commit 625d51d7ff
2 changed files with 34 additions and 31 deletions

View File

@ -2,7 +2,7 @@
// @id iitc-plugin-keys@xelio // @id iitc-plugin-keys@xelio
// @name IITC plugin: Keys // @name IITC plugin: Keys
// @category Keys // @category Keys
// @version 0.2.0.@@DATETIMEVERSION@@ // @version 0.2.1.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@ // @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@ // @downloadURL @@DOWNLOADURL@@

View File

@ -135,7 +135,8 @@ window.plugin.sync.RegisteredMap.prototype.updateMap = function(keyArray) {
} }
window.plugin.sync.RegisteredMap.prototype.isUpdatedByOthers = function() { window.plugin.sync.RegisteredMap.prototype.isUpdatedByOthers = function() {
return this.lastUpdateUUID.toString() !== this.uuid; var remoteUUID = this.lastUpdateUUID.toString();
return (remoteUUID !== '') && (remoteUUID !== this.uuid);
} }
window.plugin.sync.RegisteredMap.prototype.getFileName = function() { window.plugin.sync.RegisteredMap.prototype.getFileName = function() {
@ -159,10 +160,8 @@ window.plugin.sync.RegisteredMap.prototype.initFile = function(callback) {
} }
this.fileSearcher = new plugin.sync.FileSearcher({'fileName': this.getFileName(), this.fileSearcher = new plugin.sync.FileSearcher({'fileName': this.getFileName(),
'description': 'IITC plugin data for ' + this.getFileName(), 'description': 'IITC plugin data for ' + this.getFileName()});
'assignIdCallback': assignIdCallback, this.fileSearcher.initialize(this.forceFileSearch, assignIdCallback, failedCallback);
'failedCallback': failedCallback});
this.fileSearcher.initialize(this.forceFileSearch);
} }
window.plugin.sync.RegisteredMap.prototype.updateListener = function(e) { window.plugin.sync.RegisteredMap.prototype.updateListener = function(e) {
@ -191,14 +190,18 @@ window.plugin.sync.RegisteredMap.prototype.loadRealtimeDocument = function(callb
// this function called when the document is created first time // this function called when the document is created first time
// and the CollaborativeMap is populated with data in plugin field // and the CollaborativeMap is populated with data in plugin field
initializeModel = function(model) { initializeModel = function(model) {
var empty = true;
var map = model.createMap(); var map = model.createMap();
var lastUpdateUUID = model.createString(); var lastUpdateUUID = model.createString();
// Init the map values if this map is first created // Init the map values if this map is first created
$.each(window.plugin[_this.pluginName][_this.fieldName], function(key, val) { $.each(window.plugin[_this.pluginName][_this.fieldName], function(key, val) {
map.set(key, val); map.set(key, val);
empty = false;
}); });
lastUpdateUUID.setText(_this.uuid);
// Only set the update client if the map is not empty, avoid clearing data of other clients
lastUpdateUUID.setText(empty ? '' : _this.uuid);
model.getRoot().set('map', map); model.getRoot().set('map', map);
model.getRoot().set('last-udpate-uuid', lastUpdateUUID); model.getRoot().set('last-udpate-uuid', lastUpdateUUID);
@ -211,8 +214,8 @@ window.plugin.sync.RegisteredMap.prototype.loadRealtimeDocument = function(callb
onFileLoaded = function(doc) { onFileLoaded = function(doc) {
_this.doc = doc; _this.doc = doc;
_this.model = doc.getModel(); _this.model = doc.getModel();
_this.map = doc.getModel().getRoot().get("map"); _this.map = doc.getModel().getRoot().get('map');
_this.lastUpdateUUID = doc.getModel().getRoot().get("last-udpate-uuid"); _this.lastUpdateUUID = doc.getModel().getRoot().get('last-udpate-uuid');
_this.map.addEventListener(gapi.drive.realtime.EventType.VALUE_CHANGED, _this.updateListener); _this.map.addEventListener(gapi.drive.realtime.EventType.VALUE_CHANGED, _this.updateListener);
// Replace local value if data is changed by others // Replace local value if data is changed by others
@ -240,6 +243,10 @@ window.plugin.sync.RegisteredMap.prototype.loadRealtimeDocument = function(callb
_this.authorizer.authorize(); _this.authorizer.authorize();
} else if(e.type === gapi.drive.realtime.ErrorType.NOT_FOUND) { } else if(e.type === gapi.drive.realtime.ErrorType.NOT_FOUND) {
_this.forceFileSearch = true; _this.forceFileSearch = true;
} else if(e.type === gapi.drive.realtime.ErrorType.CLIENT_ERROR) {
// Workaround: if Realtime API open a second docuemnt and the file do not exist,
// it will rasie 'CLIENT_ERROR' instead of 'NOT_FOUND'. So we do a force file search here.
_this.forceFileSearch = true;
} else { } else {
alert('Plugin Sync error: ' + e.type + ', ' + e.message); alert('Plugin Sync error: ' + e.type + ', ' + e.message);
} }
@ -367,8 +374,6 @@ window.plugin.sync.FileSearcher = function(options) {
this.fileName = options['fileName']; this.fileName = options['fileName'];
this.description = options['description']; this.description = options['description'];
this.isFolder = options['isFolder']; this.isFolder = options['isFolder'];
this.assignIdCallback = options['assignIdCallback'];
this.failedCallback = options['failedCallback'];
this.force = false; this.force = false;
this.parent = null; this.parent = null;
@ -386,27 +391,27 @@ window.plugin.sync.FileSearcher.prototype.MIMETYPE_FOLDER = 'application/vnd.goo
window.plugin.sync.FileSearcher.prototype.parentName = 'IITC-SYNC-DATA-V2'; window.plugin.sync.FileSearcher.prototype.parentName = 'IITC-SYNC-DATA-V2';
window.plugin.sync.FileSearcher.prototype.parentDescription = 'Store IITC sync data'; window.plugin.sync.FileSearcher.prototype.parentDescription = 'Store IITC sync data';
window.plugin.sync.FileSearcher.prototype.initialize = function(force) { window.plugin.sync.FileSearcher.prototype.initialize = function(force, assignIdCallback, failedCallback) {
this.force = force; this.force = force;
// throw error if too many retry // throw error if too many retry
if(this.retryCount >= this.RETRY_LIMIT) { if(this.retryCount >= this.RETRY_LIMIT) {
plugin.sync.logger.log('Too many file operation: ' + this.fileName); plugin.sync.logger.log('Too many file operation: ' + this.fileName);
this.failedCallback(); failedCallback();
return; return;
} }
if(this.force) this.retryCount++; if(this.force) this.retryCount++;
if(this.isFolder) { if(this.isFolder) {
this.initFile(); this.initFile(assignIdCallback, failedCallback);
} else { } else {
this.initParent(); this.initParent(assignIdCallback, failedCallback);
} }
} }
window.plugin.sync.FileSearcher.prototype.initFile = function() { window.plugin.sync.FileSearcher.prototype.initFile = function(assignIdCallback, failedCallback) {
// If not force search and have cached fileId, return the fileId // If not force search and have cached fileId, return the fileId
if(!this.force && this.fileId) { if(!this.force && this.fileId) {
this.assignIdCallback(this.fileId); assignIdCallback(this.fileId);
return; return;
} }
@ -416,14 +421,14 @@ window.plugin.sync.FileSearcher.prototype.initFile = function() {
handleFileId = function(id) { handleFileId = function(id) {
_this.fileId = id; _this.fileId = id;
_this.saveFileId(); _this.saveFileId();
_this.assignIdCallback(id); assignIdCallback(id);
}; };
handleFailed = function(resp) { handleFailed = function(resp) {
_this.fileId = null; _this.fileId = null;
_this.saveFileId(); _this.saveFileId();
plugin.sync.logger.log('File operation failed: ' + (resp.error || 'unknown error')); plugin.sync.logger.log('File operation failed: ' + (resp.error || 'unknown error'));
_this.failedCallback(resp); failedCallback(resp);
} }
createCallback = function(resp) { createCallback = function(resp) {
@ -447,27 +452,25 @@ window.plugin.sync.FileSearcher.prototype.initFile = function() {
this.searchFileOrFolder(searchCallback); this.searchFileOrFolder(searchCallback);
} }
window.plugin.sync.FileSearcher.prototype.initParent = function() { window.plugin.sync.FileSearcher.prototype.initParent = function(assignIdCallback, failedCallback) {
var assignIdCallback, failedCallback, _this; var parentAssignIdCallback, parentFailedCallback, _this;
_this = this; _this = this;
assignIdCallback = function(id) { parentAssignIdCallback = function(id) {
_this.initFile(); _this.initFile(assignIdCallback, failedCallback);
} }
failedCallback = function(resp) { parentFailedCallback = function(resp) {
_this.fileId = null; _this.fileId = null;
_this.saveFileId(); _this.saveFileId();
plugin.sync.logger.log('File operation failed: ' + (resp.error || 'unknown error')); plugin.sync.logger.log('File operation failed: ' + (resp.error || 'unknown error'));
_this.failedCallback(resp); failedCallback(resp);
} }
this.parent = new plugin.sync.FileSearcher({'fileName': this.parentName, this.parent = new plugin.sync.FileSearcher({'fileName': this.parentName,
'description': this.parentDescription, 'description': this.parentDescription,
'isFolder': true, 'isFolder': true});
'assignIdCallback': assignIdCallback, this.parent.initialize(this.force, parentAssignIdCallback, parentFailedCallback);
'failedCallback': failedCallback});
this.parent.initialize(this.force);
} }
window.plugin.sync.FileSearcher.prototype.createFileOrFolder = function(callback) { window.plugin.sync.FileSearcher.prototype.createFileOrFolder = function(callback) {
@ -629,12 +632,12 @@ window.plugin.sync.generateUUID = function() {
window.crypto.getRandomValues(buf); window.crypto.getRandomValues(buf);
var S4 = function(num) { var S4 = function(num) {
var ret = num.toString(16); var ret = num.toString(16);
return "000".substring(0, 4-ret.length) + ret; return '000'.substring(0, 4-ret.length) + ret;
}; };
var yxxx = function(num) { var yxxx = function(num) {
return num&0x3fff|0x8000; return num&0x3fff|0x8000;
} }
return (S4(buf[0])+S4(buf[1])+"-"+S4(buf[2])+"-4"+S4(buf[3]).substring(1)+"-"+S4(yxxx(buf[4]))+"-"+S4(buf[5])+S4(buf[6])+S4(buf[7])); return (S4(buf[0])+S4(buf[1])+'-'+S4(buf[2])+'-4'+S4(buf[3]).substring(1)+'-'+S4(yxxx(buf[4]))+'-'+S4(buf[5])+S4(buf[6])+S4(buf[7]));
} else { } else {
var d = new Date().getTime(); var d = new Date().getTime();
var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {